Current File : /home/escuelai/public_html/wp-content/plugins/w3-total-cache/Minify_AutoCss.php |
<?php
/**
* File: Minify_AutoCss.php
*
* @package W3TC
*/
namespace W3TC;
/**
* Class Minify_AutoCss
*/
class Minify_AutoCss {
/**
* Config
*
* @var Config
*/
private $config;
/**
* Buffer
*
* @var string
*/
private $buffer;
/**
* CSS files to ignore
*
* @var array
*/
private $ignore_css_files;
/**
* Helper object to use
*
* @var _W3_MinifyHelpers
*/
private $minify_helpers;
/**
* Array of processed styles
*
* @var array
*/
private $debug_minified_urls = array();
/**
* Current position to embed minified style
*
* @var integer
*/
private $embed_pos;
/**
* Current list of files to minify
*
* @var array
*/
private $files_to_minify;
/**
* Current number of minification group
*
* @var integer
*/
private $debug = false;
/**
* Embed to HTML flag
*
* @var bool
*/
private $embed_to_html;
/**
* Constructor method for initializing the Minify_AutoCss class.
*
* @param object $config Configuration object containing settings.
* @param string $buffer The content buffer to process.
* @param object $minify_helpers Helper object for minification operations.
*
* @return void
*/
public function __construct( $config, $buffer, $minify_helpers ) {
$this->config = $config;
$this->debug = $config->get_boolean( 'minify.debug' );
$this->buffer = $buffer;
$this->minify_helpers = $minify_helpers;
// ignored files.
$this->ignore_css_files = $this->config->get_array( 'minify.reject.files.css' );
$this->ignore_css_files = array_map( array( '\W3TC\Util_Environment', 'normalize_file' ), $this->ignore_css_files );
$this->embed_to_html = $this->config->get_boolean( 'minify.css.embed' );
}
/**
* Executes the main functionality of the class, processing and minifying CSS styles.
*
* @return string The processed buffer after applying CSS minification.
*/
public function execute() {
// find all style tags.
$buffer_nocomments = preg_replace( '~<!--.*?-->\s*~s', '', $this->buffer );
$matches = null;
// end of <head> means another group of styles, cannt be combined.
if ( ! preg_match_all( '~((<style\s*[^>]*>.*?</style>)|(<link\s+([^>]+)/?>(.*</link>)?))~is', $buffer_nocomments, $matches ) ) {
$matches = null;
}
if ( is_null( $matches ) ) {
return $this->buffer;
}
$style_tags = $matches[1];
$style_tags = apply_filters( 'w3tc_minify_css_style_tags', $style_tags );
// pass styles.
$this->embed_pos = null;
$this->files_to_minify = array();
$count = count( $style_tags );
for ( $n = 0; $n < $count; $n++ ) {
$this->process_style_tag( $style_tags[ $n ], $n );
}
$this->flush_collected( '' );
return $this->buffer;
}
/**
* Retrieves the URLs of minified files for debugging purposes.
*
* @return array An array of URLs for minified files.
*/
public function get_debug_minified_urls() {
return $this->debug_minified_urls;
}
/**
* Processes individual style tags found in the buffer.
*
* @param string $style_tag The style tag to process.
* @param int $style_tag_number The position of the style tag in the sequence.
*
* @return void
*/
private function process_style_tag( $style_tag, $style_tag_number ) {
if ( $this->debug ) {
Minify_Core::log( 'processing tag ' . substr( $style_tag, 0, 150 ) );
}
$tag_pos = strpos( $this->buffer, $style_tag );
if ( false === $tag_pos ) {
// style is external but not found, skip processing it.
if ( $this->debug ) {
Minify_Core::log( 'style not found:' . $style_tag );
}
return;
}
$style_href = null;
$causes_flush = true;
if ( preg_match( '~<link\s+([^>]+)/?>(.*</link>)?~Uis', $style_tag, $match ) ) {
// all link tags dont cause automatic flush since its minified or its not style <link> tag.
$causes_flush = false;
$attrs = array();
$attr_matches = null;
if ( preg_match_all( '~(\w+)=["\']([^"\']*)["\']~', $match[1], $attr_matches, PREG_SET_ORDER ) ) {
foreach ( $attr_matches as $attr_match ) {
$name = strtolower( $attr_match[1] );
$attrs[ $name ] = trim( $attr_match[2] );
}
}
if (
isset( $attrs['href'] ) &&
isset( $attrs['rel'] ) &&
stristr( $attrs['rel'], 'stylesheet' ) !== false &&
(
! isset( $attrs['media'] ) ||
stristr( $attrs['media'], 'print' ) === false
)
) {
$style_href = $attrs['href'];
}
}
if ( $causes_flush ) {
$data = array(
'style_tag_original' => $style_tag,
'style_tag_new' => $style_tag,
'style_tag_number' => $style_tag_number,
'style_tag_pos' => $tag_pos,
'should_replace' => false,
'buffer' => $this->buffer,
);
$data = apply_filters( 'w3tc_minify_css_do_local_style_minification', $data );
$this->buffer = $data['buffer'];
if ( $data['should_replace'] ) {
$this->buffer = substr_replace(
$this->buffer,
$data['style_tag_new'],
$tag_pos,
strlen( $style_tag )
);
}
// it's not external style, have to flush what we have before it.
if ( $this->debug ) {
Minify_Core::log( 'its not link tag, flushing' );
}
$this->flush_collected( $style_tag );
return;
}
if ( empty( $style_href ) ) {
if ( $this->debug ) {
Minify_Core::log( 'its not style link tag' );
}
return;
}
$style_href = Util_Environment::url_relative_to_full( $style_href );
$file = Util_Environment::url_to_docroot_filename( $style_href );
$step1_result = $this->minify_helpers->is_file_for_minification( $style_href, $file );
if ( 'url' === $step1_result ) {
$file = $style_href;
}
$step1 = ! empty( $step1_result );
$step2 = ! in_array( $file, $this->ignore_css_files, true );
$do_tag_minification = $step1 && $step2;
$do_tag_minification = apply_filters( 'w3tc_minify_css_do_tag_minification', $do_tag_minification, $style_tag, $file );
if ( ! $do_tag_minification ) {
if ( $this->debug ) {
Minify_Core::log(
'file ' . $file .
' didnt pass minification check:' .
' file_for_min: ' . ( $step1 ? 'true' : 'false' ) .
' ignore_css_files: ' . ( $step2 ? 'true' : 'false' )
);
}
$data = array(
'style_tag_original' => $style_tag,
'style_tag_new' => $style_tag,
'style_tag_number' => $style_tag_number,
'style_tag_pos' => $tag_pos,
'style_href' => $style_href,
'should_replace' => false,
'buffer' => $this->buffer,
);
$data = apply_filters( 'w3tc_minify_css_do_excluded_tag_style_minification', $data );
$this->buffer = $data['buffer'];
if ( $data['should_replace'] ) {
$this->buffer = substr_replace(
$this->buffer,
$data['style_tag_new'],
$tag_pos,
strlen( $style_tag )
);
}
$this->flush_collected( $style_tag );
return;
}
$this->debug_minified_urls[] = $file;
$this->buffer = substr_replace(
$this->buffer,
'',
$tag_pos,
strlen( $style_tag )
);
// put minified file at the place of first tag.
if ( count( $this->files_to_minify ) <= 0 ) {
$this->embed_pos = $tag_pos;
}
$this->files_to_minify[] = $file;
if ( 'minify' === $this->config->get_string( 'minify.css.method' ) ) {
$this->flush_collected( '' );
}
}
/**
* Flushes the collected files to be minified and embeds or replaces them in the buffer.
*
* @param string $last_style_tag The last style tag processed, used for determining flushing logic.
*
* @return void
*/
private function flush_collected( $last_style_tag ) {
if ( count( $this->files_to_minify ) <= 0 ) {
return;
}
$do_flush_collected = apply_filters( 'w3tc_minify_css_do_flush_collected', true, $last_style_tag, $this );
if ( ! $do_flush_collected ) {
return;
}
// find embed position.
$embed_pos = $this->embed_pos;
// build minified style tag.
$data = array(
'files_to_minify' => $this->files_to_minify,
'embed_pos' => $embed_pos,
'buffer' => $this->buffer,
'embed_to_html' => $this->embed_to_html,
);
$data = apply_filters( 'w3tc_minify_css_step', $data );
$this->buffer = $data['buffer'];
if ( ! empty( $data['files_to_minify'] ) ) {
$style_data = $this->minify_helpers->generate_css_style_tag(
$data['files_to_minify'],
$data['embed_to_html']
);
$data['style_to_embed_url'] = $style_data['url'];
$data['style_to_embed_body'] = $style_data['body'];
$data = apply_filters( 'w3tc_minify_css_step_style_to_embed', $data );
$this->buffer = $data['buffer'];
if ( $this->config->getf_boolean( 'minify.css.http2push' ) ) {
$this->minify_helpers->http2_header_add( $data['style_to_embed_url'], 'style' );
}
// replace.
$this->buffer = substr_replace(
$this->buffer,
$data['style_to_embed_body'],
$data['embed_pos'],
0
);
}
$this->files_to_minify = array();
}
}