oont-contents/plugins/wp-rocket/inc/Engine/Optimization/IEConditionalSubscriber.php
2025-02-08 15:10:23 +01:00

140 lines
3.2 KiB
PHP

<?php
namespace WP_Rocket\Engine\Optimization;
use WP_Rocket\Event_Management\Subscriber_Interface;
/**
* Handles IE conditionals comments in the HTML to prevent their content from being processed during optimization.
*
* @since 3.6 Changes template tag to be an HTML comment.
* @since 3.1
*/
class IEConditionalSubscriber implements Subscriber_Interface {
/**
* Stores IE conditionals.
*
* @since 3.1
*
* @var array
*/
private $conditionals = [];
/**
* HTML IE conditional pattern.
*
* @since 3.6.2
*
* @var string
*/
const IE_PATTERN = '/<!--\[if[^\]]*?\]>.*?<!\[endif\]-->/is';
/**
* HTML IE conditional template tag.
*
* @since 3.6.2
*
* @var string
*/
const WP_ROCKET_CONDITIONAL = '<!--{{WP_ROCKET_CONDITIONAL}}-->';
/**
* Return an array of events that this subscriber listens to.
*
* @since 3.1
*
* @return array
*/
public static function get_subscribed_events() {
return [
'rocket_buffer' => [
[ 'extract_ie_conditionals', 1 ],
[ 'inject_ie_conditionals', 34 ],
],
];
}
/**
* Extracts IE conditionals tags and replace them with placeholders.
*
* @since 3.1
*
* @param string $html HTML content.
*
* @return string
*/
public function extract_ie_conditionals( $html ) {
preg_match_all( self::IE_PATTERN, $html, $conditionals_match );
if ( ! $conditionals_match ) {
return $html;
}
foreach ( $conditionals_match[0] as $conditional ) {
$this->conditionals[] = $conditional;
}
return preg_replace( self::IE_PATTERN, self::WP_ROCKET_CONDITIONAL, $html );
}
/**
* Replaces WP Rocket placeholders with IE conditional tags.
*
* @since 3.1
*
* @param string $html HTML content.
*
* @return string
*/
public function inject_ie_conditionals( $html ) {
if ( ! $this->has_conditional_tag( $html ) ) {
return $html;
}
foreach ( $this->conditionals as $conditional ) {
// Prevent scripts containing things like "\\s" to be striped of a backslash when put back in content.
if ( preg_match( '@^(?<opening><!--\[if[^\]]*?\]>\s*?(?:<!-->)?\s*<script(?:\s[^>]*?>))\s*(?<content>.*?)\s*(?<closing></script>\s*(?:<!--)?\s*?<!\[endif\]-->)$@is', $conditional, $matches ) ) {
$conditional = $matches['opening'] . preg_replace( '#(?<!\\\\)(\\$|\\\\)#', '\\\\$1', $matches['content'] ) . $matches['closing'];
}
$html = $this->replace_conditional_tag( $html, $conditional );
}
return $html;
}
/**
* Checks if the template tag for the IE conditional exists in the given HTML string.
*
* @since 3.6.2
*
* @param string $html HTML content.
*
* @return bool true if at least one exists; else false.
*/
private function has_conditional_tag( $html ) {
return ( false !== strpos( $html, self::WP_ROCKET_CONDITIONAL ) );
}
/**
* Replaces the template tag with the original IE conditional HTML.
*
* @since 3.6.2
*
* @param string $html HTML content.
* @param string $original Original IE conditional HTML.
*
* @return string
*/
private function replace_conditional_tag( $html, $original ) {
$template_tag_position = strpos( $html, self::WP_ROCKET_CONDITIONAL );
return substr_replace(
$html,
$original,
$template_tag_position,
strlen( self::WP_ROCKET_CONDITIONAL )
);
}
}