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

432 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace WP_Rocket\Engine\Preload;
use WP_Rocket\Admin\Options_Data;
use WP_Rocket\Engine\Preload\Activation\Activation;
use WP_Rocket\Engine\Preload\Controller\CheckExcludedTrait;
use WP_Rocket\Engine\Preload\Controller\ClearCache;
use WP_Rocket\Engine\Preload\Controller\LoadInitialSitemap;
use WP_Rocket\Engine\Preload\Controller\Queue;
use WP_Rocket\Engine\Preload\Database\Queries\Cache;
use WP_Rocket\Event_Management\Subscriber_Interface;
use WP_Rocket_Mobile_Detect;
class Subscriber implements Subscriber_Interface {
use CheckExcludedTrait;
/**
* Options instance.
*
* @var Options_Data
*/
protected $options;
/**
* Controller to load initial tasks.
*
* @var LoadInitialSitemap
*/
protected $controller;
/**
* Clear cache controller.
*
* @var ClearCache
*/
protected $clear_cache;
/**
* Cache query instance.
*
* @var Cache
*/
private $query;
/**
* Activation manager.
*
* @var Activation
*/
protected $activation;
/**
* Mobile detector instance.
*
* @var WP_Rocket_Mobile_Detect
*/
protected $mobile_detect;
/**
* Preload queue.
*
* @var Queue
*/
protected $queue;
/**
* Creates an instance of the class.
*
* @param Options_Data $options Options instance.
* @param LoadInitialSitemap $controller controller creating the initial task.
* @param Cache $query Cache query instance.
* @param Activation $activation Activation manager.
* @param WP_Rocket_Mobile_Detect $mobile_detect Mobile detector instance.
* @param ClearCache $clear_cache Clear cache controller.
* @param Queue $queue Preload queue.
*/
public function __construct( Options_Data $options, LoadInitialSitemap $controller, $query, Activation $activation, WP_Rocket_Mobile_Detect $mobile_detect, ClearCache $clear_cache, Queue $queue ) {
$this->options = $options;
$this->controller = $controller;
$this->query = $query;
$this->activation = $activation;
$this->mobile_detect = $mobile_detect;
$this->clear_cache = $clear_cache;
$this->queue = $queue;
}
/**
* Return an array of events that this subscriber listens to.
*
* @return array
*/
public static function get_subscribed_events() {
return [
'update_option_' . WP_ROCKET_SLUG => [
[ 'maybe_load_initial_sitemap', 10, 2 ],
[ 'maybe_cancel_preload', 10, 2 ],
],
'rocket_after_process_buffer' => 'update_cache_row',
'rocket_deactivation' => 'on_deactivation',
'permalink_structure_changed' => 'on_permalink_changed',
'wp_rocket_upgrade' => [ 'on_update', 16, 2 ],
'rocket_rucss_complete_job_status' => 'clean_url',
'rocket_rucss_after_clearing_usedcss' => [ 'clean_url', 20 ],
'rocket_after_automatic_cache_purge' => 'preload_after_automatic_cache_purge',
'after_rocket_clean_post' => [ 'clean_partial_cache', 10, 3 ],
'after_rocket_clean_term' => [ 'clean_partial_cache', 10, 3 ],
'after_rocket_clean_file' => 'clean_url',
'set_404' => 'delete_url_on_not_found',
'rocket_after_clean_terms' => 'clean_urls',
'after_rocket_clean_domain' => 'clean_full_cache',
'delete_post' => 'delete_post_preload_cache',
'pre_delete_term' => 'delete_term_preload_cache',
'rocket_preload_lock_url' => 'lock_url',
'rocket_preload_unlock_url' => 'unlock_url',
'rocket_preload_exclude_urls' => [
[ 'add_preload_excluded_uri' ],
[ 'add_cache_reject_uri_to_excluded' ],
],
];
}
/**
* Load first tasks from preload when preload option is enabled.
*
* @param array $old_value old configuration values.
* @param array $value new configuration values.
* @return void
*/
public function maybe_load_initial_sitemap( $old_value, $value ) {
if ( ! isset( $value['manual_preload'], $old_value['manual_preload'] ) ) {
return;
}
if ( $value['manual_preload'] === $old_value['manual_preload'] ) {
return;
}
if ( ! $value['manual_preload'] ) {
return;
}
rocket_renew_box( 'preload_notice' );
$this->controller->load_initial_sitemap();
}
/**
* Cancel preload when configuration from sitemap changed.
*
* @param array $old_value old configuration values.
* @param array $value new configuration values.
* @return void
*/
public function maybe_cancel_preload( $old_value, $value ) {
if ( ! isset( $value['manual_preload'], $old_value['manual_preload'] ) ) {
return;
}
if ( $value['manual_preload'] === $old_value['manual_preload'] ) {
return;
}
if ( $value['manual_preload'] ) {
return;
}
$this->controller->cancel_preload();
}
/**
* Create or update the cache row after processing the buffer
*
* @return void
*/
public function update_cache_row() {
global $wp;
if ( is_user_logged_in() ) {
return;
}
$url = home_url( add_query_arg( [], $wp->request ) );
if ( $this->query->is_preloaded( $url ) ) {
$detected = $this->mobile_detect->isMobile() && ! $this->mobile_detect->isTablet() ? 'mobile' : 'desktop';
/**
* Fires when the preload from an URL is completed.
*
* @param string $url URL preladed.
* @param string $device Device from the cache.
*/
do_action( 'rocket_preload_completed', $url, $detected );
}
if ( ! empty( (array) $_GET ) || ( $this->query->is_pending( $url ) && $this->options->get( 'do_caching_mobile_files', false ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
if ( $this->is_excluded_by_filter( $url ) ) {
$this->query->delete_by_url( $url );
return;
}
$this->query->create_or_update(
[
'url' => $url,
'status' => 'completed',
'last_accessed' => true,
]
);
}
/**
* Delete url from the Preload when a 404 is risen.
*
* @return void
*/
public function delete_url_on_not_found() {
global $wp;
$url = home_url( $wp->request );
$this->query->delete_by_url( $url );
}
/**
* Preload on permalink changed.
*
* @return void
*/
public function on_permalink_changed() {
$this->query->remove_all();
$this->controller->load_initial_sitemap();
}
/**
* Disable cron and jobs on update.
*
* @param string $new_version new version from the plugin.
* @param string $old_version old version from the plugin.
* @return void
*/
public function on_update( $new_version, $old_version ) {
$this->activation->clean_on_update( $new_version, $old_version );
if ( ! $this->options->get( 'manual_preload', false ) ) {
return;
}
$this->activation->refresh_on_update( $new_version, $old_version );
}
/**
* Clear preload on deactivation.
*
* @return void
*/
public function on_deactivation() {
$this->activation->deactivation();
}
/**
* Clean the url.
*
* @param string $url url.
* @return void
*/
public function clean_url( string $url ) {
$this->clear_cache->partial_clean( [ $url ] );
}
/**
* Preload after clearing full cache.
*
* @return void
*/
public function clean_full_cache() {
set_transient( 'wpr_preload_running', true );
$this->queue->add_job_preload_job_check_finished_async();
$this->clear_cache->full_clean();
}
/**
* Preload after clearing some cache.
*
* @param stdClass $object object modified.
* @param array $urls urls cleaned.
* @param string $lang lang from the website.
* @return void
*/
public function clean_partial_cache( $object, array $urls, $lang ) {
// Add Homepage URL to $purge_urls for preload.
$urls[] = get_rocket_i18n_home_url( $lang );
$urls = array_filter( $urls );
$this->clear_cache->partial_clean( $urls );
}
/**
* Clean the list of urls.
*
* @param array $urls urls.
* @return void
*/
public function clean_urls( array $urls ) {
$this->clear_cache->partial_clean( $urls );
}
/**
* Delete URL from a post from the preload.
*
* @param int $post_id ID from the post.
* @return void
*/
public function delete_post_preload_cache( $post_id ) {
if ( ! $this->options->get( 'manual_preload', 0 ) ) {
return;
}
$url = get_permalink( $post_id );
if ( empty( $url ) ) {
return;
}
$this->clear_cache->delete_url( $url );
}
/**
* Delete URL from a term from the preload.
*
* @param int $term_id ID from the term.
* @return void
*/
public function delete_term_preload_cache( $term_id ) {
if ( ! $this->options->get( 'manual_preload', 0 ) ) {
return;
}
$url = get_term_link( (int) $term_id );
if ( empty( $url ) ) {
return;
}
$this->clear_cache->delete_url( $url );
}
/**
* Pushes URLs to preload to the queue after cache directories are purged.
*
* @since 3.4
*
* @param array $deleted {
* An array of arrays, described like: {.
* @type string $home_url The home URL.
* @type string $home_path Path to home.
* @type bool $logged_in True if the home path corresponds to a logged in users folder.
* @type array $files A list of paths of files that have been deleted.
* }
* }
*/
public function preload_after_automatic_cache_purge( $deleted ) {
if ( ! $deleted || ! $this->options->get( 'manual_preload' ) ) {
return;
}
foreach ( $deleted as $data ) {
if ( $data['logged_in'] ) {
// Logged in user: no need to preload those since we would need the corresponding cookies.
continue;
}
foreach ( $data['files'] as $file_path ) {
if ( strpos( $file_path, '#' ) ) {
// URL with query string.
$file_path = preg_replace( '/#/', '?', $file_path, 1 );
} else {
$file_path = untrailingslashit( $file_path );
$data['home_path'] = untrailingslashit( $data['home_path'] );
$data['home_url'] = untrailingslashit( $data['home_url'] );
if ( '/' === substr( get_option( 'permalink_structure' ), -1 ) ) {
$file_path .= '/';
$data['home_path'] .= '/';
$data['home_url'] .= '/';
}
}
$this->clear_cache->partial_clean( [ str_replace( $data['home_path'], $data['home_url'], $file_path ) ] );
}
}
}
/**
* Lock a URL.
*
* @param string $url URL to lock.
*
* @return void
*/
public function lock_url( string $url ) {
$this->query->lock( $url );
}
/**
* Unlock a URL.
*
* @param string $url URL to unlock.
*
* @return void
*/
public function unlock_url( string $url ) {
$this->query->unlock( $url );
}
/**
* Add the excluded uri from the preload to the filter.
*
* @param array $regexes regexes containing excluded uris.
* @return array|false
*/
public function add_preload_excluded_uri( $regexes ): array {
$preload_excluded_uri = (array) $this->options->get( 'preload_excluded_uri', [] );
if ( empty( $preload_excluded_uri ) ) {
return $regexes;
}
return array_merge( $regexes, $preload_excluded_uri );
}
}