2022-02-18 19:09:35 +07:00

259 lines
7.2 KiB
PHP

<?php
namespace WP_Rocket\Engine\Preload;
use WP_Rocket_WP_Background_Process;
/**
* Abstract class to be extended by preload process classes.
* Extends the background process class for the preload background process.
* The class extending this one must have a $action property and a task() method at least.
*
* @since 3.5
* @author Grégory Viguier
*
* @see WP_Background_Process
*/
abstract class AbstractProcess extends WP_Rocket_WP_Background_Process {
/**
* Prefix
*
* @since 3.2
* @var string
* @author Remy Perona
*/
protected $prefix = 'rocket';
/**
* Format the item to an array.
*
* @since 3.5
* @author Grégory Viguier
*
* @param array|string $item {
* The item to preload: an array containing the following values.
* A string is allowed for backward compatibility (for the URL).
*
* @type string $url The URL to preload.
* @type bool $mobile True when we want to send a "mobile" user agent with the request. Optional.
* }
* @param string $source An identifier related to the source of the preload.
* @return array The formatted item. An empty array for invalid items.
*/
public function format_item( $item, $source = '' ) {
if ( is_string( $item ) ) {
$item = [
'url' => $item,
];
} elseif ( ! is_array( $item ) ) {
return [];
}
if ( empty( $item['url'] ) ) {
return [];
}
$item['mobile'] = ! empty( $item['mobile'] );
if ( empty( $item['source'] ) ) {
$item['source'] = is_string( $source ) ? $source : '';
}
return $item;
}
/**
* Tell if mobile preload is enabled.
*
* @since 3.5
* @author Grégory Viguier
*
* @return bool
*/
public function is_mobile_preload_enabled() {
$enabled = get_rocket_option( 'manual_preload' ) && get_rocket_option( 'cache_mobile' ) && get_rocket_option( 'do_caching_mobile_files' );
/**
* Tell if mobile preload is enabled.
*
* @since 3.5
* @author Grégory Viguier
*
* @param bool $enabled True when enabled. False otherwise.
* @param string $action Specific action identifier for the current preload type.
*/
return (bool) apply_filters( 'rocket_mobile_preload_enabled', $enabled, $this->action );
}
/**
* Get the user agent to use for the item.
*
* @since 3.5
* @author Grégory Viguier
*
* @param array $item {
* The item to preload: an array containing the following values.
*
* @type string $url The URL to preload.
* @type bool $mobile True when we want to send a "mobile" user agent with the request. Optional.
* }
* @return string
*/
public function get_item_user_agent( array $item ) {
if ( $item['mobile'] ) {
return $this->get_mobile_user_agent_prefix() . ' WP Rocket/Preload';
}
return 'WP Rocket/Preload';
}
/**
* Get the prefix to prepend to the user agent used for preload to make a HTTP request detected as a mobile device.
*
* @since 3.5.0.2
* @author Grégory Viguier
*
* @return string
*/
public 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.
*
* @since 3.5.0.2
* @author Grégory Viguier
*
* @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 $new_prefix;
}
/**
* Preload the URL provided by $item.
*
* @since 3.5
* @author Grégory Viguier
*
* @param array|string $item {
* The item to preload: an array containing the following values.
* A string is allowed for backward compatibility (for the URL).
*
* @type string $url The URL to preload.
* @type bool $mobile True when we want to send a "mobile" user agent with the request.
* @type string $source An identifier related to the source of the preload.
* }
* @return bool True when preload has been launched. False otherwise.
*/
protected function maybe_preload( $item ) {
$item = $this->format_item( $item );
if ( ! $item || $this->is_already_cached( $item ) ) {
return false;
}
$result = $this->preload( $item );
usleep( absint( get_rocket_option( 'sitemap_preload_url_crawl', 500000 ) ) );
return ! is_wp_error( $result );
}
/**
* Preload the URL provided by $item.
*
* @since 3.5
* @author Grégory Viguier
*
* @param array $item {
* The item to preload: an array containing the following values.
*
* @type string $url The URL to preload.
* @type bool $mobile True when we want to send a "mobile" user agent with the request.
* @type string $source An identifier related to the source of the preload.
* }
* @return array|WP_Error An array on success. A WP_Error object on failure.
*/
private function preload( array $item ) {
/**
* Filters the arguments for the partial preload request.
*
* @since 2.10.8 'rocket_preload_url_request_args'
* @since 3.2 'rocket_partial_preload_url_request_args'
* @since 3.5 "rocket_{$this->action}_url_request_args"
* @author Remy Perona
*
* @param array $args Request arguments.
*/
$args = apply_filters(
"rocket_{$this->action}_url_request_args",
[
'timeout' => 0.01,
'blocking' => false,
'user-agent' => $this->get_item_user_agent( $item ),
'sslverify' => apply_filters( 'https_local_ssl_verify', false ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
]
);
return wp_remote_get( esc_url_raw( $item['url'] ), $args );
}
/**
* Check if the cache file for $item already exists.
*
* @since 3.2
* @since 3.5 $item is an array.
* @author Remy Perona
*
* @param array $item {
* The item to preload: an array containing the following values.
*
* @type string $url The URL to preload.
* @type bool $mobile True when we want to send a "mobile" user agent with the request.
* @type string $source An identifier related to the source of the preload.
* }
* @return bool
*/
protected function is_already_cached( $item ) {
static $https;
if ( ! isset( $https ) ) {
$https = is_ssl() && get_rocket_option( 'cache_ssl' ) ? '-https' : '';
}
$url = get_rocket_parse_url( $item['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 = $item['mobile'] ? '-mobile' : '';
$file_cache_path = rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) . $url['host'] . strtolower( $url['path'] . $url['query'] ) . 'index' . $mobile . $https . '.html';
return rocket_direct_filesystem()->exists( $file_cache_path );
}
/**
* Stop the process.
*
* @since 3.5
* @author Grégory Viguier
*/
public function cancel_process() {
if ( method_exists( get_parent_class( $this ), 'cancel_process' ) ) {
parent::cancel_process();
}
}
}