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

247 lines
5.8 KiB
PHP

<?php
namespace WP_Rocket\Engine\Preload\Links;
use WP_Filesystem_Direct;
use WP_Rocket\Admin\Options_Data;
use WP_Rocket\Event_Management\Subscriber_Interface;
class Subscriber implements Subscriber_Interface {
/**
* Options Data instance
*
* @var Options_Data
*/
private $options;
/**
* WP_Filesystem_Direct instance.
*
* @var WP_Filesystem_Direct
*/
private $filesystem;
/**
* Script enqueued status.
*
* @var bool
*/
private $is_enqueued = false;
/**
* Instantiate the class.
*
* @param Options_Data $options Options Data instance.
* @param WP_Filesystem_Direct $filesystem The Filesystem object.
*/
public function __construct( Options_Data $options, $filesystem ) {
$this->options = $options;
$this->filesystem = $filesystem;
}
/**
* Return an array of events that this subscriber wants to listen to.
*
* @return array
*/
public static function get_subscribed_events() {
return [
'wp_enqueue_scripts' => 'add_preload_script',
];
}
/**
* Adds the inline script to the footer when the option is enabled
*
* @since 3.7
*
* @return void
*/
public function add_preload_script() {
/**
* Bail out if user is logged in
* Don't add preload link script
*/
if ( is_user_logged_in() ) {
return;
}
if ( $this->is_enqueued ) {
return;
}
if ( ! (bool) $this->options->get( 'preload_links', 0 ) || rocket_bypass() ) {
return;
}
$js_assets_path = rocket_get_constant( 'WP_ROCKET_PATH' ) . 'assets/js/';
if ( ! wp_script_is( 'rocket-browser-checker' ) ) {
$checker_filename = rocket_get_constant( 'SCRIPT_DEBUG' ) ? 'browser-checker.js' : 'browser-checker.min.js';
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion
wp_register_script(
'rocket-browser-checker',
'',
[],
'',
true
);
wp_enqueue_script( 'rocket-browser-checker' );
wp_add_inline_script(
'rocket-browser-checker',
$this->filesystem->get_contents( "{$js_assets_path}{$checker_filename}" )
);
}
$preload_filename = rocket_get_constant( 'SCRIPT_DEBUG' ) ? 'preload-links.js' : 'preload-links.min.js';
// Register handle with no src to add the inline script after.
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NoExplicitVersion
wp_register_script(
'rocket-preload-links',
'',
[
'rocket-browser-checker',
],
'',
true
);
wp_enqueue_script( 'rocket-preload-links' );
wp_add_inline_script(
'rocket-preload-links',
$this->filesystem->get_contents( "{$js_assets_path}{$preload_filename}" )
);
wp_localize_script(
'rocket-preload-links',
'RocketPreloadLinksConfig',
$this->get_preload_links_config()
);
$this->is_enqueued = true;
}
/**
* Gets the Preload Links script configuration parameters.
*
* @since 3.7
*
* @return string[] Preload Links script configuration parameters.
*/
private function get_preload_links_config() {
$use_trailing_slash = $this->use_trailing_slash();
$images_ext = 'jpg|jpeg|gif|png|tiff|bmp|webp|avif|pdf|doc|docx|xls|xlsx|php';
$config = [
'excludeUris' => $this->get_uris_to_exclude( $use_trailing_slash ),
'usesTrailingSlash' => $use_trailing_slash,
'imageExt' => $images_ext,
'fileExt' => $images_ext . '|html|htm',
'siteUrl' => home_url(),
'onHoverDelay' => 100, // milliseconds. -1 disables the "on hover" feature.
'rateThrottle' => 3, // on hover: limits the number of links preloaded per second.
];
/**
* Preload Links script configuration parameters.
*
* This array of parameters are passed as RocketPreloadLinksConfig object and used by the
* `preload-links.min.js` script to configure the behavior of the Preload Links feature.
*
* @since 3.7
*
* @param string[] $config Preload Links script configuration parameters.
*/
$filtered_config = apply_filters( 'rocket_preload_links_config', $config );
if ( ! is_array( $filtered_config ) ) {
return $config;
}
return array_merge( $config, $filtered_config );
}
/**
* Gets the URIs to exclude.
*
* @since 3.7
*
* @param bool $use_trailing_slash When true, uses trailing slash.
*
* @return string
*/
private function get_uris_to_exclude( $use_trailing_slash ) {
$site_url = site_url();
$uris = get_rocket_cache_reject_uri( false, false );
$uris = str_replace( [ '/(.*)|', '/(.*)/|' ], '/|', $uris );
$default = [
'/refer/',
'/go/',
'/recommend/',
'/recommends/',
];
$excluded = $default;
/**
* Filters the patterns excluded from links preload
*
* @since 3.10.8
*
* @param string[] $excluded Array of excluded patterns.
* @param string[] $default Array of default excluded patterns.
*/
$excluded = apply_filters( 'rocket_preload_links_exclusions', $excluded, $default );
if ( ! is_array( $excluded ) ) {
$excluded = (array) $excluded;
}
$excluded = array_filter( $excluded );
$login_url = wp_login_url(); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
$login_uri = str_replace( home_url(), '', $login_url );
$excluded = array_filter(
$excluded,
function ( $uri ) use ( $login_uri ) {
return ! str_contains( $login_uri, $uri );
}
);
$excluded_patterns = '';
if ( ! empty( $excluded ) ) {
$excluded_patterns = '|' . implode( '|', $excluded );
}
return $uris . $excluded_patterns;
}
/**
* Checks if the given URL has a trailing slash.
*
* @since 3.7
*
* @param string $url URL to check.
*
* @return bool
*/
private function has_trailing_slash( $url ) {
return substr( $url, -1 ) === '/';
}
/**
* Indicates if the site uses a trailing slash in the permalink structure.
*
* @since 3.7
*
* @return bool when true, uses `/`; else, no.
*/
private function use_trailing_slash() {
return $this->has_trailing_slash( get_permalink() );
}
}