true,
'object_cache' => 'off',
'cache_mobile' => true,
'cache_mobile_separate_file' => false,
'loggedin_user_cache' => false,
'ssl_cache' => true, // deprecated
'gzip_compression' => false,
'cache_timeout' => 1440,
// advanced options
'auto_configure_htaccess' => true,
'rejected_user_agents' => '',
'rejected_cookies' => '',
'vary_cookies' => '',
'rejected_uri' => '',
'accepted_query_strings' => '',
'purge_additional_pages' => '',
// file optimization
'minify_html' => false,
'combine_google_fonts' => false,
'swap_google_fonts_display' => true,
'minify_css' => false,
'combine_css' => false,
'critical_css' => false,
'critical_css_additional_files' => '',
'critical_css_excluded_files' => '',
'critical_css_appended_content' => '',
'critical_css_fallback' => '',
'excluded_css_files' => '',
'minify_js' => false,
'combine_js' => false,
'excluded_js_files' => '',
'js_execution_method' => 'blocking',
'js_execution_optimized_only' => true,
// media optimization
'enable_image_optimization' => false,
// lazyload
'enable_lazy_load' => false,
'lazy_load_post_content' => true,
'lazy_load_images' => true,
'lazy_load_iframes' => true,
'lazy_load_widgets' => true,
'lazy_load_post_thumbnail' => true,
'lazy_load_avatars' => true,
'disable_wp_lazy_load' => false,
'disable_wp_embeds' => false,
'disable_emoji_scripts' => false,
// cdn
'enable_cdn' => false,
'cdn_hostname' => array( '' ),
'cdn_zone' => array( '' ),
'cdn_rejected_files' => '',
// preload
'enable_cache_preload' => false,
'preload_homepage' => true,
'preload_public_posts' => true,
'preload_public_tax' => true,
'enable_sitemap_preload' => false,
'preload_sitemap' => '',
'prefetch_dns' => '',
'preconnect_resource' => '',
// db options
'db_cleanup_post_revisions' => false,
'db_cleanup_auto_drafts' => false,
'db_cleanup_trashed_posts' => false,
'db_cleanup_spam_comments' => false,
'db_cleanup_trashed_comments' => false,
'db_cleanup_expired_transients' => false,
'db_cleanup_all_transients' => false,
'db_cleanup_optimize_tables' => false,
'enable_scheduled_db_cleanup' => false,
'scheduled_db_cleanup_frequency' => 'daily',
// add-ons
'enable_cloudflare' => false,
'cloudflare_email' => '',
'cloudflare_api_key' => '',
'cloudflare_zone' => '',
'enable_heartbeat' => false, // extention status
'heartbeat_dashboard_status' => 'enable', // enable,disable,modify
'heartbeat_dashboard_interval' => 60, // default interval in seconds
'heartbeat_editor_status' => 'enable', // enable,disable,modify
'heartbeat_editor_interval' => 15, // default interval in seconds
'heartbeat_frontend_status' => 'enable', // enable,disable,modify
'heartbeat_frontend_interval' => 60, // default interval in seconds
'enable_varnish' => false,
'varnish_ip' => '',
// misc
'cache_footprint' => true,
// new options needs to migrate from extensions
'enable_google_tracking' => false,
'enable_fb_tracking' => false,
];
/**
* Filter default settings.
*
* @hook powered_cache_default_settings
*
* @param {array} $settings Default settings.
*
* @return {array} New value
* @since 2.0
*/
$default_settings = apply_filters( 'powered_cache_default_settings', $settings );
if ( POWERED_CACHE_IS_NETWORK || $force_network_wide ) {
$settings = get_site_option( SETTING_OPTION, [] );
} else {
$settings = get_option( SETTING_OPTION, [] );
}
$settings = wp_parse_args( $settings, $default_settings );
return $settings;
}
/**
* return base caching dir
* use this function to get base caching directory instead of directly calling constant
*
* @return string path
* @since 1.0
*/
function get_cache_dir() {
if ( defined( 'POWERED_CACHE_CACHE_DIR' ) ) {
return POWERED_CACHE_CACHE_DIR; // don't change unless have a particular reason
}
return WP_CONTENT_DIR . '/cache/';
}
/**
* Object cache methods keys will use as option
*
* @return array $object_caches
* @since 1.2 apcu added
*
* @since 1.0
*/
function get_object_cache_dropins() {
$object_caches = array(
'memcache' => POWERED_CACHE_DROPIN_DIR . 'memcache-object-cache.php',
'memcached' => POWERED_CACHE_DROPIN_DIR . 'memcached-object-cache.php',
'redis' => POWERED_CACHE_DROPIN_DIR . 'redis-object-cache.php',
'apcu' => POWERED_CACHE_DROPIN_DIR . 'apcu-object-cache.php',
);
/**
* Filter object cache dropins.
*
* @hook powered_cache_object_cache_dropins
*
* @param {array} $object_caches The list of supported object-cache dropins.
*
* @return {array} New value
* @since 1.0
*/
return apply_filters( 'powered_cache_object_cache_dropins', $object_caches );
}
/**
* Get available object cache backends
*
* @return array
* @since 1.2 unset apcu
* @since 1.0
*/
function get_available_object_caches() {
$object_cache_methods = get_object_cache_dropins();
if ( ! class_exists( '\Memcache' ) || version_compare( PHP_VERSION, '5.6.20', '<' ) ) {
unset( $object_cache_methods['memcache'] );
}
if ( ! class_exists( '\Memcached' ) ) {
unset( $object_cache_methods['memcached'] );
}
if ( ! class_exists( '\Redis' ) ) {
unset( $object_cache_methods['redis'] );
}
if ( ! function_exists( '\apcu_add' ) ) {
unset( $object_cache_methods['apcu'] );
}
return array_keys( $object_cache_methods );
}
/**
* convert minutes to possible time format
*
* @param int $timeout_in_minutes TTL in minutes
*
* @return array
* @since 1.1
*/
function get_timeout_with_interval( $timeout_in_minutes ) {
$cache_timeout = $timeout_in_minutes;
$selected_interval = 'MINUTE';
if ( $cache_timeout > 0 ) {
if ( 0 === (int) ( $cache_timeout % 1440 ) ) {
$cache_timeout = $cache_timeout / 1440;
$selected_interval = 'DAY';
} elseif ( 0 === (int) ( $cache_timeout % 60 ) ) {
$cache_timeout = $cache_timeout / 60;
$selected_interval = 'HOUR';
}
}
return array(
$cache_timeout,
$selected_interval,
);
}
/**
* Determine whether display or not display htaccess configuration
* .htaccess can affect the way of serving cached files.
* Therefore it's only available for network admin on multisite
*
* @return bool
*/
function can_configure_htaccess() {
global $is_apache;
if ( ! $is_apache ) {
return false;
}
if ( POWERED_CACHE_IS_NETWORK && current_user_can( 'manage_network' ) ) {
return true;
}
if ( is_multisite() && ! POWERED_CACHE_IS_NETWORK ) {
return false;
}
if ( current_user_can( 'manage_options' ) ) {
return true;
}
return false;
}
/**
* Whether current user capable to do any configuration changes
*
* @return bool
*/
function can_control_all_settings() {
if ( is_multisite() ) {
if ( current_user_can( 'manage_network' ) ) {
return true;
}
return false;
}
if ( current_user_can( 'manage_options' ) ) {
return true;
}
return false;
}
/**
* Object cache has an effect on all WP
* So, it should be available for the network admin on multisite
* regardless of network-wide or individual activated
*
* @return bool
*/
function can_configure_object_cache() {
if ( is_multisite() ) {
// only allow on network-wide activation
if ( POWERED_CACHE_IS_NETWORK && current_user_can( 'manage_network' ) ) {
return true;
}
return false;
}
if ( current_user_can( 'manage_options' ) ) {
return true;
}
return false;
}
/**
* Supported js execution methods
*
* @return mixed|void
*/
function js_execution_methods() {
$methods = [
'blocking' => esc_html__( 'Blocking – (default)', 'powered-cache' ),
'async' => esc_html__( 'Non-blocking using async', 'powered-cache' ),
'defer' => esc_html__( 'Non-blocking using defer', 'powered-cache' ),
];
/**
* Filter supported JS execution methods.
*
* @hook powered_cache_js_execution_methods
*
* @param {array} $powered_cache_js_execution_methods JS execution methods.
*
* @return {array} New value
* @since 2.0
*/
return apply_filters( 'powered_cache_js_execution_methods', $methods );
}
/**
* Get available zones
*
* @return mixed|void
* @since 1.0
*/
function cdn_zones() {
$zones = [
'all' => esc_html__( 'All files', 'powered-cache' ),
'image' => esc_html__( 'Images', 'powered-cache' ),
'js' => esc_html__( 'JavaScript', 'powered-cache' ),
'css' => esc_html__( 'CSS', 'powered-cache' ),
];
/**
* Filter CDN zone options.
*
* @hook powered_cache_cdn_zones
*
* @param {array} $zones CDN Zones (all,image,js,css)
*
* @return {array} New value
* @since 1.0
*/
return apply_filters( 'powered_cache_cdn_zones', $zones );
}
/**
* Which version of plugin running
*
* @return bool
*/
function is_premium() {
if ( defined( 'POWERED_CACHE_PREMIUM_PLUGIN_FILE' ) && POWERED_CACHE_PREMIUM_PLUGIN_FILE ) {
return true;
}
return false;
}
/**
* Scheduled cleanup options
*
* @return array
*/
function scheduled_cleanup_frequency_options() {
$options = [
'daily' => esc_html__( 'Daily', 'powered-cache' ),
'weekly' => esc_html__( 'Weekly', 'powered-cache' ),
'monthly' => esc_html__( 'Monthly', 'powered-cache' ),
];
/**
* Filter scheduled cleanup options.
*
* @hook powered_cache_scheduled_cleanup_frequency_options
*
* @param {array} $options The list of supported schedules.
*
* @return {array} New value
* @since 2.0
*/
return apply_filters( 'powered_cache_scheduled_cleanup_frequency_options', $options );
}
/**
* ports \settings_errors for SUI
*
* @param string $setting Slug title of a specific setting
* @param bool $sanitize Whether to re-sanitize the setting value before returning errors
* @param bool $hide_on_update Whether hide or not hide on update
*
* @see settings_errors
*/
function settings_errors( $setting = '', $sanitize = false, $hide_on_update = false ) {
if ( $hide_on_update && ! empty( $_GET['settings-updated'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
$settings_errors = get_settings_errors( $setting, $sanitize );
if ( empty( $settings_errors ) ) {
return;
}
$output = '';
foreach ( $settings_errors as $key => $details ) {
if ( 'updated' === $details['type'] ) {
$details['type'] = 'sui-notice-success';
}
if ( in_array( $details['type'], array( 'error', 'success', 'warning', 'info' ), true ) ) {
$details['type'] = 'sui-notice-' . $details['type'];
}
$css_id = sprintf(
'setting-error-%s',
esc_attr( $details['code'] )
);
$css_class = sprintf(
'sui-notice %s settings-error is-dismissible',
esc_attr( $details['type'] )
);
$output .= "
\n";
$output .= "
";
$output .= "
";
$output .= "
{$details['message']}
";
$output .= "
\n";
}
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* remove directories recursively
*
* Adopted from W3TC Utility
*
* @param string $path The target path
* @param array $exclude list of the files that will excluded
*
* @return void
* @since 1.2.5
*/
function remove_dir( $path, $exclude = array() ) {
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
$dir = @opendir( $path );
if ( $dir ) {
while ( ( $entry = @readdir( $dir ) ) !== false ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
if ( '.' === $entry || '..' === $entry ) {
continue;
}
foreach ( $exclude as $mask ) {
if ( fnmatch( $mask, basename( $entry ) ) ) {
continue 2;
}
}
$full_path = $path . DIRECTORY_SEPARATOR . $entry;
if ( @is_dir( $full_path ) ) {
remove_dir( $full_path, $exclude );
} else {
@unlink( $full_path );
}
}
@closedir( $dir );
@rmdir( $path );
}
// phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged
}
/**
* Get base caching directory of the site.
*
* @return mixed|void
* @since 1.1
*/
function site_cache_dir() {
$base_dir = get_page_cache_dir();
// compatible with multisite
$site_url = get_site_url();
$site_url_parsed = wp_parse_url( $site_url );
$site_path = $site_url_parsed['host'];
if ( ! empty( $site_url_parsed['path'] ) ) {
$site_path .= $site_url_parsed['path'];
}
$site_cache_dir = trailingslashit( $base_dir . $site_path );
/**
* Filter get base caching directory of site
*
* @hook powered_cache_site_cache_dir
*
* @param {string} $site_cache_dir Site cache dir.
*
* @return {string} New value
* @since 1.1
*/
return apply_filters( 'powered_cache_site_cache_dir', $site_cache_dir );
}
/**
* Page cache base directory.
*
* @return string
* @since 1.1 $url parameter removed
* @since 1.0
*/
function get_page_cache_dir() {
$path = get_cache_dir() . 'powered-cache/';
/**
* Filter page cache base directory.
*
* @hook powered_cache_get_page_cache_dir
*
* @param {string} $path Page cache dir
*
* @return {string} New value
* @since 1.0
*/
return apply_filters( 'powered_cache_get_page_cache_dir', $path );
}
/**
* Clean up cache directory
*
* @return mixed
* @since 1.0
*/
function clean_page_cache_dir() {
remove_dir( get_page_cache_dir() );
}
/**
* Clean cache base for the current site
*
* @return mixed
* @since 1.1
*/
function clean_site_cache_dir() {
$site_cache_dir = site_cache_dir();
/**
* When deleting cache for the main site on multisite subdirectory setup
* Don't delete other site's cache
*/
if ( is_multisite() && ! is_subdomain_install() && is_main_site() ) {
$base_dir = get_page_cache_dir();
$directories = glob( $site_cache_dir . '*', GLOB_ONLYDIR );
$site_url = get_site_url();
$site_domain = wp_parse_url( $site_url, PHP_URL_HOST );
foreach ( $directories as $directory ) {
$dir_name = str_replace( $base_dir . $site_domain, '', $directory );
$site_info = get_site_by_path( $site_domain, $dir_name );
if ( ! $site_info || is_main_site( $site_info->blog_id ) ) {
remove_dir( $directory );
}
}
} else {
remove_dir( $site_cache_dir );
}
/**
* Fires after deleting site cache dir
*
* @hook powered_cache_clean_site_cache_dir
*
* @param {string} $site_cache_dir The caching directory of the current site.
*
* @since 2.0
*/
do_action( 'powered_cache_clean_site_cache_dir', $site_cache_dir );
}
/**
* Supported mobile browsers
*
* @return mixed|void
* @since 1.0
*/
function mobile_browsers() {
$mobile_browsers
= '2.0 MMP, 240x320, 400X240, AvantGo, BlackBerry, Blazer, Cellphone, Danger, DoCoMo, Elaine/3.0, EudoraWeb, Googlebot-Mobile, hiptop, IEMobile, KYOCERA/WX310K, LG/U990, MIDP-2., MMEF20, MOT-V, NetFront, Newt, Nintendo Wii, Nitro, Nokia, Opera Mini, Palm, PlayStation Portable, portalmmm, Proxinet, ProxiNet, SHARP-TQ-GX10, SHG-i900, Small, SonyEricsson, Symbian OS, SymbianOS, TS21i-10, UP.Browser, UP.Link, webOS, Windows CE, WinWAP, YahooSeeker/M1A1-R2D2, iPhone, iPod, Android, BlackBerry9530, LG-TU915 Obigo, LGE VX, webOS, Nokia5800';
/**
* Filters supported mobile browsers.
*
* @hook powered_cache_mobile_browsers
*
* @param {string} $mobile_browsers Comma separated list of the defined mobile browsers.
*
* @since 1.0
*/
return apply_filters( 'powered_cache_mobile_browsers', $mobile_browsers );
}
/**
* Supported mobile prefixes
*
* @return mixed|void
* @since 1.0
*/
function mobile_prefixes() {
$mobile_prefixes
= 'w3c , w3c-, acs-, alav, alca, amoi, audi, avan, benq, bird, blac, blaz, brew, cell, cldc, cmd-, dang, doco, eric, hipt, htc_, inno, ipaq, ipod, jigs, kddi, keji, leno, lg-c, lg-d, lg-g, lge-, lg/u, maui, maxo, midp, mits, mmef, mobi, mot-, moto, mwbp, nec-, newt, noki, palm, pana, pant, phil, play, port, prox, qwap, sage, sams, sany, sch-, sec-, send, seri, sgh-, shar, sie-, siem, smal, smar, sony, sph-, symb, t-mo, teli, tim-, tosh, tsm-, upg1, upsi, vk-v, voda, wap-, wapa, wapi, wapp, wapr, webc, winw, winw, xda , xda-';
/**
* Filters supported mobile prefixes.
*
* @hook powered_cache_mobile_prefixes
*
* @param {string} $mobile_prefixes Comma separated list of the defined mobile prefixes.
*
* @since 1.0
*/
return apply_filters( 'powered_cache_mobile_prefixes', $mobile_prefixes );
}
/**
* Collect post related urls
*
* @param int $post_id Post ID
*
* @return array
* @since 1.0
* @since 1.1 powered_cache_post_related_urls filter added
*/
function get_post_related_urls( $post_id ) {
$current_post_status = get_post_status( $post_id );
// array to collect all our URLs
$related_urls = array();
if ( get_permalink( $post_id ) ) {
// we're going to add a ton of things to flush.
// related category urls
$categories = get_the_category( $post_id );
if ( $categories ) {
foreach ( $categories as $cat ) {
array_push( $related_urls, get_category_link( $cat->term_id ) );
}
}
// related tags url
$tags = get_the_tags( $post_id );
if ( $tags ) {
foreach ( $tags as $tag ) {
array_push( $related_urls, get_tag_link( $tag->term_id ) );
}
}
// Author URL
array_push( $related_urls, get_author_posts_url( get_post_field( 'post_author', $post_id ) ), get_author_feed_link( get_post_field( 'post_author', $post_id ) ) );
// Archives and their feeds
if ( get_post_type_archive_link( get_post_type( $post_id ) ) === true ) {
array_push( $related_urls, get_post_type_archive_link( get_post_type( $post_id ) ), get_post_type_archive_feed_link( get_post_type( $post_id ) ) );
}
// Post URL
array_push( $related_urls, get_permalink( $post_id ) );
// Also clean URL for trashed post.
if ( 'trash' === $current_post_status ) {
$trashpost = get_permalink( $post_id );
$trashpost = str_replace( '__trashed', '', $trashpost );
array_push( $related_urls, $trashpost, $trashpost . 'feed/' );
}
// Add in AMP permalink if Automattic's AMP is installed
if ( function_exists( 'amp_get_permalink' ) ) {
array_push( $related_urls, amp_get_permalink( $post_id ) );
}
// Regular AMP url for posts
array_push( $related_urls, get_permalink( $post_id ) . 'amp/' );
// Feeds
array_push( $related_urls, get_bloginfo_rss( 'rdf_url' ), get_bloginfo_rss( 'rss_url' ), get_bloginfo_rss( 'rss2_url' ), get_bloginfo_rss( 'atom_url' ), get_bloginfo_rss( 'comments_rss2_url' ), get_post_comments_feed_link( $post_id ) );
// Home Page and (if used) posts page
array_push( $related_urls, trailingslashit( home_url() ) );
if ( get_option( 'show_on_front' ) === 'page' ) {
// Ensure we have a page_for_posts setting to avoid empty URL
if ( get_option( 'page_for_posts' ) ) {
array_push( $related_urls, get_permalink( get_option( 'page_for_posts' ) ) );
}
}
}
/**
* Filters post related urls.
*
* @hook powered_cache_post_related_urls
*
* @param {array} $related_urls The list of the URLs that related with the post.
*
* @since 1.0
*/
$related_urls = apply_filters( 'powered_cache_post_related_urls', $related_urls );
return $related_urls;
}
/**
* Delete cache file
*
* @param string $url Target URL
*
* @return bool true when found cache dir, otherwise false
* @since 1.0
*/
function delete_page_cache( $url ) {
$dir = trailingslashit( get_url_dir( trim( $url ) ) );
if ( is_dir( $dir ) ) {
$files = scandir( $dir );
foreach ( $files as $file ) {
/**
* Don't need to lookup for index-https, index-https-mobile etc..
* Just clean that directory's files only.
*/
if ( ! is_dir( $dir . $file ) && ! in_array( $file, array( '.', '..' ), true ) ) {
unlink( $dir . $file );
}
if ( file_exists( $dir ) && is_dir_empty( $dir ) ) {
remove_dir( $dir );
}
}
return true;
}
return false;
}
/**
* Get cache location of given url
*
* @param string $url The url to retrieve path
*
* @return mixed|void
* @since 1.1
*/
function get_url_dir( $url ) {
$url_info = wp_parse_url( $url );
$sub_dir = $url_info['host'];
if ( ! empty( $url_info['path'] ) ) {
$sub_dir .= $url_info['path'];
}
$path = trailingslashit( get_page_cache_dir() ) . ltrim( $sub_dir, '/' );
/**
* Filters the path of the given url in the cache directory.
*
* @hook powered_cache_get_url_dir
*
* @param {string} $path The cache directory of the given URL.
*
* @since 1.1
*/
return apply_filters( 'powered_cache_get_url_dir', $path );
}
/**
* Prepare cdn addresses with hostname + zone
*
* @return mixed|void
* @since 1.0
*/
function cdn_addresses() {
$settings = get_settings(); // phpcs:ignore WordPress.WP.DeprecatedFunctions.get_settingsFound
$hostnames = $settings['cdn_hostname'];
$zones = $settings['cdn_zone'];
$cdn_addresses = array();
foreach ( $hostnames as $host_key => $host ) {
if ( filter_var( $host, FILTER_VALIDATE_URL ) ) {
$host = wp_parse_url( $host, PHP_URL_HOST );
}
if ( ! empty( $host ) ) {
$cdn_addresses[ $zones[ $host_key ] ][] = $host;
}
}
/**
* Filters CDN Addresses.
*
* @hook powered_cache_cdn_addresses
*
* @param {array} $cdn_addresses CDN Adresses.
*
* @return {array} New value.
*
* @since 1.0
*/
return apply_filters( 'powered_cache_cdn_addresses', $cdn_addresses );
}
/**
* Get list of expired files for given directory
*
* @param string $path directory location
* @param int $lifespan lifespan in seconds
*
* @return array expired file list
* @since 1.1
*/
function get_expired_files( $path, $lifespan = 0 ) {
$current_time = time();
$expired_files = array();
// return immediately if the path is not exist!
if ( ! file_exists( $path ) ) {
return $expired_files;
}
$files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ) );
foreach ( $files as $file ) {
if ( $file->isDir() ) {
continue;
}
$path = $file->getPathname();
if ( @filemtime( $path ) + $lifespan <= $current_time ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$expired_files[] = $path;
}
}
return $expired_files;
}
/**
* Flush object cache and clean cache directory
*
* @since 1.0
*/
function powered_cache_flush() {
if ( function_exists( 'wp_cache_flush' ) ) {
wp_cache_flush();
}
remove_dir( get_cache_dir() );
/**
* Fires after cache flush.
*
* @hook powered_cache_flushed
*
* @since 1.0
*/
do_action( 'powered_cache_flushed' );
}
/**
* Log to stdout or a file
*
* @param string $message Log message
*
* @return bool
*/
function log( $message ) {
if ( ! defined( 'POWERED_CACHE_ENABLE_LOG' ) ) {
return false;
}
if ( ! POWERED_CACHE_ENABLE_LOG ) {
return false;
}
$log_message = gmdate( 'H:i:s' ) . ' ' . getmypid() . ' ' . get_client_ip() . " {$message}" . PHP_EOL;
/**
* Filters log message.
*
* @hook powered_cache_log_message
*
* @param {string} $log_message The log message.
*
* @return {string} New value.
*
* @since 2.0
*/
$log_message = apply_filters( 'powered_cache_log_message', $log_message );
/**
* Filters log message type.
*
* @hook powered_cache_log_message_type
*
* @param {null|int} null default message type
*
* @return {null|int} New value.
*
* @since 2.0
*/
$message_type = apply_filters( 'powered_cache_log_message_type', null );
$destination = null;
if ( defined( 'POWERED_CACHE_LOG_FILE' ) ) {
$destination = POWERED_CACHE_LOG_FILE;
$message_type = 3;
}
/**
* Filters destination of the log.
*
* @hook powered_cache_log_destination
*
* @param {null|string} $destination The destination of the log.
*
* @return {null|string} New value.
*
* @since 2.0
*/
$log_destination = apply_filters( 'powered_cache_log_destination', $destination );
// don't log anything when it used for particular IP address
if ( defined( 'POWERED_CACHE_LOG_IP' ) && POWERED_CACHE_LOG_IP !== get_client_ip() ) {
return false;
}
return error_log( $log_message, $message_type, $log_destination ); // phpcs:ignore
}
/**
* Get client raw ip
*
* @return mixed
*/
function get_client_ip() {
if ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
return $_SERVER['HTTP_X_FORWARDED_FOR'];
}
return $_SERVER['REMOTE_ADDR'];
}
/**
* Fragment caching
*
* @link https://gist.github.com/markjaquith/2653957
* @see https://gist.github.com/westonruter/5475349
*
* @param string $key Fragment key
* @param int $ttl Cache TTL
* @param callable $function callback
*
* @throws \Exception Exception
* @since 1.2
* @since 2.0 Renamed powered_cache_fragment -> \PoweredCache\Utils\cache_fragment
*/
function cache_fragment( $key, $ttl, $function ) {
$group = 'powered-fragments';
$output = wp_cache_get( $key, $group );
if ( empty( $output ) ) {
ob_start();
call_user_func( $function );
$output = ob_get_clean();
wp_cache_add( $key, $output, $group, $ttl );
}
echo $output; // phpcs:ignore
}
/**
* Fetches known headers, ported from WP Super Cache but not using apache_response_headers
*
* @return array|false
* @since 1.2
*/
function get_response_headers() {
static $known_headers = array(
'Access-Control-Allow-Origin',
'Accept-Ranges',
'Age',
'Allow',
'Cache-Control',
'Connection',
'Content-Encoding',
'Content-Language',
'Content-Length',
'Content-Location',
'Content-MD5',
'Content-Disposition',
'Content-Range',
'Content-Type',
'Date',
'ETag',
'Expires',
'Last-Modified',
'Link',
'Location',
'P3P',
'Pragma',
'Proxy-Authenticate',
'Referrer-Policy',
'Refresh',
'Retry-After',
'Server',
'Status',
'Strict-Transport-Security',
'Trailer',
'Transfer-Encoding',
'Upgrade',
'Vary',
'Via',
'Warning',
'WWW-Authenticate',
'X-Frame-Options',
'Public-Key-Pins',
'X-XSS-Protection',
'Content-Security-Policy',
'X-Pingback',
'X-Content-Security-Policy',
'X-WebKit-CSP',
'X-Content-Type-Options',
'X-Powered-By',
'X-UA-Compatible',
'X-Robots-Tag',
);
/**
* Filters known headers.
*
* @hook powered_cache_known_headers
*
* @param {array} $known_headers The list of known HTTP headers.
*
* @return {array} New value.
*
* @since 1.2
*/
$known_headers = apply_filters( 'powered_cache_known_headers', $known_headers );
if ( ! isset( $known_headers['age'] ) ) {
$known_headers = array_map( 'strtolower', $known_headers );
}
$headers = array();
if ( function_exists( 'headers_list' ) ) {
$headers = array();
foreach ( headers_list() as $hdr ) {
$header_parts = explode( ':', $hdr, 2 );
$header_name = isset( $header_parts[0] ) ? trim( $header_parts[0] ) : '';
$header_value = isset( $header_parts[1] ) ? trim( $header_parts[1] ) : '';
$headers[ $header_name ] = $header_value;
}
}
foreach ( $headers as $key => $value ) {
if ( ! in_array( strtolower( $key ), $known_headers, true ) ) {
unset( $headers[ $key ] );
}
}
return $headers;
}
/**
* Check if the given url exists in the cache
*
* @param string $url URL
* @param bool $is_mobile Check mobile cache
* @param bool $is_gzip check gzipped cache
*
* @return bool
*/
function is_url_cached( $url, $is_mobile = false, $is_gzip = false ) {
$file_name = 'index';
$url_parts = wp_parse_url( $url );
if ( 'https' === $url_parts['scheme'] ) {
$file_name .= '-https';
}
if ( $is_mobile ) {
$file_name .= '-mobile';
}
$file_name .= '.html';
if ( $is_gzip ) {
$file_name .= '.gz';
}
$rel_path = $url_parts['host'];
if ( ! empty( $url_parts['path'] ) ) {
$rel_path .= $url_parts['path'];
}
$path = trailingslashit( get_page_cache_dir() . $rel_path );
$cache_file = $path . $file_name;
return file_exists( $cache_file );
}
/**
* Check if the permalink structure of the site end with trailingslash
*
* @return bool
* @since 2.0
*/
function permalink_structure_has_trailingslash() {
if ( '/' === substr( get_option( 'permalink_structure' ), - 1 ) ) {
return true;
}
return false;
}
/**
* Check if the given directory empty
*
* @param string $dir Path
*
* @return bool
*/
function is_dir_empty( $dir ) {
foreach ( new \DirectoryIterator( $dir ) as $file_info ) {
if ( $file_info->isDot() ) {
continue;
}
return false;
}
return true;
}
/**
* Get the documentation url
*
* @param string $path The path of documentation
* @param string $fragment URL Fragment
*
* @return string final URL
*/
function get_doc_url( $path = null, $fragment = '' ) {
$doc_site = 'https://docs.poweredcache.com/';
$utm_parameters = '?utm_source=wp_admin&utm_medium=plugin&utm_campaign=settings_page';
if ( ! empty( $path ) ) {
$doc_site .= ltrim( $path, '/' );
}
$doc_url = trailingslashit( $doc_site ) . $utm_parameters;
if ( ! empty( $fragment ) ) {
$doc_url .= '#' . $fragment;
}
return $doc_url;
}
/**
* Sanitize CSS
*
* @param string $css Input
*
* @return string|string[] $css
* @since 2.1
*/
function sanitize_css( $css ) {
$css = wp_strip_all_tags( $css );
if ( false !== strpos( $css, '<' ) ) {
$css = preg_replace( '#<(\/?\w+)#', '\00003C$1', $css );
}
return $css;
}
/**
* Test if the current browser runs on a mobile device (smart phone, tablet, etc.)
* Sort of custom version of wp_is_mobile
*/
function powered_cache_is_mobile() {
global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes;
$mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
$mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
if ( ( preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
return true;
}
return false;
}
/**
* If the site is a local site.
*
* @return bool
* @since 2.2
*/
function is_local_site() {
$site_url = site_url();
// Check for localhost and sites using an IP only first.
$is_local = $site_url && false === strpos( $site_url, '.' );
// Use Core's environment check, if available. Added in 5.5.0 / 5.5.1 (for `local` return value).
if ( function_exists( 'wp_get_environment_type' ) && 'local' === wp_get_environment_type() ) {
$is_local = true;
}
// Then check for usual usual domains used by local dev tools.
$known_local = array(
'#\.local$#i',
'#\.localhost$#i',
'#\.test$#i',
'#\.docksal$#i', // Docksal.
'#\.docksal\.site$#i', // Docksal.
'#\.dev\.cc$#i', // ServerPress.
'#\.lndo\.site$#i', // Lando.
);
if ( ! $is_local ) {
foreach ( $known_local as $url ) {
if ( preg_match( $url, $site_url ) ) {
$is_local = true;
break;
}
}
}
/**
* Filters is_local_site check.
*
* @param bool $is_local If the current site is a local site.
*
* @since 2.2
*/
$is_local = apply_filters( 'powered_cache_is_local_site', $is_local );
return $is_local;
}