Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/wp-rocket/inc/functions/files.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
3
+
use WP_Rocket\Logger\Logger;
4
+
use WP_Rocket\Engine\Cache\AdvancedCache;
5
+
6
+
defined( 'ABSPATH' ) || exit;
7
+
8
+
/**
9
+
* Creates the advanced-cache.php file.
10
+
*
11
+
* @since 3.6 Uses AdvancedCache::get_advanced_cache_content().
12
+
* @since 2.0
13
+
*
14
+
* @param AdvancedCache $advanced_cache Optional. Instance of the advanced cache handler.
15
+
*/
16
+
function rocket_generate_advanced_cache_file( $advanced_cache = null ) {
17
+
/**
18
+
* Filters whether to generate the advanced-cache.php file.
19
+
*
20
+
* @since 3.6.3
21
+
*
22
+
* @param bool True (default) to go ahead with advanced cache file generation; false to stop generation.
23
+
*/
24
+
if ( ! (bool) apply_filters( 'rocket_generate_advanced_cache_file', true ) ) {
25
+
return false;
26
+
}
27
+
28
+
static $done = false;
29
+
30
+
if ( rocket_get_constant( 'WP_ROCKET_IS_TESTING', false ) ) {
31
+
$done = false;
32
+
}
33
+
34
+
if ( $done ) {
35
+
return false;
36
+
}
37
+
$done = true;
38
+
39
+
if ( is_null( $advanced_cache ) ) {
40
+
$container = apply_filters( 'rocket_container', null );
41
+
$advanced_cache = $container->get( 'advanced_cache' );
42
+
}
43
+
44
+
return rocket_put_content(
45
+
rocket_get_constant( 'WP_CONTENT_DIR' ) . '/advanced-cache.php',
46
+
$advanced_cache->get_advanced_cache_content()
47
+
);
48
+
}
49
+
50
+
/**
51
+
* Generates the configuration file for the current domain based on the values of options
52
+
*
53
+
* @since 2.0
54
+
*
55
+
* @return array Names of all config files & The content that will be printed
56
+
*/
57
+
function get_rocket_config_file() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
58
+
$options = get_option( WP_ROCKET_SLUG );
59
+
60
+
if ( ! $options ) {
61
+
return [
62
+
[],
63
+
'',
64
+
];
65
+
}
66
+
67
+
$buffer = "<?php\n";
68
+
$buffer .= "defined( 'ABSPATH' ) || exit;\n\n";
69
+
70
+
$buffer .= '$rocket_cookie_hash = \'' . COOKIEHASH . "';\n";
71
+
$buffer .= '$rocket_logged_in_cookie = \'' . LOGGED_IN_COOKIE . "';\n";
72
+
73
+
/**
74
+
* Filters the activation of the common cache for logged-in users.
75
+
*
76
+
* @since 2.10
77
+
* @author Remy Perona
78
+
*
79
+
* @param bool True to activate the common cache, false to ignore.
80
+
*/
81
+
if ( apply_filters( 'rocket_common_cache_logged_users', false ) ) {
82
+
$buffer .= '$rocket_common_cache_logged_users = 1;' . "\n";
83
+
}
84
+
85
+
if ( ! empty( $options['cache_webp'] ) ) {
86
+
/** This filter is documented in inc/classes/buffer/class-cache.php */
87
+
$disable_webp_cache = apply_filters( 'rocket_disable_webp_cache', false );
88
+
89
+
if ( $disable_webp_cache ) {
90
+
$options['cache_webp'] = 0;
91
+
}
92
+
}
93
+
94
+
/**
95
+
* Filters the use of the mobile cache version for tablets
96
+
* 'desktop' will serve desktop to tablets, 'mobile' will serve mobile to tablets
97
+
*
98
+
* @since 3.2
99
+
* @author Remy Perona
100
+
*
101
+
* @param string $tablet_version valid values are 'mobile' or 'desktop'
102
+
*/
103
+
$buffer .= '$rocket_cache_mobile_files_tablet = \'' . apply_filters( 'rocket_cache_mobile_files_tablet', 'desktop' ) . "';\n";
104
+
105
+
foreach ( $options as $option => $value ) {
106
+
if ( 'cache_ssl' === $option ) {
107
+
if ( 1 !== (int) $value ) {
108
+
if ( rocket_is_ssl_website() ) {
109
+
update_rocket_option( 'cache_ssl', 1 );
110
+
$value = 1;
111
+
}
112
+
}
113
+
114
+
$buffer .= '$rocket_' . $option . ' = ' . (int) $value . ";\n";
115
+
}
116
+
117
+
if ( 'cache_mobile' === $option || 'do_caching_mobile_files' === $option || 'cache_webp' === $option ) {
118
+
$buffer .= '$rocket_' . $option . ' = ' . (int) $value . ";\n";
119
+
}
120
+
121
+
if ( 'secret_cache_key' === $option ) {
122
+
$buffer .= '$rocket_' . $option . ' = \'' . sanitize_key( $value ) . "';\n";
123
+
}
124
+
125
+
if ( 'cache_reject_uri' === $option ) {
126
+
$buffer .= '$rocket_' . $option . ' = \'' . get_rocket_cache_reject_uri( true ) . "';\n";
127
+
}
128
+
129
+
if ( 'cache_query_strings' === $option ) {
130
+
$buffer .= '$rocket_' . $option . ' = ' . call_user_func( 'var_export', get_rocket_cache_query_string(), true ) . ";\n";
131
+
}
132
+
133
+
if ( 'cache_reject_cookies' === $option ) {
134
+
$cookies = get_rocket_cache_reject_cookies();
135
+
136
+
if ( $cookies && get_rocket_option( 'cache_logged_user' ) ) {
137
+
// Make sure the "logged-in cookies" are not rejected.
138
+
$logged_in_cookie = explode( COOKIEHASH, LOGGED_IN_COOKIE );
139
+
$logged_in_cookie = array_map( 'preg_quote', $logged_in_cookie );
140
+
$logged_in_cookie = implode( '[^|]*', $logged_in_cookie );
141
+
$cookies = preg_replace( '/\|' . $logged_in_cookie . '\|/', '|', '|' . $cookies . '|' );
142
+
$cookies = trim( $cookies, '|' );
143
+
}
144
+
145
+
$buffer .= '$rocket_' . $option . ' = \'' . $cookies . "';\n";
146
+
}
147
+
148
+
if ( 'cache_reject_ua' === $option ) {
149
+
$buffer .= '$rocket_' . $option . ' = \'' . get_rocket_cache_reject_ua() . "';\n";
150
+
}
151
+
}
152
+
153
+
$buffer .= '$rocket_cache_ignored_parameters = ' . call_user_func( 'var_export', rocket_get_ignored_parameters(), true ) . ";\n";
154
+
$buffer .= '$rocket_cache_mandatory_cookies = ' . call_user_func( 'var_export', get_rocket_cache_mandatory_cookies(), true ) . ";\n";
155
+
156
+
$buffer .= '$rocket_cache_dynamic_cookies = ' . call_user_func( 'var_export', get_rocket_cache_dynamic_cookies(), true ) . ";\n";
157
+
158
+
$buffer .= '$rocket_permalink_structure = \'' . wp_slash( get_option( 'permalink_structure' ) ) . "';\n";
159
+
160
+
/** This filter is documented in inc/front/htaccess.php */
161
+
if ( apply_filters( 'rocket_url_no_dots', false ) ) {
162
+
$buffer .= '$rocket_url_no_dots = 1;';
163
+
}
164
+
165
+
$config_files_path = [];
166
+
$urls = [ rocket_get_home_url() ];
167
+
168
+
// Check if a translation plugin is activated and this configuration is in subdomain.
169
+
$subdomains = get_rocket_i18n_subdomains();
170
+
171
+
if ( $subdomains ) {
172
+
$urls = $subdomains;
173
+
}
174
+
175
+
foreach ( $urls as $url ) {
176
+
$file = get_rocket_parse_url( untrailingslashit( $url ) );
177
+
$file['path'] = ( ! empty( $file['path'] ) ) ? str_replace( '/', '.', untrailingslashit( $file['path'] ) ) : '';
178
+
$config_files_path[] = WP_ROCKET_CONFIG_PATH . strtolower( $file['host'] ) . $file['path'] . '.php';
179
+
}
180
+
181
+
/**
182
+
* Filter all config files path
183
+
*
184
+
* @since 2.6.5
185
+
*
186
+
* @param array $config_files_path Path of all config files.
187
+
*/
188
+
$config_files_path = apply_filters( 'rocket_config_files_path', $config_files_path );
189
+
190
+
/**
191
+
* Filter the content of all config files
192
+
*
193
+
* @since 2.1
194
+
*
195
+
* @param string $buffer The content that will be printed.
196
+
* @param array $config_files_path Names of all config files.
197
+
*/
198
+
$buffer = apply_filters( 'rocket_config_file', $buffer, $config_files_path );
199
+
$buffer = preg_replace( '@array\s+\(@i', 'array(', $buffer );
200
+
$buffer = preg_replace( '@array\(\s+\)@i', 'array()', $buffer );
201
+
202
+
return [ $config_files_path, $buffer ];
203
+
}
204
+
205
+
/**
206
+
* Create the current config domain file
207
+
* For example, if home_url() return example.com, the config domain file will be in /config/example.com
208
+
*
209
+
* @since 2.0
210
+
*
211
+
* @return void
212
+
*/
213
+
function rocket_generate_config_file() {
214
+
list( $config_files_path, $buffer ) = get_rocket_config_file();
215
+
216
+
if ( count( $config_files_path ) ) {
217
+
rocket_init_config_dir();
218
+
219
+
foreach ( $config_files_path as $file ) {
220
+
rocket_put_content( $file, $buffer );
221
+
}
222
+
}
223
+
}
224
+
225
+
/**
226
+
* Remove the current config domain file
227
+
*
228
+
* @since 2.6
229
+
*
230
+
* @return void
231
+
*/
232
+
function rocket_delete_config_file() {
233
+
list( $config_files_path ) = get_rocket_config_file();
234
+
foreach ( $config_files_path as $config_file ) {
235
+
rocket_direct_filesystem()->delete( $config_file );
236
+
}
237
+
238
+
// Bail out if WP Rocket is multisite.
239
+
if ( is_multisite() ) {
240
+
return;
241
+
}
242
+
243
+
try {
244
+
$config_dir = new FilesystemIterator( (string) rocket_get_constant( 'WP_ROCKET_CONFIG_PATH' ) );
245
+
} catch ( Exception $e ) {
246
+
return;
247
+
}
248
+
249
+
// Remove all files with php extension in the config folder.
250
+
foreach ( $config_dir as $file ) {
251
+
if ( ! $file->isFile() || 'php' !== strtolower( $file->getExtension() ) ) {
252
+
continue;
253
+
}
254
+
255
+
if ( 1 === substr_count( $file->getFilename(), '.' ) ) {
256
+
continue;
257
+
}
258
+
259
+
if ( false === strpos( rocket_direct_filesystem()->get_contents( $file->getPathname() ), '$rocket_cookie_hash' ) ) {
260
+
continue;
261
+
}
262
+
263
+
rocket_direct_filesystem()->delete( $file->getPathname() );
264
+
}
265
+
}
266
+
267
+
/**
268
+
* Create all cache folders (wp-rocket & min)
269
+
*
270
+
* @since 2.6
271
+
*
272
+
* @return void
273
+
*/
274
+
function rocket_init_cache_dir() {
275
+
global $is_apache;
276
+
277
+
$filesystem = rocket_direct_filesystem();
278
+
279
+
// Create cache folder if not exist.
280
+
if ( ! $filesystem->is_dir( WP_ROCKET_CACHE_PATH ) ) {
281
+
rocket_mkdir_p( WP_ROCKET_CACHE_PATH );
282
+
}
283
+
284
+
if ( ! $filesystem->is_file( WP_ROCKET_CACHE_PATH . 'index.html' ) ) {
285
+
$filesystem->touch( WP_ROCKET_CACHE_PATH . 'index.html' );
286
+
}
287
+
288
+
if ( $is_apache ) {
289
+
$htaccess_path = WP_ROCKET_CACHE_PATH . '.htaccess';
290
+
291
+
if ( ! $filesystem->is_file( $htaccess_path ) ) {
292
+
$filesystem->touch( $htaccess_path );
293
+
rocket_put_content( $htaccess_path, "<IfModule mod_autoindex.c>\nOptions -Indexes\n</IfModule>" );
294
+
}
295
+
}
296
+
297
+
// Create minify cache folder if not exist.
298
+
if ( ! $filesystem->is_dir( WP_ROCKET_MINIFY_CACHE_PATH ) ) {
299
+
rocket_mkdir_p( WP_ROCKET_MINIFY_CACHE_PATH );
300
+
}
301
+
302
+
if ( ! $filesystem->is_file( WP_ROCKET_MINIFY_CACHE_PATH . 'index.html' ) ) {
303
+
$filesystem->touch( WP_ROCKET_MINIFY_CACHE_PATH . 'index.html' );
304
+
}
305
+
306
+
// Create busting cache folder if not exist.
307
+
if ( ! $filesystem->is_dir( WP_ROCKET_CACHE_BUSTING_PATH ) ) {
308
+
rocket_mkdir_p( WP_ROCKET_CACHE_BUSTING_PATH );
309
+
}
310
+
311
+
if ( ! $filesystem->is_file( WP_ROCKET_CACHE_BUSTING_PATH . 'index.html' ) ) {
312
+
$filesystem->touch( WP_ROCKET_CACHE_BUSTING_PATH . 'index.html' );
313
+
}
314
+
315
+
// Create critical CSS folder if not exist.
316
+
if ( ! $filesystem->is_dir( WP_ROCKET_CRITICAL_CSS_PATH ) ) {
317
+
rocket_mkdir_p( WP_ROCKET_CRITICAL_CSS_PATH );
318
+
}
319
+
320
+
if ( ! $filesystem->is_file( WP_ROCKET_CRITICAL_CSS_PATH . 'index.html' ) ) {
321
+
$filesystem->touch( WP_ROCKET_CRITICAL_CSS_PATH . 'index.html' );
322
+
}
323
+
}
324
+
325
+
/**
326
+
* Create the config folder (wp-rocket-config)
327
+
*
328
+
* @since 2.6
329
+
*
330
+
* @return void
331
+
*/
332
+
function rocket_init_config_dir() {
333
+
$filesystem = rocket_direct_filesystem();
334
+
335
+
// Create config domain folder if not exist.
336
+
if ( ! $filesystem->is_dir( WP_ROCKET_CONFIG_PATH ) ) {
337
+
rocket_mkdir_p( WP_ROCKET_CONFIG_PATH );
338
+
}
339
+
340
+
// Initialize the config directory with index.html to prevent indexing.
341
+
if ( ! $filesystem->is_file( WP_ROCKET_CONFIG_PATH . 'index.html' ) ) {
342
+
$filesystem->touch( WP_ROCKET_CONFIG_PATH . 'index.html' );
343
+
}
344
+
}
345
+
346
+
/**
347
+
* Delete all minify cache files.
348
+
*
349
+
* @since 3.5.3 Replaces glob.
350
+
* @since 2.1
351
+
*
352
+
* @param string|array $extensions Optional. File extensions to minify. Default: js and css.
353
+
*/
354
+
function rocket_clean_minify( $extensions = [ 'js', 'css' ] ) {
355
+
// Bails out if there are no extensions to target.
356
+
if ( empty( $extensions ) ) {
357
+
return;
358
+
}
359
+
360
+
if ( is_string( $extensions ) ) {
361
+
$extensions = (array) $extensions;
362
+
}
363
+
364
+
$min_cache_path = rocket_get_constant( 'WP_ROCKET_MINIFY_CACHE_PATH' );
365
+
$min_path = $min_cache_path . get_current_blog_id() . '/';
366
+
$iterator = _rocket_get_cache_path_iterator( $min_path );
367
+
368
+
if ( false === $iterator ) {
369
+
return;
370
+
}
371
+
372
+
$filesystem = rocket_direct_filesystem();
373
+
$min_path_regex = str_replace( '/', '\/', $min_path );
374
+
375
+
foreach ( $extensions as $ext ) {
376
+
/**
377
+
* Fires before the minify cache files are deleted.
378
+
*
379
+
* @since 2.1
380
+
*
381
+
* @param string $ext File extensions to minify.
382
+
*/
383
+
do_action( 'before_rocket_clean_minify', $ext ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
384
+
385
+
try {
386
+
$entries = new RegexIterator( $iterator, "/{$min_path_regex}.*\.{$ext}/" );
387
+
} catch ( Exception $e ) {
388
+
return;
389
+
}
390
+
391
+
foreach ( $entries as $entry ) {
392
+
$filesystem->delete( $entry->getPathname() );
393
+
}
394
+
395
+
/**
396
+
* Fires after the minify cache files was deleted.
397
+
*
398
+
* @since 2.1
399
+
*
400
+
* @param string $ext File extensions to minify.
401
+
*/
402
+
do_action( 'after_rocket_clean_minify', $ext ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
403
+
}
404
+
405
+
// Delete any directories.
406
+
foreach ( $iterator as $item ) {
407
+
if ( $filesystem->is_dir( $item ) ) {
408
+
$filesystem->delete( $item );
409
+
}
410
+
}
411
+
412
+
// Clean the cache/min/3rd-party items.
413
+
try {
414
+
$files = new FilesystemIterator( "{$min_cache_path}3rd-party" );
415
+
416
+
foreach ( $files as $file ) {
417
+
if ( $filesystem->is_file( $file ) ) {
418
+
$filesystem->delete( $file );
419
+
}
420
+
}
421
+
} catch ( UnexpectedValueException $e ) {
422
+
// No logging yet.
423
+
return;
424
+
}
425
+
}
426
+
427
+
/**
428
+
* Delete all cache busting files.
429
+
*
430
+
* @since 2.9
431
+
*
432
+
* @param string|array $extensions (default: array('js','css') File extensions to clean.
433
+
* @return void
434
+
*/
435
+
function rocket_clean_cache_busting( $extensions = [ 'js', 'css' ] ) {
436
+
if ( empty( $extensions ) ) {
437
+
return;
438
+
}
439
+
440
+
if ( is_string( $extensions ) ) {
441
+
$extensions = (array) $extensions;
442
+
}
443
+
444
+
$cache_busting_path = rocket_get_constant( 'WP_ROCKET_CACHE_BUSTING_PATH' ) . get_current_blog_id() . '/';
445
+
$iterator = _rocket_get_cache_path_iterator( $cache_busting_path );
446
+
447
+
if ( false === $iterator ) {
448
+
return;
449
+
}
450
+
451
+
$filesystem = rocket_direct_filesystem();
452
+
$busting_path_regex = str_replace( '/', '\/', $cache_busting_path );
453
+
454
+
if ( ! rocket_direct_filesystem()->is_dir( $cache_busting_path ) ) {
455
+
rocket_mkdir_p( $cache_busting_path );
456
+
457
+
Logger::debug(
458
+
'No Cache Busting folder found.',
459
+
[
460
+
'mkdir cache busting folder',
461
+
'cache_busting_path' => $cache_busting_path,
462
+
]
463
+
);
464
+
465
+
return;
466
+
}
467
+
468
+
foreach ( $extensions as $ext ) {
469
+
/**
470
+
* Fires before the cache busting files are deleted
471
+
*
472
+
* @since 2.9
473
+
*
474
+
* @param string $ext File extensions to clean.
475
+
*/
476
+
do_action( 'before_rocket_clean_busting', $ext ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
477
+
478
+
try {
479
+
$entries = new RegexIterator( $iterator, "/{$busting_path_regex}.*\.{$ext}/" );
480
+
} catch ( Exception $e ) {
481
+
return;
482
+
}
483
+
484
+
foreach ( $entries as $entry ) {
485
+
$filesystem->delete( $entry->getPathname() );
486
+
}
487
+
488
+
/**
489
+
* Fires after the cache busting files was deleted
490
+
*
491
+
* @since 2.9
492
+
*
493
+
* @param string $ext File extensions to clean.
494
+
*/
495
+
do_action( 'after_rocket_clean_cache_busting', $ext ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
496
+
}
497
+
498
+
foreach ( $iterator as $item ) {
499
+
if ( $filesystem->is_dir( $item ) ) {
500
+
$filesystem->delete( $item );
501
+
}
502
+
}
503
+
}
504
+
505
+
/**
506
+
* Returns the right path when the post is trashed.
507
+
*
508
+
* @param array $parsed_url current parsed url.
509
+
* @param int $post_id ID from the post.
510
+
*
511
+
* @return array
512
+
*/
513
+
function rocket_maybe_find_right_trash_url( array $parsed_url, int $post_id ) {
514
+
515
+
$post = get_post( $post_id );
516
+
517
+
if ( ! $post || 'trash' !== $post->post_status ) {
518
+
return $parsed_url;
519
+
}
520
+
521
+
$post->post_status = 'publish';
522
+
523
+
$permalink = get_permalink( $post );
524
+
525
+
if ( ! $permalink ) {
526
+
return $parsed_url;
527
+
}
528
+
529
+
$new_permalink = str_replace( '__trashed', '', $permalink );
530
+
return get_rocket_parse_url( $new_permalink );
531
+
}
532
+
533
+
/**
534
+
* Delete one or several cache files.
535
+
*
536
+
* @since 3.5.5 Optimizes by grabbing root cache dirs once, bailing out when file/dir doesn't exist, & directly
537
+
* deleting files.
538
+
* @since 3.5.4 Replaces glob and optimizes.
539
+
* @since 2.0 Delete cache files for all users.
540
+
* @since 1.1.0 Add filter rocket_clean_files.
541
+
* @since 1.0
542
+
*
543
+
* @param string|array $urls URLs of cache files to be deleted.
544
+
* @param WP_Filesystem_Direct|null $filesystem Optional. Instance of filesystem handler.
545
+
* @param bool $run_actions Run actions.
546
+
*/
547
+
function rocket_clean_files( $urls, $filesystem = null, $run_actions = true ) {
548
+
$urls = (array) $urls;
549
+
if ( empty( $urls ) ) {
550
+
return;
551
+
}
552
+
553
+
$urls = array_filter( $urls );
554
+
if ( empty( $urls ) ) {
555
+
return;
556
+
}
557
+
558
+
/** This filter is documented in inc/front/htaccess.php */
559
+
$url_no_dots = (bool) apply_filters( 'rocket_url_no_dots', false );
560
+
$cache_path = _rocket_get_wp_rocket_cache_path();
561
+
562
+
if ( empty( $filesystem ) ) {
563
+
$filesystem = rocket_direct_filesystem();
564
+
}
565
+
566
+
if ( $run_actions ) {
567
+
/**
568
+
* Fires before all cache files are deleted.
569
+
*
570
+
* @since 3.2.2
571
+
*
572
+
* @param array $urls The URLs corresponding to the deleted cache files.
573
+
*/
574
+
do_action( 'before_rocket_clean_files', $urls ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
575
+
}
576
+
577
+
foreach ( $urls as $url_key => $url ) {
578
+
if ( $run_actions ) {
579
+
/**
580
+
* Fires before the cache file is deleted.
581
+
*
582
+
* @param string $url The URL that the cache file to be deleted.
583
+
* @since 1.0
584
+
*/
585
+
do_action( 'before_rocket_clean_file', $url ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
586
+
}
587
+
588
+
if ( $url_no_dots ) {
589
+
$url = str_replace( '.', '_', $url );
590
+
}
591
+
592
+
$parsed_url = get_rocket_parse_url( $url );
593
+
594
+
if ( ! empty( $parsed_url['host'] ) ) {
595
+
foreach ( _rocket_get_cache_dirs( $parsed_url['host'], $cache_path ) as $dir ) {
596
+
// Decode url path.
597
+
$url_chunks = explode( '/', $parsed_url['path'] );
598
+
$matches = preg_grep( '/%/', $url_chunks );
599
+
600
+
if ( ! empty( $matches ) ) {
601
+
$parsed_url['path'] = rawurldecode( $parsed_url['path'] );
602
+
}
603
+
604
+
// Encode Non-latin characters if found in url path.
605
+
if ( false !== preg_match_all( '/(?<non_latin>[^\x00-\x7F]+)/', $parsed_url['path'], $matches ) ) {
606
+
$cb_encode_non_latin = function ( $non_latin ) {
607
+
return strtolower( rawurlencode( $non_latin ) );
608
+
};
609
+
610
+
$parsed_url['path'] = str_replace( $matches['non_latin'], array_map( $cb_encode_non_latin, $matches['non_latin'] ), $parsed_url['path'] );
611
+
}
612
+
613
+
$entry = $dir . $parsed_url['path'];
614
+
615
+
// For regex we use it for file names only, and it should include the * character.
616
+
if ( str_contains( $entry, '*' ) ) {
617
+
$regex_part = basename( $entry );
618
+
$search_dir = str_replace( $regex_part, '', $entry );
619
+
$matched_files = _rocket_get_dir_files_by_regex( $search_dir, '#' . $regex_part . '#i' );
620
+
foreach ( $matched_files as $item ) {
621
+
$current_file = $item->getPath() . DIRECTORY_SEPARATOR . $item->getFilename();
622
+
if ( $filesystem->exists( $current_file ) ) {
623
+
$filesystem->delete( $current_file );
624
+
}
625
+
}
626
+
// Remove the regex part from the url.
627
+
$url = str_replace( $regex_part, '', $url );
628
+
$urls[ $url_key ] = $url;
629
+
}
630
+
631
+
// Skip if the dir/file does not exist.
632
+
if ( ! $filesystem->exists( $entry ) ) {
633
+
continue;
634
+
}
635
+
636
+
if ( $filesystem->is_dir( $entry ) ) {
637
+
rocket_rrmdir( $entry, [], $filesystem );
638
+
} else {
639
+
$filesystem->delete( $entry );
640
+
}
641
+
}
642
+
}
643
+
if ( $run_actions ) {
644
+
/**
645
+
* Fires after the cache file is deleted.
646
+
*
647
+
* @param string $url The URL that the cache file was deleted.
648
+
* @since 1.0
649
+
*/
650
+
do_action( 'after_rocket_clean_file', $url ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
651
+
}
652
+
}
653
+
654
+
if ( ! $run_actions ) {
655
+
return;
656
+
}
657
+
658
+
/**
659
+
* Fires after all cache files are deleted.
660
+
*
661
+
* @since 3.2.2
662
+
*
663
+
* @param array $urls The URLs corresponding to the deleted cache files.
664
+
*/
665
+
do_action( 'after_rocket_clean_files', $urls ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
666
+
}
667
+
668
+
/**
669
+
* Remove the home cache file and pagination
670
+
*
671
+
* $since 2.2 Add $lang argument
672
+
*
673
+
* @since 2.0 Delete cache files for all users
674
+
* @since 1.0
675
+
*
676
+
* @param string $lang (default: '') The language code.
677
+
* @return void
678
+
*/
679
+
function rocket_clean_home( $lang = '' ) {
680
+
$parse_url = get_rocket_parse_url( get_rocket_i18n_home_url( $lang ) );
681
+
682
+
/** This filter is documented in inc/front/htaccess.php */
683
+
if ( apply_filters( 'rocket_url_no_dots', false ) ) {
684
+
$parse_url['host'] = str_replace( '.', '_', $parse_url['host'] );
685
+
}
686
+
687
+
$root = WP_ROCKET_CACHE_PATH . $parse_url['host'] . '*' . untrailingslashit( $parse_url['path'] );
688
+
689
+
/**
690
+
* Filter the homepage caching folder root
691
+
*
692
+
* @since 2.6.5
693
+
* @param array $root The root that will be returned.
694
+
* @param string $host The website host.
695
+
* @param string $path The website path.
696
+
*/
697
+
$root = apply_filters( 'rocket_clean_home_root', $root, $parse_url['host'], $parse_url['path'] );
698
+
699
+
/**
700
+
* Fires before the home cache file is deleted
701
+
*
702
+
* @since 1.0
703
+
*
704
+
* @param string $root The path of home cache file.
705
+
* @param string $lang The current lang to purge.
706
+
*/
707
+
do_action( 'before_rocket_clean_home', $root, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
708
+
709
+
// Delete homepage.
710
+
$files = glob( $root . '/*', GLOB_NOSORT );
711
+
712
+
if ( $files ) {
713
+
foreach ( $files as $file ) {
714
+
if ( preg_match( '#/index(?:-.+\.|\.)html(?:_gzip)?$#', $file ) ) {
715
+
rocket_direct_filesystem()->delete( $file );
716
+
}
717
+
}
718
+
}
719
+
720
+
// Delete homepage pagination.
721
+
$dirs = glob( $root . '*/' . $GLOBALS['wp_rewrite']->pagination_base, GLOB_NOSORT );
722
+
if ( $dirs ) {
723
+
foreach ( $dirs as $dir ) {
724
+
rocket_rrmdir( $dir );
725
+
}
726
+
}
727
+
728
+
$param_dirs = glob( $root . '/#*', GLOB_NOSORT );
729
+
730
+
if ( $param_dirs ) {
731
+
foreach ( $param_dirs as $dir ) {
732
+
rocket_rrmdir( $dir );
733
+
}
734
+
}
735
+
736
+
// Remove the hidden empty file for mobile detection on NGINX with the Rocket NGINX configuration.
737
+
$nginx_mobile_detect_files = glob( $root . '/.mobile-active', GLOB_NOSORT );
738
+
if ( $nginx_mobile_detect_files ) {
739
+
foreach ( $nginx_mobile_detect_files as $nginx_mobile_detect_file ) { // no array map to use @.
740
+
rocket_direct_filesystem()->delete( $nginx_mobile_detect_file );
741
+
}
742
+
}
743
+
744
+
// Remove the hidden empty file for webp.
745
+
$nowebp_detect_files = glob( $root . '/.no-webp', GLOB_NOSORT );
746
+
if ( $nowebp_detect_files ) {
747
+
foreach ( $nowebp_detect_files as $nowebp_detect_file ) { // no array map to use @.
748
+
rocket_direct_filesystem()->delete( $nowebp_detect_file );
749
+
}
750
+
}
751
+
752
+
/**
753
+
* Fires after the home cache file was deleted
754
+
*
755
+
* @since 1.0
756
+
*
757
+
* @param string $root The path of home cache file.
758
+
* @param string $lang The current lang to purge.
759
+
*/
760
+
do_action( 'after_rocket_clean_home', $root, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
761
+
}
762
+
763
+
/**
764
+
* Remove the home cache feed
765
+
*
766
+
* @since 2.7
767
+
*
768
+
* @return void
769
+
*/
770
+
function rocket_clean_home_feeds() {
771
+
772
+
if ( ! has_filter( 'rocket_cache_reject_uri', 'wp_rocket_cache_feed' ) ) {
773
+
return;
774
+
}
775
+
776
+
$urls = [];
777
+
$urls[] = get_feed_link();
778
+
$urls[] = get_feed_link( 'comments_' );
779
+
780
+
/**
781
+
* Filter the home feeds urls
782
+
*
783
+
* @since 2.7
784
+
* @param array $urls The urls of the home feeds.
785
+
*/
786
+
$urls = apply_filters( 'rocket_clean_home_feeds', $urls );
787
+
788
+
/**
789
+
* Fires before the home feeds cache is deleted
790
+
*
791
+
* @since 2.7
792
+
*
793
+
* @param array $urls The urls of the home feeds.
794
+
*/
795
+
do_action( 'before_rocket_clean_home_feeds', $urls ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
796
+
797
+
rocket_clean_files( $urls );
798
+
799
+
/**
800
+
* Fires after the home feeds cache was deleted
801
+
*
802
+
* @since 2.7
803
+
*
804
+
* @param array $urls The urls of the home feeds.
805
+
*/
806
+
do_action( 'after_rocket_clean_home_feeds', $urls ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
807
+
}
808
+
809
+
/**
810
+
* Remove all cache files for the domain.
811
+
*
812
+
* @since 3.5.5 Optimizes by grabbing root cache dirs once, bailing out when file/dir doesn't exist, & directly
813
+
* deleting files.
814
+
* @since 3.5.3 Replaces glob with SPL.
815
+
* @since 2.0 Delete domain cache files for all users
816
+
* @since 1.0
817
+
*
818
+
* @param string $lang Optional. The language code. Default: empty string.
819
+
* @param WP_Filesystem_Direct|null $filesystem Optional. Instance of filesystem handler.
820
+
*/
821
+
function rocket_clean_domain( $lang = '', $filesystem = null ) {
822
+
if ( did_action( 'rocket_after_clean_domain' ) ) {
823
+
return;
824
+
}
825
+
826
+
if ( rocket_is_importing() ) {
827
+
return;
828
+
}
829
+
830
+
$urls = ( ! $lang || is_object( $lang ) || is_array( $lang ) || is_int( $lang ) )
831
+
? (array) get_rocket_i18n_uri()
832
+
: (array) get_rocket_i18n_home_url( $lang );
833
+
/**
834
+
* Filter URLs to delete all caching files from a domain.
835
+
*
836
+
* @since 2.6.4
837
+
*
838
+
* @param array URLs that will be returned.
839
+
* @param string The language code.
840
+
*/
841
+
$urls = (array) apply_filters( 'rocket_clean_domain_urls', $urls, $lang );
842
+
$urls = array_filter( $urls );
843
+
if ( empty( $urls ) ) {
844
+
return false;
845
+
}
846
+
847
+
/** This filter is documented in inc/front/htaccess.php */
848
+
$url_no_dots = (bool) apply_filters( 'rocket_url_no_dots', false );
849
+
$cache_path = _rocket_get_wp_rocket_cache_path();
850
+
$dirs_to_preserve = get_rocket_i18n_to_preserve( $lang, $cache_path );
851
+
852
+
if ( empty( $filesystem ) ) {
853
+
$filesystem = rocket_direct_filesystem();
854
+
}
855
+
856
+
foreach ( $urls as $url ) {
857
+
$parsed_url = get_rocket_parse_url( $url );
858
+
859
+
if ( $url_no_dots ) {
860
+
$parsed_url['host'] = str_replace( '.', '_', $parsed_url['host'] );
861
+
}
862
+
863
+
$root = $cache_path . $parsed_url['host'] . $parsed_url['path'];
864
+
865
+
/**
866
+
* Fires before all cache files are deleted.
867
+
*
868
+
* @since 1.0
869
+
*
870
+
* @param string $root The path of home cache file.
871
+
* @param string $lang The current lang to purge.
872
+
* @param string $url The home url.
873
+
*/
874
+
do_action( 'before_rocket_clean_domain', $root, $lang, $url ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
875
+
876
+
foreach ( _rocket_get_cache_dirs( $parsed_url['host'], $cache_path ) as $dir ) {
877
+
$entry = $dir . $parsed_url['path'];
878
+
// Skip if the dir/file does not exist.
879
+
if ( ! $filesystem->exists( $entry ) ) {
880
+
continue;
881
+
}
882
+
883
+
if ( $filesystem->is_dir( $entry ) ) {
884
+
rocket_rrmdir( $entry, $dirs_to_preserve, $filesystem );
885
+
} else {
886
+
$filesystem->delete( $entry );
887
+
}
888
+
}
889
+
890
+
/**
891
+
* Fires after all cache files was deleted.
892
+
*
893
+
* @since 1.0
894
+
*
895
+
* @param string $root The path of home cache file.
896
+
* @param string $lang The current lang to purge.
897
+
* @param string $url The home url.
898
+
*/
899
+
do_action( 'after_rocket_clean_domain', $root, $lang, $url ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
900
+
}
901
+
902
+
/**
903
+
* Fires after all cache files was deleted.
904
+
*
905
+
* @since 3.15.5
906
+
*
907
+
* @param string $lang The current lang to purge.
908
+
* @param array|string[] $urls All urls to clean.
909
+
*/
910
+
do_action( 'rocket_after_clean_domain', $lang, $urls );
911
+
912
+
return true;
913
+
}
914
+
915
+
/**
916
+
* Delete the caching files of a specific term.
917
+
*
918
+
* $since 2.6.8
919
+
*
920
+
* @param int $term_id The term ID.
921
+
* @param string $taxonomy_slug The taxonomy slug.
922
+
* @return void
923
+
*/
924
+
function rocket_clean_term( $term_id, $taxonomy_slug ) {
925
+
$purge_urls = [];
926
+
927
+
// Get all term infos.
928
+
$term = get_term_by( 'id', $term_id, $taxonomy_slug );
929
+
930
+
// Get the term language.
931
+
$i18n_plugin = rocket_has_i18n();
932
+
933
+
if ( 'wpml' === $i18n_plugin && ! rocket_is_plugin_active( 'woocommerce-multilingual/wpml-woocommerce.php' ) ) {
934
+
// WPML.
935
+
$lang = $GLOBALS['sitepress']->get_language_for_element( $term_id, 'tax_' . $taxonomy_slug );
936
+
} elseif ( 'polylang' === $i18n_plugin ) {
937
+
// Polylang.
938
+
$lang = pll_get_term_language( $term_id );
939
+
} else {
940
+
$lang = false;
941
+
}
942
+
943
+
// Get permalink.
944
+
$permalink = get_term_link( $term, $taxonomy_slug );
945
+
946
+
// Add permalink.
947
+
if ( '/' !== rocket_extract_url_component( $permalink, PHP_URL_PATH ) ) {
948
+
array_push( $purge_urls, $permalink );
949
+
}
950
+
951
+
/**
952
+
* Fires before deleted caching files related with the term
953
+
*
954
+
* @since 2.6.8
955
+
* @param obj $term The term object.
956
+
* @param array $purge_urls URLs cache files to remove.
957
+
* @param string $lang The term language.
958
+
*/
959
+
do_action( 'before_rocket_clean_term', $term, $purge_urls, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
960
+
961
+
/**
962
+
* Filter URLs cache files to remove
963
+
*
964
+
* @since 2.6.8
965
+
* @param array $purge_urls List of URLs cache files to remove.
966
+
* @param obj $term The term object.
967
+
*/
968
+
$purge_urls = apply_filters( 'rocket_term_purge_urls', $purge_urls, $term );
969
+
970
+
// Purge all files.
971
+
rocket_clean_files( $purge_urls );
972
+
973
+
// Never forget to purge homepage and their pagination.
974
+
rocket_clean_home( $lang );
975
+
976
+
/**
977
+
* Fires before deleted caching files related with the term
978
+
*
979
+
* @since 2.6.8
980
+
* @param obj $term The term object.
981
+
* @param array $purge_urls URLs cache files to remove.
982
+
* @param string $lang The term language.
983
+
*/
984
+
do_action( 'after_rocket_clean_term', $term, $purge_urls, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
985
+
}
986
+
987
+
/**
988
+
* Delete the caching files of a specific user
989
+
*
990
+
* $since 2.6.12
991
+
*
992
+
* @param int $user_id The user ID.
993
+
* @param string $lang The language code.
994
+
* @return void
995
+
*/
996
+
function rocket_clean_user( $user_id, $lang = '' ) {
997
+
$urls = ( ! $lang || is_object( $lang ) ) ? get_rocket_i18n_uri() : get_rocket_i18n_home_url( $lang );
998
+
$urls = (array) $urls;
999
+
1000
+
/** This filter is documented in inc/functions/files.php */
1001
+
$urls = apply_filters( 'rocket_clean_domain_urls', $urls, $lang );
1002
+
$urls = array_filter( $urls );
1003
+
$user = get_user_by( 'id', $user_id );
1004
+
1005
+
if ( ! $user ) {
1006
+
return;
1007
+
}
1008
+
1009
+
$user_key = rawurlencode( $user->user_login ) . '-' . get_rocket_option( 'secret_cache_key' );
1010
+
1011
+
foreach ( $urls as $url ) {
1012
+
$parse_url = get_rocket_parse_url( $url );
1013
+
1014
+
/** This filter is documented in inc/front/htaccess.php */
1015
+
if ( apply_filters( 'rocket_url_no_dots', false ) ) {
1016
+
$parse_url['host'] = str_replace( '.', '_', $parse_url['host'] );
1017
+
}
1018
+
1019
+
$cache_dir = $parse_url['host'] . '-' . strtolower( $user_key );
1020
+
$cache_dir = $cache_dir . $parse_url['path'];
1021
+
$root = rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) . $cache_dir;
1022
+
1023
+
/**
1024
+
* Fires before all caching files are deleted for a specific user
1025
+
*
1026
+
* @since 2.6.12
1027
+
*
1028
+
* @param int $user_id The path of home cache file.
1029
+
* @param string $lang The language code.
1030
+
*/
1031
+
do_action( 'before_rocket_clean_user', $user_id, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1032
+
1033
+
// Delete cache domain files.
1034
+
$dirs = glob( $root . '*', GLOB_NOSORT );
1035
+
if ( $dirs ) {
1036
+
foreach ( $dirs as $dir ) {
1037
+
rocket_rrmdir( $dir, get_rocket_i18n_to_preserve( $lang ) );
1038
+
}
1039
+
}
1040
+
1041
+
/**
1042
+
* Fires after all caching files are deleted for a specific user
1043
+
*
1044
+
* @since 2.6.12
1045
+
*
1046
+
* @param int $user_id The path of home cache file.
1047
+
* @param string $lang The language code.
1048
+
*/
1049
+
do_action( 'after_rocket_clean_user', $user_id, $lang ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1050
+
}
1051
+
}
1052
+
1053
+
/**
1054
+
* Remove all caching files in the cache folder
1055
+
*
1056
+
* @since 2.6.8
1057
+
*
1058
+
* @return void
1059
+
*/
1060
+
function rocket_clean_cache_dir() {
1061
+
/**
1062
+
* Fires before deleting all caching files in the cache folder
1063
+
*
1064
+
* @since 2.6.8
1065
+
*/
1066
+
do_action( 'before_rocket_clean_cache_dir' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1067
+
1068
+
// Delete all caching files.
1069
+
$dirs = glob( WP_ROCKET_CACHE_PATH . '*', GLOB_NOSORT );
1070
+
if ( $dirs ) {
1071
+
foreach ( $dirs as $dir ) {
1072
+
rocket_rrmdir( $dir );
1073
+
}
1074
+
}
1075
+
1076
+
/**
1077
+
* Fires after deleting all caching files in the cache folder
1078
+
*
1079
+
* @since 2.6.8
1080
+
*/
1081
+
do_action( 'after_rocket_clean_cache_dir' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1082
+
}
1083
+
1084
+
/**
1085
+
* Remove a single file or a folder recursively.
1086
+
*
1087
+
* @since 3.5.3 Replaces glob and optimizes.
1088
+
* @since 1.0
1089
+
* @since 3.5.3 Bails if given dir should be preserved; replaces glob; optimizes.
1090
+
*
1091
+
* @param string $dir File/Directory to delete.
1092
+
* @param array $dirs_to_preserve Optional. Dirs that should not be deleted.
1093
+
* @param WP_Filesystem_Direct|null $filesystem Optional. Instance of filesystem handler.
1094
+
*/
1095
+
function rocket_rrmdir( $dir, array $dirs_to_preserve = [], $filesystem = null ) {
1096
+
$dir = untrailingslashit( $dir );
1097
+
1098
+
if ( empty( $filesystem ) ) {
1099
+
$filesystem = rocket_direct_filesystem();
1100
+
}
1101
+
1102
+
/**
1103
+
* Fires before a file/directory cache is deleted
1104
+
*
1105
+
* @since 1.1.0
1106
+
*
1107
+
* @param string $dir File/Directory to delete.
1108
+
* @param array $dirs_to_preserve Directories that should not be deleted.
1109
+
*/
1110
+
do_action( 'before_rocket_rrmdir', $dir, $dirs_to_preserve ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1111
+
1112
+
// Remove the hidden empty file for mobile detection on NGINX with the Rocket NGINX configuration.
1113
+
$nginx_mobile_detect_file = $dir . '/.mobile-active';
1114
+
1115
+
if ( $filesystem->is_dir( $dir ) && $filesystem->exists( $nginx_mobile_detect_file ) ) {
1116
+
$filesystem->delete( $nginx_mobile_detect_file );
1117
+
}
1118
+
1119
+
// Remove the hidden empty file for webp.
1120
+
$nowebp_detect_file = $dir . '/.no-webp';
1121
+
1122
+
if ( $filesystem->is_dir( $dir ) && $filesystem->exists( $nowebp_detect_file ) ) {
1123
+
$filesystem->delete( $nowebp_detect_file );
1124
+
}
1125
+
1126
+
if ( ! $filesystem->is_dir( $dir ) ) {
1127
+
$filesystem->delete( $dir );
1128
+
1129
+
return;
1130
+
}
1131
+
1132
+
// Get the directory entries.
1133
+
$entries = [];
1134
+
try {
1135
+
foreach ( new FilesystemIterator( $dir ) as $entry ) {
1136
+
$entries[] = $entry->getPathname();
1137
+
}
1138
+
} catch ( Exception $e ) { // phpcs:disable Generic.CodeAnalysis.EmptyStatement.DetectedCatch
1139
+
// No action required, as logging not enabled.
1140
+
}
1141
+
1142
+
// Exclude directories to preserve from the entries.
1143
+
if ( ! empty( $dirs_to_preserve ) && ! empty( $entries ) ) {
1144
+
$keys = [];
1145
+
foreach ( $dirs_to_preserve as $dir_to_preserve ) {
1146
+
$matches = preg_grep( "#^$dir_to_preserve$#", $entries );
1147
+
$keys[] = reset( $matches );
1148
+
}
1149
+
1150
+
if ( ! empty( $keys ) ) {
1151
+
$keys = array_filter( $keys );
1152
+
if ( ! empty( $keys ) ) {
1153
+
$entries = array_diff( $entries, $keys );
1154
+
}
1155
+
}
1156
+
}
1157
+
1158
+
foreach ( $entries as $entry ) {
1159
+
// If not a directory, delete it.
1160
+
if ( ! $filesystem->is_dir( $entry ) ) {
1161
+
$filesystem->delete( $entry );
1162
+
} else {
1163
+
rocket_rrmdir( $entry, $dirs_to_preserve, $filesystem );
1164
+
}
1165
+
}
1166
+
1167
+
$filesystem->delete( $dir );
1168
+
1169
+
/**
1170
+
* Fires after a file/directory cache was deleted
1171
+
*
1172
+
* @since 1.1.0
1173
+
*
1174
+
* @param string $dir File/Directory to delete.
1175
+
* @param array $dirs_to_preserve Dirs that should not be deleted.
1176
+
*/
1177
+
do_action( 'after_rocket_rrmdir', $dir, $dirs_to_preserve ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
1178
+
}
1179
+
1180
+
/**
1181
+
* Instantiate the filesystem class
1182
+
*
1183
+
* @since 2.10
1184
+
*
1185
+
* @return WP_Filesystem_Direct WP_Filesystem_Direct instance
1186
+
*/
1187
+
function rocket_direct_filesystem() {
1188
+
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
1189
+
require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
1190
+
return new WP_Filesystem_Direct( new StdClass() );
1191
+
}
1192
+
1193
+
/**
1194
+
* Directory creation based on WordPress Filesystem
1195
+
*
1196
+
* @since 1.3.4
1197
+
*
1198
+
* @param string $dir The path of directory will be created.
1199
+
* @return bool
1200
+
*/
1201
+
function rocket_mkdir( $dir ) {
1202
+
$chmod = rocket_get_filesystem_perms( 'dir' );
1203
+
return rocket_direct_filesystem()->mkdir( $dir, $chmod );
1204
+
}
1205
+
1206
+
/**
1207
+
* Recursive directory creation based on full path.
1208
+
*
1209
+
* @param string $target path to the directory we want to create.
1210
+
* @param WP_Filesystem_Direct|null $filesystem WordPress filesystem.
1211
+
* @return bool True if directory is created/exists, false otherwise
1212
+
* @since 1.3.4
1213
+
*
1214
+
* @source wp_mkdir_p() in /wp-includes/functions.php
1215
+
*/
1216
+
function rocket_mkdir_p( $target, $filesystem = null ) {
1217
+
$wrapper = null;
1218
+
1219
+
$filesystem = $filesystem ?: rocket_direct_filesystem();
1220
+
1221
+
if ( rocket_is_stream( $target ) ) {
1222
+
list( $wrapper, $target ) = explode( '://', $target, 2 );
1223
+
}
1224
+
1225
+
// from php.net/mkdir user contributed notes.
1226
+
$target = str_replace( '//', '/', $target );
1227
+
1228
+
// Put the wrapper back on the target.
1229
+
if ( null !== $wrapper ) {
1230
+
$target = $wrapper . '://' . $target;
1231
+
}
1232
+
1233
+
// safe mode fails with a trailing slash under certain PHP versions.
1234
+
$target = rtrim( $target, '/\\' );
1235
+
if ( empty( $target ) ) {
1236
+
$target = '/';
1237
+
}
1238
+
1239
+
if ( $filesystem->exists( $target ) ) {
1240
+
return $filesystem->is_dir( $target );
1241
+
}
1242
+
1243
+
// Attempting to create the directory may clutter up our display.
1244
+
if ( rocket_mkdir( $target ) ) {
1245
+
return true;
1246
+
} elseif ( $filesystem->is_dir( dirname( $target ) ) ) {
1247
+
return false;
1248
+
}
1249
+
1250
+
// If the above failed, attempt to create the parent node, then try again.
1251
+
if ( ( '/' !== $target ) && ( rocket_mkdir_p( dirname( $target ), $filesystem ) ) ) {
1252
+
return rocket_mkdir_p( $target, $filesystem );
1253
+
}
1254
+
1255
+
return false;
1256
+
}
1257
+
1258
+
/**
1259
+
* Test if a given path is a stream URL.
1260
+
*
1261
+
* @since 3.5.3
1262
+
*
1263
+
* @source wp_is_stream() in /wp-includes/functions.php
1264
+
*
1265
+
* @param string $path The resource path or URL.
1266
+
*
1267
+
* @return bool true if the path is a stream URL; else false.
1268
+
*/
1269
+
function rocket_is_stream( $path ) {
1270
+
$scheme_separator = strpos( $path, '://' );
1271
+
1272
+
if ( false === $scheme_separator ) {
1273
+
// $path isn't a stream.
1274
+
return false;
1275
+
}
1276
+
1277
+
$stream = substr( $path, 0, $scheme_separator );
1278
+
1279
+
return in_array( $stream, stream_get_wrappers(), true );
1280
+
}
1281
+
1282
+
/**
1283
+
* File creation based on WordPress Filesystem.
1284
+
*
1285
+
* @since 1.3.5
1286
+
*
1287
+
* @param string $file The path of file will be created.
1288
+
* @param string $content The content that will be printed in advanced-cache.php.
1289
+
*
1290
+
* @return bool true on success; else, false on failure.
1291
+
*/
1292
+
function rocket_put_content( $file, $content ) {
1293
+
$chmod = rocket_get_filesystem_perms( 'file' );
1294
+
return rocket_direct_filesystem()->put_contents( $file, $content, $chmod );
1295
+
}
1296
+
1297
+
/**
1298
+
* Get the permissions to apply to files and folders.
1299
+
*
1300
+
* Reminder:
1301
+
* `$perm = fileperms( $file );`
1302
+
*
1303
+
* WHAT | TYPE | FILE | FOLDER |
1304
+
* ----------------------------------------------+--------+--------+--------|
1305
+
* `$perm` | int | 33188 | 16877 |
1306
+
* `substr( decoct( $perm ), -4 )` | string | '0644' | '0755' |
1307
+
* `substr( sprintf( '%o', $perm ), -4 )` | string | '0644' | '0755' |
1308
+
* `$perm & 0777` | int | 420 | 493 |
1309
+
* `decoct( $perm & 0777 )` | string | '644' | '755' |
1310
+
* `substr( sprintf( '%o', $perm & 0777 ), -4 )` | string | '644' | '755' |
1311
+
*
1312
+
* @since 3.2.4
1313
+
*
1314
+
* @param string $type The type: 'dir' or 'file'.
1315
+
*
1316
+
* @return int Octal integer.
1317
+
*/
1318
+
function rocket_get_filesystem_perms( $type ) {
1319
+
static $perms = [];
1320
+
1321
+
if ( rocket_get_constant( 'WP_ROCKET_IS_TESTING', false ) ) {
1322
+
$perms = [];
1323
+
}
1324
+
1325
+
// Allow variants.
1326
+
switch ( $type ) {
1327
+
case 'dir':
1328
+
case 'dirs':
1329
+
case 'folder':
1330
+
case 'folders':
1331
+
$type = 'dir';
1332
+
break;
1333
+
1334
+
case 'file':
1335
+
case 'files':
1336
+
$type = 'file';
1337
+
break;
1338
+
1339
+
default:
1340
+
return 0755;
1341
+
}
1342
+
1343
+
if ( isset( $perms[ $type ] ) ) {
1344
+
return $perms[ $type ];
1345
+
}
1346
+
1347
+
// If the constants are not defined, use fileperms() like WordPress does.
1348
+
if ( 'dir' === $type ) {
1349
+
$fs_chmod_dir = (int) rocket_get_constant( 'FS_CHMOD_DIR', 0 );
1350
+
$perms[ $type ] = $fs_chmod_dir > 0
1351
+
? $fs_chmod_dir
1352
+
: fileperms( rocket_get_constant( 'ABSPATH' ) ) & 0777 | 0755;
1353
+
} else {
1354
+
$fs_chmod_file = (int) rocket_get_constant( 'FS_CHMOD_FILE', 0 );
1355
+
$perms[ $type ] = $fs_chmod_file > 0
1356
+
? $fs_chmod_file
1357
+
: fileperms( rocket_get_constant( 'ABSPATH' ) . 'index.php' ) & 0777 | 0644;
1358
+
}
1359
+
1360
+
return $perms[ $type ];
1361
+
}
1362
+
1363
+
/**
1364
+
* Gets Directory files matches regex.
1365
+
*
1366
+
* @since 3.6.3
1367
+
* @access private
1368
+
*
1369
+
* @param string $dir Directory to search for files inside it.
1370
+
* @param string $regex Regular expression for files need to be searched for.
1371
+
*
1372
+
* @return array|RegexIterator List of files matches this regular expression.
1373
+
*/
1374
+
function _rocket_get_dir_files_by_regex( $dir, $regex ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1375
+
try {
1376
+
$iterator = new IteratorIterator(
1377
+
new FilesystemIterator( $dir )
1378
+
);
1379
+
1380
+
return new RegexIterator( $iterator, $regex );
1381
+
} catch ( Exception $e ) {
1382
+
return [];
1383
+
}
1384
+
}
1385
+
1386
+
/**
1387
+
* Get the recursive iterator for the cache path.
1388
+
*
1389
+
* @since 3.5.4
1390
+
* @access private
1391
+
*
1392
+
* @param string $cache_path Path to the cache directory.
1393
+
*
1394
+
* @return bool|RecursiveIteratorIterator Iterator on success; else false;
1395
+
*/
1396
+
function _rocket_get_cache_path_iterator( $cache_path ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1397
+
try {
1398
+
return new RecursiveIteratorIterator(
1399
+
new RecursiveDirectoryIterator( $cache_path ),
1400
+
RecursiveIteratorIterator::SELF_FIRST,
1401
+
RecursiveIteratorIterator::CATCH_GET_CHILD
1402
+
);
1403
+
} catch ( Exception $e ) {
1404
+
// No logging yet.
1405
+
return false;
1406
+
}
1407
+
}
1408
+
1409
+
/**
1410
+
* Gets the directories for the given URL host from the cache/wp-rocket/ directory or stored memory.
1411
+
*
1412
+
* @since 3.5.5
1413
+
* @access private
1414
+
*
1415
+
* @param string $url_host The URL's host.
1416
+
* @param string $cache_path Cache's path, e.g. cache/wp-rocket/.
1417
+
* @param bool $hard_reset Optional. When true, resets the static domain directories array and bails out.
1418
+
*
1419
+
* @return array
1420
+
*/
1421
+
function _rocket_get_cache_dirs( $url_host, $cache_path = '', $hard_reset = false ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1422
+
static $domain_dirs = [];
1423
+
1424
+
if ( true === $hard_reset ) {
1425
+
$domain_dirs = [];
1426
+
1427
+
return;
1428
+
}
1429
+
1430
+
if ( isset( $domain_dirs[ $url_host ] ) ) {
1431
+
return $domain_dirs[ $url_host ];
1432
+
}
1433
+
1434
+
if ( empty( $cache_path ) ) {
1435
+
$cache_path = _rocket_get_wp_rocket_cache_path();
1436
+
}
1437
+
1438
+
try {
1439
+
$iterator = new IteratorIterator(
1440
+
new FilesystemIterator( $cache_path )
1441
+
);
1442
+
} catch ( Exception $e ) {
1443
+
return [];
1444
+
}
1445
+
1446
+
$regex = sprintf(
1447
+
'/%1$s%2$s(.*)/i',
1448
+
_rocket_normalize_path( $cache_path, true ),
1449
+
$url_host
1450
+
);
1451
+
1452
+
try {
1453
+
$entries = new RegexIterator( $iterator, $regex );
1454
+
} catch ( Exception $e ) {
1455
+
return [];
1456
+
}
1457
+
1458
+
$domain_dirs[ $url_host ] = [];
1459
+
foreach ( $entries as $entry ) {
1460
+
$domain_dirs[ $url_host ][] = $entry->getPathname();
1461
+
}
1462
+
1463
+
return $domain_dirs[ $url_host ];
1464
+
}
1465
+
1466
+
/**
1467
+
* Normalizes the given filesystem path:
1468
+
* - Windows/IIS-based servers: converts all directory separators to "\\" or, when escaping, to "\\\\".
1469
+
* - Linux-based servers: if $forced is true, uses wp_normalize_path(); else, returns the original path.
1470
+
*
1471
+
* @since 3.5.5
1472
+
* @access private
1473
+
*
1474
+
* @param string $path Filesystem path (file or directory) to normalize.
1475
+
* @param bool $escape Optional. When true, escapes the directory separator(s).
1476
+
* @param bool $force Optional. When true, forces normalizing off non-Windows' paths.
1477
+
*
1478
+
* @return string
1479
+
*/
1480
+
function _rocket_normalize_path( $path, $escape = false, $force = false ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1481
+
if ( _rocket_is_windows_fs( $path ) ) {
1482
+
$path = str_replace( '/', '\\', $path );
1483
+
1484
+
return $escape
1485
+
? str_replace( '\\', '\\\\', $path )
1486
+
: $path;
1487
+
}
1488
+
1489
+
if ( $escape ) {
1490
+
return str_replace( '/', '\/', $path );
1491
+
}
1492
+
1493
+
if ( ! $force ) {
1494
+
return $path;
1495
+
}
1496
+
1497
+
return wp_normalize_path( $path );
1498
+
}
1499
+
1500
+
/**
1501
+
* Checks if the filesystem (fs) is for Windows/IIS server.
1502
+
*
1503
+
* @since 3.5.5
1504
+
* @access private
1505
+
*
1506
+
* @param bool $hard_reset Optional. When true, resets the memoization.
1507
+
*
1508
+
* @return bool
1509
+
*/
1510
+
function _rocket_is_windows_fs( $hard_reset = false ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1511
+
static $is_windows = null;
1512
+
1513
+
if ( $hard_reset ) {
1514
+
$is_windows = null;
1515
+
}
1516
+
1517
+
if ( is_null( $is_windows ) ) {
1518
+
$is_windows = (
1519
+
DIRECTORY_SEPARATOR === '\\'
1520
+
&&
1521
+
! rocket_get_constant( 'WP_ROCKET_RUNNING_VFS', false )
1522
+
);
1523
+
}
1524
+
1525
+
return $is_windows;
1526
+
}
1527
+
1528
+
/**
1529
+
* Gets the normalized cache path, i.e. normalizes constant "WP_ROCKET_CACHE_PATH".
1530
+
*
1531
+
* @since 3.5.5
1532
+
* @access private
1533
+
*
1534
+
* @return string
1535
+
*/
1536
+
function _rocket_get_wp_rocket_cache_path() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1537
+
return _rocket_normalize_path( rocket_get_constant( 'WP_ROCKET_CACHE_PATH' ) );
1538
+
}
1539
+
1540
+
/**
1541
+
* Gets .php files in a directory as an array of SplFileInfo objects.
1542
+
*
1543
+
* @since 3.6.3
1544
+
*
1545
+
* @param string $dir_path Directory to check.
1546
+
*
1547
+
* @return array .php files in the directory. [...SplFileInfo]
1548
+
*/
1549
+
function _rocket_get_php_files_in_dir( $dir_path ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1550
+
try {
1551
+
$config_dir = new FilesystemIterator( (string) $dir_path );
1552
+
} catch ( Exception $e ) {
1553
+
return [];
1554
+
}
1555
+
$files = [];
1556
+
1557
+
foreach ( $config_dir as $file ) {
1558
+
if ( $file->isFile() && 'php' === $file->getExtension() ) {
1559
+
$files[] = $file;
1560
+
}
1561
+
}
1562
+
1563
+
return $files;
1564
+
}
1565
+
1566
+
/**
1567
+
* Get recursive files matched by regex.
1568
+
*
1569
+
* @since 3.6.3
1570
+
*
1571
+
* @param string $regex Regular Expression to be applied.
1572
+
*
1573
+
* @return array|RegexIterator List of files which match the regular expression (SplFileInfo).
1574
+
*/
1575
+
function _rocket_get_recursive_dir_files_by_regex( $regex ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound
1576
+
try {
1577
+
$cache_path = _rocket_get_wp_rocket_cache_path();
1578
+
$iterator = new RecursiveIteratorIterator(
1579
+
new RecursiveDirectoryIterator( $cache_path, FilesystemIterator::SKIP_DOTS )
1580
+
);
1581
+
return new RegexIterator( $iterator, $regex, RecursiveRegexIterator::MATCH );
1582
+
} catch ( Exception $e ) {
1583
+
return [];
1584
+
}
1585
+
}
1586
+