updated plugin W3 Total Cache version 2.6.1

This commit is contained in:
KawaiiPunk 2023-12-08 23:23:32 +00:00 committed by Gitium
parent fa428d9da9
commit 33d18af972
82 changed files with 5759 additions and 1701 deletions

View File

@ -1,4 +1,10 @@
<?php <?php
/**
* File: Cache.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/** /**
@ -6,32 +12,34 @@ namespace W3TC;
*/ */
/** /**
* class Cache * Class: Cache
*/ */
class Cache { class Cache {
/** /**
* Returns cache engine instance * Returns cache engine instance
* *
* @param string $engine * @param string $engine Engine key code.
* @param array $config * @param array $config Configuration.
* @return W3_Cache_Base * @return W3_Cache_Base
*/ */
static function instance( $engine, $config = array() ) { public static function instance( $engine, $config = array() ) {
static $instances = array(); static $instances = array();
// common configuration data // Common configuration data.
if ( !isset( $config['blog_id'] ) ) if ( ! isset( $config['blog_id'] ) ) {
$config['blog_id'] = Util_Environment::blog_id(); $config['blog_id'] = Util_Environment::blog_id();
}
$instance_key = sprintf( '%s_%s', $engine, md5( serialize( $config ) ) ); $instance_key = sprintf( '%s_%s', $engine, md5( serialize( $config ) ) );
if ( ! isset( $instances[ $instance_key ] ) ) { if ( ! isset( $instances[ $instance_key ] ) ) {
switch ( $engine ) { switch ( $engine ) {
case 'apc': case 'apc':
if ( function_exists( 'apcu_store' ) ) if ( function_exists( 'apcu_store' ) ) {
$instances[ $instance_key ] = new Cache_Apcu( $config ); $instances[ $instance_key ] = new Cache_Apcu( $config );
else if ( function_exists( 'apc_store' ) ) } else if ( function_exists( 'apc_store' ) ) {
$instances[ $instance_key ] = new Cache_Apc( $config ); $instances[ $instance_key ] = new Cache_Apc( $config );
}
break; break;
case 'eaccelerator': case 'eaccelerator':
@ -76,8 +84,7 @@ class Cache {
break; break;
} }
if ( !isset( $instances[$instance_key] ) || if ( ! isset( $instances[ $instance_key ] ) || ! $instances[ $instance_key ]->available() ) {
!$instances[$instance_key]->available() ) {
$instances[ $instance_key ] = new Cache_Base( $config ); $instances[ $instance_key ] = new Cache_Base( $config );
} }
} }
@ -88,106 +95,115 @@ class Cache {
/** /**
* Returns caching engine name * Returns caching engine name
* *
* @param unknown $engine * @param string $engine Engine key code.
* @param unknown $module * @param string $module Module.
* *
* @return string * @return string
*/ */
static public function engine_name( $engine, $module = '' ) { public static function engine_name( $engine, $module = '' ) {
switch ( $engine ) { switch ( $engine ) {
case 'memcached': case 'memcached':
if ( class_exists( 'Memcached' ) ) if ( class_exists( 'Memcached' ) ) {
$engine_name = 'memcached'; $engine_name = 'Memcached';
else } else {
$engine_name = 'memcache'; $engine_name = 'Memcache';
}
break; break;
case 'nginx_memcached': case 'nginx_memcached':
$engine_name = 'nginx + memcached'; $engine_name = 'Nginx + Memcached';
break; break;
case 'apc': case 'apc':
$engine_name = 'apc'; $engine_name = 'APC';
break; break;
case 'eaccelerator': case 'eaccelerator':
$engine_name = 'eaccelerator'; $engine_name = 'EAccelerator';
break; break;
case 'redis': case 'redis':
$engine_name = 'redis'; $engine_name = 'Redis';
break; break;
case 'xcache': case 'xcache':
$engine_name = 'xcache'; $engine_name = 'XCache';
break; break;
case 'wincache': case 'wincache':
$engine_name = 'wincache'; $engine_name = 'WinCache';
break; break;
case 'file': case 'file':
if ( $module == 'pgcache' ) if ( 'pgcache' === $module ) {
$engine_name = 'disk: basic'; $engine_name = 'Disk: Basic';
else } else {
$engine_name = 'disk'; $engine_name = 'Disk';
}
break; break;
case 'file_generic': case 'file_generic':
$engine_name = 'disk: enhanced'; $engine_name = 'Disk: Enhanced';
break; break;
case 'ftp': case 'ftp':
$engine_name = 'self-hosted / file transfer protocol upload'; $engine_name = 'Self-hosted / file transfer protocol upload';
break; break;
case 's3': case 's3':
$engine_name = 'amazon simple storage service (s3)'; $engine_name = 'Amazon Simple Storage Service (S3)';
break; break;
case 's3_compatible': case 's3_compatible':
$engine_name = 's3 compatible'; $engine_name = 'S3 compatible';
break; break;
case 'cf': case 'cf':
$engine_name = 'amazon cloudfront'; $engine_name = 'Amazon Cloudfront';
break; break;
case 'google_drive': case 'google_drive':
$engine_name = 'google drive'; $engine_name = 'Google Drive';
break; break;
case 'highwinds': case 'highwinds':
$engine_name = 'highwinds'; $engine_name = 'Highwinds';
break; break;
case 'cf2': case 'cf2':
$engine_name = 'amazon cloudfront'; $engine_name = 'Amazon Cloudfront';
break; break;
case 'rscf': case 'rscf':
$engine_name = 'rackspace cloud files'; $engine_name = 'Rackspace Cloud Files';
break; break;
case 'azure': case 'azure':
$engine_name = 'microsoft azure storage'; $engine_name = 'Microsoft Azure Storage';
break; break;
case 'edgecast': case 'edgecast':
$engine_name = 'media template procdn / edgecast'; $engine_name = 'Media Template ProCDN / EdgeCast';
break; break;
case 'att': case 'att':
$engine_name = 'at&amp;t'; $engine_name = 'AT&amp;T';
break; break;
case 'rackspace_cdn': case 'rackspace_cdn':
$engine_name = 'rackspace'; $engine_name = 'Rackspace';
break; break;
case 'stackpath2': case 'stackpath2':
$engine_name = 'stackpath'; $engine_name = 'StackPath';
break;
case 'bunnycdn':
$engine_name = 'Bunny CDN';
break;
case '':
$engine_name = __( 'None', 'w3-total-cache' );
break; break;
default: default:
@ -197,5 +213,4 @@ class Cache {
return $engine_name; return $engine_name;
} }
} }

View File

@ -92,11 +92,14 @@ class CacheFlush {
} }
/** /**
* Purge CDN mirror cache * Purge CDN mirror cache.
*
* @param array $extras Extra configuration.
*/ */
function cdn_purge_all( $extras = array() ) { public function cdn_purge_all( $extras = array() ) {
if ( $this->_config->get_boolean( 'cdn.enabled' ) ) if ( $this->_config->get_boolean( 'cdn.enabled' ) || $this->_config->get_boolean( 'cdnfsd.enabled' ) ) {
return $this->_executor->cdn_purge_all( $extras ); return $this->_executor->cdn_purge_all( $extras );
}
return false; return false;
} }

View File

@ -122,7 +122,7 @@ if ( ! defined( 'W3TC' ) ) {
</li> </li>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ul>
<div id="mobile_groups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All user agents recieve the same page and minify cache results.', 'w3-total-cache' ); ?></div> <div id="mobile_groups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All user agents receive the same page and minify cache results.', 'w3-total-cache' ); ?></div>
<?php <?php
Util_Ui::postbox_footer(); Util_Ui::postbox_footer();
@ -226,7 +226,7 @@ if ( ! defined( 'W3TC' ) ) {
</li> </li>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ul>
<div id="referrer_groups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All referrers recieve the same page and minify cache results.', 'w3-total-cache' ); ?></div> <div id="referrer_groups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All referrers receive the same page and minify cache results.', 'w3-total-cache' ); ?></div>
<?php Util_Ui::postbox_footer(); ?> <?php Util_Ui::postbox_footer(); ?>
</div> </div>
@ -310,7 +310,7 @@ if ( ! defined( 'W3TC' ) ) {
</li> </li>
<?php endforeach; ?> <?php endforeach; ?>
</ul> </ul>
<div id="cookiegroups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All Cookies recieve the same page and minify cache results.', 'w3-total-cache' ); ?></div> <div id="cookiegroups_empty" style="display: none;"><?php esc_html_e( 'No groups added. All Cookies receive the same page and minify cache results.', 'w3-total-cache' ); ?></div>
<?php <?php
Util_Ui::postbox_footer(); Util_Ui::postbox_footer();

View File

@ -1,20 +1,25 @@
<?php <?php
/**
* File: CdnEngine.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/** /**
* class CdnEngine * Class: CdnEngine
*/ */
class CdnEngine { class CdnEngine {
/** /**
* Returns CdnEngine_Base instance * Returns CdnEngine_Base instance.
* *
* @param string $engine * @param string $engine CDN engine.
* @param array $config * @param array $config Configuration.
* @return CdnEngine_Base * @return CdnEngine_Base
*/ */
static function instance( $engine, $config = array() ) { public static function instance( $engine, array $config = array() ) {
static $instances = array(); static $instances = array();
$instance_key = sprintf( '%s_%s', $engine, md5( serialize( $config ) ) ); $instance_key = sprintf( '%s_%s', $engine, md5( serialize( $config ) ) );
if ( ! isset( $instances[ $instance_key ] ) ) { if ( ! isset( $instances[ $instance_key ] ) ) {
@ -31,6 +36,10 @@ class CdnEngine {
$instances[ $instance_key ] = new CdnEngine_Azure( $config ); $instances[ $instance_key ] = new CdnEngine_Azure( $config );
break; break;
case 'bunnycdn':
$instances[ $instance_key ] = new CdnEngine_Mirror_BunnyCdn( $config );
break;
case 'cf': case 'cf':
$instances[ $instance_key ] = new CdnEngine_CloudFront( $config ); $instances[ $instance_key ] = new CdnEngine_CloudFront( $config );
break; break;
@ -72,8 +81,7 @@ class CdnEngine {
break; break;
case 'rscf': case 'rscf':
$instances[$instance_key] = $instances[ $instance_key ] = new CdnEngine_RackSpaceCloudFiles( $config );
new CdnEngine_RackSpaceCloudFiles( $config );
break; break;
case 's3': case 's3':
@ -93,7 +101,8 @@ class CdnEngine {
break; break;
default: default:
trigger_error( 'Incorrect CDN engine', E_USER_WARNING ); empty( $engine ) || trigger_error( 'Incorrect CDN engine', E_USER_WARNING );
$instances[ $instance_key ] = new CdnEngine_Base(); $instances[ $instance_key ] = new CdnEngine_Base();
break; break;
} }

View File

@ -0,0 +1,167 @@
<?php
/**
* File: CdnEngine_Mirror_BunnyCdn.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: CdnEngine_Mirror_BunnyCdn
*
* @since X.X.X
*
* @extends CdnEngine_Mirror
*/
class CdnEngine_Mirror_BunnyCdn extends CdnEngine_Mirror {
/**
* Constructor.
*
* @param array $config {
* Configuration.
*
* @type string $account_api_key Account API key.
* @type string $storage_api_key Storage API key.
* @type string $stream_api_key Steam API key.
* @type int $pull_zone_id Pull zone id.
* @type string $cdn_hostname CDN hostname.
* }
*/
public function __construct( array $config = array() ) {
$config = \array_merge(
array(
'account_api_key' => '',
'storage_api_key' => '',
'stream_api_key' => '',
'pull_zone_id' => null,
'domain' => '',
),
$config
);
parent::__construct( $config );
}
/**
* Purge remote files.
*
* @since X.X.X
*
* @param array $files Local and remote file paths.
* @param array $results Results.
* @return bool
*/
public function purge( $files, &$results ) {
if ( empty( $this->_config['account_api_key'] ) ) {
$results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, \__( 'Missing account API key.', 'w3-total-cache' ) );
return false;
}
if ( empty( $this->_config['cdn_hostname'] ) ) {
$results = $this->_get_results( $files, W3TC_CDN_RESULT_HALT, \__( 'Missing CDN hostname.', 'w3-total-cache' ) );
return false;
}
$url_prefixes = $this->url_prefixes();
$api = new Cdn_BunnyCdn_Api( $this->_config );
$results = array();
try {
$items = array();
foreach ( $files as $file ) {
foreach ( $url_prefixes as $prefix ) {
$items[] = array(
'url' => $prefix . '/' . $file['remote_path'],
'recursive' => true,
);
}
}
$api->purge( array( 'items' => $items ) );
$results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_OK, 'OK' );
} catch ( \Exception $e ) {
$results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, \__( 'Could not purge pull zone items: ', 'w3-total-cache' ) . $e->getMessage() );
}
return ! $this->_is_error( $results );
}
/**
* Purge CDN completely.
*
* @since X.X.X
*
* @param array $results Results.
* @return bool
*/
public function purge_all( &$results ) {
if ( empty( $this->_config['account_api_key'] ) ) {
$results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Missing account API key.', 'w3-total-cache' ) );
return false;
}
// Purge active pull zones: CDN & CDNFSD.
$active_zone_ids = array();
$config = Dispatcher::config();
$cdn_zone_id = $config->get_integer( 'cdn.bunnycdn.pull_zone_id' );
$cdnfsd_zone_id = $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' );
if ( $config->get_boolean( 'cdn.enabled' ) && 'bunnycdn' === $config->get_string( 'cdn.engine' ) && $cdn_zone_id ) {
$active_ids[] = $cdn_zone_id;
}
if ( $config->get_boolean( 'cdnfsd.enabled' ) && 'bunnycdn' === $config->get_string( 'cdnfsd.engine' ) && $cdnfsd_zone_id ) {
$active_ids[] = $cdnfsd_zone_id;
}
if ( empty( $active_ids ) ) {
$results = $this->_get_results( array(), W3TC_CDN_RESULT_HALT, __( 'Missing pull zone id.', 'w3-total-cache' ) );
return false;
}
$results = array();
foreach ( $active_ids as $id ) {
$api = new Cdn_BunnyCdn_Api( array_merge( $this->_config, array( 'pull_zone_id' => $id ) ) );
try {
$api->purge_pull_zone();
$results[] = $this->_get_result( '', '' ); // W3TC_CDN_RESULT_OK.
} catch ( \Exception $e ) {
$results[] = $this->_get_result( '', '', W3TC_CDN_RESULT_HALT, \__( 'Could not purge pull zone', 'w3-total-cache' ) . '; ' . $e->getMessage() );
}
}
return ! $this->_is_error( $results );
}
/**
* Get URL prefixes.
*
* If set to "auto", then add URLs for both "http" and "https".
*
* @since X.X.X
*
* @return array
*/
private function url_prefixes() {
$url_prefixes = array();
if ( 'auto' === $this->_config['ssl'] || 'enabled' === $this->_config['ssl'] ) {
$url_prefixes[] = 'https://' . $this->_config['cdn_hostname'];
}
if ( 'auto' === $this->_config['ssl'] || 'enabled' !== $this->_config['ssl'] ) {
$url_prefixes[] = 'http://' . $this->_config['cdn_hostname'];
}
return $url_prefixes;
}
}

View File

@ -413,6 +413,7 @@ class Cdn_AdminActions {
$engine == 'stackpath2' || $engine == 'stackpath2' ||
$engine == 'rackspace_cdn' || $engine == 'rackspace_cdn' ||
$engine == 'rscf' || $engine == 'rscf' ||
'bunnycdn' === $engine ||
$engine == 's3_compatible' ) { $engine == 's3_compatible' ) {
// those use already stored w3tc config // those use already stored w3tc config
$w3_cdn = Dispatcher::component( 'Cdn_Core' )->get_cdn(); $w3_cdn = Dispatcher::component( 'Cdn_Core' )->get_cdn();
@ -471,16 +472,20 @@ class Cdn_AdminActions {
@set_time_limit( $this->_config->get_integer( 'timelimit.cdn_upload' ) ); @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_upload' ) );
$result = false; $result = false;
try { try {
$container_id = $w3_cdn->create_container(); $container_id = $w3_cdn->create_container();
$result = true; $result = true;
$error = __( 'Created successfully.', 'w3-total-cache' ); $error = __( 'Created successfully.', 'w3-total-cache' );
} catch ( \Exception $ex ) { } catch ( \Exception $ex ) {
$error = sprintf( __( 'Error: %s', 'w3-total-cache' ), $error = sprintf(
$ex->getMessage() ); __( 'Error: %s', 'w3-total-cache' ),
$ex->getMessage()
);
} }
break; break;
default: default:
$result = false; $result = false;
$error = __( 'Incorrect type.', 'w3-total-cache' ); $error = __( 'Incorrect type.', 'w3-total-cache' );
@ -489,19 +494,38 @@ class Cdn_AdminActions {
$response = array( $response = array(
'result' => $result, 'result' => $result,
'error' => $error, 'error' => $error,
'container_id' => $container_id 'container_id' => $container_id,
); );
echo json_encode( $response ); echo json_encode( $response );
} }
/**
* Redirect to the Bunny CDN signup page.
*
* @since X.X.X
*
* @return void
*/
public function w3tc_cdn_bunnycdn_signup() {
try {
$state = Dispatcher::config_state();
$state->set( 'track.bunnycdn_signup', time() );
$state->save();
} catch ( \Exception $ex ) {} // phpcs:ignore
Util_Environment::redirect( W3TC_BUNNYCDN_SIGNUP_URL );
}
/**
* Test CDN URL.
*
* @param string $url URL.
*/
private function test_cdn_url( $url ) { private function test_cdn_url( $url ) {
$response = wp_remote_get( $url ); $response = wp_remote_get( $url );
if ( is_wp_error( $response ) ) if ( is_wp_error( $response ) ) {
return false; return false;
else { } else {
$code = wp_remote_retrieve_response_code( $response ); $code = wp_remote_retrieve_response_code( $response );
return 200 == $code; return 200 == $code;
} }

View File

@ -0,0 +1,552 @@
<?php
/**
* File: Cdn_BunnyCdn_Api.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdn_BunnyCdn_Api
*
* @since X.X.X
*/
class Cdn_BunnyCdn_Api {
/**
* Account API Key.
*
* @since X.X.X
* @access private
*
* @var string
*/
private $account_api_key;
/**
* Storage API Key.
*
* @since X.X.X
* @access private
*
* @var string
*/
private $storage_api_key;
/**
* Stream API Key.
*
* @since X.X.X
* @access private
*
* @var string
*/
private $stream_api_key;
/**
* API type.
*
* One of: "account", "storage", "stream".
*
* @since X.X.X
* @access private
*
* @var string
*/
private $api_type;
/**
* Pull zone id.
*
* @since X.X.X
* @access private
*
* @var int
*/
private $pull_zone_id;
/**
* Default Edge Rules.
*
* @since X.X.X
* @access private
* @static
*
* @var array
*/
private static $default_edge_rules = array(
array(
'ActionType' => 15, // BypassPermaCache.
'TriggerMatchingType' => 0, // MatchAny.
'Enabled' => true,
'Triggers' => array(
array(
'Type' => 3, // UrlExtension.
'PatternMatchingType' => 0, // MatchAny.
'PatternMatches' => array( '.zip' ),
),
),
'Description' => 'Bypass PermaCache for ZIP files',
),
array(
'ActionType' => 3, // OverrideCacheTime.
'TriggerMatchingType' => 0, // MatchAny.
'ActionParameter1' => '0',
'ActionParameter2' => '',
'Enabled' => true,
'Triggers' => array(
array(
'Type' => 1, // RequestHeader.
'PatternMatchingType' => 0, // MatchAny.
'PatternMatches' => array(
'*wordpress_logged_in_*',
'*wordpress_sec_*',
),
'Parameter1' => 'Cookie',
),
),
'Description' => 'Override Cache Time if logged into WordPress',
),
array(
'ActionType' => 15, // BypassPermaCache.
'TriggerMatchingType' => 0, // MatchAny.
'Enabled' => true,
'Triggers' => array(
array(
'Type' => 1, // RequestHeader.
'PatternMatchingType' => 0, // MatchAny.
'PatternMatches' => array(
'*wordpress_logged_in_*',
'*wordpress_sec_*',
),
'Parameter1' => 'Cookie',
),
),
'Description' => 'Bypass PermaCache if logged into WordPress',
),
array(
'ActionType' => 16, // OverrideBrowserCacheTime.
'TriggerMatchingType' => 0, // MatchAny.
'ActionParameter1' => '0',
'Enabled' => true,
'Triggers' => array(
array(
'Type' => 1, // RequestHeader.
'PatternMatchingType' => 0, // MatchAny.
'PatternMatches' => array(
'*wordpress_logged_in_*',
'*wordpress_sec_*',
),
'Parameter1' => 'Cookie',
),
),
'Description' => 'Override Browser Cache Time if logged into WordPress',
),
);
/**
* Constructor.
*
* @since X.X.X
*
* @param array $config Configuration.
*/
public function __construct( array $config ) {
$this->account_api_key = ! empty( $config['account_api_key'] ) ? $config['account_api_key'] : '';
$this->storage_api_key = ! empty( $config['storage_api_key'] ) ? $config['storage_api_key'] : '';
$this->stream_api_key = ! empty( $config['stream_api_key'] ) ? $config['stream_api_key'] : '';
$this->pull_zone_id = ! empty( $config['pull_zone_id'] ) ? $config['pull_zone_id'] : '';
}
/**
* Increase http request timeout to 60 seconds.
*
* @since X.X.X
*
* @param int $time Timeout in seconds.
*/
public function filter_timeout_time( $time ) {
return 600;
}
/**
* Don't check certificate, some users have limited CA list
*
* @since X.X.X
*
* @param bool $verify Always false.
*/
public function https_ssl_verify( $verify = false ) {
return false;
}
/**
* List pull zones.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_index
*
* @return array
*/
public function list_pull_zones() {
$this->api_type = 'account';
return $this->wp_remote_get( \esc_url( 'https://api.bunny.net/pullzone' ) );
}
/**
* Get pull zone details by pull zone id.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_index2
*
* @param int $id Pull zone id.
* @return array
*/
public function get_pull_zone( $id ) {
$this->api_type = 'account';
return $this->wp_remote_get(
\esc_url( 'https://api.bunny.net/pullzone/id' . $id )
);
}
/**
* Add a pull zone.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_add
*
* @param array $data {
* Data used to create the pull zone.
*
* @type string $Name The name/hostname for the pull zone where the files will be accessible; only letters, numbers, and dashes.
* @type string $OriginUrl Origin URL or IP (with optional port number).
* @type string $OriginHostHeader Optional: The host HTTP header that will be sent to the origin. If empty, hostname will be automatically extracted from the Origin URL.
* @type bool $AddHostHeader Optional: If enabled, the original host header of the request will be forwarded to the origin server. This should be disabled in most cases.
* }
*
* @return array
* @throws \Exception Exception.
*/
public function add_pull_zone( array $data ) {
$this->api_type = 'account';
if ( empty( $data['Name'] ) || ! \is_string( $data['Name'] ) ) { // A Name string is required, which is used for the CDN hostname.
throw new \Exception( \esc_html__( 'A pull zone name (string) is required.', 'w3-total-cache' ) );
}
if ( \preg_match( '[^\w\d-]', $data['Name'] ) ) { // Only letters, numbers, and dashes are allowed in the Name.
throw new \Exception( \esc_html__( 'A pull zone name (string) is required.', 'w3-total-cache' ) );
}
return $this->wp_remote_post(
'https://api.bunny.net/pullzone',
$data
);
}
/**
* Update a pull zone.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_updatepullzone
*
* @param int $id Optional pull zone ID. Can be specified in the constructor configuration array parameter.
* @param array $data Data used to update the pull zone.
* @return array
* @throws \Exception Exception.
*/
public function update_pull_zone( $id, array $data ) {
$this->api_type = 'account';
$id = empty( $this->pull_zone_id ) ? $id : $this->pull_zone_id;
if ( empty( $id ) || ! \is_int( $id ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
return $this->wp_remote_post(
'https://api.bunny.net/pullzone/' . $id,
$data
);
}
/**
* Delete a pull zone.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_delete
*
* @param int $id Optional pull zone ID. Can be specified in the constructor configuration array parameter.
* @return array
* @throws \Exception Exception.
*/
public function delete_pull_zone( $id ) {
$this->api_type = 'account';
$id = empty( $this->pull_zone_id ) ? $id : $this->pull_zone_id;
if ( empty( $id ) || ! \is_int( $id ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
return $this->wp_remote_post(
\esc_url( 'https://api.bunny.net/pullzone/' . $id ),
array(),
array( 'method' => 'DELETE' )
);
}
/**
* Add a custom hostname to a pull zone.
*
* @since X.X.X
*
* @link https://docs.bunny.net/reference/pullzonepublic_addhostname
*
* @param string $hostname Custom hostname.
* @param int $pull_zone_id Optional pull zone ID. Can be specified in the constructor configuration array parameter.
* @return void
* @throws \Exception Exception.
*/
public function add_custom_hostname( $hostname, $pull_zone_id = null ) {
$this->api_type = 'account';
$pull_zone_id = empty( $this->pull_zone_id ) ? $pull_zone_id : $this->pull_zone_id;
if ( empty( $pull_zone_id ) || ! \is_int( $pull_zone_id ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
if ( empty( $hostname ) || ! \filter_var( $hostname, FILTER_VALIDATE_DOMAIN ) ) {
throw new \Exception( \esc_html__( 'Invalid hostname', 'w3-total-cache' ) . ' "' . \esc_html( $hostname ) . '".' );
}
$this->wp_remote_post(
\esc_url( 'https://api.bunny.net/pullzone/' . $pull_zone_id . '/addHostname' ),
array( 'Hostname' => $hostname )
);
}
/**
* Get the default edge rules.
*
* @since X.X.X
* @static
*
* @return array
*/
public static function get_default_edge_rules() {
return self::$default_edge_rules;
}
/**
* Add/Update Edge Rule.
*
* @since X.X.X
*
* @param array $data Data.
* @param int $pull_zone_id Optional pull zone ID. Can be specified in the constructor configuration array parameter.
* @return void
* @throws \Exception Exception.
*/
public function add_edge_rule( array $data, $pull_zone_id = null ) {
$this->api_type = 'account';
$pull_zone_id = empty( $this->pull_zone_id ) ? $pull_zone_id : $this->pull_zone_id;
if ( empty( $pull_zone_id ) || ! \is_int( $pull_zone_id ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
if ( ! isset( $data['ActionType'] ) || ! \is_int( $data['ActionType'] ) || $data['ActionType'] < 0 ) {
throw new \Exception( \esc_html__( 'Invalid parameter "ActionType".', 'w3-total-cache' ) );
}
if ( ! isset( $data['TriggerMatchingType'] ) || ! \is_int( $data['TriggerMatchingType'] ) || $data['TriggerMatchingType'] < 0 ) {
throw new \Exception( \esc_html__( 'Invalid parameter "TriggerMatchingType".', 'w3-total-cache' ) );
}
if ( ! isset( $data['Enabled'] ) || ! \is_bool( $data['Enabled'] ) ) {
throw new \Exception( \esc_html__( 'Missing parameter "Enabled".', 'w3-total-cache' ) );
}
if ( empty( $data['Triggers'] ) ) {
throw new \Exception( \esc_html__( 'Missing parameter "Triggers".', 'w3-total-cache' ) );
}
$this->wp_remote_post(
\esc_url( 'https://api.bunny.net/pullzone/' . $pull_zone_id . '/edgerules/addOrUpdate' ),
$data
);
}
/**
* Purge.
*
* @since X.X.X
*
* @param array $data Data for the POST request.
* @return array
*/
public function purge( array $data ) {
$this->api_type = 'account';
return $this->wp_remote_get(
\esc_url( 'https://api.bunny.net/purge' ),
$data
);
}
/**
* Purge an entire pull zone.
*
* @since X.X.X
*
* @param int $pull_zone_id Optional pull zone ID. Can be specified in the constructor configuration array parameter.
* @return void
* @throws \Exception Exception.
*/
public function purge_pull_zone( $pull_zone_id = null ) {
$this->api_type = 'account';
$pull_zone_id = empty( $this->pull_zone_id ) ? $pull_zone_id : $this->pull_zone_id;
if ( empty( $pull_zone_id ) || ! \is_int( $pull_zone_id ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
$this->wp_remote_post( \esc_url( 'https://api.bunny.net/pullzone/' . $pull_zone_id . '/purgeCache' ) );
}
/**
* Get the API key by API type.
*
* API type can be passed or the class property will be used.
*
* @since X.X.X
*
* @param string $type API type: One of "account", "storage", "stream" (optional).
* @return string|null
* @throws \Exception Exception.
*/
private function get_api_key( $type = null ) {
if ( empty( $type ) ) {
$type = $this->api_type;
}
if ( ! \in_array( $type, array( 'account', 'storage', 'stream' ), true ) ) {
throw new \Exception( \esc_html__( 'Invalid API type; must be one of "account", "storage", "stream".', 'w3-total-cache' ) );
}
if ( empty( $this->{$type . '_api_key'} ) ) {
throw new \Exception( \esc_html__( 'API key value is empty.', 'w3-total-cache' ) );
}
return $this->{$type . '_api_key'};
}
/**
* Decode response from a wp_remote_* call.
*
* @since X.X.X
*
* @param array|WP_Error $result Result.
* @return array
* @throws \Exception Exception.
*/
private function decode_response( $result ) {
if ( \is_wp_error( $result ) ) {
throw new \Exception( \esc_html__( 'Failed to reach API endpoint', 'w3-total-cache' ) );
}
$response_body = @\json_decode( $result['body'], true );
// Throw an exception if the response code/status is not ok.
if ( ! \in_array( $result['response']['code'], array( 200, 201, 204 ), true ) ) {
$message = isset( $response_body['Message'] ) ? $response_body['Message'] : $result['body'];
throw new \Exception(
\esc_html( \__( 'Response code ', 'w3-total-cache' ) . $result['response']['code'] . ': ' . $message )
);
}
return \is_array( $response_body ) ? $response_body : array();
}
/**
* Remote GET request.
*
* @since X.X.X
*
* @link https://developer.wordpress.org/reference/functions/wp_remote_get/
* @link https://developer.wordpress.org/reference/classes/wp_http/request/
*
* @param string $url URL address.
* @param array $data Query string data for the GET request.
* @return array
*/
private function wp_remote_get( $url, array $data = array() ) {
$api_key = $this->get_api_key();
\add_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
\add_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
$result = \wp_remote_get(
$url . ( empty( $data ) ? '' : '?' . \http_build_query( $data ) ),
array(
'headers' => array(
'AccessKey' => $api_key,
'Accept' => 'application/json',
),
)
);
\remove_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
\remove_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
return self::decode_response( $result );
}
/**
* Remote POST request.
*
* @since X.X.X
*
* @link https://developer.wordpress.org/reference/functions/wp_remote_post/
* @link https://developer.wordpress.org/reference/classes/wp_http/request/
*
* @param string $url URL address.
* @param array $data Optional data for the POSt request.
* @param array $args Optional additional arguments for the wp_remote_port call.
* @return string
*/
private function wp_remote_post( $url, array $data = array(), array $args = array() ) {
$api_key = $this->get_api_key();
\add_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
\add_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
$result = \wp_remote_post(
$url,
\array_merge(
array(
'headers' => array(
'AccessKey' => $api_key,
'Accept' => 'application/json',
'Content-Type' => 'application/json',
),
'body' => empty( $data ) ? null : \json_encode( $data ),
),
$args
)
);
\remove_filter( 'https_ssl_verify', array( $this, 'https_ssl_verify' ) );
\remove_filter( 'http_request_timeout', array( $this, 'filter_timeout_time' ) );
return self::decode_response( $result );
}
}

View File

@ -0,0 +1,204 @@
<?php
/**
* File: Cdn_BunnyCdn_Page.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdn_BunnyCdn_Page
*
* @since X.X.X
*/
class Cdn_BunnyCdn_Page {
/**
* W3TC AJAX.
*
* @since X.X.X
* @static
*
* @return void
*/
public static function w3tc_ajax() {
$o = new Cdn_BunnyCdn_Page();
\add_action(
'w3tc_ajax_cdn_bunnycdn_purge_url',
array( $o, 'w3tc_ajax_cdn_bunnycdn_purge_url' )
);
}
/**
* Determine if CDN or CDNFSD is active.
*
* @since X.X.X
* @static
*
* @return bool
*/
public static function is_active() {
$config = Dispatcher::config();
$cdn_enabled = $config->get_boolean( 'cdn.enabled' );
$cdn_engine = $config->get_string( 'cdn.engine' );
$cdn_zone_id = $config->get_integer( 'cdn.bunnycdn.pull_zone_id' );
$cdnfsd_enabled = $config->get_boolean( 'cdnfsd.enabled' );
$cdnfsd_engine = $config->get_string( 'cdnfsd.engine' );
$cdnfsd_zone_id = $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' );
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
return ( $account_api_key &&
(
( $cdn_enabled && 'bunnycdn' === $cdn_engine && $cdn_zone_id ) ||
( $cdnfsd_enabled && 'bunnycdn' === $cdnfsd_engine && $cdnfsd_zone_id )
)
);
}
/**
* Add Dashboard actions.
*
* @since X.X.X
* @static
*
* @see self::in_active()
*
* @param array $actions Actions.
* @return array
*/
public static function w3tc_dashboard_actions( array $actions ) {
if ( self::is_active() ) {
$modules = Dispatcher::component( 'ModuleStatus' );
$can_empty_memcache = $modules->can_empty_memcache();
$can_empty_opcode = $modules->can_empty_opcode();
$can_empty_file = $modules->can_empty_file();
$can_empty_varnish = $modules->can_empty_varnish();
$actions[] = sprintf(
'<input type="submit" class="dropdown-item" name="w3tc_bunnycdn_flush_all_except_bunnycdn" value="%1$s"%2$s>',
esc_attr__( 'Empty All Caches Except Bunny CDN', 'w3-total-cache' ),
( ! $can_empty_memcache && ! $can_empty_opcode && ! $can_empty_file && ! $can_empty_varnish ) ? ' disabled="disabled"' : ''
);
}
return $actions;
}
/**
* Enqueue scripts.
*
* Called from plugin-admin.
*
* @since X.X.X
* @static
*
* @return void
*/
public static function admin_print_scripts_w3tc_cdn() {
$config = Dispatcher::config();
$is_authorized = ! empty( $config->get_string( 'cdn.bunnycdn.account_api_key' ) ) &&
( $config->get_string( 'cdn.bunnycdn.pull_zone_id' ) || $config->get_string( 'cdnfsd.bunnycdn.pull_zone_id' ) );
\wp_register_script(
'w3tc_cdn_bunnycdn',
\plugins_url( 'Cdn_BunnyCdn_Page_View.js', W3TC_FILE ),
array( 'jquery' ),
W3TC_VERSION
);
\wp_localize_script(
'w3tc_cdn_bunnycdn',
'W3TC_Bunnycdn',
array(
'is_authorized' => $is_authorized,
'lang' => array(
'empty_url' => \esc_html__( 'No URL specified', 'w3-total-cache' ),
'success_purging' => \esc_html__( 'Successfully purged URL', 'w3-total-cache' ),
'error_purging' => \esc_html__( 'Error purging URL', 'w3-total-cache' ),
'error_ajax' => \esc_html__( 'Error with AJAX', 'w3-total-cache' ),
),
)
);
\wp_enqueue_script( 'w3tc_cdn_bunnycdn' );
}
/**
* CDN settings.
*
* @since X.X.X
* @static
*
* @return void
*/
public static function w3tc_settings_cdn_boxarea_configuration() {
$config = Dispatcher::config();
include W3TC_DIR . '/Cdn_BunnyCdn_Page_View.php';
}
/**
* Display purge URLs page.
*
* @since X.X.X
* @static
*/
public static function w3tc_purge_urls_box() {
$config = Dispatcher::config();
include W3TC_DIR . '/Cdn_BunnyCdn_Page_View_Purge_Urls.php';
}
/**
* W3TC AJAX: Purge a URL.
*
* Purging a URL will remove the file from the CDN cache and re-download it from your origin server.
* Please enter the exact CDN URL of each individual file.
* You can also purge folders or wildcard files using * inside of the URL path.
* Wildcard values are not supported if using Perma-Cache.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_purge_url() {
$url = Util_Request::get_string( 'url' );
// Check if URL starts with "http", starts with a valid protocol, and passes a URL validation check.
if ( 0 !== \strpos( $url, 'http' ) || ! \preg_match( '~^http(s?)://(.+)~i', $url ) || ! \filter_var( $url, FILTER_VALIDATE_URL ) ) {
\wp_send_json_error(
array( 'error_message' => \esc_html__( 'Invalid URL', 'w3-total-cache' ) ),
400
);
}
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to delete pull zone.
try {
$api->purge(
array(
'url' => \esc_url( $url, array( 'http', 'https' ) ),
'async' => true,
)
);
} catch ( \Exception $ex ) {
\wp_send_json_error( array( 'error_message' => $ex->getMessage() ), 422 );
}
\wp_send_json_success();
}
/**
* Flush all caches except Bunny CDN.
*
* @since X.X.X
*/
public function w3tc_bunnycdn_flush_all_except_bunnycdn() {
Dispatcher::component( 'CacheFlush' )->flush_all( array( 'bunnycdn' => 'skip' ) );
Util_Admin::redirect( array( 'w3tc_note' => 'flush_all' ), true );
}
}

View File

@ -0,0 +1,249 @@
/**
* File: Cdn_BunnyCdn_Page_View.js
*
* @since X.X.X
* @package W3TC
*
* @global W3TC_Bunnycdn Localization array for info and language.
*/
jQuery(function($) {
/**
* Resize the popup modal.
*
* @param object o W3tc_Lightbox object.
*/
function w3tc_bunnycdn_resize(o) {
o.options.height = $('.w3tc_cdn_bunnycdn_form').height();
o.resize();
}
// Add event handlers.
$('body')
// Load the authorization form.
.on('click', '.w3tc_cdn_bunnycdn_authorize', function() {
W3tc_Lightbox.open({
id:'w3tc-overlay',
close: '',
width: 800,
height: 300,
url: ajaxurl +
'?action=w3tc_ajax&_wpnonce=' +
w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_intro',
callback: w3tc_bunnycdn_resize
});
})
// Sanitize the account API key input value.
.on('change', '#w3tc-account-api-key', function() {
var $this = $(this);
$this.val($.trim($this.val().replace(/[^a-z0-9-]/g, '')));
})
// Load the pull zone selection form.
.on('click', '.w3tc_cdn_bunnycdn_list_pull_zones', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_list_pull_zones';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_form', w3tc_bunnycdn_resize);
})
// Enable/disable (readonly) add pull zone form fields based on selection.
.on('change', '#w3tc-pull-zone-id', function() {
var $selected_option = $(this).find(':selected'),
$origin = $('#w3tc-origin-url'),
$name = $('#w3tc-pull-zone-name'),
$hostnames = $('#w3tc-custom-hostnames');
if ($(this).find(':selected').val() === '') {
// Enable the add pull zone fields with suggested or entered values.
$origin.val($origin.data('suggested')).prop('readonly', false);
$name.val($name.data('suggested')).prop('readonly', false);
$hostnames.val($hostnames.data('suggested')).prop('readonly', false);
} else {
// Disable the add pull zone fields and change values using the selected option.
$origin.prop('readonly', true).val($selected_option.data('origin'));
$name.prop('readonly', true).val($selected_option.data('name'));
$hostnames.prop('readonly', true).val($selected_option.data('custom-hostnames'));
}
// Update the hidden input field for the selected pull zone id from the select option value.
$('[name="pull_zone_id"]').val($selected_option.val());
// Update the hidden input field for the selected pull zone CDN hostname from the select option value.
$('[name="cdn_hostname"]').val($selected_option.data('cdn-hostname'));
})
// Sanitize the origin URL/IP input value.
.on('change', '#w3tc-origin-url', function() {
var $this = $(this);
$this.val($.trim($this.val().toLowerCase().replace(/[^a-z0-9\.:\/-]/g, '')));
})
// Sanitize the pull zone name input value.
.on('change', '#w3tc-pull-zone-name', function() {
var $this = $(this);
$this.val($.trim($this.val().toLowerCase().replace(/[^a-z0-9-]/g, '')));
})
// Sanitize the CDN hostname input value.
.on('change', '#w3tc_bunnycdn_hostname', function() {
var $this = $(this);
$this.val($.trim($this.val().toLowerCase().replace(/(^https?:|:.+$|[^a-z0-9\.-])/g, '')));
})
// Configure pull zone.
.on('click', '.w3tc_cdn_bunnycdn_configure_pull_zone', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_configure_pull_zone';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_form', w3tc_bunnycdn_resize);
})
// Close the popup success modal.
.on('click', '.w3tc_cdn_bunnycdn_done', function() {
window.location = window.location + '&';
})
// Load the deauthorize form.
.on('click', '.w3tc_cdn_bunnycdn_deauthorization', function() {
W3tc_Lightbox.open({
id:'w3tc-overlay',
close: '',
width: 800,
height: 300,
url: ajaxurl +
'?action=w3tc_ajax&_wpnonce=' +
w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_deauthorization',
callback: w3tc_bunnycdn_resize
});
})
// Deauthorize and optionally delete the pull zone.
.on('click', '.w3tc_cdn_bunnycdn_deauthorize', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_deauthorize';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_form', w3tc_bunnycdn_resize);
})
// Sanitize the purge URL list.
.on('focusout', '#w3tc-purge-urls', function () {
// Abort if Bunny CDN is not authorized.
if (! W3TC_Bunnycdn.is_authorized) {
return;
}
// Declare vars.
var $this = $(this),
$button = $('.w3tc_cdn_bunnycdn_purge_urls');
// Strip whitespace, newlines, and invalid characters.
$this.val( $this.val().replace(/^(\s)*(\r\n|\n|\r)/gm, '') );
$this.val($.trim($this.val().replace(/[^a-z0-9\.:\/\r\n*-]/g, '')));
// Enable the purge button.
$button.prop('disabled', false);
})
// Purge URLs.
.on('click', '.w3tc_cdn_bunnycdn_purge_urls', function() {
// Abort if Bunny CDN is not authorized.
if (! W3TC_Bunnycdn.is_authorized) {
return;
}
// Declare vars.
var urls_processed = 0,
list = $('#w3tc-purge-urls').val().split("\n").filter((v) => v != ''),
$messages = $('#w3tc-purge-messages'),
$this = $(this);
// Disable the button clicked and show a spinner.
$this
.prop('disabled', true)
.closest('p').addClass('lightbox-loader');
// Clear the messages div.
$messages.empty();
// Abort if nothing was submitted.
if (list.length < 1) {
$('<div/>', {
class: 'error',
text: W3TC_Bunnycdn.lang.empty_url + '.'
}).appendTo($messages);
$this.closest('p').removeClass('lightbox-loader');
return;
}
list.forEach(function(url, index, array) {
$.ajax({
method: 'POST',
url: ajaxurl,
data: {
_wpnonce: w3tc_nonce[0],
action: 'w3tc_ajax',
w3tc_action: 'cdn_bunnycdn_purge_url',
url: url
}
})
.done(function(response) {
// Possible success.
if (typeof response.success !== 'undefined') {
if (response.success) {
// Successful.
$('<div/>', {
class: 'updated',
text: W3TC_Bunnycdn.lang.success_purging + ' "' + url + '".'
}).appendTo($messages);
} else {
// Unsucessful.
$('<div/>', {
class: 'error',
text: W3TC_Bunnycdn.lang.error_purging + ' "' + url + '"; ' + response.data.error_message + '.'
}).appendTo($messages);
}
} else {
// Unknown error.
$('<div/>', {
class: 'error',
text: W3TC_Bunnycdn.lang.error_ajax + '.'
}).appendTo($messages);
}
})
.fail(function(response) {
// Failure; received a non-2xx/3xx HTTP status code.
if (typeof response.responseJSON !== 'undefined' && 'data' in response.responseJSON && 'error_message' in response.responseJSON.data) {
// An error message was passed in the response data.
$('<div/>', {
class: 'error',
text: W3TC_Bunnycdn.lang.error_purging + ' "' + url + '"; ' + response.responseJSON.data.error_message + '.'
}).appendTo($messages);
} else {
// Unknown error.
$('<div/>', {
class: 'error',
text: W3TC_Bunnycdn.lang.error_ajax + '.'
}).appendTo($messages);
}
})
.complete(function() {
urls_processed++;
// When requests are all complete, then remove the spinner.
if (urls_processed === array.length) {
$this.closest('p').removeClass('lightbox-loader');
}
});
});
});
});

View File

@ -0,0 +1,130 @@
<?php
/**
* File: Cdn_BunnyCdn_Page_View.php
*
* Bunny CDN settings page section view.
*
* @since X.X.X
* @package W3TC
*
* @param array $config W3TC configuration.
*/
namespace W3TC;
defined( 'W3TC' ) || die();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$is_authorized = ! empty( $account_api_key ) && $config->get_string( 'cdn.bunnycdn.pull_zone_id' );
$is_unavailable = ! empty( $account_api_key ) && $config->get_string( 'cdnfsd.bunnycdn.pull_zone_id' ); // CDN is unavailable if CDN FSD is authorized for Bunny CDN.
?>
<table class="form-table">
<tr>
<th style="width: 300px;">
<label>
<?php esc_html_e( 'Account API key authorization', 'w3-total-cache' ); ?>:
</label>
</th>
<td>
<?php if ( $is_authorized ) : ?>
<input class="w3tc_cdn_bunnycdn_deauthorization button-primary" type="button" value="<?php esc_attr_e( 'Deauthorize', 'w3-total-cache' ); ?>" />
<?php else : ?>
<input class="w3tc_cdn_bunnycdn_authorize button-primary" type="button" value="<?php esc_attr_e( 'Authorize', 'w3-total-cache' ); ?>"
<?php echo ( $is_unavailable ? 'disabled' : '' ); ?> />
<?php if ( $is_unavailable ) : ?>
<div class="notice notice-info">
<p>
<?php esc_html_e( 'CDN for objects cannot be authorized if full-site delivery is already configured.', 'w3-total-cache' ); ?>
</p>
</div>
<?php endif; ?>
<?php endif; ?>
</td>
</tr>
<?php if ( $is_authorized ) : ?>
<tr>
<th><label><?php esc_html_e( 'Pull zone name:', 'w3-total-cache' ); ?></label></th>
<td class="w3tc_config_value_text">
<?php echo esc_html( $config->get_string( 'cdn.bunnycdn.name' ) ); ?>
</td>
</tr>
<tr>
<th>
<label>
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Opening HTML acronym tag, 3: Closing HTML acronym tag.
esc_html__(
'Origin %1$sURL%3$s/%2$sIP%3$s address:',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Universal Resource Locator', 'w3-total-cache' ) . '">',
'<acronym title="' . esc_attr__( 'Internet Protocol', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</label>
</th>
<td class="w3tc_config_value_text">
<?php echo esc_html( $config->get_string( 'cdn.bunnycdn.origin_url' ) ); ?>
</td>
</tr>
<tr>
<th>
<label>
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Closing HTML acronym tag.
esc_html__(
'%1$sCDN%2$s hostname:',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</label>
</th>
<td class="w3tc_config_value_text">
<input id="w3tc_bunnycdn_hostname" type="text" name="cdn__bunnycdn__cdn_hostname"
value="<?php echo esc_html( $config->get_string( 'cdn.bunnycdn.cdn_hostname' ) ); ?>" size="100" />
<p class="description">
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Closing HTML acronym tag.
esc_html__(
'The %1$sCDN%2$s hostname is used in media links on pages. For example: example.b-cdn.net',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</p>
</td>
</tr>
<?php endif; ?>
</table>

View File

@ -0,0 +1,63 @@
<?php
/**
* File: Cdn_BunnyCdn_Page_View_Purge_Urls.php
*
* Bunny CDN settings purge URLs view.
*
* @since X.X.X
* @package W3TC
*
* @param array $config W3TC configuration.
*/
namespace W3TC;
defined( 'W3TC' ) || die;
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$is_authorized = ! empty( $account_api_key ) &&
( $config->get_string( 'cdn.bunnycdn.pull_zone_id' ) || $config->get_string( 'cdnfsd.bunnycdn.pull_zone_id' ) );
$placeholder = \esc_url( \home_url() . '/about-us' ) . "\r\n" . \esc_url( \home_url() . '/css/*' );
?>
<table class="form-table">
<tr>
<th style="width: 300px;">
<label>
<?php \esc_html_e( 'Purge URLs', 'w3-total-cache' ); ?>:
</label>
</th>
<td>
<textarea id="w3tc-purge-urls" class="w3tc-ignore-change" cols="60" rows="5"
placeholder="<?php echo \esc_html( $placeholder ); ?>" <?php echo ( $is_authorized ? '' : 'disabled' ); ?>></textarea>
<p><?php \esc_html_e( 'Purging a URL will remove the file from the CDN cache and re-download it from your origin server. Please enter the exact CDN URL of each individual file. You can also purge folders or wildcard files using * inside of the URL path. Wildcard values are not supported if using Perma-Cache.', 'w3-total-cache' ); ?></p>
<p>
<input class="w3tc_cdn_bunnycdn_purge_urls button-primary" type="button"
value="<?php \esc_attr_e( 'Purge URLs Now', 'w3-total-cache' ); ?>"
<?php echo ( $is_authorized ? '' : 'disabled' ); ?>/>
</p>
<?php
if ( ! $is_authorized ) :
echo wp_kses(
\sprintf(
// translators: 1: Opening HTML elements, 2: Name of the CDN service, 3: Closing HTML elements.
\esc_html__( '%1$sPlease configure %2$s in order to purge URLs.%3$s', 'w3-total-cache' ),
'<div class="notice notice-info"><p>',
'Bunny CDN',
'</p></div>'
),
array(
'div' => array(
'class' => array(),
),
'p' => array(),
)
);
else :
?>
<br />
<p><div id="w3tc-purge-messages"></div></p>
<?php endif; ?>
</td>
</tr>
</table>

View File

@ -0,0 +1,279 @@
<?php
/**
* File: Cdn_BunnyCdn_Popup.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdn_BunnyCdn_Popup
*
* @since X.X.X
*/
class Cdn_BunnyCdn_Popup {
/**
* W3TC AJAX.
*
* @since X.X.X
* @static
*
* @return void
*/
public static function w3tc_ajax() {
$o = new Cdn_BunnyCdn_Popup();
\add_action(
'w3tc_ajax_cdn_bunnycdn_intro',
array( $o, 'w3tc_ajax_cdn_bunnycdn_intro' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_list_pull_zones',
array( $o, 'w3tc_ajax_cdn_bunnycdn_list_pull_zones' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_configure_pull_zone',
array( $o, 'w3tc_ajax_cdn_bunnycdn_configure_pull_zone' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_deauthorization',
array( $o, 'w3tc_ajax_cdn_bunnycdn_deauthorization' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_deauthorize',
array( $o, 'w3tc_ajax_cdn_bunnycdn_deauthorize' )
);
}
/**
* W3TC AJAX: Render intro.
*
* @since X.X.X
*
* @return void
*/
public function w3tc_ajax_cdn_bunnycdn_intro() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
// Ask for an account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
)
);
}
/**
* W3TC AJAX: List pull zones.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_list_pull_zones() {
$account_api_key = Util_Request::get_string( 'account_api_key' );
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to retrieve pull zones.
try {
$pull_zones = $api->list_pull_zones();
} catch ( \Exception $ex ) {
// Reauthorize: Ask for a new account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
'error_message' => \esc_html( \__( 'Cannot list pull zones', 'w3-total-cache' ) . '; ' . $ex->getMessage() ),
)
);
}
// Save the account API key, if added or changed.
$config = Dispatcher::config();
if ( $config->get_string( 'cdn.bunnycdn.account_api_key' ) !== $account_api_key ) {
$config->set( 'cdn.bunnycdn.account_api_key', $account_api_key );
$config->save();
}
// Print the view.
$server_ip = ! empty( $_SERVER['SERVER_ADDR'] ) && \filter_var( \wp_unslash( $_SERVER['SERVER_ADDR'] ), FILTER_VALIDATE_IP ) ?
\filter_var( \wp_unslash( $_SERVER['SERVER_ADDR'] ), FILTER_SANITIZE_URL ) : null;
$details = array(
'pull_zones' => $pull_zones,
'suggested_origin_url' => \home_url(), // Suggested origin URL or IP.
'suggested_zone_name' => \substr( \str_replace( '.', '-', \parse_url( \home_url(), PHP_URL_HOST ) ), 0, 60 ), // Suggested pull zone name.
'pull_zone_id' => $config->get_integer( 'cdn.bunnycdn.pull_zone_id' ),
);
include W3TC_DIR . '/Cdn_BunnyCdn_Popup_View_Pull_Zones.php';
\wp_die();
}
/**
* W3TC AJAX: Configure pull zone.
*
* @since X.X.X
*
* @see Cdn_BunnyCdn_Api::get_default_edge_rules()
*/
public function w3tc_ajax_cdn_bunnycdn_configure_pull_zone() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$pull_zone_id = Util_Request::get_integer( 'pull_zone_id' );
$origin_url = Util_Request::get_string( 'origin_url' ); // Origin URL or IP.
$name = Util_Request::get_string( 'name' ); // Pull zone name.
$cdn_hostname = Util_Request::get_string( 'cdn_hostname' ); // Pull zone CDN hostname (system).
// If not selecting a pull zone. then create a new one.
if ( empty( $pull_zone_id ) ) {
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to create a new pull zone.
try {
$response = $api->add_pull_zone(
array(
'Name' => $name, // The name/hostname for the pull zone where the files will be accessible; only letters, numbers, and dashes.
'OriginUrl' => $origin_url, // Origin URL or IP (with optional port number).
'CacheErrorResponses' => true, // If enabled, bunny.net will temporarily cache error responses (304+ HTTP status codes) from your servers for 5 seconds to prevent DDoS attacks on your origin. If disabled, error responses will be set to no-cache.
'DisableCookies' => false, // Determines if the Pull Zone should automatically remove cookies from the responses.
'EnableTLS1' => false, // TLS 1.0 was deprecated in 2018.
'EnableTLS1_1' => false, // TLS 1.1 was EOL's on March 31,2020.
'ErrorPageWhitelabel' => true, // Any bunny.net branding will be removed from the error page and replaced with a generic term.
'OriginHostHeader' => \parse_url( \home_url(), PHP_URL_HOST ), // Sets the host header that will be sent to the origin.
'UseStaleWhileUpdating' => true, // Serve stale content while updating. If Stale While Updating is enabled, cache will not be refreshed if the origin responds with a non-cacheable resource.
'UseStaleWhileOffline' => true, // Serve stale content if the origin is offline.
)
);
$pull_zone_id = (int) $response['Id'];
$name = $response['Name'];
$cdn_hostname = $response['Hostnames'][0]['Value'];
} catch ( \Exception $ex ) {
// Reauthorize: Ask for a new account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
'error_message' => \esc_html( \__( 'Cannot select or add a pull zone', 'w3-total-cache' ) . '; ' . $ex->getMessage() ),
)
);
}
// Initialize an error messages array.
$error_messages = array();
// Add Edge Rules.
foreach ( Cdn_BunnyCdn_Api::get_default_edge_rules() as $edge_rule ) {
try {
$api->add_edge_rule( $edge_rule, $pull_zone_id );
} catch ( \Exception $ex ) {
$error_messages[] = sprintf(
// translators: 1: Edge Rule description/name.
\__( 'Could not add Edge Rule "%1$s".', 'w3-total-cache' ) . '; ',
\esc_html( $edge_rule['Description'] )
) . $ex->getMessage();
}
}
// Convert error messages array to a string.
$error_messages = \implode( "\r\n", $error_messages );
}
// Save configuration.
$config->set( 'cdn.bunnycdn.pull_zone_id', $pull_zone_id );
$config->set( 'cdn.bunnycdn.name', $name );
$config->set( 'cdn.bunnycdn.origin_url', $origin_url );
$config->set( 'cdn.bunnycdn.cdn_hostname', $cdn_hostname );
$config->save();
// Print success view.
include W3TC_DIR . '/Cdn_BunnyCdn_Popup_View_Configured.php';
\wp_die();
}
/**
* W3TC AJAX: Deauthorization form.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_deauthorization() {
$config = Dispatcher::config();
$origin_url = $config->get_string( 'cdn.bunnycdn.origin_url' ); // Origin URL or IP.
$name = $config->get_string( 'cdn.bunnycdn.name' ); // Pull zone name.
$cdn_hostname = $config->get_string( 'cdn.bunnycdn.cdn_hostname' ); // Pull zone CDN hostname.
$cdn_pull_zone_id = $config->get_integer( 'cdn.bunnycdn.pull_zone_id' ); // CDN pull zone id.
$cdnfsd_pull_zone_id = $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ); // CDN FSD pull zone id.
// Present details and ask to deauthorize and optionally delete the pull zone.
include W3TC_DIR . '/Cdn_BunnyCdn_Popup_View_Deauthorize.php';
\wp_die();
}
/**
* W3TC AJAX: Deauthorize.
*
* Deauthorize and optionally delete the pull zone.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_deauthorize() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$cdn_pull_zone_id = $config->get_integer( 'cdn.bunnycdn.pull_zone_id' ); // CDN pull zone id.
$cdnfsd_pull_zone_id = $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ); // CDN FSD pull zone id.
$delete_pull_zone = Util_Request::get_string( 'delete_pull_zone' );
// Delete pull zone, if requested.
if ( 'yes' === $delete_pull_zone ) {
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to delete pull zone.
try {
$api->delete_pull_zone( $cdn_pull_zone_id );
} catch ( \Exception $ex ) {
$delete_error_message = $ex->getMessage();
}
// If the same pull zone is used for FSD, then deauthorize that too.
if ( ! empty( $cdn_pull_zone_id ) && $cdn_pull_zone_id === $cdnfsd_pull_zone_id ) {
$config->set( 'cdnfsd.bunnycdn.pull_zone_id', null );
$config->set( 'cdnfsd.bunnycdn.name', null );
$config->set( 'cdnfsd.bunnycdn.origin_url', null );
$config->set( 'cdnfsd.bunnycdn.cdn_hostname', null );
}
}
$config->set( 'cdn.bunnycdn.pull_zone_id', null );
$config->set( 'cdn.bunnycdn.name', null );
$config->set( 'cdn.bunnycdn.origin_url', null );
$config->set( 'cdn.bunnycdn.cdn_hostname', null );
$config->save();
// Print success view.
include W3TC_DIR . '/Cdn_BunnyCdn_Popup_View_Deauthorized.php';
\wp_die();
}
/**
* Render intro.
*
* @since X.X.X
* @access private
*
* @param array $details {
* Details for the modal.
*
* @type string $account_api_key Account API key.
* @type string $error_message Error message (optional).
* }
*/
private function render_intro( array $details ) {
include W3TC_DIR . '/Cdn_BunnyCdn_Popup_View_Intro.php';
\wp_die();
}
}

View File

@ -0,0 +1,33 @@
<?php
/**
* File: Cdn_BunnyCdn_Popup_View_Configured.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<?php if ( ! empty( $error_messages ) ) : ?>
<div class="error">
<?php echo $error_messages; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php endif; ?>
<form class="w3tc_cdn_bunnycdn_form">
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Success', 'w3-total-cache' ) ); ?>
<div style="text-align: center">
<?php esc_html_e( 'A pull zone has been configured successfully', 'w3-total-cache' ); ?>.<br />
</div>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_done w3tc-button-save button-primary"
value="<?php esc_html_e( 'Done', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,62 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_Deauthorize.php
*
* Assists to deauthorize Bunny CDN as an objects CDN and optionally delete the pull zone.
*
* @since X.X.X
* @package W3TC
*
* @param Config $config W3TC configuration.
* @param string $origin_url Origin URL or IP.
* @param string $name Pull zone name.
* @param string $cdn_hostname CDN hostname.
* @param string $cdn_pull_zone_id CDN pull zone id.
* @param string $cdnfsd_pull_zone_id CDN FSD pull zone id.
*/
namespace W3TC;
defined( 'W3TC' ) || die;
// Determine if the same pull zone is used for CDN and CDN FSD. If so, then we'll show a message that it will deactivate both.
$is_same_zone = $cdn_pull_zone_id === $cdnfsd_pull_zone_id;
?>
<form class="w3tc_cdn_bunnycdn_form" method="post">
<input type="hidden" name="pull_zone_id" />
<div class="metabox-holder">
<?php Util_Ui::postbox_header( \esc_html__( 'Deauthorize pull zone', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<td><?php \esc_html_e( 'Name', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $name ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'Origin URL / IP', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $origin_url ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'CDN hostname', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $cdn_hostname ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'Delete', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-delete-zone" type="checkbox" name="delete_pull_zone" value="yes" /> Delete the pull zone
<?php if ( $is_same_zone ) : ?>
<p class="notice notice-warning">
<?php \esc_html_e( 'This same pull zone is used for full-site delivery. If you delete this pull zone, then full-site delivery will be deauthorized.', 'w3-total-cache' ); ?>
</p>
<?php endif; ?>
</td>
</tr>
</table>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_deauthorize w3tc-button-save button-primary"
value="<?php \esc_attr_e( 'Deauthorize', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,49 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_View_Deauthorized.php
*
* @since X.X.X
* @package W3TC
*
* @param Config $config W3TC configuration.
* @param string $delete_pull_zone Delete pull zon choice ("yes").
* @param string $delete_error_message An error message if there was an error trying to delete the pull zone. String already escaped.
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_form">
<?php if ( isset( $delete_error_message ) ) : ?>
<div class="error">
<?php
esc_html_e( 'An error occurred trying to delete the pull zone; ', 'w3-total-cache' );
echo $delete_error_message . '.'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</div>
<?php endif; ?>
<div class="metabox-holder">
<?php
Util_Ui::postbox_header(
esc_html__( 'Success', 'w3-total-cache' ) .
( isset( $delete_error_message ) ? esc_html__( ' (with an error)', 'w3-total-cache' ) : '' )
);
?>
<div style="text-align: center">
<p><?php esc_html_e( 'The objects CDN has been deauthorized', 'w3-total-cache' ); ?>.</p>
</div>
<?php if ( 'yes' === $delete_pull_zone && empty( $delete_error_message ) ) : ?>
<div style="text-align: center">
<p><?php esc_html_e( 'The pull zone has been deleted', 'w3-total-cache' ); ?>.</p>
</div>
<?php endif; ?>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_done w3tc-button-save button-primary"
value="<?php esc_html_e( 'Done', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,54 @@
<?php
/**
* File: Cdn_BunnyCdn_Popup_View_Intro.php
*
* Assists with configuring Bunny CDN as an object storage CDN.
* Asks to enter an account API key from the Bunny CDN main account.
*
* @since X.X.X
* @package W3TC
*
* @param array $details {
* Bunny CDN API configuration details.
*
* @type string $account_api_key Account API key.
* @type string $error_message Error message (optional). String already escaped.
* }
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_form">
<?php if ( isset( $details['error_message'] ) ) : ?>
<div class="error">
<?php echo $details['error_message']; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php endif; ?>
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Bunny CDN API Configuration', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<td><?php esc_html_e( 'Account API Key', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-account-api-key" name="account_api_key" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $details['account_api_key'] ); ?>" />
<p class="description">
<?php esc_html_e( 'To obtain your account API key,', 'w3-total-cache' ); ?>
<a target="_blank" href="<?php echo esc_url( W3TC_BUNNYCDN_SETTINGS_URL ); ?>"><?php esc_html_e( 'click here', 'w3-total-cache' ); ?></a>,
<?php esc_html_e( 'log in using the main account credentials, and paste the API key into the field above.', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<input type="button"
class="w3tc_cdn_bunnycdn_list_pull_zones w3tc-button-save button-primary"
value="<?php esc_attr_e( 'Next', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,137 @@
<?php
/**
* File: Cdn_BunnyCdn_Popup_Pull_Zones.php
*
* Assists with configuring Bunny CDN as an object storage CDN.
* A pull zone selection is presented along with a form to add a new pull zone.
*
* @since X.X.X
* @package W3TC
*
* @param string $account_api_key Account PI key.
* @parm Cdn_BunnyCdn_Api $api API class object.
* @param array $details {
* Bunny CDN API configuration details.
*
* @type array $pull_zones Pull zones.
* @type string $suggested_origin_url Suggested origin URL or IP.
* @type string $suggested_zone_name Suggested pull zone name.
* @type int $pull_zone_id Pull zone id.
* @type string $error_message Error message (optional).
* }
* @param string $server_ip Server IP address.
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_form" method="post">
<input type="hidden" name="pull_zone_id" />
<input type="hidden" name="cdn_hostname" />
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Select a pull zone', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<select id="w3tc-pull-zone-id">
<option value=""<?php echo empty( $details['pull_zone_id'] ) ? ' selected' : ''; ?>>Add a new pull zone</option>
<?php
if ( ! empty( $details['pull_zones'] ) ) {
// List pull zones for selection.
foreach ( $details['pull_zones'] as $pull_zone ) {
// Skip pull zones that are disabled or suspended.
if ( ! $pull_zone['Enabled'] || $pull_zone['Suspended'] ) {
continue;
}
// Get the CDN hostname and custom hostnames.
$cdn_hostname = '?';
$custom_hostnames = array();
// Get the CDN hostname. It should be the system hostname.
foreach ( $pull_zone['Hostnames'] as $hostname ) {
if ( ! empty( $hostname['Value'] ) ) {
if ( ! empty( $hostname['IsSystemHostname'] ) ) {
// CDN hostname (system); there should only be one.
$cdn_hostname = $hostname['Value'];
} else {
// Custom hostnames; 0 or more.
$custom_hostnames[] = $hostname['Value'];
}
}
}
// Determine the origin URL/IP.
$origin_url = empty( $pull_zone['OriginUrl'] ) ? $cdn_hostname : $pull_zone['OriginUrl'];
// Determine if the current option is selected.
$is_selected = isset( $details['pull_zone_id'] ) && $details['pull_zone_id'] === $pull_zone['Id'];
// Print the select option.
?>
<option value="<?php echo esc_attr( $pull_zone['Id'] ); ?>"
<?php echo $is_selected ? ' selected' : ''; ?>
data-origin="<?php echo esc_html( $origin_url ); ?>"
data-name="<?php echo esc_attr( $pull_zone['Name'] ); ?>"
data-cdn-hostname="<?php echo esc_attr( $cdn_hostname ); ?>"
data-custom-hostnames="<?php echo esc_attr( implode( ',', $custom_hostnames ) ); ?>">
<?php echo esc_attr( $pull_zone['Name'] ); ?>
(<?php echo esc_html( $origin_url ); ?>)
</option>
<?php
// If selected, then get the origin URL/IP and pull zone name.
if ( $is_selected ) {
$selected_origin_url = $origin_url;
$selected_name = $pull_zone['Name'];
$selected_custom_hostnames = implode( "\r\n", $custom_hostnames );
}
}
}
// Determine origin URL and pull zone name for the fields below.
$field_origin_url = isset( $selected_origin_url ) ? $selected_origin_url : $details['suggested_origin_url'];
$field_name = isset( $selected_name ) ? $selected_name : $details['suggested_zone_name'];
?>
</select>
</tr>
<tr>
<td><?php esc_html_e( 'Pull Zone Name', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-pull-zone-name" name="name" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $field_name ); ?>"
<?php echo ( empty( $details['pull_zone_id'] ) ? '' : 'readonly ' ); ?>
data-suggested="<?php echo esc_attr( $details['suggested_zone_name'] ); ?>" />
<p class="description">
<?php esc_html_e( 'Name of the pull zone (letters, numbers, and dashes). If empty, one will be automatically generated.', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
<tr>
<td><?php esc_html_e( 'Origin URL / IP', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-origin-url" name="origin_url" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $field_origin_url ); ?>"
<?php echo ( empty( $details['pull_zone_id'] ) ? '' : 'readonly ' ); ?>
data-suggested="<?php echo esc_attr( $details['suggested_origin_url'] ); ?>" />
<p class="description">
<?php
esc_html_e( 'Pull origin site URL or IP address.', 'w3-total-cache' );
if ( ! empty( $server_ip ) ) {
echo esc_html( ' ' . __( 'Detected server IP address', 'w3-total-cache' ) . ':' . $server_ip );
}
?>
</p>
</td>
</tr>
</table>
<p class="submit">
<input type="button"
class="w3tc_cdn_bunnycdn_configure_pull_zone w3tc-button-save button-primary"
value="<?php esc_attr_e( 'Apply', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,75 @@
<?php
/**
* File: Cdn_BunnyCdn_Widget.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdn_BunnyCdn_Widget
*
* @since X.X.X
*/
class Cdn_BunnyCdn_Widget {
/**
* Initialize the WP Admin Dashboard.
*
* @since X.X.X
*
* @return void
*/
public static function admin_init_w3tc_dashboard() {
$o = new Cdn_BunnyCdn_Widget();
add_action( 'admin_print_styles', array( $o, 'admin_print_styles' ) );
Util_Widget::add2(
'w3tc_bunnycdn',
2000,
'<div class="w3tc-widget-bunnycdn-logo"></div>',
array( $o, 'widget_form' ),
Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ),
'normal'
);
}
/**
* Print widget form.
*
* @since X.X.X
*
* return void
*/
public function widget_form() {
$c = Dispatcher::config();
$authorized = $c->get_string( 'cdn.engine' ) === 'bunnycdn' &&
( ! empty( $c->get_integer( 'cdn.bunnycdn.pull_zone_id' ) ) || ! empty( $c->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ) ) );
if ( $authorized ) {
include __DIR__ . DIRECTORY_SEPARATOR . 'Cdn_BunnyCdn_Widget_View_Authorized.php';
} else {
include __DIR__ . DIRECTORY_SEPARATOR . 'Cdn_BunnyCdn_Widget_View_Unauthorized.php';
}
}
/**
* Enqueue styles.
*
* @since X.X.X
*
* @return void
*/
public function admin_print_styles() {
wp_enqueue_style( 'w3tc-widget' );
wp_enqueue_style(
'w3tc-bunnycdn-widget',
plugins_url( 'Cdn_BunnyCdn_Widget_View.css', W3TC_FILE ),
array(),
W3TC_VERSION
);
}
}

View File

@ -0,0 +1,89 @@
.w3tc-widget-bunnycdn-logo {
width: 150px;
height: 50px;
background: url('pub/img/w3tc_bunnycdn_logo.svg') 0 8px no-repeat;
float: left;
}
.w3tc_bunnycdn_h4 {
text-align: center;
}
.w3tc_bunnycdn_summary_h4 {
text-align: center;
color: #8F8F8F;
text-align: left;
margin: 0;
}
.w3tc_bunnycdn_summary {
border-bottom: 1px solid #d2d2d2;
padding-left: 10px;
padding-right: 10px;
}
.w3tc_bunnycdn_wrapper {
margin-left: -10px;
margin-right: -10px;
}
.w3tc_bunnycdn_ul li {
margin-bottom: 3px;
padding: 0;
}
.w3tc_bunnycdn_summary_col1 {
display: block;
font-weight: bold;
width: 90px;
float:left;
}
.w3tc_bunnycdn_summary_col2 {
display: block;
font-weight: bold;
width: 80px;
float:left;
}
.w3tc_bunnycdn_tools {
margin-top:15px;
padding-left: 10px;
padding-right: 10px;
}
.w3tc_bunnycdn_tools li {
display:inline-block;
margin-right:10px;
}
.w3tc_bunnycdn_chart {
clear: both;
padding-left: 10px;
padding-right: 10px;
}
.w3tc_bunnycdn_chart p {
color:#8F8F8F;
margin:0;
}
.w3tc_bunnycdn_wrapper .button-secondary {
margin-bottom: 3px;
}
.w3tc_bunnycdn_signup_h4 {
text-align: left;
margin-bottom: 0;
padding-bottom: 0;
}
.w3tc_bunnycdn_signup p {
margin-top: 4px;
padding-top: 0;
}
.w3tc_bunnycdn_signup p span.desc {
color:#8F8F8F;
}

View File

@ -0,0 +1,59 @@
<?php
/**
* File: Cdn_BunnyCdn_Widget_View_Authorized.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<div id="bunnycdn-widget" class="bunnycdn-widget-base w3tc_bunnycdn_content">
<div class="w3tc_bunnycdn_wrapper">
<div class="w3tc_bunnycdn_tools">
<p>
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.header',
\sprintf(
// translators: 1 HTML acronym for Content Delivery Network (CDN).
\__( 'Your website performance is enhanced with Bunny.Net\'s (%1$s) service.', 'w3-total-cache' ),
'<acronym title="' . \__( 'Content Delivery Network', 'w3-total-cache' ) . '">' . \__( 'CDN', 'w3-total-cache' ) . '</acronym>'
)
);
?>
</p>
</div>
<div class="w3tc_bunnycdn_tools">
<ul class="w3tc_bunnycdn_ul">
<li><a class="button" href="<?php echo \esc_url( \wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&amp;w3tc_flush_cdn' ), 'w3tc' ) ); ?>"><?php \esc_html_e( 'Purge Cache', 'w3-total-cache' ); ?></a></li>
</ul>
<p>
<a target="_blank" href="<?php echo esc_url( W3TC_BUNNYCDN_CDN_URL ); ?>"><?php esc_html_e( 'Click here', 'w3-total-cache' ); ?></a>
<?php esc_html_e( 'to configure additional settings at Bunny.net.', 'w3-total-cache' ); ?>
</p>
<p>
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.existing',
\sprintf(
// translators: 1 HTML acronym for Content Delivery Network (CDN).
\__(
'If you need help configuring your %1$s, we also offer Premium Services to assist you.',
'w3-total-cache'
),
'<acronym title="' . \__( 'Content Delivery Network', 'w3-total-cache' ) . '">' . \__( 'CDN', 'w3-total-cache' ) . '</acronym>'
)
);
?>
</p>
<a class="button" href="<?php echo \esc_url( \wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_support' ), 'w3tc' ) ); ?>">
<?php \esc_html_e( 'Premium Services', 'w3-total-cache' ); ?>
</a>
</div>
</div>
</div>

View File

@ -0,0 +1,79 @@
<?php
/**
* File: Cdn_BunnyCdn_Widget_View_Unauthorized.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<div id="bunnycdn-widget" class="w3tc_bunnycdn_signup">
<?php if ( ! $c->get_boolean( 'cdn.enabled' ) ) : ?>
<p class="notice notice-error">
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.no_cdn',
\sprintf(
// translators: 1 HTML acronym for Content Delivery Network (CDN).
\__( 'W3 Total Cache has detected that you do not have a %1$s configured', 'w3-total-cache' ),
'<acronym title="' . \__( 'Content Delivery Network', 'w3-total-cache' ) . '">' . \__( 'CDN', 'w3-total-cache' ) . '</acronym>'
)
);
?>
</p>
<?php endif ?>
<p>
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.header',
\sprintf(
// translators: 1 HTML acronym for Content Delivery Network (CDN).
\__( 'Enhance your website performance by adding Bunny.Net\'s (%1$s) service to your site.', 'w3-total-cache' ),
'<acronym title="' . \__( 'Content Delivery Network', 'w3-total-cache' ) . '">' . \__( 'CDN', 'w3-total-cache' ) . '</acronym>'
)
);
?>
</p>
<h4 class="w3tc_bunnycdn_signup_h4"><?php \esc_html_e( 'New customer? Sign up now to speed up your site!', 'w3-total-cache' ); ?></h4>
<p>
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.works_magically',
\__( 'Bunny CDN works magically with W3 Total Cache to speed up your site around the world for as little as $1 per month.', 'w3-total-cache' )
);
?>
</p>
<a class="button-primary" href="<?php echo esc_url( W3TC_BUNNYCDN_SIGNUP_URL ); ?>" target="_blank">
<?php \esc_html_e( 'Sign Up Now ', 'w3-total-cache' ); ?>
</a>
<p>
<h4 class="w3tc_bunnycdn_signup_h4"><?php esc_html_e( 'Current customers', 'w3-total-cache' ); ?></h4>
<p>
<?php
w3tc_e(
'cdn.bunnycdn.widget.v2.existing',
\sprintf(
// translators: 1 HTML acronym for Content Delivery Network (CDN).
\__(
'If you\'re an existing Bunny CDN customer, enable %1$s and authorize. If you need help configuring your %1$s, we also offer Premium Services to assist you.',
'w3-total-cache'
),
'<acronym title="' . \__( 'Content Delivery Network', 'w3-total-cache' ) . '">' . \__( 'CDN', 'w3-total-cache' ) . '</acronym>'
)
);
?>
</p>
<a class="button-primary" href="<?php echo \esc_url( \wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_cdn' ), 'w3tc' ) ); ?>">
<?php \esc_html_e( 'Authorize', 'w3-total-cache' ); ?>
</a>
<a class="button" href="<?php echo \esc_url( \wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_support' ), 'w3tc' ) ); ?>">
<?php \esc_html_e( 'Premium Services', 'w3-total-cache' ); ?>
</a>
</div>

View File

@ -1,91 +1,107 @@
<?php <?php
/**
* File: Cdn_Core.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/** /**
* W3 Total Cache CDN Plugin * Class: Cdn_Core
*/
/**
* class Cdn_Core
*/ */
class Cdn_Core { class Cdn_Core {
/** /**
* Config * Config.
*
* @var Config
*/ */
private $_config = null; private $_config = null;
/**
* Debug.
*
* @var bool
*/
private $debug; private $debug;
/** /**
* Runs plugin * Constructor
*/ */
function __construct() { public function __construct() {
$this->_config = Dispatcher::config(); $this->_config = Dispatcher::config();
$this->debug = $this->_config->get_boolean( 'cdn.debug' ); $this->debug = $this->_config->get_boolean( 'cdn.debug' );
} }
/** /**
* Adds file to queue * Adds file to queue.
* *
* @param string $local_path * @param string $local_path Local path.
* @param string $remote_path * @param string $remote_path Remote path.
* @param integer $command * @param int $command Command number.
* @param string $last_error * @param string $last_error Last error.
* @return integer * @return int
*/ */
function queue_add( $local_path, $remote_path, $command, $last_error ) { public function queue_add( $local_path, $remote_path, $command, $last_error ) {
global $wpdb; global $wpdb;
$table = $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE; $table = $wpdb->base_prefix . W3TC_CDN_TABLE_QUEUE;
$rows = $wpdb->get_results( $wpdb->prepare( $rows = $wpdb->get_results(
'SELECT id, command '. $wpdb->prepare(
"FROM $table " . 'SELECT id, command FROM ' . $table . ' WHERE local_path = %s AND remote_path = %s', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
'WHERE local_path = %s AND remote_path = %s', $local_path,
$local_path, $remote_path ) ); $remote_path
)
);
$already_exists = false; $already_exists = false;
foreach ( $rows as $row ) { foreach ( $rows as $row ) {
if ( $row->command != $command ) if ( $row->command != $command ) {
$wpdb->query( $wpdb->prepare( $wpdb->query(
"DELETE FROM $table " . $wpdb->prepare(
'WHERE id = %d', $row->id ) ); 'DELETE FROM ' . $table . ' WHERE id = %d', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
else $row->id
)
);
} else {
$already_exists = true; $already_exists = true;
} }
}
if ( $already_exists ) if ( $already_exists ) {
return true; return true;
}
// insert if not yet there // Insert if not yet there.
return $wpdb->query( $wpdb->prepare( return $wpdb->query(
"INSERT INTO $table " . $wpdb->prepare(
'(local_path, remote_path, command, last_error, date) ' . 'INSERT INTO ' . $table . ' (local_path, remote_path, command, last_error, date) VALUES (%s, %s, %d, %s, NOW())', // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
'VALUES (%s, %s, %d, %s, NOW())', $local_path,
$local_path, $remote_path, $command, $last_error ) ); $remote_path,
$command,
$last_error
)
);
} }
/** /**
* Returns array of array('local_path' => '', 'remote_path' => '') for specified file * Returns array of array('local_path' => '', 'remote_path' => '') for specified file.
* *
* @param string $file * @param string $file File.
* @return array * @return array
*/ */
function get_files_for_upload( $file ) { public function get_files_for_upload( $file ) {
$files = array(); $files = array();
$upload_info = Util_Http::upload_info(); $upload_info = Util_Http::upload_info();
if ( $upload_info ) { if ( $upload_info ) {
$file = $this->normalize_attachment_file( $file ); $file = $this->normalize_attachment_file( $file );
$local_file = $upload_info['basedir'] . '/' . $file; $local_file = $upload_info['basedir'] . '/' . $file;
$parsed = parse_url( rtrim( $upload_info['baseurl'], '/' ) . '/' . $file );
$parsed = parse_url( rtrim( $upload_info['baseurl'], '/' ) .
'/' . $file );
$local_uri = $parsed['path']; $local_uri = $parsed['path'];
$remote_uri = $this->uri_to_cdn_uri( $local_uri ); $remote_uri = $this->uri_to_cdn_uri( $local_uri );
$remote_file = ltrim( $remote_uri, '/' ); $remote_file = ltrim( $remote_uri, '/' );
$files[] = $this->build_file_descriptor( $local_file, $remote_file ); $files[] = $this->build_file_descriptor( $local_file, $remote_file );
} }
@ -93,13 +109,13 @@ class Cdn_Core {
} }
/** /**
* Returns array of files from sizes array * Returns array of files from sizes array.
* *
* @param string $attached_file * @param string $attached_file Attached file.
* @param array $sizes * @param array $sizes Sizes.
* @return array * @return array
*/ */
function _get_sizes_files( $attached_file, $sizes ) { public function _get_sizes_files( $attached_file, $sizes ) {
$files = array(); $files = array();
$base_dir = Util_File::dirname( $attached_file ); $base_dir = Util_File::dirname( $attached_file );
@ -119,12 +135,12 @@ class Cdn_Core {
} }
/** /**
* Returns attachment files by metadata * Returns attachment files by metadata.
* *
* @param array $metadata * @param array $metadata Metadata.
* @return array * @return array
*/ */
function get_metadata_files( $metadata ) { public function get_metadata_files( $metadata ) {
$files = array(); $files = array();
if ( isset( $metadata['file'] ) && isset( $metadata['sizes'] ) ) { if ( isset( $metadata['file'] ) && isset( $metadata['sizes'] ) ) {
@ -135,25 +151,21 @@ class Cdn_Core {
} }
/** /**
* Returns attachment files by attachment ID * Returns attachment files by attachment id.
* *
* @param integer $attachment_id * @param int $attachment_id Attachment id.
* @return array * @return array
*/ */
function get_attachment_files( $attachment_id ) { public function get_attachment_files( $attachment_id ) {
$files = array(); $files = array();
/** // Get attached file.
* Get attached file
*/
$attached_file = get_post_meta( $attachment_id, '_wp_attached_file', true ); $attached_file = get_post_meta( $attachment_id, '_wp_attached_file', true );
if ( $attached_file != '' ) { if ( ! empty( $attached_file ) ) {
$files = array_merge( $files, $this->get_files_for_upload( $attached_file ) ); $files = array_merge( $files, $this->get_files_for_upload( $attached_file ) );
/** // Get backup sizes files.
* Get backup sizes files
*/
$attachment_backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true ); $attachment_backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
if ( is_array( $attachment_backup_sizes ) ) { if ( is_array( $attachment_backup_sizes ) ) {
@ -161,9 +173,7 @@ class Cdn_Core {
} }
} }
/** // Get files from metadata.
* Get files from metadata
*/
$attachment_metadata = get_post_meta( $attachment_id, '_wp_attachment_metadata', true ); $attachment_metadata = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
if ( is_array( $attachment_metadata ) ) { if ( is_array( $attachment_metadata ) ) {
@ -174,17 +184,17 @@ class Cdn_Core {
} }
/** /**
* Uploads files to CDN * Uploads files to CDN.
* *
* @param array $files * @param array $files Files.
* @param boolean $queue_failed * @param bool $queue_failed Is queue failed.
* @param array $results * @param array $results Results.
* @return boolean * @param int $timeout_time Timeout time.
* @return bool
*/ */
function upload( $files, $queue_failed, &$results, $timeout_time = NULL ) { public function upload( $files, $queue_failed, &$results, $timeout_time = null ) {
if ( $this->debug ) { if ( $this->debug ) {
Util_Debug::log( 'cdn', 'upload: ' . Util_Debug::log( 'cdn', 'upload: ' . json_encode( $files, JSON_PRETTY_PRINT ) );
json_encode( $files, JSON_PRETTY_PRINT ) );
} }
$cdn = $this->get_cdn(); $cdn = $this->get_cdn();
@ -197,7 +207,7 @@ class Cdn_Core {
if ( ! $return && $queue_failed ) { if ( ! $return && $queue_failed ) {
foreach ( $results as $result ) { foreach ( $results as $result ) {
if ( $result['result'] != W3TC_CDN_RESULT_OK ) { if ( W3TC_CDN_RESULT_OK !== $result['result'] ) {
$this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_UPLOAD, $result['error'] ); $this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_UPLOAD, $result['error'] );
} }
} }
@ -207,27 +217,26 @@ class Cdn_Core {
} }
/** /**
* Deletes files frrom CDN * Deletes files from CDN.
* *
* @param array $files * @param array $files Files.
* @param boolean $queue_failed * @param bool $queue_failed Is queue failed.
* @param array $results * @param array $results Results.
* @return boolean * @return bool
*/ */
function delete( $files, $queue_failed, &$results ) { public function delete( $files, $queue_failed, &$results ) {
$cdn = $this->get_cdn(); $cdn = $this->get_cdn();
@set_time_limit( $this->_config->get_integer( 'timelimit.cdn_delete' ) ); @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_delete' ) );
$return = $cdn->delete( $files, $results ); $return = $cdn->delete( $files, $results );
if ( $this->debug ) { if ( $this->debug ) {
Util_Debug::log( 'cdn', 'delete: ' . Util_Debug::log( 'cdn', 'delete: ' . json_encode( $files, JSON_PRETTY_PRINT ) );
json_encode( $files, JSON_PRETTY_PRINT ) );
} }
if ( ! $return && $queue_failed ) { if ( ! $return && $queue_failed ) {
foreach ( $results as $result ) { foreach ( $results as $result ) {
if ( $result['result'] != W3TC_CDN_RESULT_OK ) { if ( W3TC_CDN_RESULT_OK !== $result['result'] ) {
$this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_DELETE, $result['error'] ); $this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_DELETE, $result['error'] );
} }
} }
@ -237,21 +246,19 @@ class Cdn_Core {
} }
/** /**
* Purges files from CDN * Purges files from CDN.
* *
* @param array $files consisting of array('local_path'=>'', 'remote_path'=>'') * @param array $files Files; consisting of array( 'local_path'=>'', 'remote_path'=>'' ).
* @param boolean $queue_failed * @param array $results Results.
* @param array $results * @return bool
* @return boolean
*/ */
function purge( $files, &$results ) { public function purge( $files, &$results ) {
if ( $this->debug ) { if ( $this->debug ) {
Util_Debug::log( 'cdn', 'purge: ' . Util_Debug::log( 'cdn', 'purge: ' . json_encode( $files, JSON_PRETTY_PRINT ) );
json_encode( $files, JSON_PRETTY_PRINT ) );
} }
/** /**
* Purge varnish servers before mirror purging * Purge varnish servers before mirror purging.
*/ */
if ( Cdn_Util::is_engine_mirror( $this->_config->get_string( 'cdn.engine' ) ) && $this->_config->get_boolean( 'varnish.enabled' ) ) { if ( Cdn_Util::is_engine_mirror( $this->_config->get_string( 'cdn.engine' ) ) && $this->_config->get_boolean( 'varnish.enabled' ) ) {
$varnish = Dispatcher::component( 'Varnish_Flush' ); $varnish = Dispatcher::component( 'Varnish_Flush' );
@ -263,7 +270,7 @@ class Cdn_Core {
} }
/** /**
* Purge CDN * Purge CDN.
*/ */
$cdn = $this->get_cdn(); $cdn = $this->get_cdn();
@ -273,7 +280,7 @@ class Cdn_Core {
if ( ! $return ) { if ( ! $return ) {
foreach ( $results as $result ) { foreach ( $results as $result ) {
if ( $result['result'] != W3TC_CDN_RESULT_OK ) { if ( W3TC_CDN_RESULT_OK !== $result['result'] ) {
$this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_PURGE, $result['error'] ); $this->queue_add( $result['local_path'], $result['remote_path'], W3TC_CDN_COMMAND_PURGE, $result['error'] );
} }
} }
@ -283,31 +290,28 @@ class Cdn_Core {
} }
/** /**
* Purge CDN completely * Purge CDN completely.
* *
* @param unknown $results * @param unknown $results Results of the purge.
* @return mixed * @return mixed
*/ */
function purge_all( &$results ) { public function purge_all( &$results ) {
/**
* Purge CDN
*/
$cdn = $this->get_cdn(); $cdn = $this->get_cdn();
@set_time_limit( $this->_config->get_integer( 'timelimit.cdn_purge' ) ); @set_time_limit( $this->_config->get_integer( 'timelimit.cdn_purge' ) );
$return = $cdn->purge_all( $results ); return $cdn->purge_all( $results );
return $return;
} }
/** /**
* Queues file upload. * Queues file upload.
* Links wp_cron call to do that by the end of request processing
* *
* @param string $url * Links wp_cron call to do that by the end of request processing.
*
* @param string $url Url.
* @return void * @return void
*/ */
function queue_upload_url( $url ) { public function queue_upload_url( $url ) {
$docroot_filename = Util_Environment::url_to_docroot_filename( $url ); $docroot_filename = Util_Environment::url_to_docroot_filename( $url );
if ( is_null( $docroot_filename ) ) { if ( is_null( $docroot_filename ) ) {
return; return;
@ -315,22 +319,21 @@ class Cdn_Core {
$filename = Util_Environment::docroot_to_full_filename( $docroot_filename ); $filename = Util_Environment::docroot_to_full_filename( $docroot_filename );
$a = parse_url( $url ); $a = \parse_url( $url );
$uri = $a['path']; $remote_filename = $this->uri_to_cdn_uri( $a['path'] );
$remote_file_name = $this->uri_to_cdn_uri( $uri ); $this->queue_add( $filename, $remote_filename, W3TC_CDN_COMMAND_UPLOAD, 'Pending' );
$this->queue_add( $filename, $remote_file_name,
W3TC_CDN_COMMAND_UPLOAD, 'Pending' );
} }
/** /**
* Normalizes attachment file * Normalizes attachment file.
* *
* @param string $file * @param string $file Filename.
* @return string * @return string
*/ */
function normalize_attachment_file( $file ) { public function normalize_attachment_file( $file ) {
$upload_info = Util_Http::upload_info(); $upload_info = Util_Http::upload_info();
if ( $upload_info ) { if ( $upload_info ) {
$file = ltrim( str_replace( $upload_info['basedir'], '', $file ), '/\\' ); $file = ltrim( str_replace( $upload_info['basedir'], '', $file ), '/\\' );
$matches = null; $matches = null;
@ -344,9 +347,9 @@ class Cdn_Core {
} }
/** /**
* Returns CDN object * Returns CDN object.
*/ */
function get_cdn() { public function get_cdn() {
static $cdn = null; static $cdn = null;
if ( is_null( $cdn ) ) { if ( is_null( $cdn ) ) {
@ -363,7 +366,7 @@ class Cdn_Core {
'domain' => $c->get_array( 'cdn.akamai.domain' ), 'domain' => $c->get_array( 'cdn.akamai.domain' ),
'ssl' => $c->get_string( 'cdn.akamai.ssl' ), 'ssl' => $c->get_string( 'cdn.akamai.ssl' ),
'email_notification' => $c->get_array( 'cdn.akamai.email_notification' ), 'email_notification' => $c->get_array( 'cdn.akamai.email_notification' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -373,7 +376,7 @@ class Cdn_Core {
'token' => $c->get_string( 'cdn.att.token' ), 'token' => $c->get_string( 'cdn.att.token' ),
'domain' => $c->get_array( 'cdn.att.domain' ), 'domain' => $c->get_array( 'cdn.att.domain' ),
'ssl' => $c->get_string( 'cdn.att.ssl' ), 'ssl' => $c->get_string( 'cdn.att.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -384,7 +387,7 @@ class Cdn_Core {
'container' => $c->get_string( 'cdn.azure.container' ), 'container' => $c->get_string( 'cdn.azure.container' ),
'cname' => $c->get_array( 'cdn.azure.cname' ), 'cname' => $c->get_array( 'cdn.azure.cname' ),
'ssl' => $c->get_string( 'cdn.azure.ssl' ), 'ssl' => $c->get_string( 'cdn.azure.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -398,7 +401,7 @@ class Cdn_Core {
'cname' => $c->get_array( 'cdn.cf.cname' ), 'cname' => $c->get_array( 'cdn.cf.cname' ),
'ssl' => $c->get_string( 'cdn.cf.ssl' ), 'ssl' => $c->get_string( 'cdn.cf.ssl' ),
'public_objects' => $c->get_string( 'cdn.cf.public_objects' ), 'public_objects' => $c->get_string( 'cdn.cf.public_objects' ),
'compression' => $compression 'compression' => $compression,
); );
break; break;
@ -409,7 +412,7 @@ class Cdn_Core {
'id' => $c->get_string( 'cdn.cf2.id' ), 'id' => $c->get_string( 'cdn.cf2.id' ),
'cname' => $c->get_array( 'cdn.cf2.cname' ), 'cname' => $c->get_array( 'cdn.cf2.cname' ),
'ssl' => $c->get_string( 'cdn.cf2.ssl' ), 'ssl' => $c->get_string( 'cdn.cf2.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -420,7 +423,7 @@ class Cdn_Core {
'zones' => $c->get_array( 'cdn.cotendo.zones' ), 'zones' => $c->get_array( 'cdn.cotendo.zones' ),
'domain' => $c->get_array( 'cdn.cotendo.domain' ), 'domain' => $c->get_array( 'cdn.cotendo.domain' ),
'ssl' => $c->get_string( 'cdn.cotendo.ssl' ), 'ssl' => $c->get_string( 'cdn.cotendo.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -430,7 +433,7 @@ class Cdn_Core {
'token' => $c->get_string( 'cdn.edgecast.token' ), 'token' => $c->get_string( 'cdn.edgecast.token' ),
'domain' => $c->get_array( 'cdn.edgecast.domain' ), 'domain' => $c->get_array( 'cdn.edgecast.domain' ),
'ssl' => $c->get_string( 'cdn.edgecast.ssl' ), 'ssl' => $c->get_string( 'cdn.edgecast.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -445,7 +448,7 @@ class Cdn_Core {
'domain' => $c->get_array( 'cdn.ftp.domain' ), 'domain' => $c->get_array( 'cdn.ftp.domain' ),
'ssl' => $c->get_string( 'cdn.ftp.ssl' ), 'ssl' => $c->get_string( 'cdn.ftp.ssl' ),
'compression' => false, 'compression' => false,
'docroot' => Util_Environment::document_root() 'docroot' => Util_Environment::document_root(),
); );
break; break;
@ -453,20 +456,12 @@ class Cdn_Core {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$engine_config = array( $engine_config = array(
'client_id' => 'client_id' => $c->get_string( 'cdn.google_drive.client_id' ),
$c->get_string( 'cdn.google_drive.client_id' ), 'access_token' => $state->get_string( 'cdn.google_drive.access_token' ),
'access_token' => 'refresh_token' => $c->get_string( 'cdn.google_drive.refresh_token' ),
$state->get_string( 'cdn.google_drive.access_token' ), 'root_url' => $c->get_string( 'cdn.google_drive.folder.url' ),
'refresh_token' => 'root_folder_id' => $c->get_string( 'cdn.google_drive.folder.id' ),
$c->get_string( 'cdn.google_drive.refresh_token' ), 'new_access_token_callback' => array( $this, 'on_google_drive_new_access_token' ),
'root_url' =>
$c->get_string( 'cdn.google_drive.folder.url' ),
'root_folder_id' =>
$c->get_string( 'cdn.google_drive.folder.id' ),
'new_access_token_callback' => array(
$this,
'on_google_drive_new_access_token'
)
); );
break; break;
@ -474,16 +469,11 @@ class Cdn_Core {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$engine_config = array( $engine_config = array(
'domains' => 'domains' => $c->get_array( 'cdn.highwinds.host.domains' ),
$c->get_array( 'cdn.highwinds.host.domains' ), 'ssl' => $c->get_string( 'cdn.highwinds.ssl' ),
'ssl' => 'api_token' => $c->get_string( 'cdn.highwinds.api_token' ),
$c->get_string( 'cdn.highwinds.ssl' ), 'account_hash' => $c->get_string( 'cdn.highwinds.account_hash' ),
'api_token' => 'host_hash_code' => $c->get_string( 'cdn.highwinds.host.hash_code' ),
$c->get_string( 'cdn.highwinds.api_token' ),
'account_hash' =>
$c->get_string( 'cdn.highwinds.account_hash' ),
'host_hash_code' =>
$c->get_string( 'cdn.highwinds.host.hash_code' )
); );
break; break;
@ -493,7 +483,7 @@ class Cdn_Core {
'username' => $c->get_string( 'cdn.limelight.username' ), 'username' => $c->get_string( 'cdn.limelight.username' ),
'api_key' => $c->get_string( 'cdn.limelight.api_key' ), 'api_key' => $c->get_string( 'cdn.limelight.api_key' ),
'domains' => $c->get_array( 'cdn.limelight.host.domains' ), 'domains' => $c->get_array( 'cdn.limelight.host.domains' ),
'debug' => $c->get_string( 'cdn.debug' ) 'debug' => $c->get_string( 'cdn.debug' ),
); );
break; break;
@ -501,7 +491,7 @@ class Cdn_Core {
$engine_config = array( $engine_config = array(
'domain' => $c->get_array( 'cdn.mirror.domain' ), 'domain' => $c->get_array( 'cdn.mirror.domain' ),
'ssl' => $c->get_string( 'cdn.mirror.ssl' ), 'ssl' => $c->get_string( 'cdn.mirror.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -516,12 +506,8 @@ class Cdn_Core {
'service_id' => $c->get_string( 'cdn.rackspace_cdn.service.id' ), 'service_id' => $c->get_string( 'cdn.rackspace_cdn.service.id' ),
'service_protocol' => $c->get_string( 'cdn.rackspace_cdn.service.protocol' ), 'service_protocol' => $c->get_string( 'cdn.rackspace_cdn.service.protocol' ),
'domains' => $c->get_array( 'cdn.rackspace_cdn.domains' ), 'domains' => $c->get_array( 'cdn.rackspace_cdn.domains' ),
'access_state' => 'access_state' => $state->get_string( 'cdn.rackspace_cdn.access_state' ),
$state->get_string( 'cdn.rackspace_cdn.access_state' ), 'new_access_state_callback' => array( $this, 'on_rackspace_cdn_new_access_state' ),
'new_access_state_callback' => array(
$this,
'on_rackspace_cdn_new_access_state'
)
); );
break; break;
@ -536,12 +522,8 @@ class Cdn_Core {
'cname' => $c->get_array( 'cdn.rscf.cname' ), 'cname' => $c->get_array( 'cdn.rscf.cname' ),
'ssl' => $c->get_string( 'cdn.rscf.ssl' ), 'ssl' => $c->get_string( 'cdn.rscf.ssl' ),
'compression' => false, 'compression' => false,
'access_state' => 'access_state' => $state->get_string( 'cdn.rackspace_cf.access_state' ),
$state->get_string( 'cdn.rackspace_cf.access_state' ), 'new_access_state_callback' => array( $this, 'on_rackspace_cf_new_access_state' ),
'new_access_state_callback' => array(
$this,
'on_rackspace_cf_new_access_state'
)
); );
break; break;
@ -555,7 +537,7 @@ class Cdn_Core {
'cname' => $c->get_array( 'cdn.s3.cname' ), 'cname' => $c->get_array( 'cdn.s3.cname' ),
'ssl' => $c->get_string( 'cdn.s3.ssl' ), 'ssl' => $c->get_string( 'cdn.s3.ssl' ),
'public_objects' => $c->get_string( 'cdn.s3.public_objects' ), 'public_objects' => $c->get_string( 'cdn.s3.public_objects' ),
'compression' => $compression 'compression' => $compression,
); );
break; break;
@ -567,7 +549,7 @@ class Cdn_Core {
'cname' => $c->get_array( 'cdn.s3.cname' ), 'cname' => $c->get_array( 'cdn.s3.cname' ),
'ssl' => $c->get_string( 'cdn.s3.ssl' ), 'ssl' => $c->get_string( 'cdn.s3.ssl' ),
'compression' => $compression, 'compression' => $compression,
'api_host' => $c->get_string( 'cdn.s3_compatible.api_host' ) 'api_host' => $c->get_string( 'cdn.s3_compatible.api_host' ),
); );
break; break;
@ -577,7 +559,7 @@ class Cdn_Core {
'zone_id' => $c->get_integer( 'cdn.stackpath.zone_id' ), 'zone_id' => $c->get_integer( 'cdn.stackpath.zone_id' ),
'domain' => $c->get_array( 'cdn.stackpath.domain' ), 'domain' => $c->get_array( 'cdn.stackpath.domain' ),
'ssl' => $c->get_string( 'cdn.stackpath.ssl' ), 'ssl' => $c->get_string( 'cdn.stackpath.ssl' ),
'compression' => false 'compression' => false,
); );
break; break;
@ -592,19 +574,32 @@ class Cdn_Core {
'domain' => $c->get_array( 'cdn.stackpath2.domain' ), 'domain' => $c->get_array( 'cdn.stackpath2.domain' ),
'ssl' => $c->get_string( 'cdn.stackpath2.ssl' ), 'ssl' => $c->get_string( 'cdn.stackpath2.ssl' ),
'access_token' => $state->get_string( 'cdn.stackpath2.access_token' ), 'access_token' => $state->get_string( 'cdn.stackpath2.access_token' ),
'on_new_access_token' => array( 'on_new_access_token' => array( $this, 'on_stackpath2_new_access_token' ),
$this,
'on_stackpath2_new_access_token'
)
); );
break; break;
case 'bunnycdn':
$engine_config = array(
'account_api_key' => $c->get_string( 'cdn.bunnycdn.account_api_key' ),
'storage_api_key' => $c->get_string( 'cdn.bunnycdn.storage_api_key' ),
'stream_api_key' => $c->get_string( 'cdn.bunnycdn.stream_api_key' ),
'pull_zone_id' => $c->get_integer( 'cdn.bunnycdn.pull_zone_id' ),
'domain' => $c->get_string( 'cdn.bunnycdn.cdn_hostname' ),
);
break;
default:
$engine_config = array();
break;
} }
$engine_config = array_merge( $engine_config, array( $engine_config = array_merge(
$engine_config,
array(
'debug' => $c->get_boolean( 'cdn.debug' ), 'debug' => $c->get_boolean( 'cdn.debug' ),
'headers' => apply_filters( 'w3tc_cdn_config_headers', array() ) 'headers' => apply_filters( 'w3tc_cdn_config_headers', array() ),
) ); )
);
$cdn = CdnEngine::instance( $engine, $engine_config ); $cdn = CdnEngine::instance( $engine, $engine_config );
} }
@ -613,7 +608,9 @@ class Cdn_Core {
} }
/** /**
* Called when new access token is issued by cdnengine * Called when a new access token is issued by cdnengine.
*
* @param string $access_token Access token.
*/ */
public function on_google_drive_new_access_token( $access_token ) { public function on_google_drive_new_access_token( $access_token ) {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
@ -622,7 +619,9 @@ class Cdn_Core {
} }
/** /**
* Called when new access state is issued by cdnengine * Called when a new access state is issued by cdnengine
*
* @param string $access_state Access state.
*/ */
public function on_rackspace_cdn_new_access_state( $access_state ) { public function on_rackspace_cdn_new_access_state( $access_state ) {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
@ -631,7 +630,9 @@ class Cdn_Core {
} }
/** /**
* Called when new access state is issued by cdnengine * Called when a new access state is issued by cdnengine
*
* @param string $access_state Access state.
*/ */
public function on_rackspace_cf_new_access_state( $access_state ) { public function on_rackspace_cf_new_access_state( $access_state ) {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
@ -639,6 +640,11 @@ class Cdn_Core {
$state->save(); $state->save();
} }
/**
* Called when a new access token is issued by cdnengine.
*
* @param string $access_token Access token.
*/
public function on_stackpath2_new_access_token( $access_token ) { public function on_stackpath2_new_access_token( $access_token ) {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$state->set( 'cdn.stackpath2.access_token', $access_token ); $state->set( 'cdn.stackpath2.access_token', $access_token );
@ -646,73 +652,69 @@ class Cdn_Core {
} }
/** /**
* Convert relative file which is relative to ABSPATH (wp folder on disc) to path uri * Convert relative file which is relative to ABSPATH (wp folder on disc) to path uri.
* *
* @param unknown $file * @param string $file Filename.
* @return string * @return string
*/ */
function docroot_filename_to_uri( $file ) { public function docroot_filename_to_uri( $file ) {
$file = ltrim( $file, '/' ); $file = ltrim( $file, '/' );
// Translate multisite subsite uploads paths
$file = str_replace( basename( WP_CONTENT_DIR ) . '/blogs.dir/' .
Util_Environment::blog_id() . '/', '', $file );
return $file;
// Translate multisite subsite uploads paths.
return str_replace( basename( WP_CONTENT_DIR ) . '/blogs.dir/' . Util_Environment::blog_id() . '/', '', $file );
} }
/** /**
* Convert a relative path (relative to ABSPATH (wp folder on disc) into a absolute path * Convert a relative path (relative to ABSPATH (wp folder on disc) into a absolute path.
* *
* @param unknown $file * @param string $file Filename.
* @return string * @return string
*/ */
function docroot_filename_to_absolute_path( $file ) { public function docroot_filename_to_absolute_path( $file ) {
if ( is_file( $file ) ) if ( is_file( $file ) ) {
return $file; return $file;
}
if ( DIRECTORY_SEPARATOR != '/' ) if ( DIRECTORY_SEPARATOR != '/' ) {
$file = str_replace( '/', DIRECTORY_SEPARATOR, $file ); $file = str_replace( '/', DIRECTORY_SEPARATOR, $file );
}
return rtrim( Util_Environment::document_root(), '/\\' ) . return rtrim( Util_Environment::document_root(), '/\\' ) . DIRECTORY_SEPARATOR . ltrim( $file, '/\\' );
DIRECTORY_SEPARATOR . ltrim( $file, '/\\' );
} }
/** /**
* Convert local uri path to CDN type specific path * Convert local uri path to CDN type specific path.
* *
* @param unknown $local_uri_path * @param string $local_uri Local URI.
* @return string * @return string
*/ */
function uri_to_cdn_uri( $local_uri ) { public function uri_to_cdn_uri( $local_uri ) {
$local_uri = ltrim( $local_uri, '/' ); $local_uri = ltrim( $local_uri, '/' );
$remote_uri = $local_uri; $remote_uri = $local_uri;
if ( Util_Environment::is_wpmu() && defined( 'DOMAIN_MAPPING' ) && DOMAIN_MAPPING ) if ( Util_Environment::is_wpmu() && defined( 'DOMAIN_MAPPING' ) && DOMAIN_MAPPING ) {
$remote_uri = str_replace( site_url(), '', $local_uri ); $remote_uri = str_replace( site_url(), '', $local_uri );
}
$engine = $this->_config->get_string( 'cdn.engine' ); $engine = $this->_config->get_string( 'cdn.engine' );
if ( Cdn_Util::is_engine_mirror( $engine ) ) { if ( Cdn_Util::is_engine_mirror( $engine ) ) {
if ( Util_Environment::is_wpmu() && strpos( $local_uri, 'files' ) === 0 ) { if ( Util_Environment::is_wpmu() && strpos( $local_uri, 'files' ) === 0 ) {
$upload_dir = Util_Environment::wp_upload_dir(); $upload_dir = Util_Environment::wp_upload_dir();
$remote_uri = $this->abspath_to_relative_path( $remote_uri = $this->abspath_to_relative_path( dirname( $upload_dir['basedir'] ) ) . '/' . $local_uri;
dirname( $upload_dir['basedir'] ) ) . '/' . $local_uri;
} }
} } elseif ( Util_Environment::is_wpmu() &&
elseif ( Util_Environment::is_wpmu() &&
! Util_Environment::is_wpmu_subdomain() && ! Util_Environment::is_wpmu_subdomain() &&
Util_Environment::is_using_master_config() && Util_Environment::is_using_master_config() &&
Cdn_Util::is_engine_push( $engine ) ) { Cdn_Util::is_engine_push( $engine ) ) {
// in common config mode files are uploaded for network home url /**
// so mirror will not contain /subblog/ path in uri * In common config mode files are uploaded for network home url so mirror will not contain /subblog/ path in uri.
// * Since upload process is not blog-specific and wp-content/plugins/../*.jpg files are common.
// since upload process is not blog-specific and */
// wp-content/plugins/../*.jpg files are common
$home = trim( home_url( '', 'relative' ), '/' ) . '/'; $home = trim( home_url( '', 'relative' ), '/' ) . '/';
$network_home = trim( network_home_url( '', 'relative' ), '/' ) . '/'; $network_home = trim( network_home_url( '', 'relative' ), '/' ) . '/';
if ( $home != $network_home && if ( $home !== $network_home && substr( $local_uri, 0, strlen( $home ) ) === $home ) {
substr( $local_uri, 0, strlen( $home ) ) == $home ) {
$remote_uri = $network_home . substr( $local_uri, strlen( $home ) ); $remote_uri = $network_home . substr( $local_uri, strlen( $home ) );
} }
} }
@ -721,79 +723,63 @@ class Cdn_Core {
} }
/** /**
* Need to pass full URL and it's URI * Need to pass full URL and it's URI.
* URI passed to prevent redundant parsing, normally it's available for caller * URI passed to prevent redundant parsing, normally it's available for caller.
*
* @param string $url URL.
* @param string $path Path.
* @return string|null
**/ **/
function url_to_cdn_url( $url, $path ) { public function url_to_cdn_url( $url, $path ) {
$cdn = $this->get_cdn(); $cdn = $this->get_cdn();
$remote_path = $this->uri_to_cdn_uri( $path ); $remote_path = $this->uri_to_cdn_uri( $path );
$new_url = $cdn->format_url( $remote_path ); $new_url = $cdn->format_url( $remote_path );
if ( ! $new_url ) { if ( ! $new_url ) {
return null; return null;
} }
$is_engine_mirror = Cdn_Util::is_engine_mirror(
$this->_config->get_string( 'cdn.engine' ) );
$new_url = apply_filters( 'w3tc_cdn_url', $new_url, $url, $is_engine_mirror = Cdn_Util::is_engine_mirror( $this->_config->get_string( 'cdn.engine' ) );
$is_engine_mirror ); $new_url = apply_filters( 'w3tc_cdn_url', $new_url, $url, $is_engine_mirror );
return $new_url; return $new_url;
} }
/** /**
* Returns the sitepath for multisite subfolder or subdomain path for multisite subdomain * Takes an absolute path and converts to a relative path to root.
* *
* @return string * @param string $path Path.
*/
private function _get_multisite_url_identifier() {
if ( defined( 'DOMAIN_MAPPING' ) && DOMAIN_MAPPING ) {
$parsedUrl = parse_url( site_url() );
return $parsedUrl['host'];
} elseif ( Util_Environment::is_wpmu_subdomain() ) {
$parsedUrl = parse_url( Util_Environment::home_domain_root_url() );
$urlparts = explode( '.', $parsedUrl['host'] );
if ( sizeof( $urlparts ) > 2 ) {
$subdomain = array_shift( $urlparts );
return trim( $subdomain, '/' );
}
}
return trim( Util_Environment::site_url_uri(), '/' );
}
/**
* Taks an absolute path and converts to a relative path to root
*
* @param unknown $path
* @return mixed * @return mixed
*/ */
function abspath_to_relative_path( $path ) { public function abspath_to_relative_path( $path ) {
return str_replace( Util_Environment::document_root(), '', $path ); return str_replace( Util_Environment::document_root(), '', $path );
} }
/** /**
* Takes a root relative path and converts to a full uri * Takes a root relative path and converts to a full URI.
* *
* @param unknown $path * @param string $path Path.
* @return string * @return string
*/ */
function relative_path_to_url( $path ) { public function relative_path_to_url( $path ) {
$cdnuri = $this->docroot_filename_to_uri( ltrim( $path, "/" ) ); return rtrim( Util_Environment::home_domain_root_url(), '/' ) . '/' .
return rtrim( Util_Environment::home_domain_root_url(), "/" ) . '/' . $cdnuri; $this->docroot_filename_to_uri( ltrim( $path, '/' ) );
} }
/** /**
* Constructs a CDN file descriptor * Constructs a CDN file descriptor.
* *
* @param unknown $local_path * @param string $local_path Local path.
* @param unknown $remote_path * @param string $remote_path Remote path.
* @return array * @return array
*/ */
function build_file_descriptor( $local_path, $remote_path ) { public function build_file_descriptor( $local_path, $remote_path ) {
$file = array( 'local_path' => $local_path, $file = array(
'local_path' => $local_path,
'remote_path' => $remote_path, 'remote_path' => $remote_path,
'original_url' => $this->relative_path_to_url( $local_path ) ); 'original_url' => $this->relative_path_to_url( $local_path ),
);
$file = apply_filters( 'w3tc_build_cdn_file_array', $file ); return apply_filters( 'w3tc_build_cdn_file_array', $file );
return $file;
} }
} }

View File

@ -7,9 +7,7 @@
namespace W3TC; namespace W3TC;
if ( ! defined( 'W3TC' ) ) { defined( 'W3TC' ) || die;
die();
}
Util_Ui::postbox_header_tabs( Util_Ui::postbox_header_tabs(
wp_kses( wp_kses(
@ -50,6 +48,32 @@ Util_Ui::config_overloading_button(
?> ?>
<p> <p>
<?php <?php
if ( ! $cdn_enabled ) {
echo '&nbsp;' . wp_kses(
sprintf(
// translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag,
// translators: 3 opening HTML a tag, 4 closing HTML a tag.
__(
'If you do not have a %1$sCDN%2$s provider try Bunny CDN. %3$sSign up now to enjoy a special offer%4$s!',
'w3-total-cache'
),
'<acronym title="' . __( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>',
'<a href="' . esc_url( wp_nonce_url( Util_Ui::admin_url( 'admin.php?page=w3tc_dashboard&w3tc_cdn_bunnycdn_signup' ), 'w3tc' ) ) . '" target="_blank">',
'</a>'
),
array(
'acronym' => array(
'title' => array(),
),
'a' => array(
'href' => array(),
'target' => array(),
),
)
);
}
$config = Dispatcher::config(); $config = Dispatcher::config();
$cdn_engine = $config->get_string( 'cdn.engine' ); $cdn_engine = $config->get_string( 'cdn.engine' );
$cdnfsd_engine = $config->get_string( 'cdnfsd.engine' ); $cdnfsd_engine = $config->get_string( 'cdnfsd.engine' );
@ -61,14 +85,14 @@ Util_Ui::config_overloading_button(
<p> <p>
<?php <?php
// StackPath sunset is 12:00 am Central (UTC-6:00) on November, 22, 2023 (1700629200). // StackPath sunset is 12:00 am Central (UTC-6:00) on November, 22, 2023 (1700629200).
$date_time_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); $date_time_format = \get_option( 'date_format' ) . ' ' . \get_option( 'time_format' );
printf( \printf(
// translators: 1 StackPath sunset datetime. // translators: 1 StackPath sunset datetime.
__( \esc_html__(
'StackPath will cease operations at %1$s.', 'StackPath will cease operations at %1$s.',
'w3-total-cache' 'w3-total-cache'
), ),
wp_date( $date_time_format, '1700629200' ) \wp_date( $date_time_format, '1700629200' ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
); );
?> ?>
</p> </p>
@ -80,14 +104,14 @@ Util_Ui::config_overloading_button(
<p> <p>
<?php <?php
// HighWinds sunset is 12:00 am Central (UTC-6:00) on November, 22, 2023 (1700629200). // HighWinds sunset is 12:00 am Central (UTC-6:00) on November, 22, 2023 (1700629200).
$date_time_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); $date_time_format = \get_option( 'date_format' ) . ' ' . \get_option( 'time_format' );
printf( \printf(
// translators: 1 HighWinds sunset datetime. // translators: 1 HighWinds sunset datetime.
__( \esc_html__(
'HighWinds will cease operations at %1$s.', 'HighWinds will cease operations at %1$s.',
'w3-total-cache' 'w3-total-cache'
), ),
wp_date( $date_time_format, '1700629200' ) \wp_date( $date_time_format, '1700629200' ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
); );
?> ?>
</p> </p>
@ -108,7 +132,7 @@ Util_Ui::config_overloading_button(
// translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag, // translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag,
// translators: 3 opening HTML acronym tag, 4 closing acronym tag. // translators: 3 opening HTML acronym tag, 4 closing acronym tag.
__( __(
'Theme files, media library attachments, %1$sCSS%2$s, %3$sJS%4$s files etc will quickly for site visitors.', 'Theme files, media library attachments, %1$sCSS%2$s, and %3$sJS%4$s files will load quickly for site visitors.',
'w3-total-cache' 'w3-total-cache'
), ),
'<acronym title="' . __( 'Cascading Style Sheet', 'w3-total-cache' ) . '">', '<acronym title="' . __( 'Cascading Style Sheet', 'w3-total-cache' ) . '">',

View File

@ -1,11 +1,18 @@
<?php <?php
/**
* File: Cdn_Page.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/**
* Class: Cdn_Page
*/
class Cdn_Page extends Base_Page_Settings { class Cdn_Page extends Base_Page_Settings {
/** /**
* Current page * Current page.
* *
* @var string * @var string
*/ */
@ -16,39 +23,42 @@ class Cdn_Page extends Base_Page_Settings {
* *
* @return void * @return void
*/ */
function view() { public function view() {
$config = Dispatcher::config(); $config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$cdn_engine = $config->get_string( 'cdn.engine' ); $cdn_engine = $config->get_string( 'cdn.engine' );
$cdn_enabled = $config->get_boolean( 'cdn.enabled' ); $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
$is_cdn_authorized = ! empty( $account_api_key ) && ! empty( $config->get_string( 'cdn.bunnycdn.pull_zone_id' ) );
$cdnfsd_engine = $config->get_string( 'cdnfsd.engine' );
$cdnfsd_enabled = $config->get_boolean( 'cdnfsd.enabled' );
$is_cdnfsd_authorized = ! empty( $account_api_key ) && ! empty( $config->get_string( 'cdnfsd.bunnycdn.pull_zone_id' ) );
$cdn_mirror = Cdn_Util::is_engine_mirror( $cdn_engine ); $cdn_mirror = Cdn_Util::is_engine_mirror( $cdn_engine );
$cdn_mirror_purge_all = Cdn_Util::can_purge_all( $cdn_engine ); $cdn_mirror_purge_all = Cdn_Util::can_purge_all( $cdn_engine );
$cdn_common = Dispatcher::component( 'Cdn_Core' ); $cdn_common = Dispatcher::component( 'Cdn_Core' );
$cdn = $cdn_common->get_cdn(); $cdn = $cdn_common->get_cdn();
$cdn_supports_header = $cdn->headers_support() == W3TC_CDN_HEADER_MIRRORING; $cdn_supports_header = $cdn->headers_support() == W3TC_CDN_HEADER_MIRRORING;
$minify_enabled = ( $minify_enabled = (
$config->get_boolean( 'minify.enabled' ) && $config->get_boolean( 'minify.enabled' ) &&
Util_Rule::can_check_rules() && Util_Rule::can_check_rules() &&
$config->get_boolean( 'minify.rewrite' ) && $config->get_boolean( 'minify.rewrite' ) &&
( !$config->get_boolean( 'minify.auto' ) || ( ! $config->get_boolean( 'minify.auto' ) || Cdn_Util::is_engine_mirror( $config->get_string( 'cdn.engine' ) ) )
Cdn_Util::is_engine_mirror( $config->get_string( 'cdn.engine' ) ) ) ); );
$cookie_domain = $this->get_cookie_domain(); $cookie_domain = $this->get_cookie_domain();
$set_cookie_domain = $this->is_cookie_domain_enabled(); $set_cookie_domain = $this->is_cookie_domain_enabled();
// Required for Update Media Query String button // Required for Update Media Query String button.
$browsercache_enabled = $config->get_boolean( 'browsercache.enabled' ); $browsercache_enabled = $config->get_boolean( 'browsercache.enabled' );
$browsercache_update_media_qs = ( $config->get_boolean( 'browsercache.cssjs.replace' ) || $config->get_boolean( 'browsercache.other.replace' ) ); $browsercache_update_media_qs = ( $config->get_boolean( 'browsercache.cssjs.replace' ) || $config->get_boolean( 'browsercache.other.replace' ) );
include W3TC_INC_DIR . '/options/cdn.php'; include W3TC_INC_DIR . '/options/cdn.php';
} }
/** /**
* Returns cookie domain * Returns cookie domain.
* *
* @return string * @return string
*/ */
function get_cookie_domain() { public function get_cookie_domain() {
$site_url = get_option( 'siteurl' ); $site_url = get_option( 'siteurl' );
$parse_url = @parse_url( $site_url ); $parse_url = @parse_url( $site_url );
@ -60,11 +70,11 @@ class Cdn_Page extends Base_Page_Settings {
} }
/** /**
* Checks if COOKIE_DOMAIN is enabled * Checks if COOKIE_DOMAIN is enabled.
* *
* @return bool * @return bool
*/ */
function is_cookie_domain_enabled() { public function is_cookie_domain_enabled() {
$cookie_domain = $this->get_cookie_domain(); $cookie_domain = $this->get_cookie_domain();
return defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN == $cookie_domain; return defined( 'COOKIE_DOMAIN' ) && COOKIE_DOMAIN == $cookie_domain;

View File

@ -1,30 +0,0 @@
<?php
namespace W3TC;
if ( ! defined( 'W3TC' ) ) {
die();
}
?>
<?php require W3TC_INC_DIR . '/options/common/header.php'; ?>
<p>
<?php
echo wp_kses(
sprintf(
// translators: 1 HTML strong element with CDN engine content, 2 HTML span element with CDN enabled/disabled status.
__(
'Content Delivery Network support via %1$s is currently %2$s.',
'w3-total-cache'
),
'<strong>' . esc_html( Cache::engine_name( $config->get_string( 'cdn.engine' ) ) ) . '</strong>',
'<span class="w3tc-' . ( $config->get_boolean( 'cdn.enabled' ) ? 'enabled">' . __( 'enabled', 'w3-total-cache' ) : 'disabled">' . __( 'disabled', 'w3-total-cache' ) ) . '</span>'
),
array(
'strong' => array(),
'span' => array(
'class' => array(),
),
)
);
?>
</p>

View File

@ -1,211 +1,212 @@
<?php <?php
/**
* File: Cdn_Plugin_Admin.php
*
* @since X.X.X
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/**
* Class: Cdn_Plugin_Admin
*/
class Cdn_Plugin_Admin { class Cdn_Plugin_Admin {
function run() { /**
* Run.
*
* @return void
*/
public function run() {
$config_labels = new Cdn_ConfigLabels(); $config_labels = new Cdn_ConfigLabels();
add_filter( 'w3tc_config_labels', array( $config_labels, 'config_labels' ) ); \add_filter( 'w3tc_config_labels', array( $config_labels, 'config_labels' ) );
$c = Dispatcher::config(); $c = Dispatcher::config();
$cdn_engine = $c->get_string( 'cdn.engine' ); $cdn_engine = $c->get_string( 'cdn.engine' );
if ( $c->get_boolean( 'cdn.enabled' ) ) { if ( $c->get_boolean( 'cdn.enabled' ) ) {
$admin_notes = new Cdn_AdminNotes(); $admin_notes = new Cdn_AdminNotes();
add_filter( 'w3tc_notes', array( $admin_notes, 'w3tc_notes' ) ); \add_filter( 'w3tc_notes', array( $admin_notes, 'w3tc_notes' ) );
add_filter( 'w3tc_errors', array( $admin_notes, 'w3tc_errors' ) ); \add_filter( 'w3tc_errors', array( $admin_notes, 'w3tc_errors' ) );
if ( $c->get_boolean( 'cdn.admin.media_library' ) && if ( $c->get_boolean( 'cdn.admin.media_library' ) && $c->get_boolean( 'cdn.uploads.enable' ) ) {
$c->get_boolean( 'cdn.uploads.enable' ) ) { \add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 0 );
\add_filter( 'attachment_link', array( $this, 'wp_get_attachment_url' ), 0 );
add_filter( 'wp_get_attachment_url',
array( $this, 'wp_get_attachment_url' ), 0 );
add_filter( 'attachment_link',
array( $this, 'wp_get_attachment_url' ), 0 );
} }
} }
// Attach to actions without firing class loading at all without need.
// attach to actions without firing class loading at all without need switch ( $cdn_engine ) {
if ( $cdn_engine == 'google_drive' ) { case 'google_drive':
add_action( 'w3tc_settings_cdn_boxarea_configuration', array( \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_GoogleDrive_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'\W3TC\Cdn_GoogleDrive_Page', break;
'w3tc_settings_cdn_boxarea_configuration' case 'highwinds':
) ); \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_Highwinds_Popup', 'w3tc_ajax' ) );
} elseif ( $cdn_engine == 'highwinds' ) { \add_action( 'admin_init_w3tc_dashboard', array( '\W3TC\Cdn_Highwinds_Widget', 'admin_init_w3tc_dashboard' ) );
add_action( 'w3tc_ajax', array( \add_action( 'w3tc_ajax_cdn_highwinds_widgetdata', array( '\W3TC\Cdn_Highwinds_Widget', 'w3tc_ajax_cdn_highwinds_widgetdata' ) );
'\W3TC\Cdn_Highwinds_Popup', \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_Highwinds_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'w3tc_ajax' ) ); break;
add_action( 'admin_init_w3tc_dashboard', array( case 'limelight':
'\W3TC\Cdn_Highwinds_Widget', \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_LimeLight_Popup', 'w3tc_ajax' ) );
'admin_init_w3tc_dashboard' ) ); \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_LimeLight_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
add_action( 'w3tc_ajax_cdn_highwinds_widgetdata', array( break;
'\W3TC\Cdn_Highwinds_Widget', case 'rackspace_cdn':
'w3tc_ajax_cdn_highwinds_widgetdata' ) ); \add_filter( 'w3tc_admin_actions', array( '\W3TC\Cdn_RackSpaceCdn_Page', 'w3tc_admin_actions' ) );
add_action( 'w3tc_settings_cdn_boxarea_configuration', array( \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_RackSpaceCdn_Popup', 'w3tc_ajax' ) );
'\W3TC\Cdn_Highwinds_Page', \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_RackSpaceCdn_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'w3tc_settings_cdn_boxarea_configuration' ) ); break;
} elseif ( $cdn_engine == 'limelight' ) { case 'rscf':
add_action( 'w3tc_ajax', array( \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_RackSpaceCloudFiles_Popup', 'w3tc_ajax' ) );
'\W3TC\Cdn_LimeLight_Popup', \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_RackSpaceCloudFiles_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'w3tc_ajax' ) ); break;
add_action( 'w3tc_settings_cdn_boxarea_configuration', array( case 'stackpath':
'\W3TC\Cdn_LimeLight_Page', \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_StackPath_Popup', 'w3tc_ajax' ) );
'w3tc_settings_cdn_boxarea_configuration' \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_StackPath_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
) ); \add_action( 'admin_init_w3tc_dashboard', array( '\W3TC\Cdn_StackPath_Widget', 'admin_init_w3tc_dashboard' ) );
} elseif ( $cdn_engine == 'rackspace_cdn' ) { \add_action( 'w3tc_ajax_cdn_stackpath_widgetdata', array( '\W3TC\Cdn_StackPath_Widget', 'w3tc_ajax_cdn_stackpath_widgetdata' ) );
add_filter( 'w3tc_admin_actions', array( break;
'\W3TC\Cdn_RackSpaceCdn_Page', case 'stackpath2':
'w3tc_admin_actions' ) ); \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_StackPath2_Popup', 'w3tc_ajax' ) );
add_action( 'w3tc_ajax', array( \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_StackPath2_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'\W3TC\Cdn_RackSpaceCdn_Popup', \add_action( 'admin_init_w3tc_dashboard', array( '\W3TC\Cdn_StackPath2_Widget', 'admin_init_w3tc_dashboard' ) );
'w3tc_ajax' ) ); \add_action( 'w3tc_ajax_cdn_stackpath2_widgetdata', array( '\W3TC\Cdn_StackPath2_Widget', 'w3tc_ajax_cdn_stackpath2_widgetdata' ) );
add_action( 'w3tc_settings_cdn_boxarea_configuration', array( break;
'\W3TC\Cdn_RackSpaceCdn_Page', case 'bunnycdn':
'w3tc_settings_cdn_boxarea_configuration' ) ); \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_BunnyCdn_Page', 'w3tc_ajax' ) );
} elseif ( $cdn_engine == 'rscf' ) { \add_action( 'w3tc_ajax', array( '\W3TC\Cdn_BunnyCdn_Popup', 'w3tc_ajax' ) );
add_action( 'w3tc_ajax', array( \add_action( 'w3tc_settings_cdn_boxarea_configuration', array( '\W3TC\Cdn_BunnyCdn_Page', 'w3tc_settings_cdn_boxarea_configuration' ) );
'\W3TC\Cdn_RackSpaceCloudFiles_Popup', \add_action( 'admin_init_w3tc_dashboard', array( '\W3TC\Cdn_BunnyCdn_Widget', 'admin_init_w3tc_dashboard' ) );
'w3tc_ajax' ) ); \add_action( 'w3tc_ajax_cdn_bunnycdn_widgetdata', array( '\W3TC\Cdn_BunnyCdn_Widget', 'w3tc_ajax_cdn_bunnycdn_widgetdata' ) );
add_action( 'w3tc_settings_cdn_boxarea_configuration', array( \add_action( 'w3tc_purge_urls_box', array( '\W3TC\Cdn_BunnyCdn_Page', 'w3tc_purge_urls_box' ) );
'\W3TC\Cdn_RackSpaceCloudFiles_Page', // \add_filter( 'w3tc_dashboard_actions', array( '\W3TC\Cdn_BunnyCdn_Page', 'w3tc_dashboard_actions' ) ); // @todo Revisit this item.
'w3tc_settings_cdn_boxarea_configuration' ) ); break;
} elseif ( $cdn_engine == 'stackpath' ) { default:
add_action( 'w3tc_ajax', array( \add_action( 'admin_init_w3tc_dashboard', array( '\W3TC\Cdn_BunnyCdn_Widget', 'admin_init_w3tc_dashboard' ) );
'\W3TC\Cdn_StackPath_Popup', \add_action( 'w3tc_ajax_cdn_bunnycdn_widgetdata', array( '\W3TC\Cdn_BunnyCdn_Widget', 'w3tc_ajax_cdn_bunnycdn_widgetdata' ) );
'w3tc_ajax' ) ); break;
add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
'\W3TC\Cdn_StackPath_Page',
'w3tc_settings_cdn_boxarea_configuration'
) );
add_action( 'admin_init_w3tc_dashboard', array(
'\W3TC\Cdn_StackPath_Widget',
'admin_init_w3tc_dashboard' ) );
add_action( 'w3tc_ajax_cdn_stackpath_widgetdata', array(
'\W3TC\Cdn_StackPath_Widget',
'w3tc_ajax_cdn_stackpath_widgetdata' ) );
} elseif ( $cdn_engine == 'stackpath2' ) {
add_action( 'w3tc_ajax', array(
'\W3TC\Cdn_StackPath2_Popup',
'w3tc_ajax' ) );
add_action( 'w3tc_settings_cdn_boxarea_configuration', array(
'\W3TC\Cdn_StackPath2_Page',
'w3tc_settings_cdn_boxarea_configuration'
) );
add_action( 'admin_init_w3tc_dashboard', array(
'\W3TC\Cdn_StackPath2_Widget',
'admin_init_w3tc_dashboard' ) );
add_action( 'w3tc_ajax_cdn_stackpath2_widgetdata', array(
'\W3TC\Cdn_StackPath2_Widget',
'w3tc_ajax_cdn_stackpath2_widgetdata' ) );
} else {
// default cdn widget
add_action( 'admin_init_w3tc_dashboard', array(
'\W3TC\Cdn_StackPath2_Widget',
'admin_init_w3tc_dashboard' ) );
add_action( 'w3tc_ajax_cdn_stackpath2_widgetdata', array(
'\W3TC\Cdn_StackPath2_Widget',
'w3tc_ajax_cdn_stackpath2_widgetdata' ) );
} }
add_action( 'w3tc_settings_general_boxarea_cdn', array( \add_action( 'w3tc_settings_general_boxarea_cdn', array( $this, 'w3tc_settings_general_boxarea_cdn' ) );
$this,
'w3tc_settings_general_boxarea_cdn'
) );
} }
/**
* CDN settings.
*
* @return void
*/
public function w3tc_settings_general_boxarea_cdn() { public function w3tc_settings_general_boxarea_cdn() {
$config = Dispatcher::config(); $config = Dispatcher::config();
$engine_optgroups = array(); $engine_optgroups = array();
$engine_values = array(); $engine_values = array();
$optgroup_pull = count( $engine_optgroups ); $optgroup_pull = count( $engine_optgroups );
$engine_optgroups[] = __( 'Origin Pull / Mirror:', 'w3-total-cache' ); $engine_optgroups[] = \__( 'Origin Pull / Mirror:', 'w3-total-cache' );
$optgroup_push = count( $engine_optgroups ); $optgroup_push = count( $engine_optgroups );
$engine_optgroups[] = __( 'Origin Push:', 'w3-total-cache' ); $engine_optgroups[] = \__( 'Origin Push:', 'w3-total-cache' );
$engine_values[''] = array(
'label' => 'Select a provider',
);
$engine_values['akamai'] = array( $engine_values['akamai'] = array(
'label' => __( 'Akamai', 'w3-total-cache' ), 'label' => \__( 'Akamai', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['cf2'] = array( $engine_values['cf2'] = array(
'label' => __( 'Amazon CloudFront', 'w3-total-cache' ), 'label' => \__( 'Amazon CloudFront', 'w3-total-cache' ),
'disabled' => ( !Util_Installed::curl() ? true : null ), 'disabled' => ! Util_Installed::curl() ? true : null,
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['att'] = array( $engine_values['att'] = array(
'label' => __( 'AT&amp;T', 'w3-total-cache' ), 'label' => \__( 'AT&amp;T', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['bunnycdn'] = array(
'label' => \__( 'Bunny CDN (recommended)', 'w3-total-cache' ),
'optgroup' => $optgroup_pull,
);
$engine_values['cotendo'] = array( $engine_values['cotendo'] = array(
'label' => __( 'Cotendo (Akamai)', 'w3-total-cache' ), 'label' => \__( 'Cotendo (Akamai)', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['mirror'] = array( $engine_values['mirror'] = array(
'label' => __( 'Generic Mirror', 'w3-total-cache' ), 'label' => \__( 'Generic Mirror', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['highwinds'] = array( $engine_values['highwinds'] = array(
'label' => __( 'Highwinds', 'w3-total-cache' ), 'label' => \__( 'Highwinds', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['limelight'] = array( $engine_values['limelight'] = array(
'label' => __( 'LimeLight', 'w3-total-cache' ), 'label' => \__( 'LimeLight', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['rackspace_cdn'] = array( $engine_values['rackspace_cdn'] = array(
'label' => __( 'RackSpace CDN', 'w3-total-cache' ), 'label' => \__( 'RackSpace CDN', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['stackpath2'] = array( $engine_values['stackpath2'] = array(
'label' => __( 'StackPath (recommended)', 'w3-total-cache' ), 'label' => \__( 'StackPath', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['stackpath'] = array( $engine_values['stackpath'] = array(
'label' => __( 'StackPath SecureCDN (Legacy)', 'w3-total-cache' ), 'label' => \__( 'StackPath SecureCDN (Legacy)', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['edgecast'] = array( $engine_values['edgecast'] = array(
'label' => __( 'Verizon Digital Media Services (EdgeCast) / Media Temple ProCDN', 'w3-total-cache' ), 'label' => \__( 'Verizon Digital Media Services (EdgeCast) / Media Temple ProCDN', 'w3-total-cache' ),
'optgroup' => $optgroup_pull 'optgroup' => $optgroup_pull,
); );
$engine_values['cf'] = array( $engine_values['cf'] = array(
'disabled' => ( !Util_Installed::curl() ? true : null ), 'disabled' => ! Util_Installed::curl() ? true : null,
'label' => __( 'Amazon CloudFront Over S3', 'w3-total-cache' ), 'label' => \__( 'Amazon CloudFront Over S3', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['s3'] = array( $engine_values['s3'] = array(
'disabled' => ( !Util_Installed::curl() ? true : null ), 'disabled' => ! Util_Installed::curl() ? true : null,
'label' => __( 'Amazon Simple Storage Service (S3)', 'w3-total-cache' ), 'label' => \__( 'Amazon Simple Storage Service (S3)', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['s3_compatible'] = array( $engine_values['s3_compatible'] = array(
'disabled' => ( !Util_Installed::curl() ? true : null ), 'disabled' => ! Util_Installed::curl() ? true : null,
'label' => __( 'Amazon Simple Storage Service (S3) Compatible', 'w3-total-cache' ), 'label' => \__( 'Amazon Simple Storage Service (S3) Compatible', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['google_drive'] = array( $engine_values['google_drive'] = array(
'label' => __( 'Google Drive', 'w3-total-cache' ), 'label' => \__( 'Google Drive', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['azure'] = array( $engine_values['azure'] = array(
'label' => __( 'Microsoft Azure Storage', 'w3-total-cache' ), 'label' => \__( 'Microsoft Azure Storage', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['rscf'] = array( $engine_values['rscf'] = array(
'disabled' => ( !Util_Installed::curl() ? true : null ), 'disabled' => ! Util_Installed::curl() ? true : null,
'label' => __( 'Rackspace Cloud Files', 'w3-total-cache' ), 'label' => \__( 'Rackspace Cloud Files', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$engine_values['ftp'] = array( $engine_values['ftp'] = array(
'disabled' => ( !Util_Installed::ftp() ? true : null ), 'disabled' => ! Util_Installed::ftp() ? true : null,
'label' => __( 'Self-hosted / File Transfer Protocol Upload', 'w3-total-cache' ), 'label' => \__( 'Self-hosted / File Transfer Protocol Upload', 'w3-total-cache' ),
'optgroup' => $optgroup_push 'optgroup' => $optgroup_push,
); );
$cdn_enabled = $config->get_boolean( 'cdn.enabled' ); $cdn_enabled = $config->get_boolean( 'cdn.enabled' );
@ -214,28 +215,24 @@ class Cdn_Plugin_Admin {
include W3TC_DIR . '/Cdn_GeneralPage_View.php'; include W3TC_DIR . '/Cdn_GeneralPage_View.php';
} }
/** /**
* Adjusts attachment urls to cdn. This is for those who rely on * Adjusts attachment urls to cdn. This is for those who rely on wp_get_attachment_url().
* wp_get_attachment_url()
* *
* @param string $url the local url to modify * @param string $url The local url to modify.
* @return string * @return string
*/ */
function wp_get_attachment_url( $url ) { public function wp_get_attachment_url( $url ) {
if ( defined( 'WP_ADMIN' ) ) { if ( defined( 'WP_ADMIN' ) ) {
$url = trim( $url ); $url = trim( $url );
if ( ! empty( $url ) ) { if ( ! empty( $url ) ) {
$parsed = parse_url( $url ); $parsed = \parse_url( $url );
$uri = ( isset( $parsed['path'] ) ? $parsed['path'] : '/' ) . $uri = ( isset( $parsed['path'] ) ? $parsed['path'] : '/' ) .
( isset( $parsed['query'] ) ? '?' . $parsed['query'] : '' ); ( isset( $parsed['query'] ) ? '?' . $parsed['query'] : '' );
$wp_upload_dir = \wp_upload_dir();
$wp_upload_dir = wp_upload_dir();
$upload_base_url = $wp_upload_dir['baseurl']; $upload_base_url = $wp_upload_dir['baseurl'];
if ( substr($url, 0, strlen( $upload_base_url ) ) == $upload_base_url ) { if ( \substr( $url, 0, strlen( $upload_base_url ) ) === $upload_base_url ) {
$common = Dispatcher::component( 'Cdn_Core' ); $common = Dispatcher::component( 'Cdn_Core' );
$new_url = $common->url_to_cdn_url( $url, $uri ); $new_url = $common->url_to_cdn_url( $url, $uri );
if ( ! is_null( $new_url ) ) { if ( ! is_null( $new_url ) ) {

View File

@ -1,9 +1,14 @@
<?php <?php
/**
* File: Cdn_StackPath2_Page_View.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
if ( ! defined( 'W3TC' ) ) { defined( 'W3TC' ) || die;
die();
}
?> ?>
<tr> <tr>
<th style="width: 300px;"> <th style="width: 300px;">

View File

@ -49,7 +49,7 @@ class Cdn_StackPath2_Popup {
$api = new Cdn_StackPath2_Api( $api_config ); $api = new Cdn_StackPath2_Api( $api_config );
try { try {
$r = $r = $api->stacks_list(); $r = $api->stacks_list();
$stacks = $r['results']; $stacks = $r['results'];
} catch ( \Exception $ex ) { } catch ( \Exception $ex ) {
$error_message = 'Can\'t authenticate: ' . $ex->getMessage(); $error_message = 'Can\'t authenticate: ' . $ex->getMessage();

View File

@ -46,9 +46,10 @@ class Cdn_Util {
} }
/** /**
* Returns true if CDN engine is mirror * Returns true if CDN engine is mirror.
* *
* @param string $engine CDN engine. * @param string $engine CDN engine.
* @static
* *
* @return bool * @return bool
*/ */
@ -67,6 +68,7 @@ class Cdn_Util {
'rackspace_cdn', 'rackspace_cdn',
'stackpath', 'stackpath',
'stackpath2', 'stackpath2',
'bunnycdn',
), ),
true true
); );
@ -95,6 +97,7 @@ class Cdn_Util {
$engine, $engine,
array( array(
'att', 'att',
'bunnycdn',
'cf2', 'cf2',
'cotendo', 'cotendo',
'edgecast', 'edgecast',

View File

@ -0,0 +1,96 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Engine.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdnfsd_Bunny_Cdn_Engine
*
* @since X.X.X
*/
class Cdnfsd_BunnyCdn_Engine {
/**
* CDN configuration.
*
* @since X.X.X
*
* @var array
*/
private $config;
/**
* Constructor.
*
* @since X.X.X
*
* @param array $config CDN configuration.
*/
public function __construct( array $config = array() ) {
$this->config = $config;
}
/**
* Flush URLs.
*
* @since X.X.X
*
* @param array $urls URLs.
* @throws \Exception Exception.
* @return void
*/
public function flush_urls( array $urls ) {
if ( empty( $this->config['account_api_key'] ) ) {
throw new \Exception( esc_html__( 'Account API key not specified.', 'w3-total-cache' ) );
}
$api = new Cdn_BunnyCdn_Api( $this->config );
$items = array();
foreach ( $urls as $url ) {
$items[] = array(
'url' => $url,
'recursive' => true,
);
}
try {
$api->purge( array( 'items' => $items ) );
} catch ( \Exception $ex ) {
if ( $ex->getMessage() == 'Validation Failure: Purge url must contain one of your hostnames' ) {
throw new \Exception( esc_html__( 'CDN site is not configured correctly: Delivery Domain must match your site domain', 'w3-total-cache' ) );
} else {
throw $ex;
}
}
}
/**
* Flushes CDN completely.
*
* @since X.X.X
*
* @throws \Exception Exception.
*/
public function flush_all() {
if ( empty( $this->config['account_api_key'] ) ) {
throw new \Exception( \esc_html__( 'Account API key not specified.', 'w3-total-cache' ) );
}
if ( empty( $this->config['pull_zone_id'] ) || ! \is_int( $this->config['pull_zone_id'] ) ) {
throw new \Exception( \esc_html__( 'Invalid pull zone id.', 'w3-total-cache' ) );
}
$api = new Cdn_BunnyCdn_Api( $this->config );
try {
$r = $api->purge_pull_zone();
} catch ( \Exception $ex ) {
throw new \Exception( \esc_html( \__( 'Could not purge pull zone', 'w3-total-cache' ) . '; ' . $ex->getMessage() ) );
}
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Page.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdnfsd_BunnyCdn_Page
*
* @since X.X.X
*/
class Cdnfsd_BunnyCdn_Page {
/**
* Enqueue scripts.
*
* @since X.X.X
*/
public static function admin_print_scripts_performance_page_w3tc_cdn() {
wp_enqueue_script(
'w3tc_cdn_bunnycdn_fsd',
plugins_url( 'Cdnfsd_BunnyCdn_Page_View.js', W3TC_FILE ),
array( 'jquery' ),
'1.0'
);
}
/**
* Display settings page.
*
* @since X.X.X
*/
public static function w3tc_settings_box_cdnfsd() {
$config = Dispatcher::config();
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Page_View.php';
}
}

View File

@ -0,0 +1,126 @@
/**
* File: Cdnfsd_BunnyCdn_Page_View.js
*
* @since X.X.X
* @package W3TC
*/
jQuery(function($) {
/**
* Resize the popup modal.
*
* @param object o W3tc_Lightbox object.
*/
function w3tc_bunnycdn_resize(o) {
o.options.height = $('.w3tc_cdn_bunnycdn_fsd_form').height();
o.resize();
}
// Add event handlers.
$('body')
// Load the authorization form.
.on('click', '.w3tc_cdn_bunnycdn_fsd_authorize', function() {
W3tc_Lightbox.open({
id:'w3tc-overlay',
close: '',
width: 800,
height: 300,
url: ajaxurl +
'?action=w3tc_ajax&_wpnonce=' +
w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_fsd_intro',
callback: w3tc_bunnycdn_resize
});
})
// Sanitize the account API key input value.
.on('change', '#w3tc-account-api-key', function() {
var $this = $(this);
$this.val($.trim($this.val().replace(/[^a-z0-9-]/g, '')));
})
// Load the pull zone selection form.
.on('click', '.w3tc_cdn_bunnycdn_fsd_list_pull_zones', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_fsd_list_pull_zones';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_fsd_form', w3tc_bunnycdn_resize);
})
// Enable/disable (readonly) add pull zone form fields based on selection.
.on('change', '#w3tc-pull-zone-id', function() {
var $selected_option = $(this).find(':selected'),
$origin = $('#w3tc-origin-url'),
$name = $('#w3tc-pull-zone-name'),
$hostnames = $('#w3tc-custom-hostnames');
if ($(this).find(':selected').val() === '') {
// Enable the add pull zone fields with suggested or entered values.
$origin.val($origin.data('suggested')).prop('readonly', false);
$name.val($name.data('suggested')).prop('readonly', false);
$hostnames.val($hostnames.data('suggested')).prop('readonly', false);
} else {
// Disable the add pull zone fields and change values using the selected option.
$origin.prop('readonly', true).val($selected_option.data('origin'));
$name.prop('readonly', true).val($selected_option.data('name'));
$hostnames.prop('readonly', true).val($selected_option.data('custom-hostnames'));
}
// Update the hidden input field for the selected pull zone id from the select option value.
$('[name="pull_zone_id"]').val($selected_option.val());
// Update the hidden input field for the selected pull zone CDN hostname from the select option value.
$('[name="cdn_hostname"]').val($selected_option.data('cdn-hostname'));
})
// Sanitize the origin URL/IP input value.
.on('change', '#w3tc-origin-url', function() {
var $this = $(this);
$this.val($.trim($this.val().replace(/[^a-z0-9\.:\/-]/g, '')));
})
// Sanitize the pull zone name input value.
.on('change', '#w3tc-pull-zone-name', function() {
var $this = $(this);
$this.val($.trim($this.val().replace(/[^a-z0-9-]/g, '')));
})
// Configure pull zone.
.on('click', '.w3tc_cdn_bunnycdn_fsd_configure_pull_zone', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_fsd_configure_pull_zone';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_fsd_form', w3tc_bunnycdn_resize);
})
// Close the popup success modal.
.on('click', '.w3tc_cdn_bunnycdn_fsd_done', function() {
window.location = window.location + '&';
})
// Load the deauthorize form.
.on('click', '.w3tc_cdn_bunnycdn_fsd_deauthorization', function() {
W3tc_Lightbox.open({
id:'w3tc-overlay',
close: '',
width: 800,
height: 300,
url: ajaxurl +
'?action=w3tc_ajax&_wpnonce=' +
w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_fsd_deauthorization',
callback: w3tc_bunnycdn_resize
});
})
// Deauthorize and optionally delete the pull zone.
.on('click', '.w3tc_cdn_bunnycdn_fsd_deauthorize', function() {
var url = ajaxurl + '?action=w3tc_ajax&_wpnonce=' + w3tc_nonce +
'&w3tc_action=cdn_bunnycdn_fsd_deauthorize';
W3tc_Lightbox.load_form(url, '.w3tc_cdn_bunnycdn_fsd_form', w3tc_bunnycdn_resize);
});
});

View File

@ -0,0 +1,136 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Page_View.php
*
* @since X.X.X
* @package W3TC
*
* @param array $config W3TC configuration.
*/
namespace W3TC;
defined( 'W3TC' ) || die;
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$is_authorized = $account_api_key && $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' );
$is_unavailable = ! empty( $account_api_key ) && $config->get_string( 'cdn.bunnycdn.pull_zone_id' ); // CDN FSD is unavailable if CDN is authorized for Bunny CDN.
Util_Ui::postbox_header(
esc_html__( 'Configuration: Full-Site Delivery', 'w3-total-cache' ),
'',
'configuration-fsd'
);
?>
<table class="form-table">
<tr>
<th style="width: 300px;">
<label>
<?php esc_html_e( 'Account API key authorization', 'w3-total-cache' ); ?>:
</label>
</th>
<td>
<?php if ( $is_authorized ) : ?>
<input class="w3tc_cdn_bunnycdn_fsd_deauthorization button-primary" type="button" value="<?php esc_attr_e( 'Deauthorize', 'w3-total-cache' ); ?>" />
<?php else : ?>
<input class="w3tc_cdn_bunnycdn_fsd_authorize button-primary" type="button" value="<?php esc_attr_e( 'Authorize', 'w3-total-cache' ); ?>"
<?php echo ( $is_unavailable ? 'disabled' : '' ); ?> />
<?php if ( $is_unavailable ) : ?>
<div class="notice notice-info">
<p>
<?php esc_html_e( 'Full-site delivery cannot be authorized if CDN for objects is already configured.', 'w3-total-cache' ); ?>
</p>
</div>
<?php endif; ?>
<?php endif; ?>
</td>
</tr>
<?php if ( $is_authorized ) : ?>
<tr>
<th><label><?php esc_html_e( 'Pull zone name:', 'w3-total-cache' ); ?></label></th>
<td class="w3tc_config_value_text">
<?php echo esc_html( $config->get_string( 'cdnfsd.bunnycdn.name' ) ); ?>
</td>
</tr>
<tr>
<th>
<label>
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Opening HTML acronym tag, 3: Closing HTML acronym tag.
esc_html__(
'Origin %1$sURL%3$s/%2$sIP%3$s address:',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Universal Resource Locator', 'w3-total-cache' ) . '">',
'<acronym title="' . esc_attr__( 'Internet Protocol', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</label>
</th>
<td class="w3tc_config_value_text">
<?php echo esc_html( $config->get_string( 'cdnfsd.bunnycdn.origin_url' ) ); ?>
</td>
</tr>
<tr>
<th>
<label>
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Closing HTML acronym tag.
esc_html__(
'%1$sCDN%2$s hostname:',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</label>
</th>
<td class="w3tc_config_value_text">
<?php echo esc_html( $config->get_string( 'cdnfsd.bunnycdn.cdn_hostname' ) ); ?>
<p class="description">
<?php
echo wp_kses(
sprintf(
// translators: 1: Opening HTML acronym tag, 2: Opening HTML acronym tag, 3: Closing HTML acronym tag.
esc_html__(
'The website domain %1$sCNAME%3$s must point to the %2$sCDN%3$s hostname.',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Canonical Name', 'w3-total-cache' ) . '">',
'<acronym title="' . esc_attr__( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</p>
</td>
</tr>
<?php endif; ?>
</table>
<?php Util_Ui::postbox_footer(); ?>

View File

@ -0,0 +1,297 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
/**
* Class: Cdnfsd_BunnyCdn_Popup
*
* @since X.X.X
*/
class Cdnfsd_BunnyCdn_Popup {
/**
* W3TC AJAX: Popup.
*
* @since X.X.X
* @static
*
* @return void
*/
public static function w3tc_ajax() {
$o = new Cdnfsd_BunnyCdn_Popup();
\add_action(
'w3tc_ajax_cdn_bunnycdn_fsd_intro',
array( $o, 'w3tc_ajax_cdn_bunnycdn_fsd_intro' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_fsd_list_pull_zones',
array( $o, 'w3tc_ajax_cdn_bunnycdn_fsd_list_pull_zones' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_fsd_configure_pull_zone',
array( $o, 'w3tc_ajax_cdn_bunnycdn_fsd_configure_pull_zone' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_fsd_deauthorization',
array( $o, 'w3tc_ajax_cdn_bunnycdn_fsd_deauthorization' )
);
\add_action(
'w3tc_ajax_cdn_bunnycdn_fsd_deauthorize',
array( $o, 'w3tc_ajax_cdn_bunnycdn_fsd_deauthorize' )
);
}
/**
* W3TC AJAX: Intro -- authorization.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_fsd_intro() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
// Ask for an account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
)
);
}
/**
* W3TC AJAX: List pull zones.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_fsd_list_pull_zones() {
$account_api_key = Util_Request::get_string( 'account_api_key' );
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to retrieve pull zones.
try {
$pull_zones = $api->list_pull_zones();
} catch ( \Exception $ex ) {
// Reauthorize: Ask for a new account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
'error_message' => \esc_html( \__( 'Cannot list pull zones', 'w3-total-cache' ) . '; ' . $ex->getMessage() ),
)
);
}
// Save the account API key, if added or changed.
$config = Dispatcher::config();
if ( $config->get_string( 'cdn.bunnycdn.account_api_key' ) !== $account_api_key ) {
$config->set( 'cdn.bunnycdn.account_api_key', $account_api_key );
$config->save();
}
// Print the view.
$server_ip = ! empty( $_SERVER['SERVER_ADDR'] ) && \filter_var( \wp_unslash( $_SERVER['SERVER_ADDR'] ), FILTER_VALIDATE_IP ) ?
\filter_var( \wp_unslash( $_SERVER['SERVER_ADDR'] ), FILTER_SANITIZE_URL ) : null;
$suggested_origin_url = 'http' . ( \is_ssl() ? 's' : '' ) . '://' .
( empty( $server_ip ) ? \parse_url( \home_url(), PHP_URL_HOST ) : $server_ip );
$details = array(
'pull_zones' => $pull_zones,
'suggested_origin_url' => $suggested_origin_url, // Suggested origin URL or IP.
'suggested_zone_name' => \substr( \str_replace( '.', '-', \parse_url( \home_url(), PHP_URL_HOST ) ), 0, 60 ), // Suggested pull zone name.
'pull_zone_id' => $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ),
'suggested_custom_hostname' => \parse_url( \home_url(), PHP_URL_HOST ), // Suggested custom hostname.
);
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Popup_View_Pull_Zones.php';
\wp_die();
}
/**
* W3TC AJAX: Configure pull zone.
*
* @since X.X.X
*
* @see Cdn_BunnyCdn_Api::get_default_edge_rules()
*/
public function w3tc_ajax_cdn_bunnycdn_fsd_configure_pull_zone() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$pull_zone_id = Util_Request::get_integer( 'pull_zone_id' );
$origin_url = Util_Request::get_string( 'origin_url' ); // Origin URL or IP.
$name = Util_Request::get_string( 'name' ); // Pull zone name.
$cdn_hostname = Util_Request::get_string( 'cdn_hostname' ); // Pull zone CDN hostname (system).
$custom_hostnames = explode( ',', Util_Request::get_string( 'custom_hostnames' ) );
// If not selecting a pull zone. then create a new one.
if ( empty( $pull_zone_id ) ) {
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to create a new pull zone.
try {
$response = $api->add_pull_zone(
array(
'Name' => $name, // The name/hostname for the pull zone where the files will be accessible; only letters, numbers, and dashes.
'OriginUrl' => $origin_url, // Origin URL or IP (with optional port number).
'AddHostHeader' => true, // Determines if the zone should forward the requested host header to the origin.
'CacheErrorResponses' => true, // If enabled, bunny.net will temporarily cache error responses (304+ HTTP status codes) from your servers for 5 seconds to prevent DDoS attacks on your origin. If disabled, error responses will be set to no-cache.
'DisableCookies' => false, // Determines if the Pull Zone should automatically remove cookies from the responses.
'EnableTLS1' => false, // TLS 1.0 was deprecated in 2018.
'EnableTLS1_1' => false, // TLS 1.1 was EOL's on March 31,2020.
'ErrorPageWhitelabel' => true, // Any bunny.net branding will be removed from the error page and replaced with a generic term.
'UseStaleWhileUpdating' => true, // Serve stale content while updating. If Stale While Updating is enabled, cache will not be refreshed if the origin responds with a non-cacheable resource.
'UseStaleWhileOffline' => true, // Serve stale content if the origin is offline.
)
);
$pull_zone_id = (int) $response['Id'];
$name = $response['Name'];
$cdn_hostname = $response['Hostnames'][0]['Value'];
} catch ( \Exception $ex ) {
// Reauthorize: Ask for a new account API key.
$this->render_intro(
array(
'account_api_key' => empty( $account_api_key ) ? null : $account_api_key,
'error_message' => \esc_html( \__( 'Cannot select or add a pull zone', 'w3-total-cache' ) . '; ' . $ex->getMessage() ),
)
);
}
// Initialize an error messages array.
$error_messages = array();
// Add Edge Rules.
foreach ( Cdn_BunnyCdn_Api::get_default_edge_rules() as $edge_rule ) {
try {
$api->add_edge_rule( $edge_rule, $pull_zone_id );
} catch ( \Exception $ex ) {
$error_messages[] = sprintf(
// translators: 1: Edge Rule description/name.
\__( 'Could not add Edge Rule "%1$s".', 'w3-total-cache' ) . '; ',
\esc_html( $edge_rule['Description'] )
) . $ex->getMessage();
}
}
// Add custom hostnames, if any.
if ( ! empty( $custom_hostnames ) ) {
foreach ( $custom_hostnames as $custom_hostname ) {
try {
$api->add_custom_hostname( $custom_hostname, $pull_zone_id );
} catch ( \Exception $ex ) {
$error_messages[] = sprintf(
// translators: 1: hostname.
\__( 'Could not add custom hostname "%1$s"', 'w3-total-cache' ) . '; ',
\esc_html( $custom_hostname )
) . $ex->getMessage();
}
}
}
// Convert error messages array to a string.
$error_messages = implode( "\r\n", $error_messages );
}
// Save configuration.
$config->set( 'cdnfsd.bunnycdn.pull_zone_id', (int) $pull_zone_id );
$config->set( 'cdnfsd.bunnycdn.name', $name );
$config->set( 'cdnfsd.bunnycdn.origin_url', $origin_url );
$config->set( 'cdnfsd.bunnycdn.cdn_hostname', $cdn_hostname );
$config->save();
// Print success view.
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Popup_View_Configured.php';
\wp_die();
}
/**
* W3TC AJAX: Deauthorization form.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_fsd_deauthorization() {
$config = Dispatcher::config();
$origin_url = $config->get_string( 'cdnfsd.bunnycdn.origin_url' ); // Origin URL or IP.
$name = $config->get_string( 'cdnfsd.bunnycdn.name' ); // Pull zone name.
$cdn_hostname = $config->get_string( 'cdnfsd.bunnycdn.cdn_hostname' ); // Pull zone CDN hostname.
$cdn_pull_zone_id = $config->get_string( 'cdn.bunnycdn.pull_zone_id' ); // CDN pull zone id.
$cdnfsd_pull_zone_id = $config->get_string( 'cdnfsd.bunnycdn.pull_zone_id' ); // CDN FSD pull zone id.
// Present details and ask to deauthorize and optionally delete the pull zone.
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Popup_View_Deauthorize.php';
\wp_die();
}
/**
* W3TC AJAX: Deauthorize.
*
* Deauthorize and optionally delete the pull zone.
*
* @since X.X.X
*/
public function w3tc_ajax_cdn_bunnycdn_fsd_deauthorize() {
$config = Dispatcher::config();
$account_api_key = $config->get_string( 'cdn.bunnycdn.account_api_key' );
$cdn_pull_zone_id = $config->get_integer( 'cdn.bunnycdn.pull_zone_id' ); // CDN pull zone id.
$cdnfsd_pull_zone_id = $config->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ); // CDN FSD pull zone id.
$delete_pull_zone = Util_Request::get_string( 'delete_pull_zone' );
// Delete pull zone, if requested.
if ( 'yes' === $delete_pull_zone ) {
$api = new Cdn_BunnyCdn_Api( array( 'account_api_key' => $account_api_key ) );
// Try to delete pull zone.
try {
$api->delete_pull_zone( $cdnfsd_pull_zone_id );
} catch ( \Exception $ex ) {
$delete_error_message = $ex->getMessage();
}
// If the same pull zone is used for CDN Objects, then deauthorize that too.
if ( ! empty( $cdnfsd_pull_zone_id ) && $cdnfsd_pull_zone_id === $cdn_pull_zone_id ) {
$config->set( 'cdn.bunnycdn.pull_zone_id', null );
$config->set( 'cdn.bunnycdn.name', null );
$config->set( 'cdn.bunnycdn.origin_url', null );
$config->set( 'cdn.bunnycdn.cdn_hostname', null );
}
}
$config->set( 'cdnfsd.bunnycdn.pull_zone_id', null );
$config->set( 'cdnfsd.bunnycdn.name', null );
$config->set( 'cdnfsd.bunnycdn.origin_url', null );
$config->set( 'cdnfsd.bunnycdn.cdn_hostname', null );
$config->save();
// Print success view.
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Popup_View_Deauthorized.php';
\wp_die();
}
/**
* Render intro.
*
* @since X.X.X
* @access private
*
* @param array $details {
* Details for the modal.
*
* @type string $account_api_key Account API key.
* @type string $error_message Error message (optional).
* }
*/
private function render_intro( array $details ) {
include W3TC_DIR . '/Cdnfsd_BunnyCdn_Popup_View_Intro.php';
\wp_die();
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_View_Configured.php
*
* @since X.X.X
* @package W3TC
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<?php if ( ! empty( $error_messages ) ) : ?>
<div class="error">
<?php echo $error_messages; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php endif; ?>
<form class="w3tc_cdn_bunnycdn_fsd_form">
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Success', 'w3-total-cache' ) ); ?>
<div style="text-align: center">
<p>
<?php esc_html_e( 'A pull zone has been configured successfully.', 'w3-total-cache' ); ?>
</p>
<p>
<?php esc_html_e( 'There may be additional configuration required for full-site delivery, such as DNS changes and SSL/TLS certificate installation.', 'w3-total-cache' ); ?>
</p>
<p>
<a target="_blank" href="<?php echo esc_url( W3TC_BUNNYCDN_CDN_URL ); ?>"><?php esc_html_e( 'Click here', 'w3-total-cache' ); ?></a>
<?php esc_html_e( 'to configure additional settings for this pull zone at Bunny.net.', 'w3-total-cache' ); ?>
</p>
</div>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_fsd_done w3tc-button-save button-primary"
value="<?php esc_html_e( 'Done', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,62 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_Deauthorize.php
*
* Assists to deauthorize Bunny CDN as a full-site delivery CDN and optionally delete the pull zone.
*
* @since X.X.X
* @package W3TC
*
* @param Config $config W3TC configuration.
* @param string $origin_url Origin URL or IP.
* @param string $name Pull zone name.
* @param string $cdn_hostname CDN hostname.
* @param string $cdn_pull_zone_id CDN pull zone id.
* @param string $cdnfsd_pull_zone_id CDN FSD pull zone id.
*/
namespace W3TC;
defined( 'W3TC' ) || die;
// Determine if the same pull zone is used for CDN and CDN FSD. If so, then we'll show a message that it will deactivate both.
$is_same_zone = $cdn_pull_zone_id === $cdnfsd_pull_zone_id;
?>
<form class="w3tc_cdn_bunnycdn_fsd_form" method="post">
<input type="hidden" name="pull_zone_id" />
<div class="metabox-holder">
<?php Util_Ui::postbox_header( \esc_html__( 'Deauthorize pull zone', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<td><?php \esc_html_e( 'Name', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $name ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'Origin URL / IP', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $origin_url ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'CDN hostname', 'w3-total-cache' ); ?>:</td>
<td><?php echo \esc_html( $cdn_hostname ); ?></td>
</tr>
<tr>
<td><?php \esc_html_e( 'Delete', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-delete-zone" type="checkbox" name="delete_pull_zone" value="yes" /> Delete the pull zone
<?php if ( $is_same_zone ) : ?>
<p class="notice notice-warning">
<?php \esc_html_e( 'This same pull zone is used for full-site delivery. If you delete this pull zone, then full-site delivery will be deauthorized.', 'w3-total-cache' ); ?>
</p>
<?php endif; ?>
</td>
</tr>
</table>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_fsd_deauthorize w3tc-button-save button-primary"
value="<?php \esc_attr_e( 'Deauthorize', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,49 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_View_Deauthorized.php
*
* @since X.X.X
* @package W3TC
*
* @param Config $config W3TC configuration.
* @param string $delete_pull_zone Delete pull zon choice ("yes").
* @param string $delete_error_message An error message if there was an error trying to delete the pull zone. String already escaped.
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_fsd_form">
<?php if ( isset( $delete_error_message ) ) : ?>
<div class="error">
<?php
esc_html_e( 'An error occurred trying to delete the pull zone; ', 'w3-total-cache' );
echo $delete_error_message . '.'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</div>
<?php endif; ?>
<div class="metabox-holder">
<?php
Util_Ui::postbox_header(
esc_html__( 'Success', 'w3-total-cache' ) .
( isset( $delete_error_message ) ? esc_html__( ' (with an error)', 'w3-total-cache' ) : '' )
);
?>
<div style="text-align: center">
<p><?php esc_html_e( 'The full-site delivery has been deauthorized', 'w3-total-cache' ); ?>.</p>
</div>
<?php if ( 'yes' === $delete_pull_zone && empty( $delete_error_message ) ) : ?>
<div style="text-align: center">
<p><?php esc_html_e( 'The pull zone has been deleted', 'w3-total-cache' ); ?>.</p>
</div>
<?php endif; ?>
<p class="submit">
<input type="button" class="w3tc_cdn_bunnycdn_fsd_done w3tc-button-save button-primary"
value="<?php esc_html_e( 'Done', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,54 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_View_Intro.php
*
* Assists with configuring Bunny CDN as a full-site delivery CDN.
* Asks to enter an account API key from the Bunny CDN main account.
*
* @since X.X.X
* @package W3TC
*
* @param array $details {
* Bunny CDN API configuration details.
*
* @type string $account_api_key Account API key.
* @type string $error_message Error message (optional). String already escaped.
* }
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_fsd_form">
<?php if ( isset( $details['error_message'] ) ) : ?>
<div class="error">
<?php echo $details['error_message']; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php endif; ?>
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Bunny CDN API Configuration', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<td><?php esc_html_e( 'Account API Key', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-account-api-key" name="account_api_key" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $details['account_api_key'] ); ?>" />
<p class="description">
<?php esc_html_e( 'To obtain your account API key,', 'w3-total-cache' ); ?>
<a target="_blank" href="<?php echo esc_url( W3TC_BUNNYCDN_SETTINGS_URL ); ?>"><?php esc_html_e( 'click here', 'w3-total-cache' ); ?></a>,
<?php esc_html_e( 'log in using the main account credentials, and paste the API key into the field above.', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<input type="button"
class="w3tc_cdn_bunnycdn_fsd_list_pull_zones w3tc-button-save button-primary"
value="<?php esc_attr_e( 'Next', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -0,0 +1,140 @@
<?php
/**
* File: Cdnfsd_BunnyCdn_Popup_Pull_Zones.php
*
* Assists with configuring Bunny CDN as a full-site delivery CDN.
* A pull zone selection is presented along with a form to add a new pull zone.
*
* @since X.X.X
* @package W3TC
*
* @param array $details {
* Bunny CDN API configuration details.
*
* @type array $pull_zones Pull zones.
* @type string $error_message Error message (optional).
* }
*/
namespace W3TC;
defined( 'W3TC' ) || die();
?>
<form class="w3tc_cdn_bunnycdn_fsd_form" method="post">
<input type="hidden" name="pull_zone_id" />
<input type="hidden" name="cdn_hostname" />
<div class="metabox-holder">
<?php Util_Ui::postbox_header( esc_html__( 'Select a pull zone', 'w3-total-cache' ) ); ?>
<table class="form-table">
<tr>
<select id="w3tc-pull-zone-id">
<option value=""<?php echo empty( $details['pull_zone_id'] ) ? ' selected' : ''; ?>>Add a new pull zone</option>
<?php
if ( ! empty( $details['pull_zones'] ) ) {
// List pull zones for selection.
foreach ( $details['pull_zones'] as $pull_zone ) {
// Skip pull zones that are disabled or suspended.
if ( ! $pull_zone['Enabled'] || $pull_zone['Suspended'] ) {
continue;
}
// Get the CDN hostname and custom hostnames.
$cdn_hostname = '?';
$custom_hostnames = array();
foreach ( $pull_zone['Hostnames'] as $hostname ) {
// Get the CDN hostname. It should be the system hostname.
if ( ! empty( $hostname['Value'] ) ) {
if ( ! empty( $hostname['IsSystemHostname'] ) ) {
// CDN hostname (system); there should only be one.
$cdn_hostname = $hostname['Value'];
} else {
// Custom hostnames; 0 or more.
$custom_hostnames[] = $hostname['Value'];
}
}
}
// Determine the origin URL/IP.
$origin_url = empty( $pull_zone['OriginUrl'] ) ? $cdn_hostname : $pull_zone['OriginUrl'];
// Determine if the current option is selected.
$is_selected = isset( $details['pull_zone_id'] ) && $details['pull_zone_id'] === $pull_zone['Id'];
// Print the select option.
?>
<option value="<?php echo esc_attr( $pull_zone['Id'] ); ?>"
<?php echo $is_selected ? ' selected' : ''; ?>
data-origin="<?php echo esc_html( $origin_url ); ?>"
data-name="<?php echo esc_attr( $pull_zone['Name'] ); ?>"
data-cdn-hostname="<?php echo esc_attr( $cdn_hostname ); ?>"
data-custom-hostnames="<?php echo esc_attr( implode( ',', $custom_hostnames ) ); ?>">
<?php echo esc_attr( $pull_zone['Name'] ); ?>
(<?php echo esc_html( $origin_url ); ?>)
</option>
<?php
// If selected, then get the origin URL/IP and pull zone name.
if ( $is_selected ) {
$selected_origin_url = $origin_url;
$selected_name = $pull_zone['Name'];
$selected_custom_hostnames = implode( "\r\n", $custom_hostnames );
}
}
}
// Determine origin URL and pull zone name for the fields below.
$field_origin_url = isset( $selected_origin_url ) ? $selected_origin_url : $details['suggested_origin_url'];
$field_name = isset( $selected_name ) ? $selected_name : $details['suggested_zone_name'];
$field_custom_hostnames = isset( $selected_name ) ? $selected_name : $details['suggested_custom_hostname'];
?>
</select>
</tr>
<tr>
<td><?php esc_html_e( 'Pull Zone Name', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-pull-zone-name" name="name" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $field_name ); ?>"
<?php echo ( empty( $details['pull_zone_id'] ) ? '' : 'readonly ' ); ?>
data-suggested="<?php echo esc_attr( $details['suggested_zone_name'] ); ?>" />
<p class="description">
<?php esc_html_e( 'Name of the pull zone (letters, numbers, and dashes). If empty, one will be automatically generated.', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
<tr>
<td><?php esc_html_e( 'Origin URL / IP', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-origin-url" name="origin_url" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $field_origin_url ); ?>"
<?php echo ( empty( $details['pull_zone_id'] ) ? '' : 'readonly ' ); ?>
data-suggested="<?php echo esc_attr( $details['suggested_origin_url'] ); ?>" />
<p class="description">
<?php esc_html_e( 'Pull origin site URL or IP address.', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
<tr>
<td><?php esc_html_e( 'Custom Hostnames', 'w3-total-cache' ); ?>:</td>
<td>
<input id="w3tc-custom-hostnames" name="custom_hostnames" type="text" class="w3tc-ignore-change"
style="width: 550px" value="<?php echo esc_attr( $field_custom_hostnames ); ?>"
<?php echo ( empty( $details['pull_zone_id'] ) ? '' : 'readonly ' ); ?>
data-suggested="<?php echo esc_attr( $details['suggested_custom_hostname'] ); ?>" />
<p class="description">
<?php esc_html_e( 'Custom hostnames can be used instead of the default *.b-cdn.net hostname. After adding a hostname, create a CNAME record to the CDN hostname provided after the pull zone is configured.', 'w3-total-cache' ); ?>
<br />
<?php esc_html_e( '* Separate hostnames using commas (",").', 'w3-total-cache' ); ?>
</p>
</td>
</tr>
</table>
<p class="submit">
<input type="button"
class="w3tc_cdn_bunnycdn_fsd_configure_pull_zone w3tc-button-save button-primary"
value="<?php esc_attr_e( 'Apply', 'w3-total-cache' ); ?>" />
</p>
<?php Util_Ui::postbox_footer(); ?>
</div>
</form>

View File

@ -1,14 +1,23 @@
<?php <?php
/**
* File: Cdnfsd_Core.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/** /**
* Core for FSD CDN * Core for FSD CDN.
*/ */
class Cdnfsd_Core { class Cdnfsd_Core {
/** /**
* Returns CDN object * Get the CDN engine object.
*
* @returns object
* @throws \Exception Exception.
*/ */
function get_engine() { public function get_engine() {
static $engine_object = null; static $engine_object = null;
if ( is_null( $engine_object ) ) { if ( is_null( $engine_object ) ) {
@ -17,45 +26,54 @@ class Cdnfsd_Core {
switch ( $engine ) { switch ( $engine ) {
case 'cloudflare': case 'cloudflare':
$engine_object = null; // extension handles everything $engine_object = null; // Extension handles everything.
break; break;
case 'transparentcdn': case 'transparentcdn':
$engine_object = new Cdnfsd_TransparentCDN_Engine( array( $engine_object = new Cdnfsd_TransparentCDN_Engine(
array(
'company_id' => $c->get_string( 'cdnfsd.transparentcdn.company_id' ), 'company_id' => $c->get_string( 'cdnfsd.transparentcdn.company_id' ),
'client_id' => $c->get_string( 'cdnfsd.transparentcdn.client_id' ), 'client_id' => $c->get_string( 'cdnfsd.transparentcdn.client_id' ),
'client_secret' => $c->get_string( 'cdnfsd.transparentcdn.client_secret' ) 'client_secret' => $c->get_string( 'cdnfsd.transparentcdn.client_secret' ),
) ); )
);
break; break;
case 'cloudfront': case 'cloudfront':
$engine_object = new Cdnfsd_CloudFront_Engine( array( $engine_object = new Cdnfsd_CloudFront_Engine(
array(
'access_key' => $c->get_string( 'cdnfsd.cloudfront.access_key' ), 'access_key' => $c->get_string( 'cdnfsd.cloudfront.access_key' ),
'secret_key' => $c->get_string( 'cdnfsd.cloudfront.secret_key' ), 'secret_key' => $c->get_string( 'cdnfsd.cloudfront.secret_key' ),
'distribution_id' => $c->get_string( 'cdnfsd.cloudfront.distribution_id' ) 'distribution_id' => $c->get_string( 'cdnfsd.cloudfront.distribution_id' ),
) ); )
);
break; break;
case 'limelight': case 'limelight':
$engine_object = new Cdnfsd_LimeLight_Engine( array( $engine_object = new Cdnfsd_LimeLight_Engine(
array(
'short_name' => $c->get_string( 'cdnfsd.limelight.short_name' ), 'short_name' => $c->get_string( 'cdnfsd.limelight.short_name' ),
'username' => $c->get_string( 'cdnfsd.limelight.username' ), 'username' => $c->get_string( 'cdnfsd.limelight.username' ),
'api_key' => $c->get_string( 'cdnfsd.limelight.api_key' ), 'api_key' => $c->get_string( 'cdnfsd.limelight.api_key' ),
'debug' => $c->get_string( 'cdnfsd.debug' ) 'debug' => $c->get_string( 'cdnfsd.debug' ),
) ); )
);
break; break;
case 'stackpath': case 'stackpath':
$engine_object = new Cdnfsd_StackPath_Engine( array( $engine_object = new Cdnfsd_StackPath_Engine(
array(
'api_key' => $c->get_string( 'cdnfsd.stackpath.api_key' ), 'api_key' => $c->get_string( 'cdnfsd.stackpath.api_key' ),
'zone_id' => $c->get_integer( 'cdnfsd.stackpath.zone_id' ) 'zone_id' => $c->get_integer( 'cdnfsd.stackpath.zone_id' ),
) ); )
);
break; break;
case 'stackpath2': case 'stackpath2':
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$engine_object = new Cdnfsd_StackPath2_Engine( array( $engine_object = new Cdnfsd_StackPath2_Engine(
array(
'client_id' => $c->get_string( 'cdnfsd.stackpath2.client_id' ), 'client_id' => $c->get_string( 'cdnfsd.stackpath2.client_id' ),
'client_secret' => $c->get_string( 'cdnfsd.stackpath2.client_secret' ), 'client_secret' => $c->get_string( 'cdnfsd.stackpath2.client_secret' ),
'stack_id' => $c->get_string( 'cdnfsd.stackpath2.stack_id' ), 'stack_id' => $c->get_string( 'cdnfsd.stackpath2.stack_id' ),
@ -63,22 +81,34 @@ class Cdnfsd_Core {
'domain' => $c->get_array( 'cdnfsd.stackpath2.domain' ), 'domain' => $c->get_array( 'cdnfsd.stackpath2.domain' ),
'ssl' => $c->get_string( 'cdnfsd.stackpath2.ssl' ), 'ssl' => $c->get_string( 'cdnfsd.stackpath2.ssl' ),
'access_token' => $state->get_string( 'cdnfsd.stackpath2.access_token' ), 'access_token' => $state->get_string( 'cdnfsd.stackpath2.access_token' ),
'on_new_access_token' => array( 'on_new_access_token' => array( $this, 'on_stackpath2_new_access_token' ),
$this,
'on_stackpath2_new_access_token'
) )
) ); );
break;
case 'bunnycdn':
$engine_object = new Cdnfsd_BunnyCdn_Engine(
array(
'account_api_key' => $c->get_string( 'cdn.bunnycdn.account_api_key' ),
'pull_zone_id' => $c->get_integer( 'cdnfsd.bunnycdn.pull_zone_id' ),
),
);
break; break;
default: default:
throw new \Exception( 'unknown engine ' . $engine ); throw new \Exception( esc_html( __( 'Unknown engine', 'w3-total-cache' ) . ' ' . $engine ) );
break;
} }
} }
return $engine_object; return $engine_object;
} }
/**
* Save new StackPath access token.
*
* @param string $access_token Access token.
*/
public function on_stackpath2_new_access_token( $access_token ) { public function on_stackpath2_new_access_token( $access_token ) {
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$state->set( 'cdnfsd.stackpath2.access_token', $access_token ); $state->set( 'cdnfsd.stackpath2.access_token', $access_token );

View File

@ -7,9 +7,8 @@
namespace W3TC; namespace W3TC;
if ( ! defined( 'W3TC' ) ) { defined( 'W3TC' ) || die;
die();
}
?> ?>
<p> <p>
<?php <?php

View File

@ -1,29 +0,0 @@
<?php
namespace W3TC;
if ( ! defined( 'W3TC' ) ) {
die();
}
?>
<p>
<?php
echo wp_kses(
sprintf(
// translators: 1 HTML strong tag containing CDNFSD engine name, 2 HTML span tag containing CDNFSD engine enabled/disabled.
__(
'Content Delivery Network support via %1$s is currently %2$s.',
'w3-total-cache'
),
'<strong>' . Cdnfsd_Util::engine_name( $config->get_string( 'cdnfsd.engine' ) ) . '</strong>',
'<span class="w3tc-' . ( $config->get_boolean( 'cdnfsd.enabled' ) ? 'enabled">' . __( 'enabled', 'w3-total-cache' ) : 'disabled">' . __( 'disabled', 'w3-total-cache' ) ) . '</span>'
),
array(
'strong' => array(),
'span' => array(
'class' => array(),
),
)
);
?>
</p>

View File

@ -1,101 +1,107 @@
<?php <?php
/**
* File: Cdnfsd_Plugin_Admin.php
*
* @package W3TC
*/
namespace W3TC; namespace W3TC;
/**
* Class: Cdnfsd_Plugin_Admin
*/
class Cdnfsd_Plugin_Admin { class Cdnfsd_Plugin_Admin {
function run() { /**
* Run.
*/
public function run() {
$c = Dispatcher::config(); $c = Dispatcher::config();
$cdnfsd_engine = $c->get_string( 'cdnfsd.engine' ); $cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
// attach to actions without firing class loading at all without need // Attach to actions without firing class loading at all without need.
if ( $cdnfsd_engine == 'cloudfront' ) { switch ( $cdnfsd_engine ) {
add_action( 'w3tc_ajax', array( case 'cloudfront':
'\W3TC\Cdnfsd_CloudFront_Popup', add_action( 'w3tc_ajax', array( '\W3TC\Cdnfsd_CloudFront_Popup', 'w3tc_ajax' ) );
'w3tc_ajax' ) ); add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_CloudFront_Page', 'w3tc_settings_box_cdnfsd' ) );
add_action( 'w3tc_settings_box_cdnfsd', array( break;
'\W3TC\Cdnfsd_CloudFront_Page', case 'limelight':
'w3tc_settings_box_cdnfsd' ) ); add_action( 'w3tc_ajax', array( '\W3TC\Cdnfsd_LimeLight_Popup', 'w3tc_ajax' ) );
} elseif ( $cdnfsd_engine == 'limelight' ) { add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_LimeLight_Page', 'w3tc_settings_box_cdnfsd' ) );
add_action( 'w3tc_ajax', array( break;
'\W3TC\Cdnfsd_LimeLight_Popup', case 'stackpath':
'w3tc_ajax' ) ); add_action( 'w3tc_ajax', array( '\W3TC\Cdnfsd_StackPath_Popup', 'w3tc_ajax' ) );
add_action( 'w3tc_settings_box_cdnfsd', array( add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_StackPath_Page', 'w3tc_settings_box_cdnfsd' ) );
'\W3TC\Cdnfsd_LimeLight_Page', break;
'w3tc_settings_box_cdnfsd' ) ); case 'stackpath2':
} elseif ( $cdnfsd_engine == 'stackpath' ) { add_action( 'w3tc_ajax', array( '\W3TC\Cdnfsd_StackPath2_Popup', 'w3tc_ajax' ) );
add_action( 'w3tc_ajax', array( add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_StackPath2_Page', 'w3tc_settings_box_cdnfsd' ) );
'\W3TC\Cdnfsd_StackPath_Popup', break;
'w3tc_ajax' ) ); case 'transparentcdn':
add_action( 'w3tc_settings_box_cdnfsd', array( add_action( 'init', array( '\W3TC\Cdnfsd_TransparentCDN_Page', 'admin_test_api_parameters_transparentcdn' ) );
'\W3TC\Cdnfsd_StackPath_Page', add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_TransparentCDN_Page', 'w3tc_settings_box_cdnfsd' ) );
'w3tc_settings_box_cdnfsd' ) ); break;
} elseif ( $cdnfsd_engine == 'stackpath2' ) { case 'bunnycdn':
add_action( 'w3tc_ajax', array( add_action( 'w3tc_ajax', array( '\W3TC\Cdnfsd_BunnyCdn_Popup', 'w3tc_ajax' ) );
'\W3TC\Cdnfsd_StackPath2_Popup', add_action( 'w3tc_settings_box_cdnfsd', array( '\W3TC\Cdnfsd_BunnyCdn_Page', 'w3tc_settings_box_cdnfsd' ) );
'w3tc_ajax' ) ); break;
add_action( 'w3tc_settings_box_cdnfsd', array( default:
'\W3TC\Cdnfsd_StackPath2_Page', break;
'w3tc_settings_box_cdnfsd' ) );
} elseif ( 'transparentcdn' === $cdnfsd_engine ){
add_action( 'init', array(
'\W3TC\Cdnfsd_TransparentCDN_Page',
'admin_test_api_parameters_transparentcdn' ) );
add_action( 'w3tc_settings_box_cdnfsd', array(
'\W3TC\Cdnfsd_TransparentCDN_Page',
'w3tc_settings_box_cdnfsd' ) );
} }
add_action( 'w3tc_settings_general_boxarea_cdn_footer', add_action( 'w3tc_settings_general_boxarea_cdn_footer', array( $this, 'w3tc_settings_general_boxarea_cdn_footer' ) );
array( $this, 'w3tc_settings_general_boxarea_cdn_footer' ) );
} }
/**
* Print the general settings page CDN footer.
*/
public function w3tc_settings_general_boxarea_cdn_footer() { public function w3tc_settings_general_boxarea_cdn_footer() {
$config = Dispatcher::config(); $config = Dispatcher::config();
$cdnfsd_enabled = $config->get_boolean( 'cdnfsd.enabled' ); $cdnfsd_enabled = $config->get_boolean( 'cdnfsd.enabled' );
$cdnfsd_engine = $config->get_string( 'cdnfsd.engine' ); $cdnfsd_engine = $config->get_string( 'cdnfsd.engine' );
$is_pro = Util_Environment::is_w3tc_pro( $config ); $is_pro = Util_Environment::is_w3tc_pro( $config );
$cdnfsd_engine_values = array(); $cdnfsd_engine_values = array();
$tag = '';
$cdnfsd_engine_values[''] = array( $cdnfsd_engine_values[''] = array(
'label' => 'Select a provider', 'label' => 'Select a provider',
); );
$cdnfsd_engine_values['bunnycdn'] = array(
'label' => __( 'Bunny CDN (recommended)', 'w3-total-cache' ),
);
$cdnfsd_engine_values['cloudfront'] = array( $cdnfsd_engine_values['cloudfront'] = array(
'label' => __( 'Amazon CloudFront', 'w3-total-cache' ), 'label' => __( 'Amazon CloudFront', 'w3-total-cache' ),
); );
$cdnfsd_engine_values['cloudflare'] = array( $cdnfsd_engine_values['cloudflare'] = array(
'label' => __( 'CloudFlare (extension not activated)', 'w3-total-cache' ), 'label' => __( 'CloudFlare (extension not activated)', 'w3-total-cache' ),
'disabled' => true, 'disabled' => true,
); );
$cdnfsd_engine_values['limelight'] = array( $cdnfsd_engine_values['limelight'] = array(
'label' => __( 'Limelight', 'w3-total-cache' ), 'label' => __( 'Limelight', 'w3-total-cache' ),
); );
$cdnfsd_engine_values['stackpath'] = array( $cdnfsd_engine_values['stackpath'] = array(
'label' => __( 'StackPath SecureCDN (Legacy)', 'w3-total-cache' ), 'label' => __( 'StackPath SecureCDN (Legacy)', 'w3-total-cache' ),
); );
$cdnfsd_engine_values['stackpath2'] = array( $cdnfsd_engine_values['stackpath2'] = array(
'label' => __( 'StackPath (recommended)', 'w3-total-cache' ), 'label' => __( 'StackPath', 'w3-total-cache' ),
); );
$cdnfsd_engine_values['transparentcdn'] = array( $cdnfsd_engine_values['transparentcdn'] = array(
'label' => __( 'TransparentCDN', 'w3-total-cache' ), 'label' => __( 'TransparentCDN', 'w3-total-cache' ),
); );
$tag = ''; if ( 'cloudfront' === $cdnfsd_engine ) {
if ( $cdnfsd_engine == 'cloudfront' ) {
$tag = 'https://api.w3-edge.com/v1/redirects/faq/cdn-fsd/cloudfront'; $tag = 'https://api.w3-edge.com/v1/redirects/faq/cdn-fsd/cloudfront';
} elseif ( $cdnfsd_engine == 'stackpath' || $cdnfsd_engine == 'stackpath2' ) { } elseif ( 'stackpath' === $cdnfsd_engine || 'stackpath2' === $cdnfsd_engine ) {
$tag = 'https://api.w3-edge.com/v1/redirects/faq/cdn-fsd/stackpath'; $tag = 'https://api.w3-edge.com/v1/redirects/faq/cdn-fsd/stackpath';
} }
if ( empty( $tag ) ) { $cdnfsd_engine_extra_description = empty( $tag ) ? '' : ' See <a href="' . $tag . '">setup instructions</a>';
$cdnfsd_engine_extra_description = '';
} else {
$cdnfsd_engine_extra_description =
' See <a href="' . $tag .
'">setup instructions</a>';
}
include W3TC_DIR . '/Cdnfsd_GeneralPage_View.php'; include W3TC_DIR . '/Cdnfsd_GeneralPage_View.php';
} }

View File

@ -50,7 +50,7 @@ class Cdnfsd_StackPath2_Popup {
$api = new Cdn_StackPath2_Api( $api_config ); $api = new Cdn_StackPath2_Api( $api_config );
try { try {
$r = $r = $api->stacks_list(); $r = $api->stacks_list();
$stacks = $r['results']; $stacks = $r['results'];
} catch ( \Exception $ex ) { } catch ( \Exception $ex ) {
$error_message = 'Can\'t authenticate: ' . $ex->getMessage(); $error_message = 'Can\'t authenticate: ' . $ex->getMessage();

View File

@ -10,6 +10,7 @@ class Cdnfsd_StackPath_Engine {
function __construct( $config = array() ) { function __construct( $config = array() ) {
error_log( __METHOD__ . ': ' . print_r( debug_backtrace( 0 ), true ) );
$this->api_key = $config['api_key']; $this->api_key = $config['api_key'];
$this->zone_id = $config['zone_id']; $this->zone_id = $config['zone_id'];
} }

View File

@ -50,6 +50,7 @@ namespace W3TC;
* objectcache.show_note.flush_needed * objectcache.show_note.flush_needed
* objectcache.show_note.flush_needed.timestamp - when the note was set * objectcache.show_note.flush_needed.timestamp - when the note was set
* extension.<extension_id>.hide_note_suggest_activation * extension.<extension_id>.hide_note_suggest_activation
* track.bunnycdn_signup
* track.stackpath_signup * track.stackpath_signup
*/ */
class ConfigState { class ConfigState {

View File

@ -111,6 +111,11 @@ class Extension_CloudFlare_Api {
public function zone_setting_set( $name, $value ) { public function zone_setting_set( $name, $value ) {
// Convert numeric values to the integer type.
if ( is_numeric( $value ) ) {
$value = intval( $value );
}
return $this->_wp_remote_request( 'PATCH', return $this->_wp_remote_request( 'PATCH',
self::$_root_uri . '/zones/' . $this->_zone_id . '/settings/' . $name, self::$_root_uri . '/zones/' . $this->_zone_id . '/settings/' . $name,
json_encode( array( 'value' => $value ) ) ); json_encode( array( 'value' => $value ) ) );

View File

@ -2,7 +2,7 @@
namespace W3TC; namespace W3TC;
class Extension_CloudFlare_Page { class Extension_CloudFlare_Page {
static public function admin_print_scripts_w3tc_extensions() { static public function admin_print_scripts_performance_page_w3tc_cdn() {
if ( ( isset( $_REQUEST['extension'] ) && if ( ( isset( $_REQUEST['extension'] ) &&
Util_Request::get_string( 'extension' ) == 'cloudflare' ) || Util_Request::get_string( 'extension' ) == 'cloudflare' ) ||
( isset( $_REQUEST['page'] ) && ( isset( $_REQUEST['page'] ) &&

View File

@ -588,11 +588,30 @@ if ( ! defined( 'W3TC' ) ) {
'description' => esc_html__( 'Advanced protection from Distributed Denial of Service (DDoS) attacks on your website.', 'w3-total-cache' ), 'description' => esc_html__( 'Advanced protection from Distributed Denial of Service (DDoS) attacks on your website.', 'w3-total-cache' ),
) )
); );
self::cloudflare_textbox( self::cloudflare_selectbox(
$settings, $settings,
array( array(
'key' => 'max_upload', 'key' => 'max_upload',
'label' => esc_html__( 'Max upload:', 'w3-total-cache' ), 'label' => esc_html__( 'Max upload:', 'w3-total-cache' ),
'values' => array(
'100' => '100 MB',
'125' => '125 MB (Business+)',
'150' => '150 MB (Business+)',
'175' => '175 MB (Business+)',
'200' => '200 MB (Business+)',
'225' => '225 MB (Enterprise)',
'250' => '250 MB (Enterprise)',
'275' => '275 MB (Enterprise)',
'300' => '300 MB (Enterprise)',
'325' => '325 MB (Enterprise)',
'350' => '350 MB (Enterprise)',
'375' => '375 MB (Enterprise)',
'400' => '400 MB (Enterprise)',
'425' => '425 MB (Enterprise)',
'450' => '450 MB (Enterprise)',
'475' => '475 MB (Enterprise)',
'500' => '500 MB (Enterprise)',
),
'description' => esc_html__( 'Max size of file allowed for uploading', 'w3-total-cache' ), 'description' => esc_html__( 'Max size of file allowed for uploading', 'w3-total-cache' ),
) )
); );

View File

@ -111,6 +111,12 @@ class Extensions_Util {
$w3_config->set_extension_active_frontend( $extension, true ); $w3_config->set_extension_active_frontend( $extension, true );
} }
// Check for Image Service extension status changes.
if ( 'imageservice' === $extension ) {
$w3_config->set( 'extension.imageservice', true );
}
// Save the config, unless told not to.
try { try {
if ( ! $dont_save_config ) { if ( ! $dont_save_config ) {
$w3_config->save(); $w3_config->save();
@ -150,6 +156,12 @@ class Extensions_Util {
$config->set_extension_active_frontend( $extension, false ); $config->set_extension_active_frontend( $extension, false );
// Check for Image Service extension status changes.
if ( 'imageservice' === $extension ) {
$config->set( 'extension.imageservice', false );
}
// Save the config, unless told not to.
try { try {
if ( ! $dont_save_config ) { if ( ! $dont_save_config ) {
$config->save(); $config->save();

View File

@ -84,7 +84,7 @@ class FeatureShowcase_Plugin_Admin {
*/ */
public function load() { public function load() {
$config = Dispatcher::config(); $config = Dispatcher::config();
$cards = self::get_cards(); $cards_data = self::get_cards();
require W3TC_DIR . '/FeatureShowcase_Plugin_Admin_View.php'; require W3TC_DIR . '/FeatureShowcase_Plugin_Admin_View.php';
@ -132,15 +132,17 @@ class FeatureShowcase_Plugin_Admin {
global $current_user; global $current_user;
$features_seen = (array) get_user_meta( $current_user->ID, 'w3tc_features_seen', true ); $features_seen = (array) get_user_meta( $current_user->ID, 'w3tc_features_seen', true );
$cards = self::get_cards(); $cards_data = self::get_cards();
$updated = false; $updated = false;
foreach ( $cards_data as $type => $cards ) {
foreach ( $cards as $id => $card ) { foreach ( $cards as $id => $card ) {
if ( ! empty( $card['is_new'] ) && ! in_array( $id, $features_seen, true ) ) { if ( ! empty( $card['is_new'] ) && ! in_array( $id, $features_seen, true ) ) {
$features_seen[] = $id; $features_seen[] = $id;
$updated = true; $updated = true;
} }
} }
}
if ( $updated ) { if ( $updated ) {
sort( $features_seen ); sort( $features_seen );
@ -177,14 +179,16 @@ class FeatureShowcase_Plugin_Admin {
$unseen_count = 0; $unseen_count = 0;
$features_seen = (array) get_user_meta( $current_user->ID, 'w3tc_features_seen', true ); $features_seen = (array) get_user_meta( $current_user->ID, 'w3tc_features_seen', true );
$cards = self::get_cards(); $cards_data = self::get_cards();
// Iterate through the new features and check if already seen. // Iterate through the new features and check if already seen.
foreach ( $cards_data as $type => $cards ) {
foreach ( $cards as $id => $card ) { foreach ( $cards as $id => $card ) {
if ( ! empty( $card['is_new'] ) && ! in_array( $id, $features_seen, true ) ) { if ( ! empty( $card['is_new'] ) && ! in_array( $id, $features_seen, true ) ) {
$unseen_count++; $unseen_count++;
} }
} }
}
return $unseen_count; return $unseen_count;
} }
@ -235,14 +239,30 @@ class FeatureShowcase_Plugin_Admin {
} }
return array( return array(
'new' => array(
'preload-requests' => array(
'title' => esc_html__( 'Preload Requests', 'w3-total-cache' ),
'icon' => 'dashicons-controls-repeat',
'text' => esc_html__( 'DNS prefetching, preconnecting, and preloading are essential web optimization techniques that enhance website performance by proactively resolving network-related tasks.', 'w3-total-cache' ),
'button' => '<button class="button" onclick="window.location=\'' . (
UserExperience_Preload_Requests_Extension::is_enabled() ?
esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_userexperience#preload-requests' ) ) :
esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_general#userexperience' ) )
) . '\'">' .
__( 'Settings', 'w3-total-cache' ) . '</button>',
'link' => '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/preload-requests/?utm_source=w3tc&utm_medium=feature_showcase&utm_campaign=preload-requests' ) .
'">' . __( 'More info', 'w3-total-cache' ) . '<span class="dashicons dashicons-external"></span></a>',
'is_premium' => true,
'is_new' => true,
),
'defer-scripts' => array( 'defer-scripts' => array(
'title' => esc_html__( 'Delay Scripts', 'w3-total-cache' ), 'title' => esc_html__( 'Delay Scripts', 'w3-total-cache' ),
'icon' => 'dashicons-media-code', 'icon' => 'dashicons-media-code',
'text' => esc_html__( "Delay the loading of specified internal/external JavaScript sources on your pages separate from Minify.", 'w3-total-cache' ), 'text' => esc_html__( 'Delay the loading of specified internal/external JavaScript sources on your pages separate from Minify.', 'w3-total-cache' ),
'button' => '<button class="button" onclick="window.location=\'' . ( 'button' => '<button class="button" onclick="window.location=\'' . (
Util_Environment::is_w3tc_pro( $c ) && isset( $extensions[ 'user-experience-defer-scripts' ] ) UserExperience_DeferScripts_Extension::is_enabled() ?
? esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_userexperience#application' ) ) esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_userexperience#application' ) ) :
: esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_general#userexperience' ) ) esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_general#userexperience' ) )
) . '\'">' . ) . '\'">' .
__( 'Settings', 'w3-total-cache' ) . '</button>', __( 'Settings', 'w3-total-cache' ) . '</button>',
'link' => '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/defer-scripts-tool/?utm_source=w3tc&utm_medium=feature_showcase&utm_campaign=defer-scripts-tool' ) . 'link' => '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/defer-scripts-tool/?utm_source=w3tc&utm_medium=feature_showcase&utm_campaign=defer-scripts-tool' ) .
@ -250,18 +270,8 @@ class FeatureShowcase_Plugin_Admin {
'is_premium' => true, 'is_premium' => true,
'is_new' => true, 'is_new' => true,
), ),
'pagespeed' => array(
'title' => esc_html__( 'Google Page Speed', 'w3-total-cache' ),
'icon' => 'dashicons-analytics',
'text' => esc_html__( "Adds the ability to analyze the website's homepage and provide a detailed breakdown of performance metrics including potential issues and proposed solutions.", 'w3-total-cache' ),
'button' => '<button class="button" onclick="window.location=\'' .
esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_pagespeed' ) ) . '\'">' .
__( 'Launch', 'w3-total-cache' ) . '</button>',
'link' => '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/google-pagespeed-tool/?utm_source=w3tc&utm_medium=feature_showcase&utm_campaign=pagespeed-tool' ) .
'">' . __( 'More info', 'w3-total-cache' ) . '<span class="dashicons dashicons-external"></span></a>',
'is_premium' => false,
'is_new' => true,
), ),
'old' => array(
'lazyload_gmaps' => array( 'lazyload_gmaps' => array(
'title' => esc_html__( 'Lazy Load Google Maps', 'w3-total-cache' ), 'title' => esc_html__( 'Lazy Load Google Maps', 'w3-total-cache' ),
'icon' => 'dashicons-admin-site', 'icon' => 'dashicons-admin-site',
@ -383,6 +393,18 @@ class FeatureShowcase_Plugin_Admin {
'is_premium' => false, 'is_premium' => false,
'is_new' => false, 'is_new' => false,
), ),
'pagespeed' => array(
'title' => esc_html__( 'Google Page Speed', 'w3-total-cache' ),
'icon' => 'dashicons-analytics',
'text' => esc_html__( "Adds the ability to analyze the website's homepage and provide a detailed breakdown of performance metrics including potential issues and proposed solutions.", 'w3-total-cache' ),
'button' => '<button class="button" onclick="window.location=\'' .
esc_url( Util_Ui::admin_url( 'admin.php?page=w3tc_pagespeed' ) ) . '\'">' .
__( 'Launch', 'w3-total-cache' ) . '</button>',
'link' => '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/google-pagespeed-tool/?utm_source=w3tc&utm_medium=feature_showcase&utm_campaign=pagespeed-tool' ) .
'">' . __( 'More info', 'w3-total-cache' ) . '<span class="dashicons dashicons-external"></span></a>',
'is_premium' => false,
'is_new' => false,
),
'page_cache' => array( 'page_cache' => array(
'title' => esc_html__( 'Page Cache', 'w3-total-cache' ), 'title' => esc_html__( 'Page Cache', 'w3-total-cache' ),
'icon' => 'dashicons-format-aside', 'icon' => 'dashicons-format-aside',
@ -503,6 +525,7 @@ class FeatureShowcase_Plugin_Admin {
'is_premium' => false, 'is_premium' => false,
'is_new' => false, 'is_new' => false,
), ),
),
); );
} }
} }

View File

@ -32,9 +32,14 @@ require W3TC_INC_DIR . '/options/common/header.php';
?> ?>
<div class="w3tc-page-container"> <div class="w3tc-page-container">
<div class="w3tc-card-container">
<?php <?php
foreach ( $cards_data as $card_type => $cards ) {
$class = 'new' === $card_type ? 'w3tc-card-container-new' : 'w3tc-card-container';
echo reset( $cards_data ) !== $cards ? '<hr class="w3tc-card-container-divider"/>' : '';
?>
<div class="<?php echo $class; ?>">
<?php
foreach ( $cards as $feature_id => $card ) { foreach ( $cards as $feature_id => $card ) {
$card_classes = 'w3tc-card'; $card_classes = 'w3tc-card';
$title_classes = 'w3tc-card-title'; $title_classes = 'w3tc-card-title';
@ -52,22 +57,11 @@ foreach ( $cards as $feature_id => $card ) {
?> ?>
<div class="<?php echo $card_classes; ?>" id="w3tc-feature-<?php echo esc_attr( $feature_id ); ?>"> <div class="<?php echo $card_classes; ?>" id="w3tc-feature-<?php echo esc_attr( $feature_id ); ?>">
<?php
if ( $is_new ) {
?>
<div class="w3tc-card-ribbon-new"><span>NEW</span></div>
<?php
}
?>
<div class="<?php echo $title_classes; ?>"> <div class="<?php echo $title_classes; ?>">
<p><?php echo $card['title']; ?></p> <p><?php echo $card['title']; ?></p>
<?php <?php
if ( $is_premium ) { if ( $is_premium ) {
?> echo '<p class="w3tc-card-pro">' . __( 'PRO FEATURE', 'w3-total-cache' ) . '</p>';
<p class="w3tc-card-pro"><?php echo __( 'PRO FEATURE', 'w3-total-cache' ); ?></p>
<?php
} }
?> ?>
</div> </div>
@ -77,21 +71,33 @@ foreach ( $cards as $feature_id => $card ) {
<div class="w3tc-card-button"> <div class="w3tc-card-button">
<?php <?php
if ( $is_premium && ! $is_pro ) { if ( $is_premium && ! $is_pro ) {
?> echo '<button class="button w3tc-gopro-button button-buy-plugin" data-src="feature_showcase">'
<button class="button w3tc-gopro-button button-buy-plugin" data-src="feature_showcase"> . esc_html__( 'Unlock Feature', 'w3-total-cache' ) . '</button>';
<?php esc_html_e( 'Unlock Feature', 'w3-total-cache' ); ?>
</button>
<?php
} elseif ( ! empty( $card['button'] ) ) { } elseif ( ! empty( $card['button'] ) ) {
echo $card['button']; echo $card['button'];
} }
?> ?>
</div><div class="w3tc-card-links"><?php echo $card['link']; ?></div> </div><div class="w3tc-card-links"><?php echo $card['link']; ?></div>
</div> </div>
<?php
if ( $is_new ) {
?>
<div class="w3tc-card-ribbon-new">
<span class="dashicons dashicons-awards"></span>
<b><?php esc_html_e( 'New', 'w3-total-cache' ); ?></b>
<span>
<?php esc_html_e( 'in', 'w3-total-cache' ); ?> W3 Total Cache Pro <?php echo W3TC_VERSION; ?>!
</span>
</div> </div>
<?php <?php
} }
?> ?>
</div> </div>
<?php
}
?>
</div>
<?php
}
?>
</div> </div>

View File

@ -271,6 +271,17 @@ class Generic_AdminActions_Default {
$config->set( 'pgcache.enabled', false ); $config->set( 'pgcache.enabled', false );
$data['response_errors'][] = 'fancy_permalinks_disabled_pgcache'; $data['response_errors'][] = 'fancy_permalinks_disabled_pgcache';
} }
/**
* Check for Image Service extension status changes.
*/
if ( $config->get_boolean( 'extension.imageservice' ) !== $this->_config->get_boolean( 'extension.imageservice' ) ) {
if ( $config->get_boolean( 'extension.imageservice' ) ) {
Extensions_Util::activate_extension( 'imageservice', $config );
} else {
Extensions_Util::deactivate_extension( 'imageservice', $config );
}
}
} }
/** /**
@ -558,7 +569,9 @@ class Generic_AdminActions_Default {
* *
* @return bool * @return bool
*/ */
function enable_cookie_domain() { public function enable_cookie_domain() {
WP_Filesystem();
global $wp_filesystem; global $wp_filesystem;
$config_path = Util_Environment::wp_config_path(); $config_path = Util_Environment::wp_config_path();
@ -601,7 +614,9 @@ class Generic_AdminActions_Default {
* *
* @return bool * @return bool
*/ */
function disable_cookie_domain() { public function disable_cookie_domain() {
WP_Filesystem();
global $wp_filesystem; global $wp_filesystem;
$config_path = Util_Environment::wp_config_path(); $config_path = Util_Environment::wp_config_path();

View File

@ -17,6 +17,12 @@ class Generic_AdminActions_Flush {
*/ */
function w3tc_flush_all() { function w3tc_flush_all() {
w3tc_flush_all( array( 'ui_action' => 'flush_button' ) ); w3tc_flush_all( array( 'ui_action' => 'flush_button' ) );
$state_note = Dispatcher::config_state_note();
$state_note->set( 'common.show_note.flush_statics_needed', false );
$state_note->set( 'common.show_note.flush_posts_needed', false );
$state_note->set( 'common.show_note.plugins_updated', false );
$this->_redirect_after_flush( 'flush_all' ); $this->_redirect_after_flush( 'flush_all' );
} }

View File

@ -254,6 +254,28 @@ class Generic_Plugin {
), ),
); );
// Add menu item to flush all cached except Bunny CDN.
if (
0 && // @todo Revisit this item.
Cdn_BunnyCdn_Page::is_active() && (
$modules->can_empty_memcache()
|| $modules->can_empty_opcode()
|| $modules->can_empty_file()
|| $modules->can_empty_varnish()
)
) {
$menu_items['10012.generic'] = array(
'id' => 'w3tc_flush_all_except_bunnycdn',
'parent' => 'w3tc',
'title' => __( 'Purge All Caches Except Bunny CDN', 'w3-total-cache' ),
'href' => wp_nonce_url(
network_admin_url( 'admin.php?page=w3tc_dashboard&amp;w3tc_bunnycdn_flush_all_except_bunnycdn' ),
'w3tc'
),
);
}
// Add menu item to flush all cached except Cloudflare.
if ( if (
! empty( $this->_config->get_string( array( 'cloudflare', 'email' ) ) ) ! empty( $this->_config->get_string( array( 'cloudflare', 'email' ) ) )
&& ! empty( $this->_config->get_string( array( 'cloudflare', 'key' ) ) ) && ! empty( $this->_config->get_string( array( 'cloudflare', 'key' ) ) )
@ -523,6 +545,7 @@ class Generic_Plugin {
array( array(
'swarmify', 'swarmify',
'lazyload', 'lazyload',
'deferscripts',
'minify', 'minify',
'newrelic', 'newrelic',
'cdn', 'cdn',

View File

@ -171,9 +171,7 @@ class Generic_Plugin_Admin {
} }
/** /**
* Admin init * Admin init.
*
* @return void
*/ */
public function admin_init() { public function admin_init() {
// Special handling for deactivation link, it's plugins.php file. // Special handling for deactivation link, it's plugins.php file.
@ -181,176 +179,121 @@ class Generic_Plugin_Admin {
Util_Activation::deactivate_plugin(); Util_Activation::deactivate_plugin();
} }
// These have been moved here as the admin_print_scripts-{$suffix} hook with translations won't take the user locale setting /**
// into account if it's called too soon, resulting in JS not loading. * These have been moved here as the admin_print_scripts-{$suffix} hook with translations won't take the user locale setting
* into account if it's called too soon, resulting in JS not loading.
// Translations are needed as the "prefix" used is based on the menu/page title, which is translated (11+ year old WP bug). *
* Translations are needed as the "prefix" used is based on the menu/page title, which is translated (11+ year old WP bug).
*/
// Support page. // Support page.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_support', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_support',
array( array( '\W3TC\Support_Page', 'admin_print_scripts_w3tc_support' )
'\W3TC\Support_Page',
'admin_print_scripts_w3tc_support',
)
); );
// Minify. // Minify.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_general', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_general',
array( array( '\W3TC\Minify_Plugin_Admin', 'admin_print_scripts_w3tc_general' )
'\W3TC\Minify_Plugin_Admin',
'admin_print_scripts_w3tc_general',
)
); );
// PageCache. // PageCache.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_pgcache', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_pgcache',
array( array( '\W3TC\PgCache_Page', 'admin_print_scripts_w3tc_pgcache' )
'\W3TC\PgCache_Page',
'admin_print_scripts_w3tc_pgcache',
)
); );
// Extensions. // Extensions.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_extensions', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_extensions',
array( array( '\W3TC\Extension_CloudFlare_Page', 'admin_print_scripts_performance_page_w3tc_cdn' )
'\W3TC\Extension_CloudFlare_Page',
'admin_print_scripts_w3tc_extensions',
)
); );
// Usage Statistics. // Usage Statistics.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_stats', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_stats',
array( array( '\W3TC\UsageStatistics_Page', 'admin_print_scripts_w3tc_stats' )
'\W3TC\UsageStatistics_Page',
'admin_print_scripts_w3tc_stats',
)
); );
$c = Dispatcher::config(); $c = Dispatcher::config();
$cdn_engine = $c->get_string( 'cdn.engine' );
$cdnfsd_engine = $c->get_string( 'cdnfsd.engine' );
// CDN. // CDN.
if ( 'google_drive' === $cdn_engine ) { switch ( $c->get_string( 'cdn.engine' ) ) {
case 'bunnycdn':
$cdn_class = '\W3TC\Cdn_BunnyCdn_Page';
break;
case 'google_drive':
$cdn_class = '\W3TC\Cdn_GoogleDrive_Page';
break;
case 'highwinds':
$cdn_class = '\W3TC\Cdn_Highwinds_Page';
break;
case 'limelight':
$cdn_class = '\W3TC\Cdn_LimeLight_Page';
break;
case 'rackspace_cdn':
$cdn_class = '\W3TC\Cdn_RackSpaceCdn_Page';
break;
case 'rscf':
$cdn_class = '\W3TC\Cdn_RackSpaceCloudFiles_Page';
break;
case 'stackpath':
$cdn_class = '\W3TC\Cdn_StackPath_Page';
break;
case 'stackpath2':
$cdn_class = '\W3TC\Cdn_StackPath2_Page';
break;
default:
break;
}
if ( ! empty( $cdn_class ) ) {
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array( array( $cdn_class, 'admin_print_scripts_w3tc_cdn' )
'\W3TC\Cdn_GoogleDrive_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'highwinds' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_Highwinds_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'limelight' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_LimeLight_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'rackspace_cdn' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_RackSpaceCdn_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'rscf' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_RackSpaceCloudFiles_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'stackpath' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_StackPath_Page',
'admin_print_scripts_w3tc_cdn',
)
);
} elseif ( 'stackpath2' === $cdn_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdn_StackPath2_Page',
'admin_print_scripts_w3tc_cdn',
)
); );
} }
// CDNFSD. // CDNFSD.
if ( 'cloudflare' === $cdnfsd_engine ) { switch ( $c->get_string( 'cdnfsd.engine' ) ) {
case 'bunnycdn':
$cdnfsd_class = '\W3TC\Cdnfsd_BunnyCdn_Page';
break;
case 'cloudflare':
$cdnfsd_class = '\W3TC\Extension_CloudFlare_Page';
break;
case 'cloudfront':
$cdnfsd_class = '\W3TC\Cdnfsd_CloudFront_Page';
break;
case 'limelight':
$cdnfsd_class = '\W3TC\Cdnfsd_LimeLight_Page';
break;
case 'stackpath':
$cdnfsd_class = '\W3TC\Cdnfsd_StackPath_Page';
break;
case 'stackpath2':
$cdnfsd_class = '\W3TC\Cdnfsd_StackPath2_Page';
break;
default:
break;
}
if ( ! empty( $cdnfsd_class ) ) {
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array( array( $cdnfsd_class, 'admin_print_scripts_performance_page_w3tc_cdn' )
'\W3TC\Extension_CloudFlare_Page',
'admin_print_scripts_w3tc_extensions',
)
);
} elseif ( 'cloudfront' === $cdnfsd_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdnfsd_CloudFront_Page',
'admin_print_scripts_performance_page_w3tc_cdn',
)
);
} elseif ( 'limelight' === $cdnfsd_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdnfsd_LimeLight_Page',
'admin_print_scripts_performance_page_w3tc_cdn',
)
);
} elseif ( 'stackpath' === $cdnfsd_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdnfsd_StackPath_Page',
'admin_print_scripts_performance_page_w3tc_cdn',
)
);
} elseif ( 'stackpath2' === $cdnfsd_engine ) {
add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_cdn',
array(
'\W3TC\Cdnfsd_StackPath2_Page',
'admin_print_scripts_performance_page_w3tc_cdn',
)
); );
} }
// PageSpeed page/widget. // PageSpeed page/widget.
add_action( add_action(
'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_pagespeed', 'admin_print_scripts-' . sanitize_title( __( 'Performance', 'w3-total-cache' ) ) . '_page_w3tc_pagespeed',
array( array( '\W3TC\PageSpeed_Page', 'admin_print_scripts_w3tc_pagespeed' )
'\W3TC\PageSpeed_Page',
'admin_print_scripts_w3tc_pagespeed',
)
); );
add_action( add_action(
'admin_print_scripts-toplevel_page_w3tc_dashboard', 'admin_print_scripts-toplevel_page_w3tc_dashboard',
array( array( '\W3TC\PageSpeed_Widget', 'admin_print_scripts_w3tc_pagespeed_widget' )
'\W3TC\PageSpeed_Widget',
'admin_print_scripts_w3tc_pagespeed_widget',
)
); );
$page_val = Util_Request::get_string( 'page' ); $page_val = Util_Request::get_string( 'page' );
@ -380,9 +323,7 @@ class Generic_Plugin_Admin {
wp_localize_script( wp_localize_script(
'w3tc-feature-counter', 'w3tc-feature-counter',
'W3TCFeatureShowcaseData', 'W3TCFeatureShowcaseData',
array( array( 'unseenCount' => FeatureShowcase_Plugin_Admin::get_unseen_count() )
'unseenCount' => FeatureShowcase_Plugin_Admin::get_unseen_count(),
)
); );
wp_enqueue_script( 'w3tc-feature-counter' ); wp_enqueue_script( 'w3tc-feature-counter' );
@ -645,6 +586,8 @@ class Generic_Plugin_Admin {
'cdn.flush_manually', 'cdn.flush_manually',
Cdn_Util::get_flush_manually_default_override( $this->_config->get_string( 'cdn.engine' ) ) Cdn_Util::get_flush_manually_default_override( $this->_config->get_string( 'cdn.engine' ) )
), ),
'cdnfsdEnabled' => $this->_config->get_boolean( 'cdnfsd.enabled' ),
'cdnfsdEngine' => $this->_config->get_string( 'cdnfsd.engine' ),
'cfWarning' => wp_kses( 'cfWarning' => wp_kses(
sprintf( sprintf(
// translators: 1: HTML opening a tag to docs.aws.amazon.com for invalidation payments, 2: HTML closing a tag followed by HTML line break tag, // translators: 1: HTML opening a tag to docs.aws.amazon.com for invalidation payments, 2: HTML closing a tag followed by HTML line break tag,
@ -667,6 +610,10 @@ class Generic_Plugin_Admin {
'br' => array(), 'br' => array(),
) )
), ),
'bunnyCdnWarning' => esc_html__(
'Bunny CDN should only be enabled as either a CDN for objects or full-site delivery, not both at the same time. The CDN settings have been reverted.',
'w3-total-cache'
),
) )
); );
} }

View File

@ -31,6 +31,7 @@ class ModuleStatus {
|| $this->is_enabled( 'objectcache' ) || $this->is_enabled( 'objectcache' )
|| $this->is_enabled( 'browsercache' ) || $this->is_enabled( 'browsercache' )
|| $this->is_enabled( 'cdn' ) || $this->is_enabled( 'cdn' )
|| $this->is_enabled( 'cdnfsd' )
|| $this->is_enabled( 'varnish' ) || $this->is_enabled( 'varnish' )
|| $this->is_enabled( 'newrelic' ) || $this->is_enabled( 'newrelic' )
|| $this->is_enabled( 'fragmentcache' ); || $this->is_enabled( 'fragmentcache' );

View File

@ -77,7 +77,7 @@ class PageSpeed_Widget {
'<div class="w3tc-widget-pagespeed-logo"></div>' . '<div class="w3tc-widget-pagespeed-logo"></div>' .
'<div class="w3tc-widget-text">' . esc_html__( 'PageSpeed Report', 'w3-total-cache' ) . '</div>', '<div class="w3tc-widget-text">' . esc_html__( 'PageSpeed Report', 'w3-total-cache' ) . '</div>',
array( $this, 'widget_pagespeed' ), array( $this, 'widget_pagespeed' ),
Util_Ui::admin_url( 'admin.php?page=w3tc_general#google_page_speed' ), Util_Ui::admin_url( 'admin.php?page=w3tc_general#google_pagespeed' ),
'normal' 'normal'
); );
} }

View File

@ -53,7 +53,7 @@ class UserExperience_DeferScripts_Extension {
return; return;
} }
Util_Bus::add_ob_callback( 'lazyload', array( $this, 'ob_callback' ) ); Util_Bus::add_ob_callback( 'deferscripts', array( $this, 'ob_callback' ) );
add_filter( 'w3tc_minify_js_script_tags', array( $this, 'w3tc_minify_js_script_tags' ) ); add_filter( 'w3tc_minify_js_script_tags', array( $this, 'w3tc_minify_js_script_tags' ) );
add_filter( 'w3tc_save_options', array( $this, 'w3tc_save_options' ) ); add_filter( 'w3tc_save_options', array( $this, 'w3tc_save_options' ) );
@ -289,6 +289,19 @@ class UserExperience_DeferScripts_Extension {
return $data; return $data;
} }
/**
* Gets the enabled status of the extension.
*
* @since 2.5.1
*
* @return bool
*/
public static function is_enabled() {
$config = Dispatcher::config();
$extensions_active = $config->get_array( 'extensions.active' );
return Util_Environment::is_w3tc_pro( $config ) && array_key_exists( 'user-experience-defer-scripts', $extensions_active );
}
} }
$o = new UserExperience_DeferScripts_Extension(); $o = new UserExperience_DeferScripts_Extension();

View File

@ -90,10 +90,10 @@ Util_Ui::config_overloading_button( array( 'key' => 'lazyload.configuration_over
'extension_id' => 'user-experience-defer-scripts', 'extension_id' => 'user-experience-defer-scripts',
'checkbox_label' => esc_html__( 'Delay Scripts', 'w3-total-cache' ), 'checkbox_label' => esc_html__( 'Delay Scripts', 'w3-total-cache' ),
'description' => __( 'description' => __(
'Delay the loading of specified interal/external JavaScript sources on your pages separate from Minify. For best results it is recommended to enable the Minify feature to optimize internal sources and to then use the Delay JavaScript feature to handle external sources and/or any internal sources excluded from Minify.', 'Delay the loading of specified interal/external JavaScript sources on your pages separate from Minify.',
'w3-total-cache' 'w3-total-cache'
) . ( ) . (
Util_Environment::is_w3tc_pro( $config ) && $config->is_extension_active( 'user-experience-defer-scripts' ) UserExperience_DeferScripts_Extension::is_enabled()
? wp_kses( ? wp_kses(
sprintf( sprintf(
// translators: 1 opening HTML a tag to W3TC User Experience page, 2 closing HTML a tag. // translators: 1 opening HTML a tag to W3TC User Experience page, 2 closing HTML a tag.
@ -118,6 +118,39 @@ Util_Ui::config_overloading_button( array( 'key' => 'lazyload.configuration_over
) )
); );
Util_Ui::config_item_extension_enabled(
array(
'extension_id' => 'user-experience-preload-requests',
'checkbox_label' => esc_html__( 'Preload Requests', 'w3-total-cache' ),
'description' => __(
'DNS prefetching, preconnecting, and preloading are essential web optimization techniques that enhance website performance by proactively resolving network-related tasks.',
'w3-total-cache'
) . (
UserExperience_Preload_Requests_Extension::is_enabled()
? wp_kses(
sprintf(
// translators: 1 opening HTML a tag to W3TC User Experience page, 2 closing HTML a tag.
__(
' Settings can be found on the %1$sUser Experience page%2$s.',
'w3-total-cache'
),
'<a href="' . Util_Ui::admin_url( 'admin.php?page=w3tc_userexperience#preload-requests' ) . '">',
'</a>'
),
array(
'a' => array(
'href' => array(),
),
)
)
: ''
),
'label_class' => 'w3tc_single_column',
'pro' => true,
'disabled' => ! Util_Environment::is_w3tc_pro( $config ) ? true : false,
)
);
Util_Ui::config_item_extension_enabled( Util_Ui::config_item_extension_enabled(
array( array(
'extension_id' => 'user-experience-oembed', 'extension_id' => 'user-experience-oembed',

View File

@ -46,6 +46,11 @@ class UserExperience_Plugin_Admin {
'extension_id' => 'user-experience-defer-scripts', 'extension_id' => 'user-experience-defer-scripts',
'path' => 'w3-total-cache/UserExperience_DeferScripts_Extension.php', 'path' => 'w3-total-cache/UserExperience_DeferScripts_Extension.php',
); );
$extensions['user-experience-preload-requests'] = array(
'public' => false,
'extension_id' => 'user-experience-preload-requests',
'path' => 'w3-total-cache/UserExperience_Preload_Requests_Extension.php',
);
$extensions['user-experience-emoji'] = array( $extensions['user-experience-emoji'] = array(
'public' => false, 'public' => false,
'extension_id' => 'user-experience-emoji', 'extension_id' => 'user-experience-emoji',

View File

@ -0,0 +1,203 @@
<?php
/**
* File: UserExperience_Preload_Requests_Extension.php
*
* Controls the Preload Requests feature.
*
* @since 2.5.1
*
* @package W3TC
*/
namespace W3TC;
/**
* UserExperience Preload Requests Extension.
*
* @since 2.5.1
*/
class UserExperience_Preload_Requests_Extension {
/**
* Config.
*
* @var object
*/
private $config;
/**
* User Experience DNS Prefetc constructor.
*
* @since 2.5.1
*/
public function __construct() {
$this->config = Dispatcher::config();
}
/**
* Runs User Experience DNS Prefetc feature.
*
* @since 2.5.1
*
* @return void
*/
public function run() {
if ( ! Util_Environment::is_w3tc_pro( $this->config ) ) {
$this->config->set_extension_active_frontend( 'user-experience-preload-requests', false );
return;
}
// Applies logic to display page cache flush notice if Preload Requests settings are altered and saved.
add_filter( 'w3tc_save_options', array( $this, 'w3tc_save_options' ) );
// Renders the Preload Reqeusts settings metabox on the User Expereince advanced setting page.
add_action( 'w3tc_userexperience_page', array( $this, 'w3tc_userexperience_page' ) );
// This filter is documented in Generic_AdminActions_Default.php under the read_request method.
add_filter( 'w3tc_config_key_descriptor', array( $this, 'w3tc_config_key_descriptor' ), 10, 2 );
// Applies dns-prefetch, preconnect, and preload headers.
add_action( 'wp_head', array( $this, 'w3tc_preload_requests_headers' ) );
add_action( 'admin_head', array( $this, 'w3tc_preload_requests_headers' ) );
}
/**
* Renders the user experience Preload Requests settings page.
*
* @since 2.5.1
*
* @return void
*/
public function w3tc_userexperience_page() {
include __DIR__ . '/UserExperience_Preload_Requests_Page_View.php';
}
/**
* Specify config key typing for fields that need it.
*
* @since 2.5.1
*
* @param mixed $descriptor Descriptor.
* @param mixed $key Compound key array.
*
* @return array
*/
public function w3tc_config_key_descriptor( $descriptor, $key ) {
if (
is_array( $key )
&& in_array(
implode( '.', $key ),
array(
'user-experience-preload-requests.dns-prefetch',
'user-experience-preload-requests.preconnect',
'user-experience-preload-requests.preload-css',
'user-experience-preload-requests.preload-js',
'user-experience-preload-requests.preload-fonts',
'user-experience-preload-requests.preload-images',
'user-experience-preload-requests.preload-videos',
'user-experience-preload-requests.preload-audio',
'user-experience-preload-requests.preload-documents',
)
)
) {
$descriptor = array( 'type' => 'array' );
}
return $descriptor;
}
/**
* Performs actions on save.
*
* @since 2.5.1
*
* @param array $data Array of save data.
*
* @return array
*/
public function w3tc_save_options( $data ) {
$new_config = $data['new_config'];
$old_config = $data['old_config'];
$new_includes = $new_config->get_array( array( 'user-experience-preload-requests', 'includes' ) );
$old_includes = $old_config->get_array( array( 'user-experience-preload-requests', 'includes' ) );
if ( $new_includes !== $old_includes && $this->config->get_boolean( 'pgcache.enabled' ) ) {
$state = Dispatcher::config_state();
$state->set( 'common.show_note.flush_posts_needed', true );
$state->save();
}
return $data;
}
/**
* Applies the Preload Requests headers for wp_head and admin_head.
*
* @since 2.5.1
*
* @return void
*/
public function w3tc_preload_requests_headers() {
// Preconnect hints should be printed first so they take priority. If not supported then dns-prefetch will be the fallback.
$preconnect = $this->config->get_array( array( 'user-experience-preload-requests', 'preconnect' ) );
foreach ( $preconnect as $url ) {
echo '<link rel="preconnect" href="' . esc_url( $url ) . '" crossorigin>';
}
$dns_prefetch = $this->config->get_array( array( 'user-experience-preload-requests', 'dns-prefetch' ) );
foreach ( $dns_prefetch as $url ) {
echo '<link rel="dns-prefetch" href="' . esc_url( $url ) . '">';
}
$preload_css = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-css' ) );
foreach ( $preload_css as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="style">';
}
$preload_js = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-js' ) );
foreach ( $preload_js as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="script">';
}
$preload_fonts = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-fonts' ) );
foreach ( $preload_fonts as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="font" type="font/woff2">';
}
$preload_images = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-images' ) );
foreach ( $preload_images as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="image">';
}
$preload_videos = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-videos' ) );
foreach ( $preload_videos as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="video">';
}
$preload_audio = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-audio' ) );
foreach ( $preload_audio as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="audio">';
}
$preload_documents = $this->config->get_array( array( 'user-experience-preload-requests', 'preload-documents' ) );
foreach ( $preload_documents as $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="document">';
}
}
/**
* Gets the enabled status of the extension.
*
* @since 2.5.1
*
* @return bool
*/
public static function is_enabled() {
$config = Dispatcher::config();
$extensions_active = $config->get_array( 'extensions.active' );
return Util_Environment::is_w3tc_pro( $config ) && array_key_exists( 'user-experience-preload-requests', $extensions_active );
}
}
$o = new UserExperience_Preload_Requests_Extension();
$o->run();

View File

@ -0,0 +1,102 @@
<?php
/**
* File: UserExperience_Preload_Requests_Page_View.php
*
* Renders the Preload Requests setting block on the UserExperience advanced settings page.
*
* @since 2.5.1
*
* @package W3TC
*/
namespace W3TC;
if ( ! defined( 'W3TC' ) ) {
die();
}
?>
<?php Util_Ui::postbox_header( esc_html__( 'Preload Requests', 'w3-total-cache' ), '', 'preload-requests' ); ?>
<p><?php esc_html_e( 'DNS prefetching, preconnecting, and preloading are essential web optimization techniques that enhance website performance by proactively resolving network-related tasks. DNS prefetching involves resolving domain names to IP addresses before they are needed, reducing the time it takes for the browser to initiate a connection. Preconnecting establishes early connections to servers to expedite resource fetching, anticipating the need for subsequent requests. Preloading involves instructing the browser to fetch and cache critical resources in advance, ensuring a smoother user experience during page load.', 'w3-total-cache' ); ?></p>
<p><?php esc_html_e( 'However, it\'s important to note a significant caveat: if a webpage requires connections to numerous third-party domains, indiscriminate preconnecting to all of them can actually hinder performance. Preconnecting to an excessive number of domains can overwhelm the browser and degrade overall speed, as each connection consumes resources. It\'s crucial for web developers to judiciously implement preconnecting, considering the optimal number and relevance of third-party domains to ensure efficient website loading.', 'w3-total-cache' ); ?></p>
<p><?php esc_html_e( 'Each of the below fields will default to non-HTTPS if the protocol is ommitted, e.g. (//example.com would become http://example.com). Include the protocol of the target if it is known.', 'w3-total-cache' ); ?></p>
<table class="form-table">
<?php
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'dns-prefetch' ),
'label' => esc_html__( 'DNS Prefetch Domains:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify domains whose DNS should be prefetched by browsers. Include one entry per line, e.g. (https://cdn.domain.com, https://fonts.googleapis.com, https://www.google-ananlytics.com, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preconnect' ),
'label' => esc_html__( 'Preconnect Domains:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify domains that browsers should preconnect to. Include one entry per line, e.g. (https://cdn.domain.com, https://fonts.googleapis.com, https://www.google-ananlytics.com, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-css' ),
'label' => esc_html__( 'Preload CSS:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key CSS URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.css, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-js' ),
'label' => esc_html__( 'Preload JavaScript:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key JavaScript URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.js, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-fonts' ),
'label' => esc_html__( 'Preload Fonts:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key Font URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.woff, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-images' ),
'label' => esc_html__( 'Preload Images:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key Image URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.png, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-videos' ),
'label' => esc_html__( 'Preload Videos:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key Video URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.mp4, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-audio' ),
'label' => esc_html__( 'Prelaod Audio:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key Audio URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.mp3, etc.)', 'w3-total-cache' ),
)
);
Util_Ui::config_item(
array(
'key' => array( 'user-experience-preload-requests', 'preload-documents' ),
'label' => esc_html__( 'Preload Documents:', 'w3-total-cache' ),
'control' => 'textarea',
'description' => esc_html__( 'Specify key Document URLs that should be preloaded by browsers. Include one entry per line, e.g. (https://example.com/example.pdf, etc.)', 'w3-total-cache' ),
)
);
?>
</table>
<?php Util_Ui::postbox_footer(); ?>

View File

@ -372,8 +372,10 @@ class Util_Ui {
if ( $config->getf_boolean( 'objectcache.enabled' ) ) { if ( $config->getf_boolean( 'objectcache.enabled' ) ) {
echo '<input type="submit" class="dropdown-item" name="w3tc_flush_objectcache" value="' . esc_html__( 'Empty Object Cache', 'w3-total-cache' ) . '"/>'; echo '<input type="submit" class="dropdown-item" name="w3tc_flush_objectcache" value="' . esc_html__( 'Empty Object Cache', 'w3-total-cache' ) . '"/>';
} }
if ( $config->get_boolean( 'cdn.enabled' ) ) { if ( $config->get_boolean( 'cdn.enabled' ) || $config->get_boolean( 'cdnfsd.enabled' ) ) {
$disable = $config->get_boolean( 'cdn.enabled' ) && Cdn_Util::can_purge_all( $config->get_string( 'cdn.engine' ) ) ? '' : ' disabled="disabled" '; $disable = ( $config->get_boolean( 'cdn.enabled' ) && Cdn_Util::can_purge_all( $config->get_string( 'cdn.engine' ) ) ) ||
( $config->get_boolean( 'cdnfsd.enabled' ) && Cdn_Util::can_purge_all( $config->get_string( 'cdnfsd.engine' ) ) ) ?
'' : ' disabled="disabled" ';
echo '<input type="submit" class="dropdown-item" name="w3tc_flush_cdn"' . $disable . ' value="' . esc_html__( 'Empty CDN Cache', 'w3-total-cache' ) . '"/>'; echo '<input type="submit" class="dropdown-item" name="w3tc_flush_cdn"' . $disable . ' value="' . esc_html__( 'Empty CDN Cache', 'w3-total-cache' ) . '"/>';
} }
if ( $config->is_extension_active_frontend( 'fragmentcache' ) && Util_Environment::is_w3tc_pro( $config ) && ! empty( $config->get_string( array( 'fragmentcache', 'engine' ) ) ) ) { if ( $config->is_extension_active_frontend( 'fragmentcache' ) && Util_Environment::is_w3tc_pro( $config ) && ! empty( $config->get_string( array( 'fragmentcache', 'engine' ) ) ) ) {
@ -1443,10 +1445,15 @@ class Util_Ui {
} }
/** /**
* Returns option name accepted by W3TC as http paramter * Returns option name accepted by W3TC as http paramter from its id (full name from config file).
* from it's id (full name from config file) *
* @param mixed $id ID key string/array.
*
* @return string
*/ */
public static function config_key_to_http_name( $id ) { public static function config_key_to_http_name( $id ) {
$id = isset( $id ) ? $id : '';
if ( is_array( $id ) ) { if ( is_array( $id ) ) {
$id = $id[0] . '___' . $id[1]; $id = $id[0] . '___' . $id[1];
} }
@ -1518,6 +1525,7 @@ class Util_Ui {
$config = Dispatcher::config(); $config = Dispatcher::config();
$state = Dispatcher::config_state(); $state = Dispatcher::config_state();
$page = Util_Admin::get_current_page(); $page = Util_Admin::get_current_page();
$show_purge_link = 'bunnycdn' === $config->get_string( 'cdn.engine' ) || 'bunnycdn' === $config->get_string( 'cdnfsd.engine' );
$licensing_visible = ( $licensing_visible = (
( ! Util_Environment::is_wpmu() || is_network_admin() ) && ( ! Util_Environment::is_wpmu() || is_network_admin() ) &&
! ini_get( 'w3tc.license_key' ) && ! ini_get( 'w3tc.license_key' ) &&
@ -1827,7 +1835,15 @@ class Util_Ui {
?> ?>
<div id="w3tc-options-menu"> <div id="w3tc-options-menu">
<a href="#general"><?php esc_html_e( 'General', 'w3-total-cache' ); ?></a> | <a href="#general"><?php esc_html_e( 'General', 'w3-total-cache' ); ?></a> |
<a href="#configuration"><?php esc_html_e( 'Configuration', 'w3-total-cache' ); ?></a> | <?php if ( ! empty( $config->get_string( 'cdn.engine' ) ) ) : ?>
<a href="#configuration"><?php esc_html_e( 'Configuration (Objects)', 'w3-total-cache' ); ?></a> |
<?php endif; ?>
<?php if ( ! empty( $config->get_string( 'cdnfsd.engine' ) ) ) : ?>
<a href="#configuration-fsd"><?php esc_html_e( 'Configuration (FSD)', 'w3-total-cache' ); ?></a> |
<?php endif; ?>
<?php if ( $show_purge_link ) : ?>
<a href="#purge-urls"><?php esc_html_e( 'Purge', 'w3-total-cache' ); ?></a> |
<?php endif; ?>
<a href="#advanced"><?php esc_html_e( 'Advanced', 'w3-total-cache' ); ?></a> | <a href="#advanced"><?php esc_html_e( 'Advanced', 'w3-total-cache' ); ?></a> |
<a href="#notes"><?php esc_html_e( 'Note(s)', 'w3-total-cache' ); ?></a> <a href="#notes"><?php esc_html_e( 'Note(s)', 'w3-total-cache' ); ?></a>
</div> </div>
@ -1838,14 +1854,18 @@ class Util_Ui {
?> ?>
<div id="w3tc-options-menu"> <div id="w3tc-options-menu">
<?php <?php
$extensions_active = $config->get_array( 'extensions.active' ); $subnav_links = array( '<a href="#lazy-loading">' . esc_html__( 'Lazy Loading', 'w3-total-cache' ) . '</a>' );
if ( array_key_exists( 'user-experience-defer-scripts', $extensions_active ) ) {
// If more items are added this will only encompase the Defer Scripts, but if only 1 item show no sub-nav. if ( UserExperience_DeferScripts_Extension::is_enabled() ) {
?> $subnav_links[] = '<a href="#application">' . esc_html__( 'Delay Scripts', 'w3-total-cache' ) . '</a>';
<a href="#lazy-loading"><?php esc_html_e( 'Lazy Loading', 'w3-total-cache' ); ?></a> |
<a href="#application"><?php esc_html_e( 'Delay Scripts', 'w3-total-cache' ); ?></a>
<?php
} }
if ( UserExperience_Preload_Requests_Extension::is_enabled() ) {
$subnav_links[] = '<a href="#application">' . esc_html__( 'Preload Requests', 'w3-total-cache' ) . '</a>';
}
// If there's only 1 meta box on the page, no need for nav links.
echo count( $subnav_links ) > 1 ? implode( ' | ', $subnav_links ) : '';
?> ?>
</div> </div>
<?php <?php

View File

@ -7,9 +7,7 @@
namespace W3TC; namespace W3TC;
if ( ! defined( 'W3TC' ) ) { defined( 'W3TC' ) || die();
die();
}
// when separate config is used - each blog has own uploads // when separate config is used - each blog has own uploads
// so nothing to upload from network admin. // so nothing to upload from network admin.
@ -18,19 +16,42 @@ $upload_blogfiles_enabled = $cdn_mirror || ! is_network_admin() || ! Util_Enviro
$can_purge = Cdn_Util::can_purge( $cdn_engine ); $can_purge = Cdn_Util::can_purge( $cdn_engine );
require W3TC_INC_DIR . '/options/common/header.php'; require W3TC_INC_DIR . '/options/common/header.php';
?>
?>
<p> <p>
<?php <?php
echo wp_kses( echo wp_kses(
sprintf( sprintf(
// translators: 1 HTML strong tag containing CDN Engine value, 2 HTML span tag containing CDN Engine enabled/disabled value. // translators: 1 HTML strong tag containing CDN Engine value, 2 HTML span tag containing CDN Engine enabled/disabled value.
__( __(
'Content Delivery Network support via %1$s is currently %2$s.', 'Content Delivery Network object support via %1$s is currently %2$s and %3$s.',
'w3-total-cache' 'w3-total-cache'
), ),
'<strong>' . Cache::engine_name( $this->_config->get_string( 'cdn.engine' ) ) . '</strong>', '<strong>' . Cache::engine_name( $this->_config->get_string( 'cdn.engine' ) ) . '</strong>',
'<span class="w3tc-' . ( $cdn_enabled ? 'enabled">' . esc_html__( 'enabled', 'w3-total-cache' ) : 'disabled">' . esc_html__( 'disabled', 'w3-total-cache' ) ) . '</span>' '<span class="w3tc-' . ( $cdn_enabled ? 'enabled">' . esc_html__( 'enabled', 'w3-total-cache' ) : 'disabled">' . esc_html__( 'disabled', 'w3-total-cache' ) ) . '</span>',
'<span class="w3tc-' . ( $is_cdn_authorized ? 'authorized">' . esc_html__( 'authorized', 'w3-total-cache' ) : 'not-authorized">' . esc_html__( 'not authorized', 'w3-total-cache' ) ) . '</span>'
),
array(
'strong' => array(),
'span' => array(
'class' => array(),
),
)
);
?>
</p>
<p>
<?php
echo wp_kses(
sprintf(
// translators: 1 HTML strong tag containing CDN Engine value, 2 HTML span tag containing CDN Engine enabled/disabled value.
__(
'Content Delivery Network full-site-delivery support via %1$s is currently %2$s and %3$s.',
'w3-total-cache'
),
'<strong>' . Cache::engine_name( $this->_config->get_string( 'cdnfsd.engine' ) ) . '</strong>',
'<span class="w3tc-' . ( $cdnfsd_enabled ? 'enabled">' . esc_html__( 'enabled', 'w3-total-cache' ) : 'disabled">' . esc_html__( 'disabled', 'w3-total-cache' ) ) . '</span>',
'<span class="w3tc-' . ( $is_cdnfsd_authorized ? 'authorized">' . esc_html__( 'authorized', 'w3-total-cache' ) : 'not-authorized">' . esc_html__( 'not authorized', 'w3-total-cache' ) ) . '</span>'
), ),
array( array(
'strong' => array(), 'strong' => array(),
@ -42,25 +63,67 @@ require W3TC_INC_DIR . '/options/common/header.php';
?> ?>
</p> </p>
<form id="w3tc_cdn" action="admin.php?page=<?php echo esc_attr( $this->_page ); ?>" method="post"> <form id="w3tc_cdn" action="admin.php?page=<?php echo esc_attr( $this->_page ); ?>" method="post">
<?php if ( $cdn_mirror ) : ?> <?php
if ( ! empty( $cdn_engine ) ) {
if ( $cdn_mirror ) {
?>
<p> <p>
Maximize <acronym title="Content Delivery Network">CDN</acronym> usage by <input id="cdn_rename_domain" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="modify attachment URLs" /> or <?php
<input id="cdn_import_library" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="importing attachments into the Media Library" /> echo wp_kses(
sprintf(
// translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag.
__(
'Maximize %1$sCDN%2$s usage by %3$s or %4$s.',
'w3-total-cache'
),
'<acronym title="' . esc_attr__( 'Content Delivery Network', 'w3-total-cache' ) . '">',
'</acronym>',
'<input id="cdn_rename_domain" class="button {nonce: \'' . esc_attr( wp_create_nonce( 'w3tc' ) ) .
'\'}" type="button" value="' . esc_attr__( 'modify attachment URLs' ) . '" />',
'<input id="cdn_import_library" class="button {nonce: \'' . esc_attr( wp_create_nonce( 'w3tc' ) ) .
'\'}" type="button" value="' . esc_attr__( 'importing attachments into the Media Library' ) . '" />'
),
array(
'acronym' => array(
'title' => array(),
),
)
);
?>
</p> </p>
<?php <?php
if ( $can_purge || $cdn_mirror_purge_all ) { if ( $can_purge || $cdn_mirror_purge_all ) {
?> ?>
<p> <p>
<?php <?php
$cdn_purge_button = $can_purge ? '<input id="cdn_purge" class="button {nonce: ' . esc_attr( wp_create_nonce( 'w3tc' ) ) . '}" type="button" value="Purge" /> objects from the <acronym title="Content Delivery Network">CDN</acronym>' : ''; $cdn_purge_button = $can_purge ?
$cdn_mirror_purge_button = $cdn_mirror_purge_all ? ( $can_purge ? ' or ' : '' ) . '<input class="button" type="submit" name="w3tc_flush_cdn" value="purge CDN completely" />' : ''; '<input id="cdn_purge" class="button {nonce: ' . esc_attr( wp_create_nonce( 'w3tc' ) ) .
echo $cdn_purge_button . $cdn_mirror_purge_button; '}" type="button" value="Purge" /> objects from the <acronym title="Content Delivery Network">CDN</acronym>' :
'';
$cdn_mirror_purge_button = $cdn_mirror_purge_all ?
( $can_purge ? ' or ' : '' ) . '<input class="button" type="submit" name="w3tc_flush_cdn" value="purge CDN completely" />' :
'';
echo wp_kses(
$cdn_purge_button . $cdn_mirror_purge_button,
array(
'acronym' => array(
'title' => array(),
),
'input' => array(
'class' => array(),
'id' => array(),
'name' => array(),
'type' => array(),
'value' => array(),
),
)
);
?> ?>
</p> </p>
<?php <?php
} }
?> } else {
<?php else :
echo wp_kses( echo wp_kses(
sprintf( sprintf(
// translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag. // translators: 1 opening HTML acronym tag, 2 closing HTML acronym tag.
@ -80,6 +143,7 @@ require W3TC_INC_DIR . '/options/common/header.php';
?> ?>
<input id="cdn_import_library" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'importing attachments into the Media Library', 'w3-total-cache' ); ?>" />. <input id="cdn_import_library" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'importing attachments into the Media Library', 'w3-total-cache' ); ?>" />.
Check <input id="cdn_queue" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'unsuccessful file transfers', 'w3-total-cache' ); ?>" /> <?php esc_html_e( 'if some objects appear to be missing.', 'w3-total-cache' ); ?> Check <input id="cdn_queue" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'unsuccessful file transfers', 'w3-total-cache' ); ?>" /> <?php esc_html_e( 'if some objects appear to be missing.', 'w3-total-cache' ); ?>
<?php if ( $can_purge ) : ?> <?php if ( $can_purge ) : ?>
<input id="cdn_purge" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'Purge', 'w3-total-cache' ); ?>" /> <input id="cdn_purge" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="<?php esc_attr_e( 'Purge', 'w3-total-cache' ); ?>" />
<?php <?php
@ -101,8 +165,12 @@ require W3TC_INC_DIR . '/options/common/header.php';
); );
?> ?>
<?php endif; ?> <?php endif; ?>
<input id="cdn_rename_domain" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="Modify attachment URLs" /> <?php esc_html_e( 'if the domain name of your site has ever changed.', 'w3-total-cache' ); ?> <input id="cdn_rename_domain" class="button {nonce: '<?php echo esc_attr( wp_create_nonce( 'w3tc' ) ); ?>'}" type="button" value="Modify attachment URLs" /> <?php esc_html_e( 'if the domain name of your site has ever changed.', 'w3-total-cache' ); ?>
<?php endif; ?> <?php
}
}
?>
<p> <p>
<?php <?php
echo wp_kses( echo wp_kses(
@ -351,30 +419,42 @@ require W3TC_INC_DIR . '/options/common/header.php';
</tr> </tr>
<?php endif; ?> <?php endif; ?>
</table> </table>
<?php Util_Ui::postbox_footer(); ?> <?php Util_Ui::postbox_footer(); ?>
<?php if ( ! empty( $cdn_engine ) ) : ?>
<?php Util_Ui::postbox_header( esc_html__( 'Configuration: Objects', 'w3-total-cache' ), '', 'configuration' ); ?> <?php Util_Ui::postbox_header( esc_html__( 'Configuration: Objects', 'w3-total-cache' ), '', 'configuration' ); ?>
<table class="form-table"> <table class="form-table">
<?php <?php
if ( 'google_drive' === $cdn_engine || $known_engines = array(
'highwinds' === $cdn_engine || 'bunnycdn',
'limelight' === $cdn_engine || 'google_drive',
'rackspace_cdn' === $cdn_engine || 'highwinds',
'rscf' === $cdn_engine || 'limelight',
'stackpath' === $cdn_engine || 'rackspace_cdn',
'stackpath2' === $cdn_engine ) { 'rscf',
'stackpath',
'stackpath2',
);
if ( in_array( $cdn_engine, $known_engines, true ) ) {
do_action( 'w3tc_settings_cdn_boxarea_configuration' ); do_action( 'w3tc_settings_cdn_boxarea_configuration' );
} elseif ( Cdn_Util::is_engine( $cdn_engine ) ) { } elseif ( Cdn_Util::is_engine( $cdn_engine ) ) {
include W3TC_INC_DIR . '/options/cdn/' . $cdn_engine . '.php'; include W3TC_INC_DIR . '/options/cdn/' . $cdn_engine . '.php';
} }
?> ?>
</table> </table>
<?php Util_Ui::postbox_footer(); ?> <?php Util_Ui::postbox_footer(); ?>
<?php endif; ?>
<?php do_action( 'w3tc_settings_box_cdnfsd' ); ?> <?php do_action( 'w3tc_settings_box_cdnfsd' ); ?>
<?php
if ( 'bunnycdn' === $cdn_engine || 'bunnycdn' === $cdnfsd_engine ) {
Util_Ui::postbox_header( esc_html__( 'Purge', 'w3-total-cache' ), '', 'purge-urls' );
do_action( 'w3tc_purge_urls_box' );
Util_Ui::postbox_footer();
}
?>
<?php Util_Ui::postbox_header( esc_html__( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?> <?php Util_Ui::postbox_header( esc_html__( 'Advanced', 'w3-total-cache' ), '', 'advanced' ); ?>
<table class="form-table"> <table class="form-table">

View File

@ -70,6 +70,9 @@ do_action( 'w3tc-dashboard-footer' );
<a class="w3tc-footer-link" target="_blank" href="<?php echo esc_url( 'https://www.boldgrid.com/support/w3-total-cache/minify/render-blocking-css/' ); ?>" alt="<?php esc_attr_e( 'Eliminate Render Blocking CSS', 'w3-total-cache' ); ?>"> <a class="w3tc-footer-link" target="_blank" href="<?php echo esc_url( 'https://www.boldgrid.com/support/w3-total-cache/minify/render-blocking-css/' ); ?>" alt="<?php esc_attr_e( 'Eliminate Render Blocking CSS', 'w3-total-cache' ); ?>">
<?php esc_html_e( 'Eliminate Render Blocking CSS', 'w3-total-cache' ); ?> <?php esc_html_e( 'Eliminate Render Blocking CSS', 'w3-total-cache' ); ?>
</a> </a>
<a class="w3tc-footer-link" target="_blank" href="<?php echo esc_url( 'https://www.boldgrid.com/support/w3-total-cache/delay-scripts-tool/' ); ?>" alt="<?php esc_attr_e( 'Delay Scripts', 'w3-total-cache' ); ?>">
<?php esc_html_e( 'Delay Scripts', 'w3-total-cache' ); ?>
</a>
</div> </div>
<div class="w3tc-footer-inner-column-50"> <div class="w3tc-footer-inner-column-50">
<a class="w3tc-footer-link" target="_blank" href="<?php echo esc_url( 'https://www.boldgrid.com/support/w3-total-cache/configuring-lazy-loading-for-your-wordpress-website-with-w3-total-cache/' ); ?>" alt="<?php esc_attr_e( 'Lazy Load Google Maps', 'w3-total-cache' ); ?>"> <a class="w3tc-footer-link" target="_blank" href="<?php echo esc_url( 'https://www.boldgrid.com/support/w3-total-cache/configuring-lazy-loading-for-your-wordpress-website-with-w3-total-cache/' ); ?>" alt="<?php esc_attr_e( 'Lazy Load Google Maps', 'w3-total-cache' ); ?>">

View File

@ -960,12 +960,6 @@ require W3TC_INC_DIR . '/options/common/header.php';
? Util_UI::admin_url( 'upload.php?page=w3tc_extension_page_imageservice' ) ? Util_UI::admin_url( 'upload.php?page=w3tc_extension_page_imageservice' )
: '' : ''
); );
if ( $this->_config->get_boolean( 'extension.imageservice' ) ) {
Extensions_Util::activate_extension( 'imageservice', $this->_config );
} else {
Extensions_Util::deactivate_extension( 'imageservice', $this->_config );
}
?> ?>
<table class="form-table"> <table class="form-table">
<?php <?php

View File

@ -379,7 +379,7 @@ class ServiceRestProxy extends RestProxy
} }
/** /**
* Throws ServiceException if the recieved status code is not expected. * Throws ServiceException if the received status code is not expected.
* *
* @param string $actual The received status code. * @param string $actual The received status code.
* @param string $reason The reason phrase. * @param string $reason The reason phrase.

View File

@ -132,17 +132,19 @@ class Minify_Cache_File {
* *
* @param string $id cache id (e.g. a filename) * @param string $id cache id (e.g. a filename)
* *
* @return string * @return string|false
*/ */
public function fetch($id) public function fetch($id)
{ {
$path = $this->_path . '/' . $id; $path = $this->_path . '/' . $id;
$data = @file_get_contents($path . '_meta'); $data = @file_get_contents($path . '_meta');
if ($data) { if ( ! empty( $data ) ) {
$data = @unserialize($data); $data = @unserialize($data);
if (!is_array($data)) if (!is_array($data))
$data = array(); $data = array();
} else {
$data = array();
} }
if (is_readable($path)) { if (is_readable($path)) {

View File

@ -589,7 +589,7 @@ class W3tcOAuthUtil {
$value = isset($split[1]) ? W3tcOAuthUtil::urldecode_rfc3986($split[1]) : ''; $value = isset($split[1]) ? W3tcOAuthUtil::urldecode_rfc3986($split[1]) : '';
if (isset($parsed_parameters[$parameter])) { if (isset($parsed_parameters[$parameter])) {
// We have already recieved parameter(s) with this name, so add to the list // We have already received parameter(s) with this name, so add to the list
// of parameters with this name // of parameters with this name
if (is_scalar($parsed_parameters[$parameter])) { if (is_scalar($parsed_parameters[$parameter])) {

View File

@ -8,18 +8,35 @@
.w3tc-card-container { .w3tc-card-container {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.w3tc-card-container-new {
grid-template-columns: 1fr;
row-gap: 2em;
}
}
@media screen and (min-width: 560px) {
.w3tc-card-container-new {
grid-template-columns: repeat(auto-fit, minmax(275px, .4fr));
grid-gap: 3em 4%;
}
} }
@media screen and (min-width: 900px) { @media screen and (min-width: 900px) {
.w3tc-card-container { .w3tc-card-container {
grid-template-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
} }
.w3tc-card-container-new {
grid-gap: 3.75em 5%;
}
} }
@media screen and (min-width: 1400px) { @media screen and (min-width: 1400px) {
.w3tc-card-container { .w3tc-card-container {
grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr 1fr;
} }
.w3tc-card-container-new {
grid-gap: 6em 7%;
}
} }
.w3tc-page-container { .w3tc-page-container {
@ -32,11 +49,55 @@
width: 100%; width: 100%;
} }
.w3tc-card-container-divider {
border-top-color: #CFCFD0;
}
.w3tc-card-container { .w3tc-card-container {
display: grid; display: grid;
grid-gap: 2em; grid-gap: 2em;
} }
.w3tc-card-container-new {
display: grid;
justify-content: center;
}
.w3tc-card-container,
.w3tc-card-container-new {
margin-top: 5em;
margin-bottom: 5em;
}
.w3tc-card-container-title {
text-align: center;
font-weight: 600 !important;
font-size: 30px !important;
margin: 10px 0 1em !important;
box-shadow: 0 1px 1px -1px #888;
background: #fff;
background-image: none;
background-image: none;
padding: 33px 10px !important;
background-image: linear-gradient( to right, #f9f9f9, #f9f9f9, #f9f9f9, #f0f0f0, #e7f3f3, #56bec1, #16252c);
position: relative;
padding-right: 280px;
border: 1px solid #c3c4c7;
}
.w3tc-card-container-title::after {
background-image: url("../img/transparent-comet.png");
background-repeat: no-repeat;
background-position: top right;
background-size: 100% 100%;
content: "";
width: 251px;
height: 104px;
position: absolute;
top: 0;
right: 0;
}
.w3tc-card { .w3tc-card {
background: #fff; background: #fff;
border: 1px solid #ddd; border: 1px solid #ddd;
@ -45,6 +106,11 @@
position: relative; position: relative;
} }
.w3tc-card-container-new .w3tc-card {
box-shadow: rgb(38, 57, 77) 0px 20px 30px -10px;;
border: none;
}
.w3tc-card-title { .w3tc-card-title {
height: 2.5em; height: 2.5em;
} }
@ -104,61 +170,18 @@
} }
.w3tc-card-ribbon-new { .w3tc-card-ribbon-new {
height: 75px;
overflow: hidden;
position: absolute;
right: -5px;
top: -5px;
text-align: right;
width: 75px;
z-index: 1;
}
.w3tc-card-ribbon-new span {
background: #30bec3;
box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 0.5);
color: #fff;
display: block;
font-size: 12px;
font-weight: bold;
line-height: 20px;
position: absolute;
right: -21px;
text-transform: uppercase;
text-align: center; text-align: center;
top: 19px; padding: 7px 5px;
transform: rotate(45deg); background: #69BCC3;
-webkit-transform: rotate(45deg); color: #fff;
/* Needed for Safari */
width: 100px;
} }
.w3tc-card-ribbon-new span::before { .w3tc-card-ribbon-new b {
border-left: 3px solid #30bec3; font-weight: 600;
border-right: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #30bec3;
content: '';
left: 0px;
position: absolute;
top: 100%;
z-index: -1;
}
.w3tc-card-ribbon-new span::after {
border-right: 3px solid #30bec3;
border-left: 3px solid transparent;
border-bottom: 3px solid transparent;
border-top: 3px solid #30bec3;
content: '';
position: absolute;
right: 0%;
top: 100%;
z-index: -1;
} }
.w3tc-card-footer { .w3tc-card-footer {
margin: 0 0 10px 10px; margin: 0 0 20px 10px;
} }
.w3tc-card-footer>div { .w3tc-card-footer>div {

View File

@ -60,12 +60,14 @@
display: none; display: none;
} }
.w3tc-enabled { .w3tc-enabled,
.w3tc-authorized {
color: #090; color: #090;
font-weight: 700; font-weight: 700;
} }
.w3tc-disabled { .w3tc-disabled,
.w3tc-not-authorized {
color: #f00; color: #f00;
font-weight: 700; font-weight: 700;
} }

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="149px" height="43px" viewBox="0 0 149 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 59 (86127) - https://sketch.com -->
<title>bunnynet-light</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="29.4352883%" y1="45.3176687%" x2="80.6309178%" y2="58.7602308%" id="linearGradient-1">
<stop stop-color="#FEBE2D" offset="0%"></stop>
<stop stop-color="#F85E23" offset="100%"></stop>
</linearGradient>
<linearGradient x1="-33.9398264%" y1="50.04095%" x2="153.690572%" y2="50.04095%" id="linearGradient-2">
<stop stop-color="#FBAA19" offset="0%"></stop>
<stop stop-color="#EF3E23" offset="100%"></stop>
</linearGradient>
<linearGradient x1="32.8908646%" y1="96.6666487%" x2="67.1130842%" y2="3.11111053%" id="linearGradient-3">
<stop stop-color="#F78D1E" offset="0%"></stop>
<stop stop-color="#F37121" offset="100%"></stop>
</linearGradient>
<linearGradient x1="14.4028408%" y1="75.177305%" x2="63.2274953%" y2="12.4480313%" id="linearGradient-4">
<stop stop-color="#FEBE2D" offset="0%"></stop>
<stop stop-color="#F04E23" offset="100%"></stop>
</linearGradient>
<linearGradient x1="69.8803244%" y1="3.21352923%" x2="33.1012862%" y2="81.5809617%" id="linearGradient-5">
<stop stop-color="#EA4425" offset="0%"></stop>
<stop stop-color="#FDBB27" offset="100%"></stop>
</linearGradient>
<linearGradient x1="-40.1271778%" y1="49.9893198%" x2="144.708119%" y2="49.9893198%" id="linearGradient-6">
<stop stop-color="#F47920" offset="0%"></stop>
<stop stop-color="#E93825" offset="100%"></stop>
</linearGradient>
<linearGradient x1="-143.227273%" y1="49.9166667%" x2="243.363636%" y2="49.9166667%" id="linearGradient-7">
<stop stop-color="#FDCA0B" offset="0%"></stop>
<stop stop-color="#F5841F" offset="100%"></stop>
</linearGradient>
<linearGradient x1="39.6769732%" y1="-25.0126839%" x2="63.8868118%" y2="131.608321%" id="linearGradient-8">
<stop stop-color="#E73C25" offset="0%"></stop>
<stop stop-color="#FAA21B" offset="100%"></stop>
</linearGradient>
<linearGradient x1="-562.993864%" y1="49.9979816%" x2="562.904684%" y2="49.9979816%" id="linearGradient-9">
<stop stop-color="#FDBA12" offset="0%"></stop>
<stop stop-color="#F7921E" offset="100%"></stop>
</linearGradient>
<linearGradient x1="1.98261285%" y1="41.5011038%" x2="106.167127%" y2="60.0441501%" id="linearGradient-10">
<stop stop-color="#FEBE2D" offset="0%"></stop>
<stop stop-color="#F04E23" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="bunnynet-light">
<path d="M125.05,30.91 C124.518166,30.9565037 124.096504,31.3781664 124.05,31.91 C123.97,32.5 124.29,32.91 124.8,32.91 C125.328244,32.855872 125.745872,32.438244 125.8,31.91 C125.869942,31.6721932 125.822688,31.4152993 125.672701,31.2179474 C125.522713,31.0205954 125.287851,30.9062836 125.04,30.91 L125.05,30.91 Z M132.41,25.2 C131.302177,25.175309 130.263866,25.7382026 129.68,26.68 L129.88,25.28 L128.17,25.28 L127.08,32.81 L128.79,32.81 L129.33,29.11 C129.384558,27.9425258 130.313081,27.0053651 131.48,26.94 C132.48,26.94 132.95,27.59 132.8,28.64 L132.2,32.81 L133.92,32.81 L134.6,28.11 C134.86,26.32 134.03,25.2 132.41,25.2 L132.41,25.2 Z M139.62,25.2 C137.461113,25.2377633 135.678985,26.8990689 135.49,29.05 C135.17,31.31 136.37,32.86 138.56,32.86 C139.738178,32.8729989 140.871234,32.407508 141.7,31.57 L140.93,30.57 C140.395352,31.0955617 139.679582,31.3961851 138.93,31.41 C138.464676,31.4352649 138.00996,31.2649522 137.675728,30.9402155 C137.341496,30.6154788 137.158153,30.1658589 137.17,29.7 L142.36,29.7 C142.93,26.96 142.11,25.23 139.64,25.23 L139.62,25.2 Z M137.29,28.44 C137.497188,27.4117835 138.381857,26.6594015 139.43,26.62 C139.910353,26.570951 140.384163,26.7609266 140.697575,27.1282375 C141.010987,27.4955484 141.124031,27.9933518 141,28.46 L137.29,28.44 Z M147.12,31 C146.812403,31.1730344 146.471536,31.2787031 146.12,31.31 C145.66,31.31 145.42,31.07 145.52,30.31 L146.01,26.91 L148.01,26.91 L148.2,25.58 L146.2,25.58 L146.5,23.5 L144.81,23.5 L144.51,25.58 L143.51,25.58 L143.33,26.91 L144.33,26.91 L143.8,30.63 C143.57,32.18 144.39,32.89 145.54,32.89 C146.191356,32.8737148 146.826556,32.683845 147.38,32.34 L147.12,31 Z" id="Shape" fill="url(#linearGradient-1)"></path>
<path d="M44.62,22.83 C45.1588263,22.8259486 45.6468532,23.1474113 45.8558665,23.6440637 C46.0648797,24.1407162 45.9535722,24.7144053 45.5739942,25.0968589 C45.1944162,25.4793125 44.6215835,25.5949465 44.1233677,25.3896875 C43.625152,25.1844284 43.3,24.6988415 43.3,24.16 C43.3,23.4293489 43.8893695,22.8354936 44.62,22.83 L44.62,22.83 Z M57.83,19.14 C58.9551033,18.281581 60.3250401,17.8050813 61.74,17.78 C63.4161637,17.7558263 65.0194182,18.464326 66.13,19.72 C67.4152379,21.3588232 67.9161107,23.4793065 67.5,25.52 C67.1623114,28.9990404 64.8129084,31.9553726 61.5,33.07 C60.8263376,33.2600615 60.1299562,33.3576222 59.43,33.36 C57.8816051,33.4313238 56.4050754,32.7024996 55.52,31.43 L55.34,32.71 C55.3164857,32.8301195 55.2123754,32.9175722 55.09,32.92 L52,32.92 C51.9355875,32.924029 51.8728997,32.8982164 51.83,32.85 C51.8055468,32.7924915 51.8055468,32.7275085 51.83,32.67 L52.9,25.29 L48.9,25.29 C48.2781817,25.284569 47.775431,24.7818183 47.77,24.16 L47.77,24.16 C47.7575313,23.5562663 48.2180121,23.0475446 48.82,23 L57.44,23 C56.8400906,23.7351644 56.4527724,24.6204631 56.32,25.56 C56.01,27.71 57.08,29.72 59.41,29.72 C61.7284521,29.610167 63.621276,27.8276871 63.87,25.52 L63.87,25.52 C64.17,23.41 62.96,21.41 60.72,21.41 L50.89,21.41 C50.2643041,21.4045112 49.7599759,20.89572 49.76,20.27 L49.76,20.27 C49.765431,19.6481817 50.2681817,19.145431 50.89,19.14 L53.74,19.14 L54.55,13.48 C54.5735143,13.3598805 54.6776246,13.2724278 54.8,13.27 L58,13.27 C58.0602316,13.2724121 58.11735,13.2974014 58.16,13.34 C58.1844532,13.3975085 58.1844532,13.4624915 58.16,13.52 L57.35,19.14 L57.83,19.14 Z M77.39,31.62 C76.3368829,32.7860409 74.8199241,33.4236033 73.25,33.36 C69.31,33.36 68.25,30.47 68.74,27.05 L70,18.44 C70.0228017,18.3178878 70.1259798,18.2270911 70.25,18.22 L73.4,18.22 C73.4625924,18.2214819 73.521259,18.2508153 73.56,18.3 C73.5839618,18.3541336 73.5839618,18.4158664 73.56,18.47 L72.44,26.22 C72.18,28.06 72.44,29.72 74.59,29.71 C76.74,29.7 77.59,28.23 77.92,26.29 L79.05,18.44 C79.0728017,18.3178878 79.1759798,18.2270911 79.3,18.22 L82.47,18.22 C82.5325924,18.2214819 82.591259,18.2508153 82.63,18.3 C82.6539618,18.3541336 82.6539618,18.4158664 82.63,18.47 L80.63,32.71 C80.6064857,32.8301195 80.5023754,32.9175722 80.38,32.92 L77.38,32.92 C77.3155875,32.924029 77.2528997,32.8982164 77.21,32.85 C77.1686193,32.7997753 77.1504517,32.7343716 77.16,32.67 L77.31,31.62 L77.39,31.62 Z M88.25,19.51 C89.3060183,18.3610798 90.8103096,17.7294235 92.37,17.78 C96.28,17.78 97.37,20.66 96.85,24.12 L95.61,32.71 C95.5947951,32.8307149 95.491665,32.9209538 95.37,32.92 L92.2,32.92 C92.1384675,32.9240125 92.0788145,32.8979143 92.04,32.85 C91.9946134,32.8019485 91.9758988,32.7345759 91.99,32.67 L93.1,25 C93.36,23.19 93.17,21.47 90.98,21.48 C88.79,21.49 87.98,22.99 87.68,24.9 L86.54,32.76 C86.5208281,32.8785613 86.4200571,32.966736 86.3,32.97 L83.13,32.97 C83.0658326,32.9725973 83.0037338,32.9470272 82.96,32.9 C82.9343315,32.8427453 82.9343315,32.7772547 82.96,32.72 L84.96,18.49 C84.979274,18.3659182 85.0844746,18.2733416 85.21,18.27 L88.21,18.27 C88.2733359,18.2683216 88.3333412,18.2983242 88.37,18.35 C88.4153367,18.3939706 88.4343118,18.4584857 88.42,18.52 L88.27,19.52 L88.25,19.51 Z M103.14,19.51 C104.196018,18.3610798 105.70031,17.7294235 107.26,17.78 C111.17,17.78 112.26,20.66 111.74,24.12 L110.5,32.71 C110.480828,32.8285613 110.380057,32.916736 110.26,32.92 L107.09,32.92 C107.028468,32.9240125 106.968814,32.8979143 106.93,32.85 C106.884613,32.8019485 106.865899,32.7345759 106.88,32.67 L108,25 C108.26,23.19 108.07,21.47 105.88,21.48 C103.69,21.49 102.88,22.99 102.57,24.9 L101.44,32.76 C101.420828,32.8785613 101.320057,32.966736 101.2,32.97 L98,32.97 C97.9358326,32.9725973 97.8737338,32.9470272 97.83,32.9 C97.8043315,32.8427453 97.8043315,32.7772547 97.83,32.72 L99.83,18.49 C99.8485019,18.3694548 99.9483039,18.2779697 100.07,18.27 L103.07,18.27 C103.133336,18.2683216 103.193341,18.2983242 103.23,18.35 C103.270929,18.3965159 103.289228,18.458732 103.28,18.52 L103.13,19.52 L103.14,19.51 Z M115.54,32.13 L112.54,18.52 C112.506216,18.4576135 112.506216,18.3823865 112.54,18.32 C112.58406,18.258616 112.654456,18.2215656 112.73,18.2199645 L116.11,18.2199645 C116.212,18.2181356 116.300585,18.2898471 116.32,18.39 L118.07,27.2 L122.33,18.37 C122.36633,18.2801743 122.453111,18.2210058 122.55,18.2199645 L126,18.2199645 C126.076031,18.2194709 126.145787,18.2620992 126.18,18.33 C126.219299,18.3980682 126.219299,18.4819318 126.18,18.55 L116.4,37.76 C116.360626,37.8459108 116.274501,37.9007177 116.18,37.9001527 L112.79,37.9001527 C112.713286,37.9030681 112.642265,37.8596661 112.61,37.79 C112.570701,37.7219318 112.570701,37.6380682 112.61,37.57 L115.54,32.13 Z" id="Shape" fill="#183D6D"></path>
<path d="M21,6.85 L30.87,12.21 L21.75,0 C20.2759177,1.97822822 19.9888984,4.59967135 21,6.85 L21,6.85 Z" id="Path" fill="url(#linearGradient-2)"></path>
<path d="M16.54,26.73 C17.7800264,26.730049 18.7862599,27.7333715 18.789911,28.9733925 C18.7935429,30.2134136 17.7932196,31.2226286 16.5532149,31.23 C15.3132102,31.2372927 14.3010225,30.2399774 14.29,29 C14.2846647,28.3998052 14.5193602,27.8223574 14.9418967,27.396065 C15.3644332,26.9697726 15.9397815,26.73 16.54,26.73 L16.54,26.73 Z" id="Path" fill="url(#linearGradient-3)"></path>
<path d="M9.67,1.79 L37.31,16.79 C37.7711606,17.0143241 38.0638473,17.4821741 38.0638473,17.995 C38.0638473,18.5078259 37.7711606,18.9756759 37.31,19.2 C35.2195524,20.4579157 32.9301642,21.3506757 30.54,21.84 L24.79,33.64 C24.79,33.64 22.97,37.78 17.96,36.19 C20.06,34.09 22.6,32.19 22.6,28.96 C22.6,25.6076316 19.8823684,22.8900001 16.53,22.8900001 C13.1776316,22.8900001 10.46,25.6076316 10.46,28.96 C10.46,33.18 14.62,34.96 16.93,37.89 C17.9703951,39.3627359 17.832531,41.363854 16.6,42.68 C13.73,39.84 8.18,35.05 5.9,31.91 C4.65347852,30.3269066 3.96762686,28.3748672 3.95,26.36 C4.17432898,21.9678993 7.12448134,18.1862677 11.33,16.9 C12.5891396,16.5332363 13.8997077,16.3744819 15.21,16.43 C17.0369827,16.5684111 18.8116805,17.1042333 20.41,18 C22.86,19.44 24.05,19.06 25.74,17.64 C26.74,16.82 27.83,14.15 26.14,13.53 C25.587447,13.3497251 25.022661,13.2093641 24.45,13.11 C21.31,12.5 15.82,11.92 13.8,10.77 C10.59,9 8.43,5.35 9.67,1.79 Z" id="Path" fill="url(#linearGradient-4)"></path>
<path d="M22.55,28.99 C23.83,22.26 17,15.84 11.76,16.8 L12.11,16.72 C11.83,16.78 11.56,16.85 11.3,16.93 C7.09448134,18.2162677 4.14432898,21.9978993 3.92,26.39 C3.95187229,28.4107619 4.65553172,30.3634168 5.92,31.94 C8.2,35.08 13.75,39.87 16.62,42.71 C17.852531,41.393854 17.9903951,39.3927359 16.95,37.92 C14.59,35 10.43,33.21 10.43,29 C10.43,25.6476316 13.1476316,22.93 16.5,22.93 C19.8523684,22.93 22.57,25.6476316 22.57,29 L22.55,28.99 Z" id="Shape" fill="url(#linearGradient-5)"></path>
<path d="M9.67,1.79 L30.67,13.23 L30.67,13.23 L31.27,13.56 C31.77,13.95 32.27,14.73 31.62,16.17 C30.62,18.32 26.62,20.4 22.01,18.77 C23.45,19.19 24.43,18.71 25.69,17.65 C26.69,16.83 27.78,14.16 26.09,13.54 C25.537447,13.3597251 24.972661,13.2193641 24.4,13.12 C21.26,12.51 15.77,11.93 13.75,10.78 C10.59,9 8.43,5.35 9.67,1.79 Z" id="Path" fill="url(#linearGradient-6)"></path>
<path d="M9.67,1.79 C11.84,9.79 25.05,10.45 31.67,13.79 L9.67,1.79 Z" id="Path" fill="url(#linearGradient-7)"></path>
<path d="M16.9,37.92 C14.59,35 10.43,33.21 10.43,29 C10.4418178,25.946602 12.7199738,23.3772532 15.75,23 C10.9243431,23.0164606 7.0164606,26.9243431 6.99998539,31.75 C6.99890621,32.3413162 7.05922982,32.9311471 7.18,33.51 C9.09,35.67 11.85,38.22 14.18,40.38 C15.09,41.23 15.93,42.03 16.62,42.71 C17.1941689,42.0447548 17.544076,41.2154751 17.62,40.34 L17.62,40.34 C17.6746432,39.473467 17.4194484,38.6157289 16.9,37.92 L16.9,37.92 Z" id="Path" fill="url(#linearGradient-8)"></path>
<path d="M22.52,29.71 C22.5515717,29.4712681 22.5682706,29.2308043 22.57,28.99 C23.83,22.26 17,15.84 11.76,16.8 C12.878886,16.5296125 14.0297792,16.4151962 15.18,16.46 C22.05,16.74 23.97,24.08 22.52,29.71 Z" id="Path" fill="url(#linearGradient-9)"></path>
<path d="M2.26,14.84 L2.26,14.84 C3.50977937,14.8455057 4.52,15.8602085 4.52,17.11 L4.52,19.37 L2.26,19.37 C1.01183647,19.37 0,18.3581635 0,17.11 L0,17.11 C0,15.8602085 1.01022063,14.8455057 2.26,14.84 L2.26,14.84 Z" id="Path" fill="url(#linearGradient-10)"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -153,7 +153,7 @@ var W3tc_Lightbox = {
* adds all controls of the form to the url * adds all controls of the form to the url
*/ */
load_form: function(url, form_selector, callback) { load_form: function(url, form_selector, callback) {
data = {} data = {};
var v = jQuery(form_selector).find('input').each(function(i) { var v = jQuery(form_selector).find('input').each(function(i) {
var name = jQuery(this).attr('name'); var name = jQuery(this).attr('name');
var type = jQuery(this).attr('type'); var type = jQuery(this).attr('type');

View File

@ -317,6 +317,57 @@ function w3tc_csp_reference() {
}); });
} }
/**
* Bunny CDN check.
*
* Prevent enabling Bunny CDN ("bunnycdn" engine) for both CDN and CDNFSD.
*
* @since X.X.X
*
* @returns null
*/
function cdn_bunnycdn_check() {
// Prevents JS error for non W3TC pages.
if (typeof w3tcData === 'undefined') {
return;
}
var $cdn_enabled = jQuery('#cdn__enabled'),
$cdn_engine = jQuery('#cdn__engine'),
$cdnfsd_enabled = jQuery('#cdnfsd__enabled'),
$cdnfsd_engine = jQuery('#cdnfsd__engine'),
cdn_enabled = $cdn_enabled.is(':checked'),
cdn_engine = $cdn_engine.find(':selected').val(),
cdnfsd_enabled = $cdnfsd_enabled.is(':checked'),
cdnfsd_engine = $cdnfsd_engine.find(':selected').val(),
$cdn_inside = jQuery('#cdn .inside');
if (cdn_enabled && cdnfsd_enabled && 'bunnycdn' === cdn_engine && cdnfsd_engine === cdn_engine ) {
// Reset to what was last saved.
$cdn_enabled.prop('checked', w3tcData.cdnEnabled);
$cdn_engine.val(w3tcData.cdnEngine).change();
$cdnfsd_enabled.prop('checked', w3tcData.cdnfsdEnabled);
$cdnfsd_engine.val(w3tcData.cdnfsdEngine).change();
// Display a warning.
jQuery('<div/>', {
class: 'notice notice-warning',
id: 'w3tc-bunnycdn-warning',
text: w3tcData.bunnyCdnWarning
}).prependTo($cdn_inside);
} else {
// Remove the warning.
jQuery('#w3tc-bunnycdn-warning').remove();
}
}
/**
* Cloudfront CDN check.
*
* When CDN is enabled as "cf" or "cf2", then display a notice about possible charges.
*
* @returns null
*/
function cdn_cf_check() { function cdn_cf_check() {
// Prevents JS error for non W3TC pages. // Prevents JS error for non W3TC pages.
if (typeof w3tcData === 'undefined') { if (typeof w3tcData === 'undefined') {
@ -387,8 +438,13 @@ function debounce(func){
}; };
} }
// On document ready.
jQuery(function() { jQuery(function() {
// general page // Global vars.
var $cdn_enabled = jQuery('#cdn__enabled'),
$cdn_engine = jQuery('#cdn__engine');
// General page.
jQuery('.w3tc_read_technical_info').on('click', function() { jQuery('.w3tc_read_technical_info').on('click', function() {
jQuery('.w3tc_technical_info').toggle(); jQuery('.w3tc_technical_info').toggle();
}); });
@ -424,10 +480,16 @@ jQuery(function() {
}); });
}); });
// Prevent enabling Bunny CDN for both CDN and CDNFSD.
$cdn_enabled.on('click', cdn_bunnycdn_check);
$cdn_engine.on('change', cdn_bunnycdn_check);
jQuery('#cdnfsd__enabled').on('click', cdn_bunnycdn_check);
jQuery('#cdnfsd__engine').on('change', cdn_bunnycdn_check);
// When CDN is enabled as "cf" or "cf2", then display a notice about possible charges. // When CDN is enabled as "cf" or "cf2", then display a notice about possible charges.
cdn_cf_check(); cdn_cf_check();
jQuery('#cdn__enabled').on('click', cdn_cf_check); $cdn_enabled.on('click', cdn_cf_check);
jQuery('#cdn__engine').on('change', cdn_cf_check); $cdn_engine.on('change', cdn_cf_check);
/** /**
* CDN page. * CDN page.
@ -435,7 +497,7 @@ jQuery(function() {
*/ */
jQuery('[name="cdn__flush_manually"]').on('click', cdn_cf_check); jQuery('[name="cdn__flush_manually"]').on('click', cdn_cf_check);
// pagecache page // Pagecache page.
w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').length); w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').length);
jQuery('#pgcache__reject__logged_roles').on('click', function() { jQuery('#pgcache__reject__logged_roles').on('click', function() {
w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').length); w3tc_input_enable('#pgcache_reject_roles input[type=checkbox]', jQuery('#pgcache__reject__logged_roles:checked').length);
@ -449,7 +511,7 @@ jQuery(function() {
jQuery('#pgcache__cache__nginx_handle_xml').attr('checked', this.checked); jQuery('#pgcache__cache__nginx_handle_xml').attr('checked', this.checked);
}); });
// browsercache page // Browsercache page.
w3tc_toggle2('browsercache_last_modified', ['browsercache__cssjs__last_modified', 'browsercache__html__last_modified', w3tc_toggle2('browsercache_last_modified', ['browsercache__cssjs__last_modified', 'browsercache__html__last_modified',
'browsercache__other__last_modified' 'browsercache__other__last_modified'
]); ]);
@ -477,7 +539,7 @@ jQuery(function() {
w3tc_security_headers(); w3tc_security_headers();
// minify page // Minify page.
w3tc_input_enable('.html_enabled', jQuery('#minify__html__enable:checked').length); w3tc_input_enable('.html_enabled', jQuery('#minify__html__enable:checked').length);
w3tc_input_enable('.js_enabled', jQuery('#minify__js__enable:checked').length); w3tc_input_enable('.js_enabled', jQuery('#minify__js__enable:checked').length);
w3tc_input_enable('.css_enabled', jQuery('#minify__css__enable:checked').length); w3tc_input_enable('.css_enabled', jQuery('#minify__css__enable:checked').length);
@ -663,7 +725,7 @@ jQuery(function() {
return true; return true;
}); });
// CDN // CDN.
jQuery('.w3tc-tab').on('click', function() { jQuery('.w3tc-tab').on('click', function() {
jQuery('.w3tc-tab-content').hide(); jQuery('.w3tc-tab-content').hide();
jQuery(this.rel).show(); jQuery(this.rel).show();
@ -1126,7 +1188,7 @@ jQuery(function() {
}, 'json'); }, 'json');
}); });
// CDN cnames // CDN cnames.
jQuery('body').on('click', '#cdn_cname_add', function() { jQuery('body').on('click', '#cdn_cname_add', function() {
jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>'); jQuery('#cdn_cnames').append('<li><input type="text" name="cdn_cnames[]" value="" size="60" /> <input class="button cdn_cname_delete" type="button" value="Delete" /> <span></span></li>');
w3tc_cdn_cnames_assign(); w3tc_cdn_cnames_assign();
@ -1164,7 +1226,7 @@ jQuery(function() {
return ret; return ret;
}); });
// add sortable // Add sortable.
if (jQuery.ui && jQuery.ui.sortable) { if (jQuery.ui && jQuery.ui.sortable) {
jQuery('#js_files,#css_files').sortable({ jQuery('#js_files,#css_files').sortable({
axis: 'y', axis: 'y',
@ -1199,7 +1261,7 @@ jQuery(function() {
}); });
} }
// show hide rules // Show hide rules.
jQuery('.w3tc-show-rules').on('click', function() { jQuery('.w3tc-show-rules').on('click', function() {
var btn = jQuery(this), var btn = jQuery(this),
rules = btn.parent().find('.w3tc-rules'); rules = btn.parent().find('.w3tc-rules');
@ -1214,7 +1276,7 @@ jQuery(function() {
}); });
// show hide missing files // Show hide missing files.
jQuery('.w3tc-show-required-changes').on('click', function() { jQuery('.w3tc-show-required-changes').on('click', function() {
var btn = jQuery(this), var btn = jQuery(this),
rules = jQuery('.w3tc-required-changes'); rules = jQuery('.w3tc-required-changes');
@ -1228,7 +1290,7 @@ jQuery(function() {
} }
}); });
// show hide missing files // Show hide missing files.
jQuery('.w3tc-show-ftp-form').on('click', function() { jQuery('.w3tc-show-ftp-form').on('click', function() {
var btn = jQuery(this), var btn = jQuery(this),
rules = jQuery('.w3tc-ftp-form'); rules = jQuery('.w3tc-ftp-form');
@ -1242,7 +1304,7 @@ jQuery(function() {
} }
}); });
// show hide missing files // Show hide missing files.
jQuery('.w3tc-show-technical-info').on('click', function() { jQuery('.w3tc-show-technical-info').on('click', function() {
var btn = jQuery(this), var btn = jQuery(this),
info = jQuery('.w3tc-technical-info'); info = jQuery('.w3tc-technical-info');
@ -1256,18 +1318,18 @@ jQuery(function() {
} }
}); });
// add ignore class to the ftp form elements // Add ignore class to the ftp form elements.
jQuery('#ftp_upload_form').find('input').each(function() { jQuery('#ftp_upload_form').find('input').each(function() {
jQuery(this).addClass('w3tc-ignore-change'); jQuery(this).addClass('w3tc-ignore-change');
}); });
// toggle hiddent content // Toggle hidden content.
jQuery('.w3tc_link_more').on('click', function() { jQuery('.w3tc_link_more').on('click', function() {
var target_class = jQuery(this).metadata().for_class; var target_class = jQuery(this).metadata().for_class;
jQuery('.' + target_class).slideToggle(); jQuery('.' + target_class).slideToggle();
}); });
// check for unsaved changes // Check for unsaved changes.
jQuery('#w3tc input,#w3tc select,#w3tc textarea').on('change', function() { jQuery('#w3tc input,#w3tc select,#w3tc textarea').on('change', function() {
var ignore = false; var ignore = false;
jQuery(this).parents().addBack().each(function() { jQuery(this).parents().addBack().each(function() {
@ -1284,7 +1346,6 @@ jQuery(function() {
jQuery('body').on('click', '.w3tc-button-save', w3tc_beforeupload_unbind); jQuery('body').on('click', '.w3tc-button-save', w3tc_beforeupload_unbind);
jQuery('.contextual-help-tabs ul li a').on('click', function() { jQuery('.contextual-help-tabs ul li a').on('click', function() {
var id = jQuery(this).attr('aria-controls'); var id = jQuery(this).attr('aria-controls');
var i = jQuery('#' + id + ' .w3tchelp_content'); var i = jQuery('#' + id + ' .w3tchelp_content');
@ -1321,7 +1382,7 @@ jQuery(function() {
}); });
} }
// extensions page // Extensions page.
jQuery('.w3tc_extensions_manage_input_checkall').on('click', function(v) { jQuery('.w3tc_extensions_manage_input_checkall').on('click', function(v) {
var c = jQuery(this).is(':checked'); var c = jQuery(this).is(':checked');
@ -1332,7 +1393,7 @@ jQuery(function() {
}); });
}); });
// gopro block // Go Pro block.
jQuery('.w3tc-gopro-more').on('click', function(e) { jQuery('.w3tc-gopro-more').on('click', function(e) {
e.preventDefault(); e.preventDefault();
if (!jQuery(this).data('expanded')) { if (!jQuery(this).data('expanded')) {
@ -1357,13 +1418,13 @@ jQuery(function() {
} }
}); });
// Bootstrap dropdown toggle // Bootstrap dropdown toggle.
jQuery('.dropdown-toggle').on('click', function() { jQuery('.dropdown-toggle').on('click', function() {
jQuery('.dropdown-toggle').not(this).next().hide(); jQuery('.dropdown-toggle').not(this).next().hide();
jQuery(this).next().toggle(); jQuery(this).next().toggle();
}); });
// Bootstrap dropdown hide on click away // Bootstrap dropdown hide on click away.
jQuery(document).mouseup(function(e) { jQuery(document).mouseup(function(e) {
var dropdowns = jQuery('.dropdown-toggle'); var dropdowns = jQuery('.dropdown-toggle');
if (!dropdowns.is(e.target) && dropdowns.has(e.target).length === 0) { if (!dropdowns.is(e.target) && dropdowns.has(e.target).length === 0) {
@ -1371,7 +1432,7 @@ jQuery(function() {
} }
}); });
// Options menu achor links // Options menu anchor links.
jQuery('#w3tc-top-nav-bar a').on('click', function(e) { jQuery('#w3tc-top-nav-bar a').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1385,7 +1446,7 @@ jQuery(function() {
} }
}); });
// Options menu achor links // Options menu anchor links.
jQuery('#w3tc-options-menu a').on('click', function(e) { jQuery('#w3tc-options-menu a').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1399,7 +1460,7 @@ jQuery(function() {
} }
}); });
// Form control bar buttons // Form control bar buttons.
jQuery('.w3tc_form_bar input').on('click', function(e) { jQuery('.w3tc_form_bar input').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1413,7 +1474,7 @@ jQuery(function() {
} }
}); });
// Footer links // Footer links.
jQuery('#w3tc-footer a').on('click', function(e) { jQuery('#w3tc-footer a').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1427,7 +1488,7 @@ jQuery(function() {
} }
}); });
// General settings advanced options links // General settings advanced options links.
jQuery('.advanced-settings a').on('click', function(e) { jQuery('.advanced-settings a').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1441,7 +1502,7 @@ jQuery(function() {
} }
}); });
// Extra links // Extra links.
jQuery('.extra-link a').on('click', function(e) { jQuery('.extra-link a').on('click', function(e) {
if (window.w3tc_ga) { if (window.w3tc_ga) {
w3tc_ga( w3tc_ga(
@ -1582,13 +1643,13 @@ jQuery(function() {
var hash = window.location.hash; var hash = window.location.hash;
if (hash !== "") { if (hash !== "") {
// Start at top of page rather than instantly loading at the anchor point // Start at top of page rather than instantly loading at the anchor point.
window.scrollTo(0, 0); window.scrollTo(0, 0);
var wpadminbar_height = (jQuery(window).width() > 600 && jQuery('#wpadminbar').length) ? jQuery('#wpadminbar').outerHeight() : 0, var wpadminbar_height = (jQuery(window).width() > 600 && jQuery('#wpadminbar').length) ? jQuery('#wpadminbar').outerHeight() : 0,
nav_bar_height = (jQuery('#w3tc-top-nav-bar').length) ? jQuery('#w3tc-top-nav-bar').outerHeight() : 0, nav_bar_height = (jQuery('#w3tc-top-nav-bar').length) ? jQuery('#w3tc-top-nav-bar').outerHeight() : 0,
options_menu_height = (jQuery('#w3tc > #w3tc-options-menu').length) ? jQuery('#w3tc > #w3tc-options-menu').outerHeight() : 0, options_menu_height = (jQuery('#w3tc > #w3tc-options-menu').length) ? jQuery('#w3tc > #w3tc-options-menu').outerHeight() : 0,
form_bar_height = (jQuery('.w3tc_form_bar').length) ? jQuery('.w3tc_form_bar').outerHeight() : 0; form_bar_height = (jQuery('.w3tc_form_bar').length) ? jQuery('.w3tc_form_bar').outerHeight() : 0;
// Scroll to taget after .5 seconds // Scroll to taget after .5 seconds.
setTimeout( setTimeout(
function() { function() {
jQuery('html, body').animate({ jQuery('html, body').animate({

View File

@ -2,8 +2,8 @@
Contributors: boldgrid, fredericktownes, maxicusc, gidomanders, bwmarkle, harryjackson1221, joemoto, vmarko, jacobd91 Contributors: boldgrid, fredericktownes, maxicusc, gidomanders, bwmarkle, harryjackson1221, joemoto, vmarko, jacobd91
Tags: seo, cache, CDN, pagespeed, caching, performance, compression, optimize, cloudflare, nginx, apache, varnish, redis, aws, amazon web services, s3, cloudfront, azure Tags: seo, cache, CDN, pagespeed, caching, performance, compression, optimize, cloudflare, nginx, apache, varnish, redis, aws, amazon web services, s3, cloudfront, azure
Requires at least: 5.3 Requires at least: 5.3
Tested up to: 6.3 Tested up to: 6.4
Stable tag: 2.5.0 Stable tag: 2.6.1
License: GPLv2 or later License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -285,12 +285,28 @@ Please reach out to all of these people and support their projects if you're so
== Changelog == == Changelog ==
= 2.6.1 =
* Fix: WebP Converter extension activation
* Fix: Media Library upload may fail when using Bunny CDN
* Fix: Cloudflare API error when updating certain settings
* Fix: Lazy Loading issue with the Delay Scripts feature enabled
* Update: Allow custom hostname changes for Bunny CDN
= 2.6.0 =
* Feature: Added support for Bunny.Net CDN
* Feature: Preload requests (Pro)
* Fix: Error when changing CDN cookie domain setting
* Fix: Admin notice when flushing cache from the admin bar
* Fix: Error in some Minify cache file operations
* Fix: PHP 8 compatibility
* Update: Delay scripts UI changes
= 2.5.0 = = 2.5.0 =
* Feature: Added Delay Scripts (Pro) * Feature: Added Delay Scripts (Pro)
* Fix: Several PHP 8 warnings * Fix: Several PHP 8 warnings
* Fix: Fragment Cache extension PHP warnings when no engine was selected * Fix: Fragment Cache extension PHP warnings when no engine was selected
* Fix: Fragment Cache engine selection disabled for pro license under certain conditions * Fix: Fragment Cache engine selection disabled for pro license under certain conditions
* Fix: Added Database Cluster compatiblity for older db.php files * Fix: Added Database Cluster compatibility for older db.php files
* Fix: Fixed one PageSpeed tool metric not outputting data and adjusted a few labels * Fix: Fixed one PageSpeed tool metric not outputting data and adjusted a few labels
* Fix: Multiple anchor links for PageSpeed block on General Settings page * Fix: Multiple anchor links for PageSpeed block on General Settings page
* Fix: Cache Groups validation on save * Fix: Cache Groups validation on save

View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531::getLoader(); return ComposerAutoloaderInit0a460180fd05a263e1d1b80239cc4d46::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531 class ComposerAutoloaderInit0a460180fd05a263e1d1b80239cc4d46
{ {
private static $loader; private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit0a460180fd05a263e1d1b80239cc4d46', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit0a460180fd05a263e1d1b80239cc4d46', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46::getInitializer($loader));
} else { } else {
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {
@ -51,19 +51,19 @@ class ComposerAutoloaderInit81e756b29c31a6c9f87bd8a321bf7531
$loader->register(true); $loader->register(true);
if ($useStaticLoader) { if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531::$files; $includeFiles = Composer\Autoload\ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46::$files;
} else { } else {
$includeFiles = require __DIR__ . '/autoload_files.php'; $includeFiles = require __DIR__ . '/autoload_files.php';
} }
foreach ($includeFiles as $fileIdentifier => $file) { foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire81e756b29c31a6c9f87bd8a321bf7531($fileIdentifier, $file); composerRequire0a460180fd05a263e1d1b80239cc4d46($fileIdentifier, $file);
} }
return $loader; return $loader;
} }
} }
function composerRequire81e756b29c31a6c9f87bd8a321bf7531($fileIdentifier, $file) function composerRequire0a460180fd05a263e1d1b80239cc4d46($fileIdentifier, $file)
{ {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file; require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531 class ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46
{ {
public static $files = array ( public static $files = array (
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
@ -986,9 +986,9 @@ class ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit81e756b29c31a6c9f87bd8a321bf7531::$classMap; $loader->classMap = ComposerStaticInit0a460180fd05a263e1d1b80239cc4d46::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
} }
define( 'W3TC', true ); define( 'W3TC', true );
define( 'W3TC_VERSION', '2.5.0' ); define( 'W3TC_VERSION', '2.6.1' );
define( 'W3TC_POWERED_BY', 'W3 Total Cache' ); define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' ); define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' ); define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
@ -35,6 +35,9 @@ define( 'W3TC_NEWRELIC_SIGNUP_URL', 'https://api.w3-edge.com/v1/redirects/newrel
define( 'W3TC_STACKPATH_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/redirects/stackpath/authorize' ); define( 'W3TC_STACKPATH_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/redirects/stackpath/authorize' );
define( 'W3TC_STACKPATH2_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/redirects/stackpath2/authorize' ); define( 'W3TC_STACKPATH2_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/redirects/stackpath2/authorize' );
define( 'W3TC_GOOGLE_DRIVE_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/googledrive/authorize' ); define( 'W3TC_GOOGLE_DRIVE_AUTHORIZE_URL', 'https://api.w3-edge.com/v1/googledrive/authorize' );
define( 'W3TC_BUNNYCDN_SIGNUP_URL', 'https://api.w3-edge.com/v1/redirects/bunnycdn/signup' );
define( 'W3TC_BUNNYCDN_SETTINGS_URL', 'https://api.w3-edge.com/v1/redirects/bunnycdn/settings' );
define( 'W3TC_BUNNYCDN_CDN_URL', 'https://api.w3-edge.com/v1/redirects/bunnycdn/cdn' );
// Image Service rate constants. // Image Service rate constants.
define( 'W3TC_IMAGE_SERVICE_FREE_HLIMIT', 100 ); define( 'W3TC_IMAGE_SERVICE_FREE_HLIMIT', 100 );

View File

@ -3,7 +3,7 @@
* Plugin Name: W3 Total Cache * Plugin Name: W3 Total Cache
* Plugin URI: https://www.boldgrid.com/totalcache/ * Plugin URI: https://www.boldgrid.com/totalcache/
* Description: The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress. * Description: The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress.
* Version: 2.5.0 * Version: 2.6.1
* Requires at least: 5.3 * Requires at least: 5.3
* Requires PHP: 5.6 * Requires PHP: 5.6
* Author: BoldGrid * Author: BoldGrid