PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 3.6.3
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v3.6.3
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / classes / Config.php

Config.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 3.6.3, at includes/classes/Config.php

798 lines 24.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Configurator Class of the plugin
4 *
5 * @package PoweredCache
6 */
7
8 namespace PoweredCache;
9
10 use function PoweredCache\Utils\can_configure_htaccess;
11 use function PoweredCache\Utils\can_configure_object_cache;
12 use function PoweredCache\Utils\get_cache_dir;
13 use function PoweredCache\Utils\get_object_cache_dropins;
14 use function PoweredCache\Utils\mobile_browsers;
15 use function PoweredCache\Utils\mobile_prefixes;
16 use function PoweredCache\Utils\permalink_structure_has_trailingslash;
17 use function PoweredCache\Utils\remove_dir;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit; // Exit if accessed directly.
21 }
22
23 // phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found
24 // phpcs:disable WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
25 // phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_var_export
26 // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
27 // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
28
29 /**
30 * Class Config
31 */
32 class Config {
33 /**
34 * placeholder
35 *
36 * @since 1.0
37 */
38 public function __construct() {
39 }
40
41 /**
42 * Return an instance of the current class
43 *
44 * @return Config
45 * @since 2.0 removed WP_Filesystem_Direct deps
46 * @since 1.1 initialize WP_Filesystem_Direct
47 * @since 1.0
48 */
49 public static function factory() {
50 static $instance = false;
51
52 if ( ! $instance ) {
53 $instance = new self();
54 }
55
56 return $instance;
57 }
58
59
60 /**
61 * Setup object-cache.php
62 *
63 * @param string $backend Persistent object cache backend. (memcached, redis etc..)
64 *
65 * @return bool
66 * @since 1.0
67 */
68 public function setup_object_cache( $backend = 'off' ) {
69 $file = untrailingslashit( WP_CONTENT_DIR ) . '/object-cache.php';
70
71 /**
72 * Since object cache has impact on the entire network
73 * It only allowed by the network admin
74 */
75 if ( is_multisite() && ! current_user_can( 'manage_network' ) ) {
76 return false;
77 }
78
79 if ( 'off' === $backend && file_exists( $file ) && false !== strpos( file_get_contents( $file ), 'POWERED_OBJECT_CACHE' ) ) {
80 /**
81 * Remove object-cache.php file only when the created file belongs to PoweredCache
82 */
83 unlink( $file );
84
85 return true;
86 }
87
88 if ( 'off' === $backend ) {
89 return true;
90 }
91
92 $file_string = $this->object_cache_file_content( $backend );
93
94 if ( ! file_put_contents( $file, $file_string, LOCK_EX ) ) {
95 return false;
96 }
97
98 return true;
99 }
100
101 /**
102 * object-cache.php contents
103 *
104 * @param string $backend Persistent object cache backend
105 *
106 * @return mixed|void
107 * @since 1.0
108 * @see Powered_Cache_Admin_Helper::object_cache_dropins
109 *
110 * @since 1.1 supports `POWERED_CACHE_OBJECT_CACHE_DROPIN`
111 */
112 public function object_cache_file_content( $backend ) {
113 $string = '<?php ' . "\n";
114 $string .= "defined( 'ABSPATH' ) || exit;" . PHP_EOL;
115 $string .= "define( 'POWERED_OBJECT_CACHE', true );" . PHP_EOL;
116 $string .= "if ( ! defined( 'WP_CACHE_KEY_SALT' ) ) {" . PHP_EOL;
117 $string .= "\t" . "define( 'WP_CACHE_KEY_SALT', DB_NAME );" . PHP_EOL;
118 $string .= '}' . PHP_EOL;
119
120 $object_caches = get_object_cache_dropins();
121
122 $string .= 'if ( defined( \'POWERED_CACHE_OBJECT_CACHE_DROPIN\') && @file_exists( POWERED_CACHE_OBJECT_CACHE_DROPIN ) ) {' . PHP_EOL;
123 $string .= "\t" . 'include( POWERED_CACHE_OBJECT_CACHE_DROPIN );' . PHP_EOL;
124 $string .= '} elseif ( @file_exists( \'' . $object_caches[ $backend ] . '\' ) ) {' . PHP_EOL;
125 $string .= "\t" . 'include( \'' . $object_caches[ $backend ] . '\' );' . PHP_EOL;
126 $string .= '} else {' . PHP_EOL;
127 $string .= "\t" . 'define( \'POWERED_OBJECT_CACHE_HAS_PROBLEM\', true );' . PHP_EOL;
128 $string .= '}';
129
130 /**
131 * Filters object-cache.php file contents.
132 *
133 * @hook powered_cache_object_cache_file_content
134 *
135 * @param {string} $string The content of the object-cache.php file
136 *
137 * @return {string} New value.
138 *
139 * @since 1.0
140 */
141 return apply_filters( 'powered_cache_object_cache_file_content', $string );
142 }
143
144 /**
145 * Generate advanced-cache.php and define WP_CACHE
146 *
147 * @param bool $status status of the page caching
148 *
149 * @return bool
150 * @since 1.0
151 */
152 public function setup_page_cache( $status ) {
153
154 /**
155 * Forcing multisite settings always true
156 */
157 if ( is_multisite() && ! POWERED_CACHE_IS_NETWORK ) {
158 $status = true;
159 }
160
161 $this->generate_advanced_cache_file();
162 $this->define_wp_cache( $status );
163
164 if ( can_configure_htaccess() ) {
165 $this->configure_htaccess( $status );
166 }
167
168 $this->protect_cache_dir();
169
170 return true;
171 }
172
173
174 /**
175 * Generates advanced-cache.php
176 *
177 * @return bool
178 * @since 1.1 is_multisite control added
179 * @since 1.0
180 */
181 public function generate_advanced_cache_file() {
182 $file = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
183 $settings = \PoweredCache\Utils\get_settings();
184
185 $file_string = '';
186
187 /**
188 * multisite setups should always have `advanced-cache.php` file
189 */
190 if ( true === $settings['enable_page_cache'] || is_multisite() ) {
191 $file_string = $this->advanced_cache_file_content();
192 }
193
194 if ( ! file_put_contents( $file, $file_string ) ) {
195 return false;
196 }
197
198 return true;
199 }
200
201
202 /**
203 * Prepare advanced-cache.php contents
204 *
205 * @return mixed|void
206 * @since 1.1 supports `POWERED_CACHE_ADVANCED_CACHE_DROPIN`
207 * @since 1.0
208 */
209 public function advanced_cache_file_content() {
210 $string = '<?php ' . PHP_EOL;
211 $string .= "defined( 'ABSPATH' ) || exit;" . PHP_EOL;
212 $string .= "define( 'POWERED_CACHE_PAGE_CACHING', true );" . PHP_EOL . PHP_EOL;
213 // lookup order 1) network-wide , 2) subdomain specific (if any) 3) domain specific
214 $string .= "\$config_locations[] = WP_CONTENT_DIR . '/pc-config/config-network.php';" . PHP_EOL;
215 $string .= "\$host = isset( \$_SERVER['HTTP_HOST'] ) ? \$_SERVER['HTTP_HOST'] : '';" . PHP_EOL . PHP_EOL;
216 $string .= "if ( is_multisite() && defined( 'SUBDOMAIN_INSTALL' ) && ! SUBDOMAIN_INSTALL ) {" . PHP_EOL;
217 $string .= "\t" . "\$request_uri = explode( '/', ltrim( \$_SERVER['REQUEST_URI'], '/' ) );" . PHP_EOL;
218 $string .= "\t" . 'if ( ! empty( $request_uri[0] ) ) {' . PHP_EOL;
219 $string .= "\t" . "\t" . "\$config_locations[] = WP_CONTENT_DIR . '/pc-config/config-' . \$host . '-' . \$request_uri[0] . '.php';" . PHP_EOL;
220 $string .= "\t" . '}' . PHP_EOL;
221 $string .= '}' . PHP_EOL;
222
223 $string .= "\$config_locations[] = WP_CONTENT_DIR . '/pc-config/config-' . \$host . '.php';" . PHP_EOL . PHP_EOL;
224
225 $string .= 'foreach ( $config_locations as $config_file ) {' . PHP_EOL;
226 $string .= "\t" . 'if ( @file_exists( $config_file ) ) {' . PHP_EOL;
227 $string .= "\t" . "\t" . 'include( $config_file );' . PHP_EOL;
228 $string .= "\t" . "\t" . 'break;' . PHP_EOL;
229 $string .= "\t" . '}' . PHP_EOL;
230 $string .= '}' . PHP_EOL . PHP_EOL;
231
232 $string .= "if ( ! isset( \$GLOBALS['powered_cache_options'] ) ) {" . PHP_EOL;
233 $string .= "\t" . 'return;' . PHP_EOL;
234 $string .= '}' . PHP_EOL . PHP_EOL;
235
236 $string .= 'if ( defined( \'POWERED_CACHE_ADVANCED_CACHE_DROPIN\') && @file_exists( POWERED_CACHE_ADVANCED_CACHE_DROPIN ) ) {' . PHP_EOL;
237 $string .= "\t" . 'include( POWERED_CACHE_ADVANCED_CACHE_DROPIN );' . PHP_EOL;
238 $string .= '} elseif ( @file_exists( \'' . POWERED_CACHE_DROPIN_DIR . 'page-cache.php' . '\' ) ) {' . PHP_EOL;
239 $string .= "\t" . 'include( \'' . POWERED_CACHE_DROPIN_DIR . 'page-cache.php' . '\' );' . PHP_EOL;
240 $string .= '} else {' . PHP_EOL;
241 $string .= "\t" . 'define( \'POWERED_CACHE_PAGE_CACHING_HAS_PROBLEM\', true );' . PHP_EOL;
242 $string .= '}';
243
244 /**
245 * Filters advanced-cache.php file contents.
246 *
247 * @hook powered_cache_advanced_cache_file_content
248 *
249 * @param {string} $string The content of the advanced-cache.php file
250 *
251 * @return {string} New value.
252 *
253 * @since 1.0
254 */
255 return apply_filters( 'powered_cache_advanced_cache_file_content', $string );
256 }
257
258
259 /**
260 * Define WP_CACHE constant
261 *
262 * @param bool $status The status of the caching
263 *
264 * @return bool
265 * @since 1.0
266 */
267 public function define_wp_cache( $status ) {
268 $config_path = $this->find_wp_config_file();
269
270 if ( ! $config_path ) {
271 return false;
272 }
273
274 if ( defined( 'WP_CACHE' ) && WP_CACHE === $status ) {
275 return true;
276 }
277
278 $config_file_string = file_get_contents( $config_path );
279
280 // Config file is empty. Maybe couldn't read it?
281 if ( empty( $config_file_string ) ) {
282 return false;
283 }
284
285 $config_file = preg_split( "#(\r\n|\r|\n)#", $config_file_string );
286 $line_key = false;
287
288 foreach ( $config_file as $key => $line ) {
289 if ( ! preg_match( '/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/', $line, $match ) ) {
290 continue;
291 }
292
293 if ( 'WP_CACHE' === $match[2] ) {
294 $line_key = $key;
295 }
296 }
297
298 if ( false !== $line_key ) {
299 unset( $config_file[ $line_key ] );
300 }
301
302 $status_string = ( $status ) ? 'true' : 'false';
303
304 array_shift( $config_file );
305 array_unshift( $config_file, '<?php', "define( 'WP_CACHE', $status_string ); // Powered Cache" );
306
307 if ( ! @file_put_contents( $config_path, implode( PHP_EOL, $config_file ) ) ) { // phpcs:ignore
308 return false;
309 }
310
311 return true;
312 }
313
314 /**
315 * seeking wp-config file
316 *
317 * @return bool|string
318 * @since 1.0
319 */
320 public function find_wp_config_file() {
321 $file = '/wp-config.php';
322
323 for ( $i = 1; $i <= 3; $i ++ ) {
324 if ( $i > 1 ) {
325 $file = '/..' . $file;
326 }
327
328 if ( file_exists( untrailingslashit( ABSPATH ) . $file ) ) {
329 $config_path = untrailingslashit( ABSPATH ) . $file;
330 break;
331 }
332 }
333
334 if ( ! isset( $config_path ) ) {
335 return false;
336 }
337
338 return $config_path;
339 }
340
341 /**
342 * Create .htaccess file based on current setting preferences
343 *
344 * @param bool $enable Configure .htaccess automatically when it's true
345 *
346 * @return bool
347 * @since 1.0
348 */
349 public function configure_htaccess( $enable = true ) {
350 if ( ! function_exists( '\get_home_path' ) ) {
351 require_once ABSPATH . '/wp-admin/includes/file.php';
352 }
353
354 $htaccess_file = get_home_path() . '.htaccess';
355 $settings = \PoweredCache\Utils\get_settings();
356
357 /**
358 * Filters whether automatically update or not update .htaccess file
359 *
360 * @hook powered_cache_auto_htaccess_update
361 *
362 * @param {boolean} true to automatic update.
363 *
364 * @return {boolean} New value.
365 *
366 * @since 1.1.1
367 */
368 if ( true !== apply_filters( 'powered_cache_auto_htaccess_update', true ) ) {
369 return false;
370 }
371
372 /**
373 * Apache users can control automatic configuration
374 *
375 * @since 1.2
376 */
377 $automatic_configuration = $settings['auto_configure_htaccess'];
378
379 if ( is_multisite() && ! POWERED_CACHE_IS_NETWORK ) {
380 $automatic_configuration = false; // individual sites shouldn't use .htaccess on multisite
381 }
382
383 if ( ! $automatic_configuration ) {
384 return false;
385 }
386
387 if ( is_writable( $htaccess_file ) ) {
388 $contents = file_get_contents( $htaccess_file );
389
390 // clean up
391 $contents = preg_replace( '/# BEGIN POWERED CACHE(.*)# END POWERED CACHE\s*?/isU', '', $contents );
392
393 if ( false === $enable ) {
394 return file_put_contents( $htaccess_file, $contents );
395 }
396
397 $rules = Htaccess::factory()->htaccess_rules();
398 $contents = $rules . $contents;
399
400 // Update the .htacces file
401 if ( ! file_put_contents( $htaccess_file, $contents ) ) {
402 return false;
403 }
404
405 return true;
406 }
407
408 return false;
409 }
410
411 /**
412 * Prepares .htaccess rules for the caching
413 *
414 * @return string $rules
415 * @since 1.1
416 * @deprecated 2.5.0 Use the {@see '\PoweredCache\Htaccess::factory()->htaccess_rules()'} instead.
417 */
418 public function htaccess_rules() {
419 $rules = Htaccess::factory()->htaccess_rules();
420
421 return $rules;
422 }
423
424 /**
425 * Make sure directory listing disabled
426 *
427 * @return bool
428 * @since 1.2
429 */
430 public function protect_cache_dir() {
431
432 if ( ! file_exists( get_cache_dir() ) ) {
433 mkdir( get_cache_dir() );
434 }
435
436 $file = get_cache_dir() . '.htaccess';
437
438 $file_string = '<IfModule mod_autoindex.c>' . PHP_EOL;
439 $file_string .= ' Options -Indexes' . PHP_EOL;
440 $file_string .= '</IfModule>' . PHP_EOL . PHP_EOL;
441 $file_string .= '<FilesMatch "^.*-user_.*\.(html|html\.gz)$">' . PHP_EOL;
442 $file_string .= ' Order Allow,Deny' . PHP_EOL;
443 $file_string .= ' Deny from all' . PHP_EOL;
444 $file_string .= '</FilesMatch>' . PHP_EOL;
445
446 /**
447 * Filters the content of the .htaccess file in the cache directory.
448 *
449 * @param {string} $file_string Default configuration
450 *
451 * @hook powered_cache_cache_dir_htaccess_file_content
452 * @since 3.5.3
453 */
454 $file_string = apply_filters( 'powered_cache_cache_dir_htaccess_file_content', $file_string );
455
456 if ( ! file_put_contents( $file, $file_string ) ) {
457 return false;
458 }
459
460 return true;
461 }
462
463 /**
464 * Prepare config name
465 *
466 * @param bool $is_network Whether network-wide config name or not
467 *
468 * @return string configuration file name
469 * @since 2.0
470 */
471 public function get_config_filename( $is_network ) {
472 if ( $is_network ) {
473 return 'config-network.php';
474 } else {
475 $url_parts = wp_parse_url( home_url() );
476 $config_name = 'config-' . $url_parts['host'];
477
478 if ( is_multisite() && ! is_subdomain_install() ) {
479 if ( ! is_main_site( get_current_blog_id() ) && ! empty( $url_parts['path'] ) ) {
480 $subdir_name = ltrim( $url_parts['path'], '/' );
481 $config_name .= '-' . $subdir_name;
482 }
483 }
484
485 $config_name .= '.php';
486
487 return $config_name;
488 }
489 }
490
491 /**
492 * Save settings to file
493 *
494 * @param array $configuration plugin settings
495 * @param bool $network_wide Whether network-wide configuration or not
496 *
497 * @return bool
498 * @since 1.0
499 */
500 public function save_to_file( $configuration, $network_wide = false ) {
501 $config_dir = WP_CONTENT_DIR . '/pc-config';
502 $config_file_name = $this->get_config_filename( $network_wide );
503
504 if ( ! file_exists( $config_dir ) ) {
505 mkdir( $config_dir );
506 }
507
508 $config_file = trailingslashit( $config_dir ) . $config_file_name;
509
510 if ( ! file_exists( $config_file ) ) {
511 touch( $config_file );
512 }
513
514 $configuration['cache_location'] = get_cache_dir();
515
516 $config_file_string = '<?php' . PHP_EOL . "defined( 'ABSPATH' ) || exit;" . PHP_EOL . PHP_EOL;
517
518 $config_file_string .= "\$GLOBALS['powered_cache_options'] = " . var_export( $configuration, true ) . ';' . PHP_EOL . PHP_EOL;
519
520 // mobile cache variables
521 $config_file_string .= '$powered_cache_mobile_browsers = ' . var_export( mobile_browsers(), true ) . ';' . PHP_EOL;
522 $config_file_string .= '$powered_cache_mobile_prefixes = ' . var_export( mobile_prefixes(), true ) . ';' . PHP_EOL;
523 $config_file_string .= '$powered_cache_rejected_user_agents = ' . var_export( AdvancedCache::get_rejected_user_agents(), true ) . ';' . PHP_EOL;
524 $config_file_string .= '$powered_cache_rejected_cookies = ' . var_export( AdvancedCache::get_rejected_cookies(), true ) . ';' . PHP_EOL;
525 $config_file_string .= '$powered_cache_rejected_referrers = ' . var_export( AdvancedCache::get_rejected_referrers(), true ) . ';' . PHP_EOL;
526 $config_file_string .= '$powered_cache_vary_cookies = ' . var_export( AdvancedCache::get_vary_cookies(), true ) . ';' . PHP_EOL;
527 $config_file_string .= '$powered_cache_rejected_uri = ' . var_export( AdvancedCache::get_rejected_uri(), true ) . ';' . PHP_EOL;
528 $config_file_string .= '$powered_cache_ignored_query_strings = ' . var_export( AdvancedCache::get_ignored_query_strings(), true ) . ';' . PHP_EOL;
529 $config_file_string .= '$powered_cache_cache_query_strings = ' . var_export( AdvancedCache::get_cache_query_string(), true ) . ';' . PHP_EOL;
530
531 if ( permalink_structure_has_trailingslash() ) {
532 $config_file_string .= '$powered_cache_slash_check = true;' . PHP_EOL;
533 } else {
534 $config_file_string .= '$powered_cache_slash_check = false;' . PHP_EOL;
535 }
536
537 /**
538 * Fires before writing configuration file.
539 *
540 * @hook powered_cache_create_config_file
541 *
542 * @param {string} $config_file The path of the configuration file.
543 * @param {string} $config_file_string The contents of the configurations.
544 * @param {bool} $network_wide Whether network-wide configuration or not.
545 *
546 * @since 2.0
547 */
548 do_action( 'powered_cache_create_config_file', $config_file, $config_file_string, $network_wide );
549
550 if ( ! file_put_contents( $config_file, $config_file_string ) ) {
551 return false;
552 }
553
554 // OPCache invalidate
555 if ( function_exists( 'opcache_invalidate' ) ) {
556 opcache_invalidate( $config_file, true );
557 }
558
559 return true;
560 }
561
562
563 /**
564 * Prepares nginx configuration
565 *
566 * @return string $contents nginx rules
567 * @since 1.2 trailingslash rule added
568 *
569 * @since 1.1
570 */
571 public function nginx_rules() {
572 $settings = \PoweredCache\Utils\get_settings();
573
574 $contents = '';
575 $contents .= '##### POWERED CACHE CONF #####' . PHP_EOL;
576 $contents .= 'set $cache_uri $request_uri;' . PHP_EOL;
577 $contents .= 'set $pc_ssl "";' . PHP_EOL;
578 $contents .= 'set $pc_enc "";' . PHP_EOL;
579 $contents .= 'set $pc_ua "";' . PHP_EOL . PHP_EOL;
580
581 // post
582 $contents .= '# POST requests and urls with a query string should always go to PHP' . PHP_EOL;
583 $contents .= 'if ($request_method = POST) {' . PHP_EOL;
584 $contents .= ' set $cache_uri \'null cache\';' . PHP_EOL;
585 $contents .= '}' . PHP_EOL . PHP_EOL;
586
587 $contents .= 'location = /favicon.ico { log_not_found off; access_log off; }' . PHP_EOL;
588 $contents .= 'location = /robots.txt { try_files $uri $uri/ /index.php?$args; log_not_found off; access_log off; }' . PHP_EOL . PHP_EOL;
589
590 // query string
591 $contents .= 'if ($query_string != "") {' . PHP_EOL;
592 $contents .= ' set $cache_uri \'null cache\';' . PHP_EOL;
593 $contents .= '}' . PHP_EOL . PHP_EOL;
594
595 // Add CORS rules
596 if ( $settings['enable_cdn'] ) {
597 $contents .= 'location ~* .(jpg|jpeg|png|gif|ico|css|js|svg|eot|woff|woff2|ttf|otf)$ {' . PHP_EOL;
598 $contents .= 'add_header Access-Control-Allow-Origin *;' . PHP_EOL;
599 $contents .= '}' . PHP_EOL . PHP_EOL;
600 }
601
602 /**
603 * Documented in htaccess config
604 */
605 if ( apply_filters( 'powered_cache_browser_cache', true ) ) {
606 $contents .= 'location ~* .(js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|rtf|swf|ico|flv|txt|woff|woff2|svg|webp|avif)$ {' . PHP_EOL;
607 $contents .= ' expires 6M;' . PHP_EOL;
608 $contents .= '}' . PHP_EOL . PHP_EOL;
609 }
610
611 // file optimizer rewrite rule
612 if ( $settings['rewrite_file_optimizer'] ) {
613 $file_optimizer_path = \PoweredCache\Optimizer\Helper::get_file_optimizer_relative_path();
614
615 $contents .= 'location /_static/ {' . PHP_EOL;
616 $contents .= ' fastcgi_pass unix:/var/run/fastcgi.sock;' . PHP_EOL;
617 $contents .= ' include /etc/nginx/fastcgi_params;' . PHP_EOL;
618 $contents .= ' fastcgi_param SCRIPT_FILENAME $document_root/' . $file_optimizer_path . ';' . PHP_EOL;
619 $contents .= '}' . PHP_EOL . PHP_EOL;
620 }
621
622 // https
623 $contents .= '# HTTPS' . PHP_EOL;
624 $contents .= 'if ($https = "on") {' . PHP_EOL;
625 $contents .= ' set $pc_ssl "-https";' . PHP_EOL;
626 $contents .= '}' . PHP_EOL . PHP_EOL;
627
628 $contents .= '# Don\'t cache uris containing the following segments' . PHP_EOL;
629 $contents .= 'if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {' . PHP_EOL;
630 $contents .= ' set $cache_uri \'null cache\';' . PHP_EOL;
631 $contents .= '}' . PHP_EOL . PHP_EOL;
632
633 $rejected_user_agents = (array) AdvancedCache::get_rejected_user_agents();
634
635 $contents .= '# Don\'t use the cache for rejected agents' . PHP_EOL;
636 $contents .= 'if ($http_user_agent ~* "(' . implode( '|', $rejected_user_agents ) . ')") {' . PHP_EOL;
637 $contents .= ' set $cache_uri \'null cache\';' . PHP_EOL;
638 $contents .= '}' . PHP_EOL . PHP_EOL;
639
640 $rejected_cookies = (array) AdvancedCache::get_rejected_cookies();
641
642 $contents .= '# Don\'t use the cache for logged in users or recent commenters' . PHP_EOL;
643 $contents .= 'if ($http_cookie ~* "wordpress_[a-f0-9]+|' . implode( '|', $rejected_cookies ) . '") {' . PHP_EOL;
644 $contents .= ' set $cache_uri \'null cache\';' . PHP_EOL;
645 $contents .= '}' . PHP_EOL . PHP_EOL;
646
647 $contents .= 'if ($http_x_wap_profile) {' . PHP_EOL;
648 $contents .= ' set $pc_ua \'-mobile\';' . PHP_EOL;
649 $contents .= '}' . PHP_EOL . PHP_EOL;
650
651 if ( true === $settings['cache_mobile'] && true === $settings['cache_mobile_separate_file'] ) {
652 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', mobile_browsers() ) ), ' ' );
653 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', mobile_prefixes() ) ), ' ' );
654
655 $contents .= 'if ($http_user_agent ~* (' . $mobile_browsers . ')) {' . PHP_EOL;
656 $contents .= ' set $pc_ua \'-mobile\';' . PHP_EOL;
657 $contents .= '}' . PHP_EOL . PHP_EOL;
658
659 $contents .= 'if ($http_user_agent ~* (' . $mobile_prefixes . ')) {' . PHP_EOL;
660 $contents .= ' set $pc_ua \'-mobile\';' . PHP_EOL;
661 $contents .= '}' . PHP_EOL . PHP_EOL;
662 }
663
664 $cache_suffix = 'html';
665
666 if ( true === $settings['gzip_compression'] ) {
667 $cache_suffix .= '.gz';
668 }
669
670 $contents .= 'location / {' . PHP_EOL;
671 /**
672 * Documented in htaccess config
673 */
674 if ( apply_filters( 'powered_cache_mod_rewrite', true ) ) { // rewrite
675 $contents .= ' add_header X-Powered-Cache nginx;' . PHP_EOL;
676 $contents .= ' try_files /wp-content/cache/powered-cache/$http_host/$cache_uri/index${pc_ssl}${pc_ua}.' . $cache_suffix . ' $uri $uri/ /index.php?$args;' . PHP_EOL;
677
678 } else {
679 $contents .= ' try_files $uri $uri/ /index.php?$args;' . PHP_EOL;
680 }
681
682 $contents .= '}' . PHP_EOL . PHP_EOL;
683
684 if ( permalink_structure_has_trailingslash() ) {
685 $contents .= '# add trailingslash rule' . PHP_EOL;
686 $contents .= 'rewrite ^([^.]*[^/])$ $1/ permanent;' . PHP_EOL;
687 }
688
689 return $contents;
690 }
691
692 /**
693 * Downloads configuration files
694 *
695 * @param string $server type supports apache and nginx
696 *
697 * @since 1.1
698 */
699 public function download_rewrite_rules( $server ) {
700
701 $rules = '';
702 $filename = 'conf';
703
704 if ( 'apache' === $server ) {
705 $rules = Htaccess::factory()->htaccess_rules();
706 $filename = '.htaccess_powered_cache';
707 }
708
709 if ( 'nginx' === $server ) {
710 $rules = $this->nginx_rules();
711 $filename = 'poweredcache.conf';
712 }
713
714 nocache_headers();
715 @header( 'Content-Type: text/plain' );
716 @header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
717 @header( 'Content-Transfer-Encoding: binary' );
718 @header( 'Content-Length: ' . strlen( $rules ) );
719 @header( 'Connection: close' );
720 echo $rules; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
721 exit;
722 }
723
724 /**
725 * Make the caching configurations with given options
726 *
727 * @param array $settings Plugin settings
728 * @param bool $network_wide Whether network-wide configuration or not
729 *
730 * @since 2.0
731 */
732 public function save_configuration( $settings, $network_wide = false ) {
733
734 if ( can_configure_object_cache() ) {
735 if ( ! empty( $settings['dev_mode'] ) ) {
736 $this->setup_object_cache(); // dev mode, no object cache
737 } else {
738 $this->setup_object_cache( $settings['object_cache'] );
739 }
740 }
741
742 $this->setup_page_cache( $settings['enable_page_cache'] );
743 $private_settings = [ 'cloudflare_email', 'cloudflare_api_key', 'cloudflare_api_token', 'cloudflare_zone' ];
744
745 foreach ( $private_settings as $setting_key ) {
746 unset( $settings[ $setting_key ] );
747 }
748
749 $this->save_to_file( $settings, $network_wide );
750 }
751
752 /**
753 * Clean-up all the configurations and cache related footprints
754 */
755 public function clean_up() {
756 $object_cache_dropin = untrailingslashit( WP_CONTENT_DIR ) . '/object-cache.php';
757 if ( file_exists( $object_cache_dropin ) && false !== strpos( file_get_contents( $object_cache_dropin ), 'POWERED_OBJECT_CACHE' ) ) {
758 unlink( $object_cache_dropin );
759 }
760
761 $advanced_cache_dropin = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
762 if ( file_exists( $advanced_cache_dropin ) ) {
763 unlink( $advanced_cache_dropin );
764 }
765
766 $this->define_wp_cache( false );
767 $this->configure_htaccess( false );
768 $this->protect_cache_dir();
769
770 if ( ! file_exists( get_cache_dir() ) ) {
771 remove_dir( get_cache_dir() );
772 }
773
774 $config_dir = WP_CONTENT_DIR . '/pc-config';
775
776 if ( is_multisite() ) {
777 $config_file_name = $this->get_config_filename( POWERED_CACHE_IS_NETWORK );
778 $config_file = trailingslashit( $config_dir ) . $config_file_name;
779 if ( file_exists( $config_file ) ) {
780 unlink( $config_file );
781 }
782 } else { // remove entire configuration directory on single site setup
783 remove_dir( $config_dir );
784 }
785
786 /**
787 * Fires after cleanup all configurations
788 *
789 * @hook powered_cache_after_clean_up
790 *
791 * @since 2.0
792 */
793 do_action( 'powered_cache_after_clean_up' );
794
795 }
796
797 }
798