%PDF- %PDF-
Direktori : /home/tradesc/www/relax/wp-content/plugins/wp-rocket/inc/Engine/Preload/Controller/ |
Current File : /home/tradesc/www/relax/wp-content/plugins/wp-rocket/inc/Engine/Preload/Controller/PreloadUrl.php |
<?php declare(strict_types=1); namespace WP_Rocket\Engine\Preload\Controller; use WP_Rocket\Admin\Options_Data; use WP_Rocket\Engine\Preload\Database\Queries\Cache; use WP_Filesystem_Direct; class PreloadUrl { use CheckExcludedTrait; /** * Preload queue. * * @var Queue */ protected $queue; /** * Preload database query. * * @var Cache */ protected $query; /** * Configurations options. * * @var Options_Data */ protected $options; /** * Filesystem. * * @var WP_Filesystem_Direct */ protected $filesystem; /** * Instantiate preload controller. * * @param Options_Data $options configuration options. * @param Queue $queue preload queue. * @param Cache $rocket_cache preload database query. * @param WP_Filesystem_Direct $filesystem Filesystem. */ public function __construct( Options_Data $options, Queue $queue, Cache $rocket_cache, WP_Filesystem_Direct $filesystem ) { $this->options = $options; $this->query = $rocket_cache; $this->queue = $queue; $this->filesystem = $filesystem; } /** * Preload an url. * * @param string $url url to preload. * * @return void */ public function preload_url( string $url ) { $is_mobile = $this->options->get( 'do_caching_mobile_files', false ); if ( $this->is_already_cached( $url ) && ( ! $is_mobile || $this->is_already_cached( $url, true ) ) ) { $this->query->make_status_complete( $url ); return; } // Should we perform a duration check? $check_duration = ( false === get_transient( 'rocket_preload_check_duration' ) ) ? true : false; $requests = [ [ 'url' => $url, 'is_mobile' => false, 'headers' => [ 'blocking' => false, 'timeout' => 0.01, 'user-agent' => 'WP Rocket/Preload', ], ], ]; if ( $is_mobile ) { $requests[] = [ 'url' => $url, 'headers' => [ 'user-agent' => $this->get_mobile_user_agent_prefix(), ], 'is_mobile' => true, ]; } /** * Filters to modify requests done to preload an url. * * @param array $requests Requests that will be done. */ $requests = apply_filters( 'rocket_preload_before_preload_url', $requests ); if ( ! is_array( $requests ) ) { return; } $requests = array_filter( $requests ); foreach ( $requests as $request ) { if ( ! isset( $request['url'] ) || ! is_string( $request['url'] ) ) { continue; } $headers = isset( $request['headers'] ) && is_array( $request['headers'] ) ? $request['headers'] : []; $headers = array_merge( $headers, [ 'blocking' => false, 'timeout' => 0.01, 'sslverify' => apply_filters( 'https_local_ssl_verify', false ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound ] ); if ( $check_duration ) { $headers['blocking'] = true; $headers['timeout'] = 20; } /** * Filters the arguments for the preload request. * * @param array $headers Request arguments. */ $headers = apply_filters( 'rocket_preload_url_request_args', $headers ); if ( ! is_array( $headers ) ) { return; } if ( $check_duration ) { $start = microtime( true ); } wp_safe_remote_get( user_trailingslashit( $request['url'] ), $headers ); if ( $check_duration ) { $duration = ( microtime( true ) - $start ); // Duration of the request. } $default_delay_between = 500000; /** * Filter the delay between each preload request. * * @param int $delay_between the defined delay. */ $delay_between = apply_filters( 'rocket_preload_delay_between_requests', $default_delay_between ); $delay_between = absint( $delay_between ); if ( empty( $delay_between ) ) { $delay_between = $default_delay_between; } usleep( $delay_between ); if ( ! $check_duration ) { continue; } $duration_transient = get_transient( 'rocket_preload_previous_requests_durations' ); $average_duration = ( false !== $duration_transient ) ? $duration_transient : 0; // Update average duration. $average_duration = ( $average_duration <= 0 ) ? $duration : ( $average_duration * 0.7 + $duration * 0.3 ); set_transient( 'rocket_preload_previous_requests_durations', $average_duration, 5 * MINUTE_IN_SECONDS ); set_transient( 'rocket_preload_check_duration', $duration, MINUTE_IN_SECONDS ); // Don't check request duration for 1 minute. $check_duration = false; } } /** * Get the prefix to prepend to the user agent used for preload to make a HTTP request detected as a mobile device. * * @return string */ protected function get_mobile_user_agent_prefix() { $prefix = 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'; /** * Filter the prefix to prepend to the user agent used for preload to make a HTTP request detected as a mobile device. * * @param string $prefix The prefix. */ $new_prefix = apply_filters( 'rocket_mobile_preload_user_agent_prefix', $prefix ); if ( empty( $new_prefix ) || ! is_string( $new_prefix ) ) { return $prefix; } return 'WP Rocket/Preload ' . $new_prefix; } /** * Process pending jobs inside CRON iteration. * * @return void */ public function process_pending_jobs() { $pending_actions = $this->queue->get_pending_preload_actions(); // Retrieve batch size limits and request timing estimation. /** * Get the number of pending cron job * * @param int $args Maximum number of job size. */ $max_batch_size = ( (int) apply_filters( 'rocket_preload_cache_pending_jobs_cron_rows_count', 45 ) ) - count( $pending_actions ); /** * Get the number of in progress cron job * * @param int $args Minimum number of job size. */ $min_batch_size = ( (int) apply_filters( 'rocket_preload_cache_min_in_progress_jobs_count', 5 ) ); $average_duration = get_transient( 'rocket_preload_previous_requests_durations' ); /** * Estimate batch size based on request duration. * In case no estimation or there is an issue with the value use $min_batch_size. */ $next_batch_size = (int) ( ! $average_duration ? $min_batch_size : round( -5 * $average_duration + 55 ) ); // Limit next_batch_size. $next_batch_size = max( $next_batch_size, $min_batch_size ); // Not lower than 5. $next_batch_size = min( $next_batch_size, $max_batch_size ); // Not higher than 45. $next_batch_size = max( $next_batch_size, 0 ); // Not lower than 0. // Get all in-progress jobs with request sent and no results. /** * Set the delay before an in-progress row is considered as outdated. * * @param int $delay delay. * @return int */ $delay = (int) apply_filters( 'rocket_preload_outdated', /** * Set the max number of rows in batches. * * @param int $count number of rows in batches. * @return int */ (int) ( $max_batch_size / 15 ) ); $stuck_rows = $this->query->get_outdated_in_progress_jobs( $delay ); // Make sure the request has been sent for those jobs. $stuck_rows = array_filter( $stuck_rows, function ( $row ) use ( $pending_actions ) { foreach ( $pending_actions as $action ) { if ( count( $action->get_args() ) > 0 && $row->url === $action->get_args()[0] ) { return false; } } return true; } ); // Make those hanging jobs failed. foreach ( $stuck_rows as $row ) { $this->query->make_status_failed( (int) $row->id ); } // Add new jobs in progress. $rows = $this->query->get_pending_jobs( $next_batch_size ); foreach ( $rows as $row ) { if ( $this->is_excluded_by_filter( $row->url ) ) { $this->query->delete_by_url( $row->url ); continue; } $this->query->make_status_inprogress( (int) $row->id ); $this->queue->add_job_preload_job_preload_url_async( $row->url ); } } /** * Check if the cache file for $item already exists. * * @param string $url The URL to preload. * @param bool $is_mobile is mobile text. * * @return bool */ public function is_already_cached( string $url, bool $is_mobile = false ) { static $https; if ( ! isset( $https ) ) { $https = is_ssl() && $this->options->get( 'cache_ssl' ) ? '-https' : ''; } $url = get_rocket_parse_url( $url ); /** This filter is documented in inc/functions/htaccess.php */ if ( apply_filters( 'rocket_url_no_dots', false ) ) { $url['host'] = str_replace( '.', '_', $url['host'] ); } $url['path'] = trailingslashit( $url['path'] ); if ( '' !== $url['query'] ) { $url['query'] = '#' . $url['query'] . '/'; } $mobile = $is_mobile ? '-mobile' : ''; $file_cache_path = rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) . $url['host'] . strtolower( $url['path'] . $url['query'] ) . 'index' . $mobile . $https . '.html'; if ( ! $this->options->get( 'cache_webp', false ) ) { return $this->filesystem->exists( $file_cache_path ); } $webp_path = rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) . $url['host'] . strtolower( $url['path'] . $url['query'] ) . 'index' . $mobile . $https . '-webp.html'; $no_webp_path = rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) . $url['host'] . strtolower( $url['path'] . $url['query'] ) . '.no-webp'; return $this->filesystem->exists( $webp_path ) || ( $this->filesystem->exists( $no_webp_path ) && $this->filesystem->exists( $file_cache_path ) ); } }