| @@ -19,13 +19,18 @@ | ||
| 19 | 19 | |
| 20 | 20 | /** |
| 21 | 21 | * Instance of this class |
| 22 | 22 | * |
| 23 | - * @var mixed | |
| 23 | + * @var WPO_Cache_Config | null | |
| 24 | 24 | */ |
| 25 | 25 | public static $instance; |
| 26 | 26 | |
| 27 | + /** | |
| 28 | + * @var array | |
| 29 | + */ | |
| 30 | + public $config; | |
| 27 | 31 | |
| 32 | + | |
| 28 | 33 | /** |
| 29 | 34 | * Set config defaults |
| 30 | 35 | */ |
| 31 | 36 | public function __construct() { |
| @@ -39,14 +44,14 @@ | ||
| 39 | 44 | */ |
| 40 | 45 | public function get() { |
| 41 | 46 | |
| 42 | 47 | if (is_multisite()) { |
| 43 | - $config = get_site_option('wpo_cache_config', $this->get_defaults()); | |
| 48 | + $config = get_site_option('wpo_cache_config', $this->defaults); | |
| 44 | 49 | } else { |
| 45 | - $config = get_option('wpo_cache_config', $this->get_defaults()); | |
| 50 | + $config = get_option('wpo_cache_config', $this->defaults); | |
| 46 | 51 | } |
| 47 | 52 | |
| 48 | - return wp_parse_args($config, $this->get_defaults()); | |
| 53 | + return wp_parse_args($config, $this->defaults); | |
| 49 | 54 | } |
| 50 | 55 | |
| 51 | 56 | /** |
| 52 | 57 | * Get a specific configuration option |
| @@ -51,14 +56,14 @@ | ||
| 51 | 56 | /** |
| 52 | 57 | * Get a specific configuration option |
| 53 | 58 | * |
| 54 | 59 | * @param string $option_key The option identifier |
| 55 | - * @param boolean $default Default value if the option doesn't exist (Default to false) | |
| 60 | + * @param mixed $default Default value if the option doesn't exist (Default to false) | |
| 56 | 61 | * @return mixed |
| 57 | 62 | */ |
| 58 | 63 | public function get_option($option_key, $default = false) { |
| 59 | 64 | $options = $this->get(); |
| 60 | - return apply_filters("wpo_option_key_{$option_key}", (isset($options[$option_key]) ? $options[$option_key] : $default)); | |
| 65 | + return apply_filters("wpo_option_key_{$option_key}", ($options[$option_key] ?? $default)); | |
| 61 | 66 | } |
| 62 | 67 | |
| 63 | 68 | /** |
| 64 | 69 | * Updates the given config object in file and DB |
| @@ -65,15 +70,22 @@ | ||
| 65 | 70 | * |
| 66 | 71 | * @param array $config - the cache configuration |
| 67 | 72 | * @param boolean $skip_disk_if_not_yet_present - only write the configuration file to disk if it already exists. This presents PHP notices if the cache has never been on, and settings are saved. |
| 68 | 73 | * |
| 69 | - * @return bool | |
| 74 | + * @return true|WP_Error - returns true on success or WP_Error if the config cannot be written to disk | |
| 70 | 75 | */ |
| 71 | 76 | public function update($config, $skip_disk_if_not_yet_present = false) { |
| 72 | - $config = wp_parse_args($config, $this->get_defaults()); | |
| 77 | + $config = wp_parse_args($config, $this->defaults); | |
| 73 | 78 | |
| 74 | 79 | $config['page_cache_length_value'] = intval($config['page_cache_length_value']); |
| 75 | 80 | $config['page_cache_length'] = $this->calculate_page_cache_length($config['page_cache_length_value'], $config['page_cache_length_unit']); |
| 81 | + | |
| 82 | + $fields_to_trim = array('cache_exception_conditional_tags', 'cache_exception_urls', 'cache_ignore_query_variables', 'cache_exception_cookies', 'cache_exception_browser_agents'); | |
| 83 | + foreach ($fields_to_trim as $field) { | |
| 84 | + if (!empty($config[$field]) && is_array($config[$field])) { | |
| 85 | + $config[$field] = array_map('trim', $config[$field]); | |
| 86 | + } | |
| 87 | + } | |
| 76 | 88 | |
| 77 | 89 | /** |
| 78 | 90 | * Filters the cookies used to set cache file names |
| 79 | 91 | * |
| @@ -93,9 +105,9 @@ | ||
| 93 | 105 | sort($wpo_query_variables); |
| 94 | 106 | |
| 95 | 107 | $config['wpo_cache_cookies'] = $wpo_cache_cookies; |
| 96 | 108 | $config['wpo_cache_query_variables'] = $wpo_query_variables; |
| 97 | - | |
| 109 | + | |
| 98 | 110 | $config = apply_filters('wpo_cache_update_config', $config); |
| 99 | 111 | |
| 100 | 112 | if (is_multisite()) { |
| 101 | 113 | update_site_option('wpo_cache_config', $config); |
| @@ -151,15 +163,15 @@ | ||
| 151 | 163 | * |
| 152 | 164 | * @param array $config - Configuration array. |
| 153 | 165 | * @param boolean $only_if_present - only writes to the disk if the configuration file already exists |
| 154 | 166 | * |
| 155 | - * @return boolean - returns false if an attempt to write failed | |
| 167 | + * @return true|WP_Error - returns true on success or WP_Error if an attempt to write failed | |
| 156 | 168 | */ |
| 157 | 169 | public function write($config, $only_if_present = false) { |
| 158 | 170 | |
| 159 | - $config_file = WPO_CACHE_CONFIG_DIR.'/'.$this->get_cache_config_filename(); | |
| 171 | + $config_file = $this->get_config_file_path(); | |
| 160 | 172 | |
| 161 | - $this->config = wp_parse_args($config, $this->get_defaults()); | |
| 173 | + $this->config = wp_parse_args($config, $this->defaults); | |
| 162 | 174 | |
| 163 | 175 | // from 3.0.17 we use more secure way to store cache config files. |
| 164 | 176 | $advanced_cache_version = WPO_Page_Cache::instance()->get_advanced_cache_version(); |
| 165 | 177 | // if advanced-cache.php exists and has at least 3.0.17 version or |
| @@ -165,17 +177,29 @@ | ||
| 165 | 177 | // if advanced-cache.php exists and has at least 3.0.17 version or |
| 166 | 178 | // advanced-cache.php doesn't exist then |
| 167 | 179 | // we write the cache config in a new format. |
| 168 | 180 | if (($advanced_cache_version && (version_compare($advanced_cache_version, '3.0.17', '>='))) || !$advanced_cache_version) { |
| 181 | + // Apply the encoding required for placing within PHP single quotes - https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.single | |
| 182 | + $json_encoded_string = str_replace(array('\\', "'"), array('\\\\', '\\\''), wp_json_encode($this->config)); | |
| 183 | + | |
| 169 | 184 | $config_content = '<?php' . "\n" |
| 170 | 185 | . 'if (!defined(\'ABSPATH\')) die(\'No direct access allowed\');' . "\n\n" |
| 171 | - . '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . json_encode($this->config) . '\', true);' . "\n"; | |
| 186 | + . '$GLOBALS[\'wpo_cache_config\'] = json_decode(\'' . $json_encoded_string . '\', true);' . "\n"; | |
| 172 | 187 | } else { |
| 173 | - $config_content = json_encode($this->config); | |
| 188 | + $config_content = wp_json_encode($this->config); | |
| 174 | 189 | } |
| 175 | 190 | |
| 176 | - if ((!$only_if_present || file_exists($config_file)) && !file_put_contents($config_file, $config_content)) { | |
| 177 | - return new WP_Error('write_cache_config', sprintf(__('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', 'wp-optimize'), $config_file)); | |
| 191 | + if ((!$only_if_present || file_exists($config_file)) && (!wp_is_writable(WPO_CACHE_CONFIG_DIR) || !file_put_contents($config_file, $config_content))) { | |
| 192 | + // If translations are already loaded, use the translated string | |
| 193 | + if (is_textdomain_loaded('wp-optimize')) { | |
| 194 | + /* translators: %s is the path to the cache config file */ | |
| 195 | + $message = sprintf(__('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', 'wp-optimize'), $config_file); | |
| 196 | + } else { | |
| 197 | + // Fallback to plain English string to avoid triggering premature translation loading | |
| 198 | + $message = sprintf('The cache configuration file could not be saved to the disk; please check the file/folder permissions of %s .', $config_file); | |
| 199 | + } | |
| 200 | + | |
| 201 | + return new WP_Error('write_cache_config', $message); | |
| 178 | 202 | } |
| 179 | 203 | |
| 180 | 204 | return true; |
| 181 | 205 | } |
| @@ -180,47 +204,16 @@ | ||
| 180 | 204 | return true; |
| 181 | 205 | } |
| 182 | 206 | |
| 183 | 207 | /** |
| 184 | - * Verify we can write to the file system | |
| 208 | + * Get config file name with full path. | |
| 185 | 209 | * |
| 186 | - * @since 1.0 | |
| 187 | - * @return boolean | |
| 210 | + * @return string | |
| 188 | 211 | */ |
| 189 | - public function verify_file_access() { | |
| 190 | - if (function_exists('clearstatcache')) { | |
| 191 | - clearstatcache(); | |
| 192 | - } | |
| 193 | - | |
| 194 | - // First check wp-config.php. | |
| 195 | - if (!is_writable(ABSPATH . 'wp-config.php') && !is_writable(ABSPATH . '../wp-config.php')) { | |
| 196 | - return false; | |
| 197 | - } | |
| 198 | - | |
| 199 | - // Now check wp-content. We need to be able to create files of the same user as this file. | |
| 200 | - if (!$this->_is_dir_writable(untrailingslashit(WP_CONTENT_DIR))) { | |
| 201 | - return false; | |
| 202 | - } | |
| 203 | - | |
| 204 | - // If the cache and config directories exist, make sure they're writeable | |
| 205 | - if (file_exists(untrailingslashit(WP_CONTENT_DIR) . '/wpo-cache')) { | |
| 206 | - | |
| 207 | - if (file_exists(WPO_CACHE_DIR)) { | |
| 208 | - if (!$this->_is_dir_writable(WPO_CACHE_DIR)) { | |
| 209 | - return false; | |
| 210 | - } | |
| 211 | - } | |
| 212 | - | |
| 213 | - if (file_exists(WPO_CACHE_CONFIG_DIR)) { | |
| 214 | - if (!$this->_is_dir_writable(WPO_CACHE_CONFIG_DIR)) { | |
| 215 | - return false; | |
| 216 | - } | |
| 217 | - } | |
| 218 | - } | |
| 219 | - | |
| 220 | - return true; | |
| 212 | + public function get_config_file_path() { | |
| 213 | + return WPO_CACHE_CONFIG_DIR . '/' . $this->get_cache_config_filename(); | |
| 221 | 214 | } |
| 222 | - | |
| 215 | + | |
| 223 | 216 | /** |
| 224 | 217 | * Return defaults |
| 225 | 218 | * |
| 226 | 219 | * @return array |
| @@ -227,25 +220,39 @@ | ||
| 227 | 220 | */ |
| 228 | 221 | public function get_defaults() { |
| 229 | 222 | |
| 230 | 223 | $defaults = array( |
| 231 | - 'enable_page_caching' => false, | |
| 232 | - 'page_cache_length_value' => 24, | |
| 233 | - 'page_cache_length_unit' => 'hours', | |
| 234 | - 'page_cache_length' => 86400, | |
| 235 | - 'cache_exception_conditional_tags' => array(), | |
| 236 | - 'cache_exception_urls' => array(), | |
| 237 | - 'cache_exception_cookies' => array(), | |
| 238 | - 'cache_exception_browser_agents' => array(), | |
| 239 | - 'enable_sitemap_preload' => false, | |
| 240 | - 'enable_schedule_preload' => false, | |
| 241 | - 'preload_schedule_type' => '', | |
| 242 | - 'enable_mobile_caching' => false, | |
| 243 | - 'enable_user_caching' => false, | |
| 244 | - 'site_url' => network_site_url('/'), | |
| 245 | - 'enable_cache_per_country' => false, | |
| 246 | - 'permalink_structure' => get_option('permalink_structure'), | |
| 247 | - 'uploads' => wp_upload_dir()['basedir'], | |
| 224 | + 'enable_page_caching' => false, | |
| 225 | + 'page_cache_length_value' => 24, | |
| 226 | + 'page_cache_length_unit' => 'hours', | |
| 227 | + 'page_cache_length' => 86400, | |
| 228 | + 'cache_exception_conditional_tags' => array(), | |
| 229 | + 'cache_specific_urls_only' => false, | |
| 230 | + 'cache_include_urls' => array(), | |
| 231 | + 'cache_exception_urls' => array(), | |
| 232 | + 'cache_ignore_query_variables' => array(), | |
| 233 | + 'cache_exception_cookies' => array(), | |
| 234 | + 'cache_exception_browser_agents' => array(), | |
| 235 | + 'enable_sitemap_preload' => false, | |
| 236 | + 'enable_schedule_preload' => false, | |
| 237 | + 'preload_schedule_type' => '', | |
| 238 | + 'enable_mobile_caching' => false, | |
| 239 | + 'enable_user_caching' => false, | |
| 240 | + 'site_url' => network_home_url('/'), | |
| 241 | + 'enable_cache_per_country' => false, | |
| 242 | + 'enable_cache_aelia_currency' => false, | |
| 243 | + 'permalink_structure' => get_option('permalink_structure'), | |
| 244 | + 'uploads' => wp_normalize_path(wp_upload_dir()['basedir']), | |
| 245 | + 'gmt_offset' => get_option('gmt_offset'), | |
| 246 | + 'timezone_string' => get_option('timezone_string'), | |
| 247 | + 'date_format' => get_option('date_format'), | |
| 248 | + 'time_format' => get_option('time_format'), | |
| 249 | + 'use_webp_images' => false, | |
| 250 | + 'host_gravatars_locally' => 0, | |
| 251 | + 'auto_preload_purged_contents' => true, | |
| 252 | + 'enable_rest_caching' => false, | |
| 253 | + 'last_cleared' => time(), | |
| 254 | + 'lcp_preload_enable' => false, | |
| 248 | 255 | ); |
| 249 | 256 | |
| 250 | 257 | return apply_filters('wpo_cache_defaults', $defaults); |
| 251 | 258 | } |
| @@ -255,11 +262,11 @@ | ||
| 255 | 262 | * |
| 256 | 263 | * @return string |
| 257 | 264 | */ |
| 258 | 265 | public function get_cache_config_filename() { |
| 259 | - $url = parse_url(network_site_url()); | |
| 266 | + $url = wp_parse_url(network_site_url()); | |
| 260 | 267 | |
| 261 | - if (isset($url['port']) && '' != $url['port'] && 80 != $url['port']) { | |
| 268 | + if (isset($url['port']) && '' !== (string) $url['port'] && 80 !== $url['port']) { | |
| 262 | 269 | return 'config-'.strtolower($url['host']).'-port'.$url['port'].'.php'; |
| 263 | 270 | } else { |
| 264 | 271 | return 'config-'.strtolower($url['host']).'.php'; |
| 265 | 272 | } |