add wp-rocket
This commit is contained in:
371
wp-content/plugins/wp-rocket/inc/Engine/CDN/CDN.php
Normal file
371
wp-content/plugins/wp-rocket/inc/Engine/CDN/CDN.php
Normal file
@@ -0,0 +1,371 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN;
|
||||
|
||||
use WP_Rocket\Admin\Options_Data;
|
||||
|
||||
/**
|
||||
* CDN class
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
class CDN {
|
||||
/**
|
||||
* WP Rocket Options instance
|
||||
*
|
||||
* @var Options_Data
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Home URL host
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $home_host;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Options_Data $options WP Rocket Options instance.
|
||||
*/
|
||||
public function __construct( Options_Data $options ) {
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search & Replace URLs with the CDN URLs in the provided content
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $html HTML content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite( $html ) {
|
||||
$pattern = '#[("\']\s*(?<url>(?:(?:https?:|)' . preg_quote( $this->get_base_url(), '#' ) . ')\/(?:(?:(?:' . $this->get_allowed_paths() . ')[^"\',)]+))|\/[^/](?:[^"\')\s>]+\.[[:alnum:]]+))\s*["\')]#i';
|
||||
return preg_replace_callback(
|
||||
$pattern,
|
||||
function( $matches ) {
|
||||
return str_replace( $matches['url'], $this->rewrite_url( $matches['url'] ), $matches[0] );
|
||||
},
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites URLs in a srcset attribute using the CDN URL
|
||||
*
|
||||
* @since 3.4.0.4
|
||||
*
|
||||
* @param string $html HTML content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite_srcset( $html ) {
|
||||
$pattern = '#\s+(?:data-lazy-|data-)?srcset\s*=\s*["\']\s*(?<sources>[^"\',\s]+\.[^"\',\s]+(?:\s+\d+[wx])?(?:\s*,\s*[^"\',\s]+\.[^"\',\s]+\s+\d+[wx])*)\s*["\']#i';
|
||||
|
||||
if ( ! preg_match_all( $pattern, $html, $srcsets, PREG_SET_ORDER ) ) {
|
||||
return $html;
|
||||
}
|
||||
foreach ( $srcsets as $srcset ) {
|
||||
$sources = explode( ',', $srcset['sources'] );
|
||||
$sources = array_unique( array_map( 'trim', $sources ) );
|
||||
$cdn_srcset = $srcset['sources'];
|
||||
foreach ( $sources as $source ) {
|
||||
$url = preg_split( '#\s+#', trim( $source ) );
|
||||
$cdn_srcset = str_replace( $url[0], $this->rewrite_url( $url[0] ), $cdn_srcset );
|
||||
}
|
||||
|
||||
$cdn_srcsets = str_replace( $srcset['sources'], $cdn_srcset, $srcset[0] );
|
||||
$html = str_replace( $srcset[0], $cdn_srcsets, $html );
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites an URL with the CDN URL
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $url Original URL.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite_url( $url ) {
|
||||
if ( ! $this->options->get( 'cdn', 0 ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if ( $this->is_excluded( $url ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$cdn_urls = $this->get_cdn_urls( $this->get_zones_for_url( $url ) );
|
||||
|
||||
if ( ! $cdn_urls ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$parsed_url = wp_parse_url( $url );
|
||||
$cdn_url = untrailingslashit( $cdn_urls[ ( abs( crc32( $parsed_url['path'] ) ) % count( $cdn_urls ) ) ] );
|
||||
|
||||
if ( ! isset( $parsed_url['host'] ) ) {
|
||||
return rocket_add_url_protocol( $cdn_url . '/' . ltrim( $url, '/' ) );
|
||||
}
|
||||
|
||||
$home_host = $this->get_home_host();
|
||||
|
||||
if ( ! isset( $parsed_url['scheme'] ) ) {
|
||||
return str_replace( $home_host, rocket_remove_url_protocol( $cdn_url ), $url );
|
||||
}
|
||||
|
||||
$home_url = [
|
||||
'http://' . $home_host,
|
||||
'https://' . $home_host,
|
||||
];
|
||||
|
||||
return str_replace( $home_url, rocket_add_url_protocol( $cdn_url ), $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites URLs to CDN URLs in CSS content
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $content CSS content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite_css_properties( $content ) {
|
||||
if ( ! preg_match_all( '#url\(\s*(\'|")?\s*(?![\'"]?data)(?<url>(?:https?:|)' . preg_quote( $this->get_base_url(), '#' ) . '\/[^"|\'|\)|\s]+)\s*#i', $content, $matches, PREG_SET_ORDER ) ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
foreach ( $matches as $property ) {
|
||||
/**
|
||||
* Filters the URL of the CSS property
|
||||
*
|
||||
* @since 2.8
|
||||
*
|
||||
* @param string $url URL of the CSS property.
|
||||
*/
|
||||
$cdn_url = $this->rewrite_url( apply_filters( 'rocket_cdn_css_properties_url', $property['url'] ) );
|
||||
$replacement = str_replace( $property['url'], $cdn_url, $property[0] );
|
||||
$content = str_replace( $property[0], $replacement, $content );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all CDN URLs for one or more zones.
|
||||
*
|
||||
* @since 2.1
|
||||
* @since 3.0 Don't check for WP Rocket CDN option activated to be able to use the function on Hosting with CDN auto-enabled.
|
||||
*
|
||||
* @param array $zones List of zones. Default is [ 'all' ].
|
||||
* @return array
|
||||
*/
|
||||
public function get_cdn_urls( $zones = [ 'all' ] ) {
|
||||
$hosts = [];
|
||||
$zones = (array) $zones;
|
||||
$cdn_urls = $this->options->get( 'cdn_cnames', [] );
|
||||
|
||||
if ( $cdn_urls ) {
|
||||
$cdn_zones = $this->options->get( 'cdn_zone', [] );
|
||||
|
||||
foreach ( $cdn_urls as $k => $urls ) {
|
||||
if ( ! in_array( $cdn_zones[ $k ], $zones, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$urls = explode( ',', $urls );
|
||||
$urls = array_map( 'trim', $urls );
|
||||
|
||||
foreach ( $urls as $url ) {
|
||||
$hosts[] = $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter all CDN URLs.
|
||||
*
|
||||
* @since 2.7
|
||||
* @since 3.4 Added $zone parameter.
|
||||
*
|
||||
* @param array $hosts List of CDN URLs.
|
||||
* @param array $zones List of zones. Default is [ 'all' ].
|
||||
*/
|
||||
$hosts = (array) apply_filters( 'rocket_cdn_cnames', $hosts, $zones );
|
||||
$hosts = array_filter( $hosts );
|
||||
$hosts = array_flip( array_flip( $hosts ) );
|
||||
$hosts = array_values( $hosts );
|
||||
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base URL for the website
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Remy Perona
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_base_url() {
|
||||
return '//' . $this->get_home_host();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the allowed paths as a regex pattern for the CDN rewrite
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Remy Perona
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_allowed_paths() {
|
||||
$wp_content_dirname = ltrim( trailingslashit( wp_parse_url( content_url(), PHP_URL_PATH ) ), '/' );
|
||||
$wp_includes_dirname = ltrim( trailingslashit( wp_parse_url( includes_url(), PHP_URL_PATH ) ), '/' );
|
||||
|
||||
$upload_dirname = '';
|
||||
$uploads_info = wp_upload_dir();
|
||||
|
||||
if ( ! empty( $uploads_info['baseurl'] ) ) {
|
||||
$upload_dirname = '|' . ltrim( trailingslashit( wp_parse_url( $uploads_info['baseurl'], PHP_URL_PATH ) ), '/' );
|
||||
}
|
||||
|
||||
return $wp_content_dirname . $upload_dirname . '|' . $wp_includes_dirname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided URL can be rewritten with the CDN URL
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Remy Perona
|
||||
*
|
||||
* @param string $url URL to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_excluded( $url ) {
|
||||
$path = wp_parse_url( $url, PHP_URL_PATH );
|
||||
|
||||
$excluded_extensions = [
|
||||
'php',
|
||||
'html',
|
||||
'htm',
|
||||
];
|
||||
|
||||
if ( in_array( pathinfo( $path, PATHINFO_EXTENSION ), $excluded_extensions, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! $path ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( '/' === $path ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( preg_match( '#^(' . $this->get_excluded_files( '#' ) . ')$#', $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the home URL host
|
||||
*
|
||||
* @since 3.5.5
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_home_host() {
|
||||
if ( empty( $this->home_host ) ) {
|
||||
$this->home_host = wp_parse_url( home_url(), PHP_URL_HOST );
|
||||
}
|
||||
|
||||
return $this->home_host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CDN zones for the provided URL
|
||||
*
|
||||
* @since 3.4
|
||||
* @author Remy Perona
|
||||
*
|
||||
* @param string $url URL to check.
|
||||
* @return array
|
||||
*/
|
||||
private function get_zones_for_url( $url ) {
|
||||
$zones = [ 'all' ];
|
||||
|
||||
$ext = pathinfo( wp_parse_url( $url, PHP_URL_PATH ), PATHINFO_EXTENSION );
|
||||
|
||||
$image_types = [
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'jpe',
|
||||
'png',
|
||||
'gif',
|
||||
'webp',
|
||||
'bmp',
|
||||
'tiff',
|
||||
'svg',
|
||||
];
|
||||
|
||||
if ( 'css' === $ext || 'js' === $ext ) {
|
||||
$zones[] = 'css_and_js';
|
||||
}
|
||||
|
||||
if ( 'css' === $ext ) {
|
||||
$zones[] = 'css';
|
||||
}
|
||||
|
||||
if ( 'js' === $ext ) {
|
||||
$zones[] = 'js';
|
||||
}
|
||||
|
||||
if ( in_array( $ext, $image_types, true ) ) {
|
||||
$zones[] = 'images';
|
||||
}
|
||||
|
||||
return $zones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all files we don't allow to get in CDN.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @param string $delimiter RegEx delimiter.
|
||||
* @return string A pipe-separated list of excluded files.
|
||||
*/
|
||||
private function get_excluded_files( $delimiter ) {
|
||||
$files = $this->options->get( 'cdn_reject_files', [] );
|
||||
|
||||
/**
|
||||
* Filter the excluded files.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @param array $files List of excluded files.
|
||||
*/
|
||||
$files = (array) apply_filters( 'rocket_cdn_reject_files', $files );
|
||||
$files = array_filter( $files );
|
||||
|
||||
if ( ! $files ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$files = array_flip( array_flip( $files ) );
|
||||
$files = array_map(
|
||||
function ( $file ) use ( $delimiter ) {
|
||||
return str_replace( $delimiter, '\\' . $delimiter, $file );
|
||||
},
|
||||
$files
|
||||
);
|
||||
|
||||
return implode( '|', $files );
|
||||
}
|
||||
}
|
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class to Interact with the RocketCDN API
|
||||
*/
|
||||
class APIClient {
|
||||
const ROCKETCDN_API = 'https://rocketcdn.me/api/';
|
||||
|
||||
/**
|
||||
* Gets current RocketCDN subscription data from cache if it exists
|
||||
*
|
||||
* Else do a request to the API to get fresh data
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_subscription_data() {
|
||||
$status = get_transient( 'rocketcdn_status' );
|
||||
|
||||
if ( false !== $status ) {
|
||||
return $status;
|
||||
}
|
||||
|
||||
return $this->get_remote_subscription_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets fresh RocketCDN subscription data from the API
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_remote_subscription_data() {
|
||||
$default = [
|
||||
'id' => 0,
|
||||
'is_active' => false,
|
||||
'cdn_url' => '',
|
||||
'subscription_next_date_update' => 0,
|
||||
'subscription_status' => 'cancelled',
|
||||
];
|
||||
|
||||
$token = get_option( 'rocketcdn_user_token' );
|
||||
|
||||
if ( empty( $token ) ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$args = [
|
||||
'headers' => [
|
||||
'Authorization' => 'Token ' . $token,
|
||||
],
|
||||
];
|
||||
|
||||
$response = wp_remote_get(
|
||||
self::ROCKETCDN_API . 'website/search/?url=' . home_url(),
|
||||
$args
|
||||
);
|
||||
|
||||
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
$this->set_status_transient( $default, 3 * MINUTE_IN_SECONDS );
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
$data = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
$this->set_status_transient( $default, 3 * MINUTE_IN_SECONDS );
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
$data = json_decode( $data, true );
|
||||
$data = array_intersect_key( (array) $data, $default );
|
||||
$data = array_merge( $default, $data );
|
||||
|
||||
$this->set_status_transient( $data, WEEK_IN_SECONDS );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RocketCDN status transient with the provided value
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $value Transient value.
|
||||
* @param int $duration Transient duration.
|
||||
* @return void
|
||||
*/
|
||||
private function set_status_transient( $value, $duration ) {
|
||||
set_transient( 'rocketcdn_status', $value, $duration );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets pricing & promotion data for RocketCDN from cache if it exists
|
||||
*
|
||||
* Else do a request to the API to get fresh data
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_pricing_data() {
|
||||
$pricing = get_transient( 'rocketcdn_pricing' );
|
||||
|
||||
if ( false !== $pricing ) {
|
||||
return $pricing;
|
||||
}
|
||||
|
||||
return $this->get_remote_pricing_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets fresh pricing & promotion data for RocketCDN
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
private function get_remote_pricing_data() {
|
||||
$response = wp_remote_get( self::ROCKETCDN_API . 'pricing' );
|
||||
|
||||
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
return $this->get_wp_error();
|
||||
}
|
||||
|
||||
$data = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
return $this->get_wp_error();
|
||||
}
|
||||
|
||||
$data = json_decode( $data, true );
|
||||
|
||||
set_transient( 'rocketcdn_pricing', $data, 6 * HOUR_IN_SECONDS );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new WP_Error instance
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return WP_Error
|
||||
*/
|
||||
private function get_wp_error() {
|
||||
return new WP_Error( 'rocketcdn_error', __( 'RocketCDN is not available at the moment. Please retry later', 'rocket' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the API to purge the CDN cache
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function purge_cache_request() {
|
||||
$subscription = $this->get_subscription_data();
|
||||
$status = 'error';
|
||||
|
||||
if ( ! isset( $subscription['id'] ) || 0 === $subscription['id'] ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => __( 'RocketCDN cache purge failed: Missing identifier parameter.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
$token = get_option( 'rocketcdn_user_token' );
|
||||
|
||||
if ( empty( $token ) ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => __( 'RocketCDN cache purge failed: Missing user token.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
$args = [
|
||||
'method' => 'DELETE',
|
||||
'headers' => [
|
||||
'Authorization' => 'Token ' . $token,
|
||||
],
|
||||
];
|
||||
|
||||
$response = wp_remote_request(
|
||||
self::ROCKETCDN_API . 'website/' . $subscription['id'] . '/purge/',
|
||||
$args
|
||||
);
|
||||
|
||||
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => __( 'RocketCDN cache purge failed: The API returned an unexpected response code.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
$data = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => __( 'RocketCDN cache purge failed: The API returned an empty response.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
$data = json_decode( $data );
|
||||
|
||||
if ( ! isset( $data->success ) ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => __( 'RocketCDN cache purge failed: The API returned an unexpected response.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
if ( ! $data->success ) {
|
||||
return [
|
||||
'status' => $status,
|
||||
'message' => sprintf(
|
||||
// translators: %s = message returned by the API.
|
||||
__( 'RocketCDN cache purge failed: %s.', 'rocket' ),
|
||||
$data->message
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'status' => 'success',
|
||||
'message' => __( 'RocketCDN cache purge successful.', 'rocket' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the arguments used in an HTTP request, to make sure our user token has not been overwritten
|
||||
* by some other plugin.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $args An array of HTTP request arguments.
|
||||
* @param string $url The request URL.
|
||||
* @return array
|
||||
*/
|
||||
public function preserve_authorization_token( $args, $url ) {
|
||||
if ( strpos( $url, self::ROCKETCDN_API ) === false ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
if ( empty( $args['headers']['Authorization'] ) && self::ROCKETCDN_API . 'pricing' === $url ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$token = get_option( 'rocketcdn_user_token' );
|
||||
|
||||
if ( empty( $token ) ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$value = 'token ' . $token;
|
||||
|
||||
if ( isset( $args['headers']['Authorization'] ) && $value === $args['headers']['Authorization'] ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$args['headers']['Authorization'] = $value;
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Abstract_Render;
|
||||
use WP_Rocket\Admin\Options_Data;
|
||||
use WP_Rocket\Engine\Admin\Beacon\Beacon;
|
||||
use WP_Rocket\Event_Management\Subscriber_Interface;
|
||||
|
||||
/**
|
||||
* Subscriber for the RocketCDN integration in WP Rocket settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class AdminPageSubscriber extends Abstract_Render implements Subscriber_Interface {
|
||||
/**
|
||||
* RocketCDN API Client instance.
|
||||
*
|
||||
* @var APIClient
|
||||
*/
|
||||
private $api_client;
|
||||
|
||||
/**
|
||||
* WP Rocket options instance
|
||||
*
|
||||
* @var Options_Data
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Beacon instance
|
||||
*
|
||||
* @var Beacon
|
||||
*/
|
||||
private $beacon;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param APIClient $api_client RocketCDN API Client instance.
|
||||
* @param Options_Data $options WP Rocket options instance.
|
||||
* @param Beacon $beacon Beacon instance.
|
||||
* @param string $template_path Path to the templates.
|
||||
*/
|
||||
public function __construct( APIClient $api_client, Options_Data $options, Beacon $beacon, $template_path ) {
|
||||
parent::__construct( $template_path );
|
||||
|
||||
$this->api_client = $api_client;
|
||||
$this->options = $options;
|
||||
$this->beacon = $beacon;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function get_subscribed_events() {
|
||||
return [
|
||||
'rocket_dashboard_after_account_data' => 'display_rocketcdn_status',
|
||||
'rocket_after_cdn_sections' => 'display_manage_subscription',
|
||||
'rocket_cdn_settings_fields' => 'rocketcdn_field',
|
||||
'admin_post_rocket_purge_rocketcdn' => 'purge_cdn_cache',
|
||||
'rocket_settings_page_footer' => 'add_subscription_modal',
|
||||
'http_request_args' => [ 'preserve_authorization_token', PHP_INT_MAX, 2 ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the RocketCDN section on the dashboard tab
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_rocketcdn_status() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_data = $this->api_client->get_subscription_data();
|
||||
|
||||
if ( 'running' === $subscription_data['subscription_status'] ) {
|
||||
$label = __( 'Next Billing Date', 'rocket' );
|
||||
$status_class = ' wpr-isValid';
|
||||
$container_class = '';
|
||||
$status_text = date_i18n( get_option( 'date_format' ), strtotime( $subscription_data['subscription_next_date_update'] ) );
|
||||
$is_active = true;
|
||||
} elseif ( 'cancelled' === $subscription_data['subscription_status'] ) {
|
||||
$label = '';
|
||||
$status_class = ' wpr-isInvalid';
|
||||
$container_class = ' wpr-flex--egal';
|
||||
$status_text = __( 'No Subscription', 'rocket' );
|
||||
$is_active = false;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'is_live_site' => rocket_is_live_site(),
|
||||
'container_class' => $container_class,
|
||||
'label' => $label,
|
||||
'status_class' => $status_class,
|
||||
'status_text' => $status_text,
|
||||
'is_active' => $is_active,
|
||||
];
|
||||
|
||||
echo $this->generate( 'dashboard-status', $data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic content is properly escaped in the view.
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the RocketCDN fields to the CDN section
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $fields CDN settings fields.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rocketcdn_field( $fields ) {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$subscription_data = $this->api_client->get_subscription_data();
|
||||
|
||||
if ( 'running' !== $subscription_data['subscription_status'] ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$helper_text = __( 'Your RocketCDN subscription is currently active.', 'rocket' );
|
||||
$cdn_cnames = $this->options->get( 'cdn_cnames', [] );
|
||||
|
||||
if ( empty( $cdn_cnames ) || $cdn_cnames[0] !== $subscription_data['cdn_url'] ) {
|
||||
$helper_text = sprintf(
|
||||
// translators: %1$s = opening <code> tag, %2$s = CDN URL, %3$s = closing </code> tag.
|
||||
__( 'To use RocketCDN, replace your CNAME with %1$s%2$s%3$s.', 'rocket' ),
|
||||
'<code>',
|
||||
$subscription_data['cdn_url'],
|
||||
'</code>'
|
||||
);
|
||||
}
|
||||
|
||||
$beacon = $this->beacon->get_suggest( 'rocketcdn' );
|
||||
|
||||
$more_info = sprintf(
|
||||
// translators: %1$is = opening link tag, %2$s = closing link tag.
|
||||
__( '%1$sMore Info%2$s', 'rocket' ),
|
||||
'<a href="' . esc_url( $beacon['url'] ) . '" data-beacon-article="' . esc_attr( $beacon['id'] ) . '" rel="noopener noreferrer" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
|
||||
$fields['cdn_cnames'] = [
|
||||
'type' => 'rocket_cdn',
|
||||
'label' => __( 'CDN CNAME(s)', 'rocket' ),
|
||||
'description' => __( 'Specify the CNAME(s) below', 'rocket' ),
|
||||
'helper' => $helper_text . ' ' . $more_info,
|
||||
'default' => '',
|
||||
'section' => 'cnames_section',
|
||||
'page' => 'page_cdn',
|
||||
'beacon' => [
|
||||
'url' => $beacon['url'],
|
||||
'id' => $beacon['id'],
|
||||
],
|
||||
];
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the button to open the subscription modal
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_manage_subscription() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! rocket_is_live_site() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_data = $this->api_client->get_subscription_data();
|
||||
|
||||
if ( 'running' !== $subscription_data['subscription_status'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<p class="wpr-rocketcdn-subscription">
|
||||
<button class="wpr-rocketcdn-open" data-micromodal-trigger="wpr-rocketcdn-modal"><?php esc_html_e( 'Manage Subscription', 'rocket' ); ?></button>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Purges the CDN cache and store the response in a transient.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function purge_cdn_cache() {
|
||||
if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'rocket_purge_rocketcdn' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
|
||||
wp_nonce_ays( '' );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
set_transient( 'rocketcdn_purge_cache_response', $this->api_client->purge_cache_request(), HOUR_IN_SECONDS );
|
||||
|
||||
wp_safe_redirect( esc_url_raw( wp_get_referer() ) );
|
||||
rocket_get_constant( 'WP_ROCKET_IS_TESTING', false ) ? wp_die() : exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the subscription modal on the WP Rocket settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_subscription_modal() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! rocket_is_live_site() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$iframe_src = add_query_arg(
|
||||
[
|
||||
'website' => home_url(),
|
||||
'callback' => rest_url( 'wp-rocket/v1/rocketcdn/' ),
|
||||
],
|
||||
rocket_get_constant( 'WP_ROCKET_WEB_MAIN' ) . 'cdn/iframe'
|
||||
);
|
||||
?>
|
||||
<div class="wpr-rocketcdn-modal" id="wpr-rocketcdn-modal" aria-hidden="true">
|
||||
<div class="wpr-rocketcdn-modal__overlay" tabindex="-1">
|
||||
<div class="wpr-rocketcdn-modal__container" role="dialog" aria-modal="true" aria-labelledby="wpr-rocketcdn-modal-title">
|
||||
<div id="wpr-rocketcdn-modal-content">
|
||||
<iframe id="rocketcdn-iframe" src="<?php echo esc_url( $iframe_src ); ?>" width="674" height="425"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the arguments used in an HTTP request, to make sure our user token has not been overwritten
|
||||
* by some other plugin.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $args An array of HTTP request arguments.
|
||||
* @param string $url The request URL.
|
||||
* @return array
|
||||
*/
|
||||
public function preserve_authorization_token( $args, $url ) {
|
||||
return $this->api_client->preserve_authorization_token( $args, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if white label is enabled
|
||||
*
|
||||
* @since 3.6
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_white_label_account() {
|
||||
return (bool) rocket_get_constant( 'WP_ROCKET_WHITE_LABEL_ACCOUNT' );
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Admin\Options;
|
||||
use WP_Rocket\Admin\Options_Data;
|
||||
|
||||
/**
|
||||
* Manager for WP Rocket CDN options
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class CDNOptionsManager {
|
||||
/**
|
||||
* WP Options API instance
|
||||
*
|
||||
* @var Options
|
||||
*/
|
||||
private $options_api;
|
||||
|
||||
/**
|
||||
* WP Rocket Options instance
|
||||
*
|
||||
* @var Options_Data
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Options $options_api WP Options API instance.
|
||||
* @param Options_Data $options WP Rocket Options instance.
|
||||
*/
|
||||
public function __construct( Options $options_api, Options_Data $options ) {
|
||||
$this->options_api = $options_api;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable CDN option, save CDN URL & delete RocketCDN status transient
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param string $cdn_url CDN URL.
|
||||
* @return void
|
||||
*/
|
||||
public function enable( $cdn_url ) {
|
||||
$this->options->set( 'cdn', 1 );
|
||||
$this->options->set( 'cdn_cnames', [ $cdn_url ] );
|
||||
$this->options->set( 'cdn_zone', [ 'all' ] );
|
||||
|
||||
$this->options_api->set( 'settings', $this->options->get_options() );
|
||||
|
||||
delete_transient( 'rocketcdn_status' );
|
||||
rocket_clean_domain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable CDN option, remove CDN URL & user token, delete RocketCDN status transient
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable() {
|
||||
$this->options->set( 'cdn', 0 );
|
||||
$this->options->set( 'cdn_cnames', [] );
|
||||
$this->options->set( 'cdn_zone', [] );
|
||||
|
||||
$this->options_api->set( 'settings', $this->options->get_options() );
|
||||
|
||||
delete_option( 'rocketcdn_user_token' );
|
||||
delete_transient( 'rocketcdn_status' );
|
||||
rocket_clean_domain();
|
||||
}
|
||||
}
|
@@ -0,0 +1,289 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Event_Management\Subscriber_Interface;
|
||||
|
||||
/**
|
||||
* Subscriber for the RocketCDN integration in WP Rocket settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class DataManagerSubscriber implements Subscriber_Interface {
|
||||
const CRON_EVENT = 'rocketcdn_check_subscription_status_event';
|
||||
|
||||
/**
|
||||
* RocketCDN API Client instance.
|
||||
*
|
||||
* @var APIClient
|
||||
*/
|
||||
private $api_client;
|
||||
|
||||
/**
|
||||
* CDNOptionsManager instance.
|
||||
*
|
||||
* @var CDNOptionsManager
|
||||
*/
|
||||
private $cdn_options;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param APIClient $api_client RocketCDN API Client instance.
|
||||
* @param CDNOptionsManager $cdn_options CDNOptionsManager instance.
|
||||
*/
|
||||
public function __construct( APIClient $api_client, CDNOptionsManager $cdn_options ) {
|
||||
$this->api_client = $api_client;
|
||||
$this->cdn_options = $cdn_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function get_subscribed_events() {
|
||||
return [
|
||||
'wp_ajax_save_rocketcdn_token' => 'update_user_token',
|
||||
'wp_ajax_rocketcdn_enable' => 'enable',
|
||||
'wp_ajax_rocketcdn_disable' => 'disable',
|
||||
'wp_ajax_rocketcdn_process_set' => 'set_process_status',
|
||||
'wp_ajax_rocketcdn_process_status' => 'get_process_status',
|
||||
self::CRON_EVENT => 'maybe_disable_cdn',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the RocketCDN user token value
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update_user_token() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
wp_send_json_error( 'unauthorized_user' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $_POST['value'] ) ) {
|
||||
delete_option( 'rocketcdn_user_token' );
|
||||
|
||||
wp_send_json_success( 'user_token_deleted' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! is_string( $_POST['value'] ) ) {
|
||||
wp_send_json_error( 'invalid_token' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$token = sanitize_key( $_POST['value'] );
|
||||
|
||||
if ( 40 !== strlen( $token ) ) {
|
||||
wp_send_json_error( 'invalid_token_length' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
update_option( 'rocketcdn_user_token', $token );
|
||||
|
||||
wp_send_json_success( 'user_token_saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to enable RocketCDN
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enable() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
$data = [
|
||||
'process' => 'subscribe',
|
||||
];
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
$data['message'] = 'unauthorized_user';
|
||||
|
||||
wp_send_json_error( $data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $_POST['cdn_url'] ) ) {
|
||||
$data['message'] = 'cdn_url_empty';
|
||||
|
||||
wp_send_json_error( $data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$cdn_url = filter_var( wp_unslash( $_POST['cdn_url'] ), FILTER_VALIDATE_URL );
|
||||
|
||||
if ( ! $cdn_url ) {
|
||||
$data['message'] = 'cdn_url_invalid_format';
|
||||
|
||||
wp_send_json_error( $data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cdn_options->enable( esc_url_raw( $cdn_url ) );
|
||||
|
||||
$subscription = $this->api_client->get_subscription_data();
|
||||
|
||||
$this->schedule_subscription_check( $subscription );
|
||||
$this->delete_process();
|
||||
|
||||
$data['message'] = 'rocketcdn_enabled';
|
||||
|
||||
wp_send_json_success( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to disable RocketCDN
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
$data = [
|
||||
'process' => 'unsubscribe',
|
||||
];
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
$data['message'] = 'unauthorized_user';
|
||||
|
||||
wp_send_json_error( $data );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cdn_options->disable();
|
||||
|
||||
$timestamp = wp_next_scheduled( self::CRON_EVENT );
|
||||
|
||||
if ( $timestamp ) {
|
||||
wp_unschedule_event( $timestamp, self::CRON_EVENT );
|
||||
}
|
||||
|
||||
$this->delete_process();
|
||||
|
||||
$data['message'] = 'rocketcdn_disabled';
|
||||
|
||||
wp_send_json_success( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the option tracking the RocketCDN process state
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function delete_process() {
|
||||
delete_option( 'rocketcdn_process' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the RocketCDN subscription process status
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_process_status() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $_POST['status'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$status = filter_var( $_POST['status'], FILTER_VALIDATE_BOOLEAN ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Used as a boolean.
|
||||
|
||||
if ( false === $status ) {
|
||||
delete_option( 'rocketcdn_process' );
|
||||
return;
|
||||
}
|
||||
|
||||
update_option( 'rocketcdn_process', $status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for RocketCDN subscription process status
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_process_status() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
wp_send_json_error();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( get_option( 'rocketcdn_process' ) ) {
|
||||
wp_send_json_success();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cron job to disable CDN if the subscription expired
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_disable_cdn() {
|
||||
delete_transient( 'rocketcdn_status' );
|
||||
|
||||
$subscription = $this->api_client->get_subscription_data();
|
||||
|
||||
if ( rocket_get_constant( 'WP_ROCKET_IS_TESTING', false ) ) {
|
||||
$subscription = apply_filters( 'rocket_pre_get_subscription_data', $subscription );
|
||||
}
|
||||
|
||||
if ( 'running' === $subscription['subscription_status'] ) {
|
||||
$this->schedule_subscription_check( $subscription );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cdn_options->disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the next cron subscription check
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $subscription Array containing the subscription data.
|
||||
* @return void
|
||||
*/
|
||||
private function schedule_subscription_check( $subscription ) {
|
||||
$timestamp = strtotime( $subscription['subscription_next_date_update'] ) + strtotime( '+2 days' );
|
||||
|
||||
if ( ! wp_next_scheduled( self::CRON_EVENT ) ) {
|
||||
wp_schedule_single_event( $timestamp, self::CRON_EVENT );
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Abstract_Render;
|
||||
use WP_Rocket\Event_Management\Subscriber_Interface;
|
||||
|
||||
/**
|
||||
* Subscriber for the RocketCDN notices on WP Rocket settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class NoticesSubscriber extends Abstract_Render implements Subscriber_Interface {
|
||||
/**
|
||||
* RocketCDN API Client instance.
|
||||
*
|
||||
* @var APIClient
|
||||
*/
|
||||
private $api_client;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param APIClient $api_client RocketCDN API Client instance.
|
||||
* @param string $template_path Path to the templates.
|
||||
*/
|
||||
public function __construct( APIClient $api_client, $template_path ) {
|
||||
parent::__construct( $template_path );
|
||||
|
||||
$this->api_client = $api_client;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function get_subscribed_events() {
|
||||
return [
|
||||
'admin_notices' => [
|
||||
[ 'promote_rocketcdn_notice' ],
|
||||
[ 'purge_cache_notice' ],
|
||||
],
|
||||
'rocket_before_cdn_sections' => 'display_rocketcdn_cta',
|
||||
'wp_ajax_toggle_rocketcdn_cta' => 'toggle_cta',
|
||||
'wp_ajax_rocketcdn_dismiss_notice' => 'dismiss_notice',
|
||||
'admin_footer' => 'add_dismiss_script',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds notice to promote RocketCDN on settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function promote_rocketcdn_notice() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! rocket_is_live_site() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->should_display_notice() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $this->generate( 'promote-notice' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic content is properly escaped in the view.
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inline script to permanently dismissing the RocketCDN promotion notice
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_dismiss_script() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! rocket_is_live_site() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->should_display_notice() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$nonce = wp_create_nonce( 'rocketcdn_dismiss_notice' );
|
||||
?>
|
||||
<script>
|
||||
window.addEventListener( 'load', function() {
|
||||
var dismissBtn = document.querySelectorAll( '#rocketcdn-promote-notice .notice-dismiss, #rocketcdn-promote-notice #rocketcdn-learn-more-dismiss' );
|
||||
|
||||
dismissBtn.forEach(function(element) {
|
||||
element.addEventListener( 'click', function( event ) {
|
||||
var httpRequest = new XMLHttpRequest(),
|
||||
postData = '';
|
||||
|
||||
postData += 'action=rocketcdn_dismiss_notice';
|
||||
postData += '&nonce=<?php echo esc_attr( $nonce ); ?>';
|
||||
httpRequest.open( 'POST', '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>' );
|
||||
httpRequest.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' )
|
||||
httpRequest.send( postData );
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the promotion notice should be displayed
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function should_display_notice() {
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'settings_page_wprocket' !== get_current_screen()->id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( get_user_meta( get_current_user_id(), 'rocketcdn_dismiss_notice', true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subscription_data = $this->api_client->get_subscription_data();
|
||||
|
||||
return 'running' !== $subscription_data['subscription_status'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to save the dismiss as a user meta
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dismiss_notice() {
|
||||
check_ajax_referer( 'rocketcdn_dismiss_notice', 'nonce', true );
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_user_meta( get_current_user_id(), 'rocketcdn_dismiss_notice', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the RocketCDN Call to Action on the CDN tab of WP Rocket settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_rocketcdn_cta() {
|
||||
if ( $this->is_white_label_account() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! rocket_is_live_site() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_data = $this->api_client->get_subscription_data();
|
||||
|
||||
if ( 'running' === $subscription_data['subscription_status'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pricing = $this->api_client->get_pricing_data();
|
||||
|
||||
$regular_price = '';
|
||||
$nopromo_variant = '--no-promo';
|
||||
$cta_small_class = 'wpr-isHidden';
|
||||
$cta_big_class = '';
|
||||
|
||||
if ( get_user_meta( get_current_user_id(), 'rocket_rocketcdn_cta_hidden', true ) ) {
|
||||
$cta_small_class = '';
|
||||
$cta_big_class = 'wpr-isHidden';
|
||||
}
|
||||
|
||||
$small_cta_data = [
|
||||
'container_class' => $cta_small_class,
|
||||
];
|
||||
|
||||
if ( is_wp_error( $pricing ) ) {
|
||||
$big_cta_data = [
|
||||
'container_class' => $cta_big_class,
|
||||
'nopromo_variant' => $nopromo_variant,
|
||||
'error' => true,
|
||||
'message' => $pricing->get_error_message(),
|
||||
];
|
||||
} else {
|
||||
$current_price = number_format_i18n( $pricing['monthly_price'], 2 );
|
||||
$promotion_campaign = '';
|
||||
$end_date = strtotime( $pricing['end_date'] );
|
||||
$promotion_end_date = '';
|
||||
|
||||
if (
|
||||
$pricing['is_discount_active']
|
||||
&&
|
||||
$end_date > time()
|
||||
) {
|
||||
$promotion_campaign = $pricing['discount_campaign_name'];
|
||||
$regular_price = $current_price;
|
||||
$current_price = number_format_i18n( $pricing['discounted_price_monthly'], 2 ) . '*';
|
||||
$nopromo_variant = '';
|
||||
$promotion_end_date = date_i18n( get_option( 'date_format' ), $end_date );
|
||||
}
|
||||
|
||||
$big_cta_data = [
|
||||
'container_class' => $cta_big_class,
|
||||
'promotion_campaign' => $promotion_campaign,
|
||||
'promotion_end_date' => $promotion_end_date,
|
||||
'nopromo_variant' => $nopromo_variant,
|
||||
'regular_price' => $regular_price,
|
||||
'current_price' => $current_price,
|
||||
];
|
||||
}
|
||||
|
||||
echo $this->generate( 'cta-small', $small_cta_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic content is properly escaped in the view.
|
||||
echo $this->generate( 'cta-big', $big_cta_data ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Dynamic content is properly escaped in the view.
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles display of the RocketCDN CTAs on the settings page
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function toggle_cta() {
|
||||
check_ajax_referer( 'rocket-ajax', 'nonce', true );
|
||||
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['status'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'big' === $_POST['status'] ) {
|
||||
delete_user_meta( get_current_user_id(), 'rocket_rocketcdn_cta_hidden' );
|
||||
} elseif ( 'small' === $_POST['status'] ) {
|
||||
update_user_meta( get_current_user_id(), 'rocket_rocketcdn_cta_hidden', true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a notice after purging the RocketCDN cache.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function purge_cache_notice() {
|
||||
if ( ! current_user_can( 'rocket_manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'settings_page_wprocket' !== get_current_screen()->id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$purge_response = get_transient( 'rocketcdn_purge_cache_response' );
|
||||
|
||||
if ( false === $purge_response ) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete_transient( 'rocketcdn_purge_cache_response' );
|
||||
|
||||
rocket_notice_html(
|
||||
[
|
||||
'status' => $purge_response['status'],
|
||||
'message' => $purge_response['message'],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if white label is enabled
|
||||
*
|
||||
* @since 3.6
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_white_label_account() {
|
||||
return (bool) rocket_get_constant( 'WP_ROCKET_WHITE_LABEL_ACCOUNT' );
|
||||
}
|
||||
}
|
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Event_Management\Subscriber_Interface;
|
||||
use WP_Rocket\Admin\Options_Data;
|
||||
|
||||
/**
|
||||
* Subscriber for RocketCDN REST API Integration
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class RESTSubscriber implements Subscriber_Interface {
|
||||
const ROUTE_NAMESPACE = 'wp-rocket/v1';
|
||||
|
||||
/**
|
||||
* CDNOptionsManager instance
|
||||
*
|
||||
* @var CDNOptionsManager
|
||||
*/
|
||||
private $cdn_options;
|
||||
|
||||
/**
|
||||
* WP Rocket Options instance
|
||||
*
|
||||
* @var Options_Data
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param CDNOptionsManager $cdn_options CDNOptionsManager instance.
|
||||
* @param Options_Data $options WP Rocket Options instance.
|
||||
*/
|
||||
public function __construct( CDNOptionsManager $cdn_options, Options_Data $options ) {
|
||||
$this->cdn_options = $cdn_options;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function get_subscribed_events() {
|
||||
return [
|
||||
'rest_api_init' => [
|
||||
[ 'register_enable_route' ],
|
||||
[ 'register_disable_route' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Enable route in the WP REST API
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_enable_route() {
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'rocketcdn/enable',
|
||||
[
|
||||
'methods' => 'PUT',
|
||||
'callback' => [ $this, 'enable' ],
|
||||
'args' => [
|
||||
'email' => [
|
||||
'required' => true,
|
||||
'validate_callback' => [ $this, 'validate_email' ],
|
||||
],
|
||||
'key' => [
|
||||
'required' => true,
|
||||
'validate_callback' => [ $this, 'validate_key' ],
|
||||
],
|
||||
'url' => [
|
||||
'required' => true,
|
||||
'validate_callback' => function ( $param ) {
|
||||
$url = esc_url_raw( $param );
|
||||
|
||||
return ! empty( $url );
|
||||
},
|
||||
'sanitize_callback' => function ( $param ) {
|
||||
return esc_url_raw( $param );
|
||||
},
|
||||
],
|
||||
],
|
||||
'permission_callback' => '__return_true',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Disable route in the WP REST API
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_disable_route() {
|
||||
register_rest_route(
|
||||
self::ROUTE_NAMESPACE,
|
||||
'rocketcdn/disable',
|
||||
[
|
||||
'methods' => 'PUT',
|
||||
'callback' => [ $this, 'disable' ],
|
||||
'args' => [
|
||||
'email' => [
|
||||
'required' => true,
|
||||
'validate_callback' => [ $this, 'validate_email' ],
|
||||
],
|
||||
'key' => [
|
||||
'required' => true,
|
||||
'validate_callback' => [ $this, 'validate_key' ],
|
||||
],
|
||||
],
|
||||
'permission_callback' => '__return_true',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable CDN and add RocketCDN URL to WP Rocket options
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param \WP_REST_Request $request the WP REST Request object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function enable( \WP_REST_Request $request ) {
|
||||
$params = $request->get_body_params();
|
||||
|
||||
$this->cdn_options->enable( $params['url'] );
|
||||
|
||||
$response = [
|
||||
'code' => 'success',
|
||||
'message' => __( 'RocketCDN enabled', 'rocket' ),
|
||||
'data' => [
|
||||
'status' => 200,
|
||||
],
|
||||
];
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the CDN and remove the RocketCDN URL from WP Rocket options
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param \WP_REST_Request $request the WP Rest Request object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function disable( \WP_REST_Request $request ) {
|
||||
$this->cdn_options->disable();
|
||||
|
||||
$response = [
|
||||
'code' => 'success',
|
||||
'message' => __( 'RocketCDN disabled', 'rocket' ),
|
||||
'data' => [
|
||||
'status' => 200,
|
||||
],
|
||||
];
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the email sent along the request corresponds to the one saved in the DB
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param string $param Parameter value to validate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate_email( $param ) {
|
||||
return $param === $this->options->get( 'consumer_email' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the key sent along the request corresponds to the one saved in the DB
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param string $param Parameter value to validate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate_key( $param ) {
|
||||
return $param === $this->options->get( 'consumer_key' );
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN\RocketCDN;
|
||||
|
||||
use WP_Rocket\Engine\Container\ServiceProvider\AbstractServiceProvider;
|
||||
|
||||
/**
|
||||
* Service provider for RocketCDN
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class ServiceProvider extends AbstractServiceProvider {
|
||||
/**
|
||||
* The provides array is a way to let the container
|
||||
* know that a service is provided by this service
|
||||
* provider. Every service that is registered via
|
||||
* this service provider must have an alias added
|
||||
* to this array or it will be ignored.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $provides = [
|
||||
'rocketcdn_api_client',
|
||||
'rocketcdn_options_manager',
|
||||
'rocketcdn_data_manager_subscriber',
|
||||
'rocketcdn_rest_subscriber',
|
||||
'rocketcdn_admin_subscriber',
|
||||
'rocketcdn_notices_subscriber',
|
||||
];
|
||||
|
||||
/**
|
||||
* Registers the RocketCDN classes in the container
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register() {
|
||||
$options = $this->getContainer()->get( 'options' );
|
||||
// RocketCDN API Client.
|
||||
$this->getContainer()->add( 'rocketcdn_api_client', 'WP_Rocket\Engine\CDN\RocketCDN\APIClient' );
|
||||
// RocketCDN CDN options manager.
|
||||
$this->getContainer()->add( 'rocketcdn_options_manager', 'WP_Rocket\Engine\CDN\RocketCDN\CDNOptionsManager' )
|
||||
->withArgument( $this->getContainer()->get( 'options_api' ) )
|
||||
->withArgument( $options );
|
||||
// RocketCDN Data manager subscriber.
|
||||
$this->getContainer()->share( 'rocketcdn_data_manager_subscriber', 'WP_Rocket\Engine\CDN\RocketCDN\DataManagerSubscriber' )
|
||||
->withArgument( $this->getContainer()->get( 'rocketcdn_api_client' ) )
|
||||
->withArgument( $this->getContainer()->get( 'rocketcdn_options_manager' ) );
|
||||
// RocketCDN REST API Subscriber.
|
||||
$this->getContainer()->share( 'rocketcdn_rest_subscriber', 'WP_Rocket\Engine\CDN\RocketCDN\RESTSubscriber' )
|
||||
->withArgument( $this->getContainer()->get( 'rocketcdn_options_manager' ) )
|
||||
->withArgument( $options );
|
||||
// RocketCDN Notices Subscriber.
|
||||
$this->getContainer()->share( 'rocketcdn_notices_subscriber', 'WP_Rocket\Engine\CDN\RocketCDN\NoticesSubscriber' )
|
||||
->withArgument( $this->getContainer()->get( 'rocketcdn_api_client' ) )
|
||||
->withArgument( __DIR__ . '/views' );
|
||||
// RocketCDN settings page subscriber.
|
||||
$this->getContainer()->share( 'rocketcdn_admin_subscriber', 'WP_Rocket\Engine\CDN\RocketCDN\AdminPageSubscriber' )
|
||||
->withArgument( $this->getContainer()->get( 'rocketcdn_api_client' ) )
|
||||
->withArgument( $options )
|
||||
->withArgument( $this->getContainer()->get( 'beacon' ) )
|
||||
->withArgument( __DIR__ . '/views' );
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "wp-media/module-rocketcdn",
|
||||
"description": "Module for RocketCDN integration",
|
||||
"homepage": "https://github.com/wp-media/module-rocketcdn",
|
||||
"license": "GPL-2.0+",
|
||||
"authors": [
|
||||
{
|
||||
"name": "WP Media",
|
||||
"email": "contact@wp-media.me",
|
||||
"homepage": "https://wp-media.me"
|
||||
}
|
||||
],
|
||||
"type": "library",
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"support": {
|
||||
"issues": "https://github.com/wp-media/module-rocketcdn/issues",
|
||||
"source": "https://github.com/wp-media/module-rocketcdn"
|
||||
},
|
||||
"require-dev": {
|
||||
"php": "^5.6 || ^7",
|
||||
"brain/monkey": "^2.0",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
|
||||
"phpcompatibility/phpcompatibility-wp": "^2.0",
|
||||
"phpunit/phpunit": "^5.7 || ^7",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"wp-coding-standards/wpcs": "^2",
|
||||
"wp-media/event-manager": "^3.1",
|
||||
"wp-media/options": "^3.0",
|
||||
"wp-media/module-container": "^2.4",
|
||||
"wp-media/phpunit": "^1.0",
|
||||
"wp-media/phpunit-wp-rocket": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "WP_Rocket\\Engine\\CDN\\RocketCDN\\": "." }
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "WP_Rocket\\Tests\\": "Tests/" }
|
||||
},
|
||||
"scripts": {
|
||||
"test-unit": "\"vendor/bin/phpunit\" --testsuite unit --colors=always --configuration Tests/Unit/phpunit.xml.dist",
|
||||
"test-integration": "\"vendor/bin/phpunit\" --testsuite integration --colors=always --configuration Tests/Integration/phpunit.xml.dist --exclude-group AdminOnly",
|
||||
"test-integration-adminonly": "\"vendor/bin/phpunit\" --testsuite integration --colors=always --configuration Tests/Integration/phpunit.xml.dist --group AdminOnly",
|
||||
"run-tests": [
|
||||
"@test-unit",
|
||||
"@test-integration",
|
||||
"@test-integration-adminonly"
|
||||
],
|
||||
"install-codestandards": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run",
|
||||
"phpcs": "phpcs --basepath=.",
|
||||
"phpcs-changed": "./bin/phpcs-changed.sh",
|
||||
"phpcs:fix": "phpcbf"
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* RocketCDN small CTA template.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $data {
|
||||
* @type string $container_class container CSS class.
|
||||
* @type string $promotion_campaign Promotion campaign title.
|
||||
* @type string $promotion_end_date Promotion end date.
|
||||
* @type string $nopromo_variant CSS modifier for the no promotion display.
|
||||
* @type string $regular_price RocketCDN regular price.
|
||||
* @type string $current_price RocketCDN current price.
|
||||
* }
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
?>
|
||||
<div class="wpr-rocketcdn-cta <?php echo esc_attr( $data['container_class'] ); ?>" id="wpr-rocketcdn-cta">
|
||||
<?php if ( ! empty( $data['promotion_campaign'] ) ) : ?>
|
||||
<div class="wpr-flex wpr-rocketcdn-promo">
|
||||
<h3 class="wpr-title1"><?php echo esc_html( $data['promotion_campaign'] ); ?></h3>
|
||||
<p class="wpr-title2 wpr-rocketcdn-promo-date">
|
||||
<?php
|
||||
printf(
|
||||
// Translators: %s = date formatted using date_i18n() and get_option( 'date_format' ).
|
||||
esc_html__( 'Valid until %s only!', 'rocket' ),
|
||||
esc_html( $data['promotion_end_date'] )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<section class="wpr-rocketcdn-cta-content<?php echo esc_attr( $data['nopromo_variant'] ); ?>">
|
||||
<h3 class="wpr-title2">RocketCDN</h3>
|
||||
<p class="wpr-rocketcdn-cta-subtitle"><?php esc_html_e( 'Speed up your website thanks to:', 'rocket' ); ?></p>
|
||||
<div class="wpr-flex">
|
||||
<ul class="wpr-rocketcdn-features">
|
||||
<li class="wpr-rocketcdn-feature wpr-rocketcdn-bandwidth">
|
||||
<?php
|
||||
// translators: %1$s = opening strong tag, %2$s = closing strong tag.
|
||||
printf( esc_html__( 'High performance Content Delivery Network (CDN) with %1$sunlimited bandwith%2$s', 'rocket' ), '<strong>', '</strong>' );
|
||||
?>
|
||||
</li>
|
||||
<li class="wpr-rocketcdn-feature wpr-rocketcdn-configuration">
|
||||
<?php
|
||||
// translators: %1$s = opening strong tag, %2$s = closing strong tag.
|
||||
printf( esc_html__( 'Easy configuration: the %1$sbest CDN settings%2$s are automatically applied', 'rocket' ), '<strong>', '</strong>' );
|
||||
?>
|
||||
</li>
|
||||
<li class="wpr-rocketcdn-feature wpr-rocketcdn-automatic">
|
||||
<?php
|
||||
// translators: %1$s = opening strong tag, %2$s = closing strong tag.
|
||||
printf( esc_html__( 'WP Rocket integration: the CDN option is %1$sautomatically configured%2$s in our plugin', 'rocket' ), '<strong>', '</strong>' );
|
||||
?>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="wpr-rocketcdn-pricing">
|
||||
<?php if ( ! empty( $data['error'] ) ) : ?>
|
||||
<p><?php echo esc_html( $data['message'] ); ?></p>
|
||||
<?php else : ?>
|
||||
<?php if ( ! empty( $data['regular_price'] ) ) : ?>
|
||||
<h4 class="wpr-title2 wpr-rocketcdn-pricing-regular"><del>$<?php echo esc_html( $data['regular_price'] ); ?></del></h4>
|
||||
<?php endif; ?>
|
||||
<h4 class="wpr-rocketcdn-pricing-current">
|
||||
<?php
|
||||
printf(
|
||||
// translators: %s = price of RocketCDN subscription.
|
||||
esc_html__( '%s / month', 'rocket' ),
|
||||
'<span class="wpr-title1">$' . esc_html( $data['current_price'] ) . '</span>'
|
||||
);
|
||||
?>
|
||||
</h4>
|
||||
<button class="wpr-button wpr-rocketcdn-open" data-micromodal-trigger="wpr-rocketcdn-modal"><?php esc_html_e( 'Get Started', 'rocket' ); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="wpr-rocketcdn-cta-footer">
|
||||
<a href="https://go.wp-rocket.me/rocket-cdn" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Learn more about RocketCDN', 'rocket' ); ?></a>
|
||||
</div>
|
||||
<button class="wpr-rocketcdn-cta-close<?php echo esc_attr( $data['nopromo_variant'] ); ?>" id="wpr-rocketcdn-close-cta"><span class="screen-reader-text"><?php esc_html_e( 'Reduce this banner', 'rocket' ); ?></span></button>
|
||||
<?php if ( ! empty( $data['promotion_campaign'] ) ) : ?>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
// translators: %1$s = discounted price, %2$s = regular price.
|
||||
esc_html__( '* $%1$s/month for 12 months then $%2$s/month. You can cancel your subscription at any time.', 'rocket' ),
|
||||
esc_html( str_replace( '*', '', $data['current_price'] ) ),
|
||||
esc_html( $data['regular_price'] )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* RocketCDN small CTA template.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $data {
|
||||
* @type string $container_class container CSS class.
|
||||
* }
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
?>
|
||||
<div class="wpr-rocketcdn-cta-small notice-alt notice-warning <?php echo esc_attr( $data['container_class'] ); ?>" id="wpr-rocketcdn-cta-small">
|
||||
<div class="wpr-flex">
|
||||
<section>
|
||||
<h3 class="notice-title"><?php esc_html_e( 'Speed up your website with RocketCDN, WP Rocket’s Content Delivery Network.', 'rocket' ); ?></strong></h3>
|
||||
</section>
|
||||
<div>
|
||||
<button class="wpr-button" id="wpr-rocketcdn-open-cta"><?php esc_html_e( 'Learn More', 'rocket' ); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* RocketCDN status on dashboard tab template.
|
||||
*
|
||||
* @since 3.5
|
||||
*
|
||||
* @param array $data {
|
||||
* @type bool $is_live_site Identifies if the current website is a live or local/staging one
|
||||
* @type string $container_class Flex container CSS class.
|
||||
* @type string $label Content label.
|
||||
* @type string $status_class CSS Class to display the status.
|
||||
* @type string $status_text Text to display the subscription status.
|
||||
* @type bool $is_active Boolean identifying the activation status.
|
||||
* }
|
||||
*/
|
||||
|
||||
?>
|
||||
<div class="wpr-optionHeader">
|
||||
<h3 class="wpr-title2">RocketCDN</h3>
|
||||
</div>
|
||||
<div class="wpr-field wpr-field-account">
|
||||
<?php if ( ! $data['is_live_site'] ) : ?>
|
||||
<span class="wpr-infoAccount wpr-isInvalid"><?php esc_html_e( 'RocketCDN is unavailable on local domains and staging sites.', 'rocket' ); ?></span>
|
||||
<?php else : ?>
|
||||
<div class="wpr-flex<?php echo esc_attr( $data['container_class'] ); ?>">
|
||||
<div>
|
||||
<span class="wpr-title3"><?php echo esc_html( $data['label'] ); ?></span>
|
||||
<span class="wpr-infoAccount<?php echo esc_attr( $data['status_class'] ); ?>"><?php echo esc_html( $data['status_text'] ); ?></span>
|
||||
</div>
|
||||
<?php if ( ! $data['is_active'] ) : ?>
|
||||
<div>
|
||||
<a href="#page_cdn" class="wpr-button"><?php esc_html_e( 'Get RocketCDN', 'rocket' ); ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* Promote RocketCDN notice template.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
?>
|
||||
<div class="notice notice-alt notice-warning is-dismissible" id="rocketcdn-promote-notice">
|
||||
<h2 class="notice-title"><?php esc_html_e( 'New!', 'rocket' ); ?></h2>
|
||||
<p><?php esc_html_e( 'Speed up your website with RocketCDN, WP Rocket’s Content Delivery Network!', 'rocket' ); ?></p>
|
||||
<p><a href="#page_cdn" class="wpr-button" id="rocketcdn-learn-more-dismiss"><?php esc_html_e( 'Learn More', 'rocket' ); ?></a></p>
|
||||
</div>
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN;
|
||||
|
||||
use WP_Rocket\Engine\Container\ServiceProvider\AbstractServiceProvider;
|
||||
|
||||
/**
|
||||
* Service provider for WP Rocket CDN
|
||||
*
|
||||
* @since 3.5.5
|
||||
*/
|
||||
class ServiceProvider extends AbstractServiceProvider {
|
||||
/**
|
||||
* The provides array is a way to let the container
|
||||
* know that a service is provided by this service
|
||||
* provider. Every service that is registered via
|
||||
* this service provider must have an alias added
|
||||
* to this array or it will be ignored.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $provides = [
|
||||
'cdn',
|
||||
'cdn_subscriber',
|
||||
];
|
||||
|
||||
/**
|
||||
* Registers the services in the container
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register() {
|
||||
$options = $this->getContainer()->get( 'options' );
|
||||
|
||||
$this->getContainer()->share( 'cdn', 'WP_Rocket\Engine\CDN\CDN' )
|
||||
->withArgument( $options );
|
||||
$this->getContainer()->share( 'cdn_subscriber', 'WP_Rocket\Engine\CDN\Subscriber' )
|
||||
->withArgument( $options )
|
||||
->withArgument( $this->getContainer()->get( 'cdn' ) );
|
||||
}
|
||||
}
|
277
wp-content/plugins/wp-rocket/inc/Engine/CDN/Subscriber.php
Normal file
277
wp-content/plugins/wp-rocket/inc/Engine/CDN/Subscriber.php
Normal file
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
namespace WP_Rocket\Engine\CDN;
|
||||
|
||||
use WP_Rocket\Admin\Options_Data;
|
||||
use WP_Rocket\Event_Management\Subscriber_Interface;
|
||||
|
||||
/**
|
||||
* Subscriber for the CDN feature
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
class Subscriber implements Subscriber_Interface {
|
||||
/**
|
||||
* WP Rocket Options instance
|
||||
*
|
||||
* @var Options_Data
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* CDN instance
|
||||
*
|
||||
* @var CDN
|
||||
*/
|
||||
private $cdn;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Options_Data $options WP Rocket Options instance.
|
||||
* @param CDN $cdn CDN instance.
|
||||
*/
|
||||
public function __construct( Options_Data $options, CDN $cdn ) {
|
||||
$this->options = $options;
|
||||
$this->cdn = $cdn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of events that this subscriber wants to listen to.
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_subscribed_events() {
|
||||
return [
|
||||
'rocket_buffer' => [
|
||||
[ 'rewrite', 20 ],
|
||||
[ 'rewrite_srcset', 21 ],
|
||||
],
|
||||
'rocket_css_content' => 'rewrite_css_properties',
|
||||
'rocket_cdn_hosts' => [ 'get_cdn_hosts', 10, 2 ],
|
||||
'rocket_dns_prefetch' => 'add_dns_prefetch_cdn',
|
||||
'rocket_facebook_sdk_url' => 'add_cdn_url',
|
||||
'rocket_css_url' => [ 'add_cdn_url', 10, 2 ],
|
||||
'rocket_js_url' => [ 'add_cdn_url', 10, 2 ],
|
||||
'rocket_asset_url' => [ 'maybe_replace_url', 10, 2 ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites URLs to the CDN URLs if allowed
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $html HTML content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite( $html ) {
|
||||
if ( ! $this->is_allowed() ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
return $this->cdn->rewrite( $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites URLs in srcset attributes to the CDN URLs if allowed
|
||||
*
|
||||
* @since 3.4.0.4
|
||||
*
|
||||
* @param string $html HTML content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite_srcset( $html ) {
|
||||
if ( ! $this->is_allowed() ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
return $this->cdn->rewrite_srcset( $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites URLs to the CDN URLs in CSS files
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $content CSS content.
|
||||
* @return string
|
||||
*/
|
||||
public function rewrite_css_properties( $content ) {
|
||||
/**
|
||||
* Filters the application of the CDN on CSS properties
|
||||
*
|
||||
* @since 2.6
|
||||
*
|
||||
* @param bool true to apply CDN to properties, false otherwise
|
||||
*/
|
||||
$do_rewrite = apply_filters( 'do_rocket_cdn_css_properties', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
|
||||
|
||||
if ( ! $do_rewrite ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if ( ! $this->is_cdn_enabled() ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
return $this->cdn->rewrite_css_properties( $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host value for each CDN URLs
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param array $hosts Base hosts.
|
||||
* @param array $zones Zones to get the CND URLs associated with.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_cdn_hosts( array $hosts = [], array $zones = [ 'all' ] ) {
|
||||
$cdn_urls = $this->cdn->get_cdn_urls( $zones );
|
||||
|
||||
if ( empty( $cdn_urls ) ) {
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
foreach ( $cdn_urls as $cdn_url ) {
|
||||
$parsed = get_rocket_parse_url( rocket_add_url_protocol( $cdn_url ) );
|
||||
|
||||
if ( empty( $parsed['host'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$hosts[] = untrailingslashit( $parsed['host'] . $parsed['path'] );
|
||||
}
|
||||
|
||||
return array_unique( $hosts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds CDN URLs to the DNS prefetch links
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param array $domains Domain names to DNS prefetch.
|
||||
* @return array
|
||||
*/
|
||||
public function add_dns_prefetch_cdn( $domains ) {
|
||||
if ( ! $this->is_allowed() ) {
|
||||
return $domains;
|
||||
}
|
||||
|
||||
$cdn_urls = $this->cdn->get_cdn_urls( [ 'all', 'images', 'css_and_js', 'css', 'js' ] );
|
||||
|
||||
if ( ! $cdn_urls ) {
|
||||
return $domains;
|
||||
}
|
||||
|
||||
return array_merge( $domains, $cdn_urls );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the CDN URL on the provided URL
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @param string $url URL to rewrite.
|
||||
* @param string $original_url Original URL for this URL. Optional.
|
||||
* @return string
|
||||
*/
|
||||
public function add_cdn_url( $url, $original_url = '' ) {
|
||||
if ( ! empty( $original_url ) ) {
|
||||
if ( $this->cdn->is_excluded( $original_url ) ) {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->cdn->rewrite_url( $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace CDN URL with site URL on the provided asset URL.
|
||||
*
|
||||
* @since 3.5.3
|
||||
*
|
||||
* @param string $url URL of the asset.
|
||||
* @param array $zones Array of corresponding zones for the asset.
|
||||
* @return string
|
||||
*/
|
||||
public function maybe_replace_url( $url, array $zones = [ 'all' ] ) {
|
||||
if ( ! $this->is_allowed() ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$url_parts = get_rocket_parse_url( $url );
|
||||
|
||||
if ( empty( $url_parts['host'] ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$site_url_parts = get_rocket_parse_url( site_url() );
|
||||
|
||||
if ( empty( $site_url_parts['host'] ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
if ( $url_parts['host'] === $site_url_parts['host'] ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$cdn_urls = $this->cdn->get_cdn_urls( $zones );
|
||||
|
||||
if ( empty( $cdn_urls ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$cdn_urls = array_map( 'rocket_add_url_protocol', $cdn_urls );
|
||||
|
||||
$site_url = $site_url_parts['scheme'] . '://' . $site_url_parts['host'];
|
||||
|
||||
foreach ( $cdn_urls as $cdn_url ) {
|
||||
if ( false === strpos( $url, $cdn_url ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return str_replace( $cdn_url, $site_url, $url );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if CDN can be applied
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_allowed() {
|
||||
if ( rocket_get_constant( 'DONOTROCKETOPTIMIZE' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->is_cdn_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( is_rocket_post_excluded_option( 'cdn' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the CDN option is enabled
|
||||
*
|
||||
* @since 3.5.5
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_cdn_enabled() {
|
||||
return (bool) $this->options->get( 'cdn', 0 );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user