Asset CleanUp: Page Speed Booster - Version 1.3.3.5

Version Description

  • New Option To Conveniently Site-Wide Unload Gutenberg CSS Library Block in "Settings" -> "Site-Wide Common Unloads"
  • Better way to clear cached files as the system doesn't just check the version number of the enqueued file, but also the contents of the file in case an update is made for a CSS/JS file on the server, and the developer(s) forgot to update the version number
  • When CSS/JS caching is cleared, the previously cached assets older than (X) days (set in "Settings" -> "Plugin Usage Preferences") are deleted from the server to free up space
  • New Information was added to "Tools" -> "Storage Info" about the total number of cached assets and their total size
  • Prevent specific already minified CSS files (based on their handle name) from various plugins from being minified again by Asset CleanUp (to save resources)
  • Bug Fix: When the asset's note was saved, any quotes from the text were saved with backslashes that kept increasing on every save action
Download this release

Release Info

Developer gabelivan
Plugin Icon 128x128 Asset CleanUp: Page Speed Booster
Version 1.3.3.5
Comparing to
See all releases

Code changes from version 1.3.3.4 to 1.3.3.5

classes/Misc.php CHANGED
@@ -349,6 +349,26 @@ class Misc
349
  return in_array($plugin, apply_filters('active_plugins', get_option('active_plugins')));
350
  }
351
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  /**
353
  * @param string $returnType
354
  *
@@ -1087,4 +1107,46 @@ SQL;
1087
  // Default to false
1088
  return false;
1089
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1090
  }
349
  return in_array($plugin, apply_filters('active_plugins', get_option('active_plugins')));
350
  }
351
 
352
+ /**
353
+ * If it matches true, it's very likely there is no need for the Gutenberg CSS Block Library
354
+ * The user will be reminded about it
355
+ *
356
+ * @return bool
357
+ */
358
+ public static function isClassicEditorUsed()
359
+ {
360
+ if (self::isPluginActive('classic-editor/classic-editor.php')) {
361
+ $ceReplaceOption = get_option('classic-editor-replace');
362
+ $ceAllowUsersOption = get_option('classic-editor-allow-users');
363
+
364
+ if ($ceReplaceOption === 'classic' && $ceAllowUsersOption === 'disallow') {
365
+ return true;
366
+ }
367
+ }
368
+
369
+ return false;
370
+ }
371
+
372
  /**
373
  * @param string $returnType
374
  *
1107
  // Default to false
1108
  return false;
1109
  }
1110
+
1111
+ /**
1112
+ * Adapted from: https://stackoverflow.com/questions/2510434/format-bytes-to-kilobytes-megabytes-gigabytes
1113
+ *
1114
+ * @param $size
1115
+ * @param int $precision
1116
+ *
1117
+ * @return string
1118
+ */
1119
+ public static function formatBytes($size, $precision = 2)
1120
+ {
1121
+ // In case a string is passed, make it to float
1122
+ $size = (float)$size;
1123
+
1124
+ if (! ($size > 0)) {
1125
+ return 'N/A';
1126
+ }
1127
+
1128
+ $base = log($size, 1024);
1129
+ $suffixes = array('bytes', 'KB', 'MB');
1130
+
1131
+ $floorBase = floor($base);
1132
+
1133
+ if ($floorBase > 2) {
1134
+ $floorBase = 2;
1135
+ }
1136
+
1137
+ $result = round(
1138
+ // 1024 ** ($base - $floorBase) is available only from PHP 5.6+
1139
+ pow(1024, ($base - $floorBase)),
1140
+ $precision
1141
+ );
1142
+
1143
+ $output = $result.' '. $suffixes[$floorBase];
1144
+
1145
+ // If KB, also show the MB equivalent
1146
+ if ($floorBase === 1) {
1147
+ $output .= ' ('.number_format($result / 1024, 4).' MB)';
1148
+ }
1149
+
1150
+ return $output;
1151
+ }
1152
  }
classes/OptimiseAssets/MinifyCss.php CHANGED
@@ -147,7 +147,7 @@ class MinifyCss
147
 
148
  $src = isset($value->src) ? $value->src : false;
149
 
150
- if (! $src || $this->skipMinify($src)) {
151
  return array();
152
  }
153
 
@@ -283,7 +283,15 @@ class MinifyCss
283
  // Relative path to the new file
284
  $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
285
 
286
- $newFilePathUri = OptimizeCss::getRelPathCssCacheDir() . 'min/' . $value->handle . '-v' . $ver . '.css';
 
 
 
 
 
 
 
 
287
 
288
  $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
289
  $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
@@ -357,14 +365,33 @@ class MinifyCss
357
 
358
  /**
359
  * @param $src
 
360
  *
361
  * @return bool
362
  */
363
- public function skipMinify($src)
364
  {
 
 
 
 
 
 
365
  $regExps = array(
366
  '#/wp-content/plugins/wp-asset-clean-up(.*?).min.css#',
367
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  // Other libraries from the core that end in .min.css
369
  '#/wp-includes/css/(.*?).min.css#',
370
 
147
 
148
  $src = isset($value->src) ? $value->src : false;
149
 
150
+ if (! $src || $this->skipMinify($src, $value->handle)) {
151
  return array();
152
  }
153
 
283
  // Relative path to the new file
284
  $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
285
 
286
+ $newFilePathUri = OptimizeCss::getRelPathCssCacheDir() . 'min/' . $value->handle . '-v' . $ver;
287
+
288
+ $sha1File = @sha1_file($localAssetPath);
289
+
290
+ if ($sha1File) {
291
+ $newFilePathUri .= '-'.$sha1File;
292
+ }
293
+
294
+ $newFilePathUri .= '.css';
295
 
296
  $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
297
  $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
365
 
366
  /**
367
  * @param $src
368
+ * @param string $handle
369
  *
370
  * @return bool
371
  */
372
+ public function skipMinify($src, $handle = '')
373
  {
374
+ // Things like WP Fastest Cache Toolbar CSS shouldn't be minified and take up space on the server
375
+ if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['styles'])) {
376
+ return true;
377
+ }
378
+
379
+ // Some of these files (e.g. from Oxygen, WooCommerce) are already minified
380
  $regExps = array(
381
  '#/wp-content/plugins/wp-asset-clean-up(.*?).min.css#',
382
 
383
+ // Formidable Forms
384
+ '#/wp-content/plugins/formidable/css/formidableforms.css#',
385
+
386
+ // Oxygen
387
+ '#/wp-content/plugins/oxygen/component-framework/oxygen.css#',
388
+
389
+ // WooCommerce
390
+ '#/wp-content/plugins/woocommerce/assets/css/woocommerce-layout.css#',
391
+ '#/wp-content/plugins/woocommerce/assets/css/woocommerce.css#',
392
+ '#/wp-content/plugins/woocommerce/assets/css/woocommerce-smallscreen.css#',
393
+ '#/wp-content/plugins/woocommerce/assets/css/blocks/style.css#',
394
+
395
  // Other libraries from the core that end in .min.css
396
  '#/wp-includes/css/(.*?).min.css#',
397
 
classes/OptimiseAssets/MinifyJs.php CHANGED
@@ -130,7 +130,7 @@ class MinifyJs
130
 
131
  $src = isset($value->src) ? $value->src : false;
132
 
133
- if (! $src || $this->skipMinify($src)) {
134
  return array();
135
  }
136
 
@@ -199,7 +199,15 @@ class MinifyJs
199
  // Relative path to the new file
200
  $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
201
 
202
- $newFilePathUri = OptimizeJs::getRelPathJsCacheDir() . 'min/' . $value->handle . '-v' . $ver . '.js';
 
 
 
 
 
 
 
 
203
 
204
  $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
205
  $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
@@ -389,7 +397,7 @@ class MinifyJs
389
  '( ' => '(',
390
 
391
  ', ' => ',',
392
- ' + ' => '+'
393
 
394
  );
395
 
@@ -400,11 +408,17 @@ class MinifyJs
400
 
401
  /**
402
  * @param $src
 
403
  *
404
  * @return bool
405
  */
406
- public function skipMinify($src)
407
  {
 
 
 
 
 
408
  $regExps = array(
409
  '#/wp-content/plugins/wp-asset-clean-up(.*?).min.js#',
410
 
@@ -418,7 +432,13 @@ class MinifyJs
418
  // Files within /wp-content/uploads/ or /wp-content/cache/
419
  // Could belong to plugins such as "Elementor, "Oxygen" etc.
420
  '#/wp-content/uploads/(.*?).js#',
421
- '#/wp-content/cache/(.*?).js#'
 
 
 
 
 
 
422
 
423
  );
424
 
@@ -428,11 +448,11 @@ class MinifyJs
428
  if (strpos($loadedJsExceptionsPatterns, "\n")) {
429
  // Multiple values (one per line)
430
  foreach (explode("\n", $loadedJsExceptionsPatterns) as $loadedJsExceptionPattern) {
431
- $regExps[] = '#'.$loadedJsExceptionPattern.'#';
432
  }
433
  } else {
434
  // Only one value?
435
- $regExps[] = '#'.$loadedJsExceptionsPatterns.'#';
436
  }
437
  }
438
 
130
 
131
  $src = isset($value->src) ? $value->src : false;
132
 
133
+ if (! $src || $this->skipMinify($src, $value->handle)) {
134
  return array();
135
  }
136
 
199
  // Relative path to the new file
200
  $ver = (isset($value->ver) && $value->ver) ? $value->ver : $wp_version;
201
 
202
+ $newFilePathUri = OptimizeJs::getRelPathJsCacheDir() . 'min/' . $value->handle . '-v' . $ver;
203
+
204
+ $sha1File = @sha1_file($localAssetPath);
205
+
206
+ if ($sha1File) {
207
+ $newFilePathUri .= '-'.$sha1File;
208
+ }
209
+
210
+ $newFilePathUri .= '.js';
211
 
212
  $newLocalPath = WP_CONTENT_DIR . $newFilePathUri; // Ful Local path
213
  $newLocalPathUrl = WP_CONTENT_URL . $newFilePathUri; // Full URL path
397
  '( ' => '(',
398
 
399
  ', ' => ',',
400
+ //' + ' => '+'
401
 
402
  );
403
 
408
 
409
  /**
410
  * @param $src
411
+ * @param string $handle
412
  *
413
  * @return bool
414
  */
415
+ public function skipMinify($src, $handle = '')
416
  {
417
+ // Things like WP Fastest Cache Toolbar JS shouldn't be minified and take up space on the server
418
+ if ($handle !== '' && in_array($handle, Main::instance()->skipAssets['scripts'])) {
419
+ return true;
420
+ }
421
+
422
  $regExps = array(
423
  '#/wp-content/plugins/wp-asset-clean-up(.*?).min.js#',
424
 
432
  // Files within /wp-content/uploads/ or /wp-content/cache/
433
  // Could belong to plugins such as "Elementor, "Oxygen" etc.
434
  '#/wp-content/uploads/(.*?).js#',
435
+ '#/wp-content/cache/(.*?).js#',
436
+
437
+ // Elementor .min.js
438
+ '#/wp-content/plugins/elementor/assets/(.*?).min.js#',
439
+
440
+ // WooCommerce Assets
441
+ '#/wp-content/plugins/woocommerce/assets/js/(.*?).min.js#'
442
 
443
  );
444
 
448
  if (strpos($loadedJsExceptionsPatterns, "\n")) {
449
  // Multiple values (one per line)
450
  foreach (explode("\n", $loadedJsExceptionsPatterns) as $loadedJsExceptionPattern) {
451
+ $regExps[] = '#'.trim($loadedJsExceptionPattern).'#';
452
  }
453
  } else {
454
  // Only one value?
455
+ $regExps[] = '#'.trim($loadedJsExceptionsPatterns).'#';
456
  }
457
  }
458
 
classes/OptimiseAssets/OptimizeCommon.php CHANGED
@@ -2,6 +2,7 @@
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
4
  use WpAssetCleanUp\FileSystem;
 
5
  use WpAssetCleanUp\Misc;
6
  use WpAssetCleanUp\Plugin;
7
  use WpAssetCleanUp\Tools;
@@ -22,13 +23,15 @@ class OptimizeCommon
22
  */
23
  public function init()
24
  {
25
- add_action('switch_theme', array($this, 'clearAllCache'));
26
  add_action('after_switch_theme', array($this, 'clearAllCache'));
27
 
28
  // Is WP Rocket's page cache cleared? Clear Asset CleanUp's CSS cache files too
29
  if (array_key_exists('action', $_GET) && $_GET['action'] === 'purge_cache') {
30
  // Leave its default parameters, no redirect needed
31
- self::clearAllCache();
 
 
32
  }
33
 
34
  add_action('admin_post_assetcleanup_clear_assets_cache', function() {
@@ -73,8 +76,8 @@ class OptimizeCommon
73
  public static function doCombineIsRegularPage()
74
  {
75
  // In particular situations, do not process this
76
- if ( strpos($_SERVER['REQUEST_URI'], '/wp-content/plugins/') !== false
77
- && strpos($_SERVER['REQUEST_URI'], '/wp-content/themes/') !== false) {
78
  return false;
79
  }
80
 
@@ -82,7 +85,7 @@ class OptimizeCommon
82
  return false;
83
  }
84
 
85
- if (str_replace('//', '/', site_url().'/feed/') === $_SERVER['REQUEST_URI']) {
86
  return false;
87
  }
88
 
@@ -122,7 +125,7 @@ class OptimizeCommon
122
  libxml_use_internal_errors(true);
123
  $domTag->loadHTML($matchedSourceFromTag);
124
 
125
- foreach ($domTag->getElementsByTagName( $tagName ) as $tagObject) {
126
  if (! $tagObject->hasAttributes()) {
127
  continue;
128
  }
@@ -181,12 +184,12 @@ class OptimizeCommon
181
  }
182
 
183
  // Not using "?ver="
184
- if (strpos($localAssetPath, '.'.$assetType.'?') !== false) {
185
- list($localAssetPathAlt,) = explode('.'.$assetType.'?', $localAssetPath);
186
- $localAssetPath = $localAssetPathAlt.'.'.$assetType;
187
  }
188
 
189
- if (strrchr($localAssetPath, '.') === '.'.$assetType && file_exists($localAssetPath)) {
190
  return $localAssetPath;
191
  }
192
 
@@ -251,9 +254,9 @@ class OptimizeCommon
251
  $siteDbUrl = get_option('siteurl');
252
  $parseDbSiteUrl = parse_url($siteDbUrl);
253
 
254
- $dbSiteUrlHost = $parseDbSiteUrl['host'];
255
 
256
- $finalBaseUrl = str_replace($dbSiteUrlHost, $hrefHost, $siteDbUrl);
257
 
258
  return str_replace($finalBaseUrl, '', $href);
259
  }
@@ -280,9 +283,9 @@ class OptimizeCommon
280
  $requestUriPart = '';
281
  }
282
 
283
- $dirToFilename = WP_CONTENT_DIR . dirname($relPathAssetCacheDir).'/_storage/'
284
- .parse_url(site_url(), PHP_URL_HOST).
285
- $requestUriPart.'/';
286
 
287
  $dirToFilename = str_replace('//', '/', $dirToFilename);
288
 
@@ -303,6 +306,7 @@ class OptimizeCommon
303
  // Delete cached file after it expired as it will be regenerated
304
  if (filemtime($assetsFile) < (time() - 1 * $cachedAssetsFileExpiresIn)) {
305
  self::clearAssetCachedData($jsonStorageFile);
 
306
  return array();
307
  }
308
 
@@ -311,7 +315,7 @@ class OptimizeCommon
311
  if ($optionValue) {
312
  $optionValueArray = @json_decode($optionValue, ARRAY_A);
313
 
314
- if ($assetType === 'css' && (! empty( $optionValueArray) && (isset($optionValueArray['head']['link_hrefs']) || isset($optionValueArray['body']['link_hrefs'])))) {
315
  return $optionValueArray;
316
  }
317
 
@@ -322,6 +326,7 @@ class OptimizeCommon
322
 
323
  // File exists, but it's invalid or outdated; Delete it as it has to be re-generated
324
  self::clearAssetCachedData($jsonStorageFile);
 
325
  return array();
326
  }
327
 
@@ -345,9 +350,9 @@ class OptimizeCommon
345
  $requestUriPart = '';
346
  }
347
 
348
- $dirToFilename = WP_CONTENT_DIR . dirname($relPathAssetCacheDir).'/_storage/'
349
- .parse_url(site_url(), PHP_URL_HOST).
350
- $requestUriPart.'/';
351
 
352
  $dirToFilename = str_replace('//', '/', $dirToFilename);
353
 
@@ -405,49 +410,122 @@ class OptimizeCommon
405
  * Clears all CSS & JS cache
406
  *
407
  * @param bool $redirectAfter
408
- * @param bool $keepAssetFiles
409
- *
410
- * $keepAssetFiles is kept to "true" as default
411
- * there could be cache plugins still having cached pages that load specific merged files,
412
- * to avoid breaking the layout/functionality
413
  */
414
- public static function clearAllCache($redirectAfter = false, $keepAssetFiles = true)
415
  {
416
  if (self::doNotClearAllCache()) {
417
  return;
418
  }
419
 
420
  /*
421
- * STEP 1: Clear all .json, maybe .css & .js files that are related to "Combine CSS/JS files" feature
422
  */
423
- $fileExtToRemove = array('.json');
 
424
 
425
- // Also delete .css & .js
426
- if (! $keepAssetFiles) {
427
- $fileExtToRemove[] = '.css';
428
- $fileExtToRemove[] = '.js';
429
- }
430
 
431
  $assetCleanUpCacheDir = WP_CONTENT_DIR . self::getRelPathPluginCacheDir();
432
- $storageDir = $assetCleanUpCacheDir.'_storage';
 
 
433
 
434
  if (is_dir($assetCleanUpCacheDir)) {
435
- $dirItems = new \RecursiveDirectoryIterator( $assetCleanUpCacheDir, \RecursiveDirectoryIterator::SKIP_DOTS );
436
 
437
- $storageEmptyDirs = array();
438
 
439
- foreach ( new \RecursiveIteratorIterator( $dirItems, \RecursiveIteratorIterator::SELF_FIRST ) as $item ) {
440
- $fileBaseName = strrchr( $item, '/' );
 
441
 
442
- if ( is_file( $item ) && in_array( strrchr( $fileBaseName, '.' ), $fileExtToRemove ) ) {
443
- @unlink( $item );
444
- } elseif ( strpos( $item, $storageDir ) !== false && $item != $storageDir ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  $storageEmptyDirs[] = $item;
446
  }
447
  }
448
 
449
- foreach ( array_reverse( $storageEmptyDirs ) as $storageEmptyDir ) {
450
- @rmdir( $storageEmptyDir );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  }
452
  }
453
 
@@ -460,12 +538,44 @@ class OptimizeCommon
460
  // Make sure all the caching files/folders are there in case the plugin was upgraded
461
  Plugin::createCacheFoldersFiles(array('css', 'js'));
462
 
463
- if ( $redirectAfter && wp_get_referer() ) {
464
- wp_safe_redirect( wp_get_referer() );
465
  exit;
466
  }
467
  }
468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  /**
470
  * Prevent clear cache function in the following situations
471
  *
2
  namespace WpAssetCleanUp\OptimiseAssets;
3
 
4
  use WpAssetCleanUp\FileSystem;
5
+ use WpAssetCleanUp\Main;
6
  use WpAssetCleanUp\Misc;
7
  use WpAssetCleanUp\Plugin;
8
  use WpAssetCleanUp\Tools;
23
  */
24
  public function init()
25
  {
26
+ add_action('switch_theme', array($this, 'clearAllCache'));
27
  add_action('after_switch_theme', array($this, 'clearAllCache'));
28
 
29
  // Is WP Rocket's page cache cleared? Clear Asset CleanUp's CSS cache files too
30
  if (array_key_exists('action', $_GET) && $_GET['action'] === 'purge_cache') {
31
  // Leave its default parameters, no redirect needed
32
+ add_action('init', function() {
33
+ OptimizeCommon::clearAllCache();
34
+ }, PHP_INT_MAX);
35
  }
36
 
37
  add_action('admin_post_assetcleanup_clear_assets_cache', function() {
76
  public static function doCombineIsRegularPage()
77
  {
78
  // In particular situations, do not process this
79
+ if (strpos($_SERVER['REQUEST_URI'], '/wp-content/plugins/') !== false
80
+ && strpos($_SERVER['REQUEST_URI'], '/wp-content/themes/') !== false) {
81
  return false;
82
  }
83
 
85
  return false;
86
  }
87
 
88
+ if (str_replace('//', '/', site_url() . '/feed/') === $_SERVER['REQUEST_URI']) {
89
  return false;
90
  }
91
 
125
  libxml_use_internal_errors(true);
126
  $domTag->loadHTML($matchedSourceFromTag);
127
 
128
+ foreach ($domTag->getElementsByTagName($tagName) as $tagObject) {
129
  if (! $tagObject->hasAttributes()) {
130
  continue;
131
  }
184
  }
185
 
186
  // Not using "?ver="
187
+ if (strpos($localAssetPath, '.' . $assetType . '?') !== false) {
188
+ list($localAssetPathAlt,) = explode('.' . $assetType . '?', $localAssetPath);
189
+ $localAssetPath = $localAssetPathAlt . '.' . $assetType;
190
  }
191
 
192
+ if (strrchr($localAssetPath, '.') === '.' . $assetType && file_exists($localAssetPath)) {
193
  return $localAssetPath;
194
  }
195
 
254
  $siteDbUrl = get_option('siteurl');
255
  $parseDbSiteUrl = parse_url($siteDbUrl);
256
 
257
+ $dbSiteUrlHost = $parseDbSiteUrl['host'];
258
 
259
+ $finalBaseUrl = str_replace($dbSiteUrlHost, $hrefHost, $siteDbUrl);
260
 
261
  return str_replace($finalBaseUrl, '', $href);
262
  }
283
  $requestUriPart = '';
284
  }
285
 
286
+ $dirToFilename = WP_CONTENT_DIR . dirname($relPathAssetCacheDir) . '/_storage/'
287
+ . parse_url(site_url(), PHP_URL_HOST) .
288
+ $requestUriPart . '/';
289
 
290
  $dirToFilename = str_replace('//', '/', $dirToFilename);
291
 
306
  // Delete cached file after it expired as it will be regenerated
307
  if (filemtime($assetsFile) < (time() - 1 * $cachedAssetsFileExpiresIn)) {
308
  self::clearAssetCachedData($jsonStorageFile);
309
+
310
  return array();
311
  }
312
 
315
  if ($optionValue) {
316
  $optionValueArray = @json_decode($optionValue, ARRAY_A);
317
 
318
+ if ($assetType === 'css' && (! empty($optionValueArray) && (isset($optionValueArray['head']['link_hrefs']) || isset($optionValueArray['body']['link_hrefs'])))) {
319
  return $optionValueArray;
320
  }
321
 
326
 
327
  // File exists, but it's invalid or outdated; Delete it as it has to be re-generated
328
  self::clearAssetCachedData($jsonStorageFile);
329
+
330
  return array();
331
  }
332
 
350
  $requestUriPart = '';
351
  }
352
 
353
+ $dirToFilename = WP_CONTENT_DIR . dirname($relPathAssetCacheDir) . '/_storage/'
354
+ . parse_url(site_url(), PHP_URL_HOST) .
355
+ $requestUriPart . '/';
356
 
357
  $dirToFilename = str_replace('//', '/', $dirToFilename);
358
 
410
  * Clears all CSS & JS cache
411
  *
412
  * @param bool $redirectAfter
 
 
 
 
 
413
  */
414
+ public static function clearAllCache($redirectAfter = false)
415
  {
416
  if (self::doNotClearAllCache()) {
417
  return;
418
  }
419
 
420
  /*
421
+ * STEP 1: Clear all .json, .css & .js files (older than $clearFilesOlderThan days) that are related to "Minify/Combine CSS/JS files" feature
422
  */
423
+ $skipFiles = array('index.php', '.htaccess');
424
+ $fileExtToRemove = array('.json', '.css', '.js');
425
 
426
+ $clearFilesOlderThan = Main::instance()->settings['clear_cached_files_after']; // days
 
 
 
 
427
 
428
  $assetCleanUpCacheDir = WP_CONTENT_DIR . self::getRelPathPluginCacheDir();
429
+ $storageDir = $assetCleanUpCacheDir . '_storage';
430
+
431
+ $userIdDirs = array();
432
 
433
  if (is_dir($assetCleanUpCacheDir)) {
434
+ $storageEmptyDirs = $allJsons = $allAssets = $allAssetsToKeep = array();
435
 
436
+ $dirItems = new \RecursiveDirectoryIterator($assetCleanUpCacheDir, \RecursiveDirectoryIterator::SKIP_DOTS);
437
 
438
+ foreach (new \RecursiveIteratorIterator($dirItems, \RecursiveIteratorIterator::SELF_FIRST) as $item) {
439
+ $fileBaseName = trim(strrchr($item, '/'), '/');
440
+ $fileExt = strrchr($fileBaseName, '.');
441
 
442
+ if (is_file($item) && in_array($fileExt, $fileExtToRemove) && (! in_array($fileBaseName, $skipFiles))) {
443
+ $isJsonFile = ($fileExt === '.json');
444
+ $isAssetFile = in_array($fileExt, array('.css', '.js'));
445
+
446
+ // Remove all JSONs and .css & .js ONLY if they are older than $clearFilesOlderThan
447
+ if ($isJsonFile || ($isAssetFile && (strtotime('-' . $clearFilesOlderThan . ' days') > $item->getCTime()))) {
448
+ if ($isJsonFile) {
449
+ $allJsons[] = $item;
450
+ }
451
+
452
+ if ($isAssetFile) {
453
+ $allAssets[] = $item;
454
+ }
455
+ }
456
+ } elseif (is_dir($item) && (strpos($item, '/css/logged-in/') !== false || strpos($item, '/js/logged-in/') !== false)) {
457
+ $userIdDirs[] = $item;
458
+ } elseif (strpos($item, $storageDir) !== false && $item != $storageDir) {
459
  $storageEmptyDirs[] = $item;
460
  }
461
  }
462
 
463
+ // Now go through the JSONs and collect the latest assets so they would be kept
464
+ foreach ($allJsons as $jsonFile) {
465
+ $jsonContents = FileSystem::file_get_contents($jsonFile);
466
+ $jsonContentsArray = @json_decode($jsonContents, ARRAY_A);
467
+
468
+ $uriToFinalCssFileIndexKey = 'uri_to_final_css_file';
469
+ $uriToFinalJsFileIndexKey = 'uri_to_final_js_file';
470
+
471
+ if (is_array($jsonContentsArray) && strpos($jsonContents, $uriToFinalCssFileIndexKey) !== false) {
472
+ if (isset($jsonContentsArray['head'][$uriToFinalCssFileIndexKey])) {
473
+ $allAssetsToKeep[] = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $jsonContentsArray['head'][$uriToFinalCssFileIndexKey];
474
+ }
475
+
476
+ if (isset($jsonContentsArray['body'][$uriToFinalCssFileIndexKey])) {
477
+ $allAssetsToKeep[] = WP_CONTENT_DIR . OptimizeCss::getRelPathCssCacheDir() . $jsonContentsArray['body'][$uriToFinalCssFileIndexKey];
478
+ }
479
+ } elseif (is_array($jsonContentsArray) && strpos($jsonContents, $uriToFinalJsFileIndexKey) !== false) {
480
+ foreach ($jsonContentsArray as $jsGroupVal) {
481
+ if (isset($jsGroupVal[$uriToFinalJsFileIndexKey]) ) {
482
+ $allAssetsToKeep[] = WP_CONTENT_DIR . OptimizeJs::getRelPathJsCacheDir() . $jsGroupVal[$uriToFinalJsFileIndexKey];
483
+ }
484
+ }
485
+ }
486
+
487
+ // Clear the JSON files as new ones will be generated
488
+ @unlink($jsonFile);
489
+ }
490
+
491
+ // Finally, collect the rest of $allAssetsToKeep from the database transients
492
+ // Do not check if they are expired or not as their assets could still be referenced
493
+ // until those pages will be accessed in a non-cached way
494
+ global $wpdb;
495
+
496
+ $sqlGetCacheTransients = <<<SQL
497
+ SELECT option_value FROM `{$wpdb->options}`
498
+ WHERE `option_name` LIKE '%transient_wpacu_js_minify%' OR `option_name` LIKE '%transient_wpacu_css_minify%'
499
+ SQL;
500
+ $cacheTransients = $wpdb->get_col($sqlGetCacheTransients);
501
+
502
+ if (! empty($cacheTransients)) {
503
+ foreach ($cacheTransients as $optionValue) {
504
+ $jsonValueArray = @json_decode($optionValue, ARRAY_A);
505
+
506
+ if (isset($jsonValueArray['min_uri'])) {
507
+ $allAssetsToKeep[] = rtrim(ABSPATH, '/') . $jsonValueArray['min_uri'];
508
+ }
509
+ }
510
+ }
511
+
512
+ // Finally clear the matched assets, except the active ones
513
+ foreach ($allAssets as $assetFile) {
514
+ if (in_array($assetFile, $allAssetsToKeep)) {
515
+ continue;
516
+ }
517
+ @unlink($assetFile);
518
+ }
519
+
520
+ foreach (array_reverse($storageEmptyDirs) as $storageEmptyDir) {
521
+ @rmdir($storageEmptyDir);
522
+ }
523
+
524
+ // Remove empty dirs from /css/logged-in/ and /js/logged-in/
525
+ if (! empty($userIdDirs)) {
526
+ foreach ($userIdDirs as $userIdDir) {
527
+ @rmdir($userIdDir); // it needs to be empty, otherwise, it will not be removed
528
+ }
529
  }
530
  }
531
 
538
  // Make sure all the caching files/folders are there in case the plugin was upgraded
539
  Plugin::createCacheFoldersFiles(array('css', 'js'));
540
 
541
+ if ($redirectAfter && wp_get_referer()) {
542
+ wp_safe_redirect(wp_get_referer());
543
  exit;
544
  }
545
  }
546
 
547
+ /**
548
+ * @return array
549
+ */
550
+ public static function getStorageStats()
551
+ {
552
+ $assetCleanUpCacheDir = WP_CONTENT_DIR . self::getRelPathPluginCacheDir();
553
+
554
+ if (is_dir($assetCleanUpCacheDir)) {
555
+ $dirItems = new \RecursiveDirectoryIterator($assetCleanUpCacheDir, \RecursiveDirectoryIterator::SKIP_DOTS);
556
+
557
+ $totalFiles = 0;
558
+ $totalSize = 0;
559
+
560
+ foreach (new \RecursiveIteratorIterator($dirItems, \RecursiveIteratorIterator::SELF_FIRST) as $item) {
561
+ $fileBaseName = trim(strrchr($item, '/'), '/');
562
+ $fileExt = strrchr($fileBaseName, '.');
563
+
564
+ if ($item->isFile() && in_array($fileExt, array('.css', '.js'))) {
565
+ $totalSize += $item->getSize();
566
+ $totalFiles++;
567
+ }
568
+ }
569
+
570
+ return array(
571
+ 'total_size' => Misc::formatBytes($totalSize),
572
+ 'total_files' => $totalFiles
573
+ );
574
+ }
575
+
576
+ return array();
577
+ }
578
+
579
  /**
580
  * Prevent clear cache function in the following situations
581
  *
classes/Settings.php CHANGED
@@ -63,6 +63,7 @@ class Settings
63
  'disable_dashicons_for_guests',
64
 
65
  // Stored in 'wpassetcleanup_global_unload' option
 
66
  'disable_jquery_migrate',
67
  'disable_comment_reply',
68
 
@@ -88,7 +89,10 @@ class Settings
88
  'disable_xmlrpc',
89
 
90
  // Allow Usage Tracking
91
- 'allow_usage_tracking'
 
 
 
92
  );
93
 
94
  /**
@@ -129,8 +133,8 @@ class Settings
129
 
130
  'assets_list_inline_code_status' => 'contracted', // takes less space overall
131
 
132
- 'minify_loaded_css_exceptions' => '(.*?).min.css'. "\n". '/plugins/wd-instagram-feed/(.*?).css',
133
- 'minify_loaded_js_exceptions' => '(.*?).min.js' . "\n". '/plugins/wd-instagram-feed/(.*?).js',
134
 
135
  'combine_loaded_css_exceptions' => '/plugins/wd-instagram-feed/(.*?).css',
136
  'combine_loaded_js_exceptions' => '/plugins/wd-instagram-feed/(.*?).js',
@@ -138,7 +142,9 @@ class Settings
138
  'input_style' => 'enhanced',
139
 
140
  // Since v1.2.8.6 (lite), WordPress core files are hidden in the assets list as a default setting
141
- 'hide_core_files' => '1'
 
 
142
  );
143
  }
144
 
@@ -194,6 +200,7 @@ class Settings
194
  check_admin_referer('wpacu_settings_update', 'wpacu_settings_nonce');
195
 
196
  $savedSettings = Misc::getVar('post', WPACU_PLUGIN_ID . '_settings', array());
 
197
 
198
  // Hooks can be attached here
199
  // e.g. from PluginTracking.php (check if "Allow Usage Tracking" has been enabled)
@@ -218,6 +225,10 @@ class Settings
218
 
219
  $globalUnloadList = Main::instance()->getGlobalUnload();
220
 
 
 
 
 
221
  if (in_array('jquery-migrate', $globalUnloadList['scripts'])) {
222
  $data['disable_jquery_migrate'] = 1;
223
  }
@@ -280,7 +291,7 @@ class Settings
280
 
281
  // If it doesn't exist, it was never saved
282
  // Make sure the default value is added to the textarea
283
- if (in_array($settingsKey, array('frontend_show_exceptions', 'minify_loaded_css_exceptions', 'minify_loaded_js_exceptions'))) {
284
  $settings[$settingsKey] = $this->defaultSettings[$settingsKey];
285
  }
286
  }
@@ -365,6 +376,11 @@ class Settings
365
 
366
  foreach ($settings as $settingKey => $settingValue) {
367
  if ($settingValue !== '') {
 
 
 
 
 
368
  $settingsNotNull[$settingKey] = $settingValue;
369
  }
370
  }
@@ -382,12 +398,14 @@ class Settings
382
  // The following are only triggered IF the user submitted the form from "Settings" area
383
  if (Misc::getVar('post', 'wpacu_settings_nonce')) {
384
  // "Site-Wide Common Unloads" tab
 
385
  $disableJQueryMigrate = isset($_POST[WPACU_PLUGIN_ID . '_global_unloads']['disable_jquery_migrate']);
386
  $disableCommentReply = isset($_POST[WPACU_PLUGIN_ID . '_global_unloads']['disable_comment_reply']);
387
 
388
  $this->updateSiteWideRuleForCommonAssets(array(
389
- 'jquery_migrate' => $disableJQueryMigrate,
390
- 'comment_reply' => $disableCommentReply
 
391
  ));
392
  }
393
 
@@ -410,12 +428,17 @@ class Settings
410
  {
411
  $wpacuUpdate = new Update;
412
 
 
413
  $disableJQueryMigrate = $unloadsList['jquery_migrate'];
414
  $disableCommentReply = $unloadsList['comment_reply'];
415
 
416
  /*
417
  * Add element(s) to the global unload rules
418
  */
 
 
 
 
419
  if ($disableJQueryMigrate || $disableCommentReply) {
420
  $unloadList = array();
421
 
@@ -435,6 +458,10 @@ class Settings
435
  /*
436
  * Remove element(s) from the global unload rules
437
  */
 
 
 
 
438
  if (! $disableJQueryMigrate || ! $disableCommentReply) {
439
  $removeFromUnloadList = array();
440
 
63
  'disable_dashicons_for_guests',
64
 
65
  // Stored in 'wpassetcleanup_global_unload' option
66
+ 'disable_wp_block_library',
67
  'disable_jquery_migrate',
68
  'disable_comment_reply',
69
 
89
  'disable_xmlrpc',
90
 
91
  // Allow Usage Tracking
92
+ 'allow_usage_tracking',
93
+
94
+ // Clear Cached CSS/JS files after (x) days
95
+ 'clear_cached_files_after'
96
  );
97
 
98
  /**
133
 
134
  'assets_list_inline_code_status' => 'contracted', // takes less space overall
135
 
136
+ 'minify_loaded_css_exceptions' => '(.*?)\.min.css'. "\n". '/plugins/wd-instagram-feed/(.*?).css',
137
+ 'minify_loaded_js_exceptions' => '(.*?)\.min.js' . "\n". '/plugins/wd-instagram-feed/(.*?).js',
138
 
139
  'combine_loaded_css_exceptions' => '/plugins/wd-instagram-feed/(.*?).css',
140
  'combine_loaded_js_exceptions' => '/plugins/wd-instagram-feed/(.*?).js',
142
  'input_style' => 'enhanced',
143
 
144
  // Since v1.2.8.6 (lite), WordPress core files are hidden in the assets list as a default setting
145
+ 'hide_core_files' => '1',
146
+
147
+ 'clear_cached_files_after' => '10'
148
  );
149
  }
150
 
200
  check_admin_referer('wpacu_settings_update', 'wpacu_settings_nonce');
201
 
202
  $savedSettings = Misc::getVar('post', WPACU_PLUGIN_ID . '_settings', array());
203
+ $savedSettings = stripslashes_deep($savedSettings);
204
 
205
  // Hooks can be attached here
206
  // e.g. from PluginTracking.php (check if "Allow Usage Tracking" has been enabled)
225
 
226
  $globalUnloadList = Main::instance()->getGlobalUnload();
227
 
228
+ if (in_array('wp-block-library', $globalUnloadList['styles'])) {
229
+ $data['disable_wp_block_library'] = 1;
230
+ }
231
+
232
  if (in_array('jquery-migrate', $globalUnloadList['scripts'])) {
233
  $data['disable_jquery_migrate'] = 1;
234
  }
291
 
292
  // If it doesn't exist, it was never saved
293
  // Make sure the default value is added to the textarea
294
+ if (in_array($settingsKey, array('frontend_show_exceptions', 'minify_loaded_css_exceptions', 'minify_loaded_js_exceptions', 'clear_cached_files_after'))) {
295
  $settings[$settingsKey] = $this->defaultSettings[$settingsKey];
296
  }
297
  }
376
 
377
  foreach ($settings as $settingKey => $settingValue) {
378
  if ($settingValue !== '') {
379
+ // Some validation
380
+ if ($settingKey === 'clear_cached_files_after') {
381
+ $settingValue = (int)$settingValue;
382
+ }
383
+
384
  $settingsNotNull[$settingKey] = $settingValue;
385
  }
386
  }
398
  // The following are only triggered IF the user submitted the form from "Settings" area
399
  if (Misc::getVar('post', 'wpacu_settings_nonce')) {
400
  // "Site-Wide Common Unloads" tab
401
+ $disableGutenbergCssBlockLibrary = isset($_POST[WPACU_PLUGIN_ID . '_global_unloads']['disable_wp_block_library']);
402
  $disableJQueryMigrate = isset($_POST[WPACU_PLUGIN_ID . '_global_unloads']['disable_jquery_migrate']);
403
  $disableCommentReply = isset($_POST[WPACU_PLUGIN_ID . '_global_unloads']['disable_comment_reply']);
404
 
405
  $this->updateSiteWideRuleForCommonAssets(array(
406
+ 'wp_block_library' => $disableGutenbergCssBlockLibrary,
407
+ 'jquery_migrate' => $disableJQueryMigrate,
408
+ 'comment_reply' => $disableCommentReply
409
  ));
410
  }
411
 
428
  {
429
  $wpacuUpdate = new Update;
430
 
431
+ $disableGutenbergCssBlockLibrary = $unloadsList['wp_block_library'];
432
  $disableJQueryMigrate = $unloadsList['jquery_migrate'];
433
  $disableCommentReply = $unloadsList['comment_reply'];
434
 
435
  /*
436
  * Add element(s) to the global unload rules
437
  */
438
+ if ($disableGutenbergCssBlockLibrary) {
439
+ $wpacuUpdate->saveToEverywhereUnloads(array('wp-block-library'), array());
440
+ }
441
+
442
  if ($disableJQueryMigrate || $disableCommentReply) {
443
  $unloadList = array();
444
 
458
  /*
459
  * Remove element(s) from the global unload rules
460
  */
461
+ if (! $disableGutenbergCssBlockLibrary) {
462
+ $wpacuUpdate->removeEverywhereUnloads(array('wp-block-library'), array());
463
+ }
464
+
465
  if (! $disableJQueryMigrate || ! $disableCommentReply) {
466
  $removeFromUnloadList = array();
467
 
classes/Tips.php CHANGED
@@ -22,6 +22,10 @@ class Tips
22
  This asset is related to the Gutenberg block editor. If you do not use it (e.g. you have an alternative option such as Divi, Elementor etc.), then it is safe to unload this file.
23
  HTML;
24
 
 
 
 
 
25
  $this->list['css']['astra-contact-form-7'] = <<<HTML
26
  This asset is related to the "Contact Form 7" plugin. If you do not use it on this page (e.g. only needed on a page such as "Contact"), then you can safely unload it.
27
  HTML;
@@ -41,4 +45,20 @@ HTML;
41
  This JavaScript file is related to "Contact Form 7" and if you don't load any form on this page (e.g. you use it only on pages such as Contact, Make a booking etc.), then you can safely unload it (e.g. side-wide and make exceptions on the few pages you use it).
42
  HTML;
43
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
22
  This asset is related to the Gutenberg block editor. If you do not use it (e.g. you have an alternative option such as Divi, Elementor etc.), then it is safe to unload this file.
23
  HTML;
24
 
25
+ if ($extraWpBlockLibraryTip = self::ceGutenbergCssLibraryBlockTip()) {
26
+ $this->list['css']['wp-block-library'] .= ' '.$extraWpBlockLibraryTip;
27
+ }
28
+
29
  $this->list['css']['astra-contact-form-7'] = <<<HTML
30
  This asset is related to the "Contact Form 7" plugin. If you do not use it on this page (e.g. only needed on a page such as "Contact"), then you can safely unload it.
31
  HTML;
45
  This JavaScript file is related to "Contact Form 7" and if you don't load any form on this page (e.g. you use it only on pages such as Contact, Make a booking etc.), then you can safely unload it (e.g. side-wide and make exceptions on the few pages you use it).
46
  HTML;
47
  }
48
+
49
+ /**
50
+ * Tip related to "Classic Editor" plugin and some of its active settings
51
+ *
52
+ * @return string
53
+ */
54
+ public static function ceGutenbergCssLibraryBlockTip()
55
+ {
56
+ if (Misc::isClassicEditorUsed()) {
57
+ return <<<HTML
58
+ You are using "Classic Editor" plugin and the option "Default editor for all users" is set to "Classic Editor" and "Allow users to switch editors" option is set to "No". It is very likely you do not need the Gutenberg CSS Library Block in any page.
59
+ HTML;
60
+ }
61
+
62
+ return false;
63
+ }
64
  }
classes/Tools.php CHANGED
@@ -349,6 +349,8 @@ class Tools
349
  $return .= 'CSS/JS Storage Directory: '. $storageCssJsDir . ' ('.(is_writable($storageCssJsDir) ? 'writable' : 'NON WRITABLE').')' ."\n\n";
350
 
351
  $return .= 'Disable Emojis? '. (($settings['disable_emojis'] == 1) ? 'Yes' : 'No') . "\n";
 
 
352
  $return .= 'Disable jQuery Migrate (site-wide)? '. (($settings['disable_jquery_migrate'] == 1) ? 'Yes' : 'No') . "\n";
353
  $return .= 'Disable Comment Reply (site-wide)? '. (($settings['disable_comment_reply'] == 1) ? 'Yes' : 'No') . "\n\n";
354
 
@@ -372,7 +374,17 @@ class Tools
372
 
373
  $return .= "\n" . 'XML-RPC protocol: '. $xmlProtocolStatus . "\n";
374
 
375
- $return .= "\n" . '# Asset CleanUp Database Storage '. "\n";
 
 
 
 
 
 
 
 
 
 
376
 
377
  $wpacuPluginId = WPACU_PLUGIN_ID;
378
 
349
  $return .= 'CSS/JS Storage Directory: '. $storageCssJsDir . ' ('.(is_writable($storageCssJsDir) ? 'writable' : 'NON WRITABLE').')' ."\n\n";
350
 
351
  $return .= 'Disable Emojis? '. (($settings['disable_emojis'] == 1) ? 'Yes' : 'No') . "\n";
352
+ $return .= 'Disable Dashicons Site-Wide For Guests? '. (($settings['disable_dashicons_for_guests'] == 1) ? 'Yes' : 'No') . "\n";
353
+ $return .= 'Disable Gutenberg CSS Block Editor (site-wide)? '. (($settings['disable_wp_block_library'] == 1) ? 'Yes' : 'No') . "\n";
354
  $return .= 'Disable jQuery Migrate (site-wide)? '. (($settings['disable_jquery_migrate'] == 1) ? 'Yes' : 'No') . "\n";
355
  $return .= 'Disable Comment Reply (site-wide)? '. (($settings['disable_comment_reply'] == 1) ? 'Yes' : 'No') . "\n\n";
356
 
374
 
375
  $return .= "\n" . 'XML-RPC protocol: '. $xmlProtocolStatus . "\n";
376
 
377
+ $return .= "\n" . '# Asset CleanUp: CSS/JS Caching Storage'. "\n";
378
+
379
+ $storageStats = OptimizeCommon::getStorageStats();
380
+
381
+ if (isset($storageStats['total_size'], $storageStats['total_files'])) {
382
+ $return .= 'Total cached assets: '.$storageStats['total_files'].' ('.$storageStats['total_size'].')';
383
+ } else {
384
+ $return .= 'Not used';
385
+ }
386
+
387
+ $return .= "\n\n" . '# Asset CleanUp: Database Storage';
388
 
389
  $wpacuPluginId = WPACU_PLUGIN_ID;
390
 
classes/Update.php CHANGED
@@ -323,6 +323,9 @@ HTML;
323
  return; // only arrays (empty or not) should be used
324
  }
325
 
 
 
 
326
  $jsonNoAssetsLoadList = json_encode($wpacuNoLoadAssets);
327
 
328
  Misc::addUpdateOption(WPACU_PLUGIN_ID . '_front_page_no_load', $jsonNoAssetsLoadList);
@@ -799,7 +802,7 @@ HTML;
799
  $existingList = $existingListData['list'];
800
 
801
  foreach ($_POST['wpacu_handle_notes']['styles'] as $styleHandle => $styleNote) {
802
- $styleNote = trim($styleNote);
803
 
804
  if ($styleNote === '' && isset($existingList['styles'][$globalKey][$styleHandle])) {
805
  unset($existingList['styles'][$globalKey][$styleHandle]);
@@ -809,7 +812,7 @@ HTML;
809
  }
810
 
811
  foreach ($_POST['wpacu_handle_notes']['scripts'] as $scriptHandle => $scriptNote) {
812
- $scriptNote = trim($scriptNote);
813
 
814
  if ($scriptNote === '' && isset($existingList['scripts'][$globalKey][$scriptHandle])) {
815
  unset($existingList['scripts'][$globalKey][$scriptHandle]);
323
  return; // only arrays (empty or not) should be used
324
  }
325
 
326
+ // Was the Assets List Layout changed?
327
+ self::updateAssetListLayoutSettings();
328
+
329
  $jsonNoAssetsLoadList = json_encode($wpacuNoLoadAssets);
330
 
331
  Misc::addUpdateOption(WPACU_PLUGIN_ID . '_front_page_no_load', $jsonNoAssetsLoadList);
802
  $existingList = $existingListData['list'];
803
 
804
  foreach ($_POST['wpacu_handle_notes']['styles'] as $styleHandle => $styleNote) {
805
+ $styleNote = stripslashes($styleNote);
806
 
807
  if ($styleNote === '' && isset($existingList['styles'][$globalKey][$styleHandle])) {
808
  unset($existingList['styles'][$globalKey][$styleHandle]);
812
  }
813
 
814
  foreach ($_POST['wpacu_handle_notes']['scripts'] as $scriptHandle => $scriptNote) {
815
+ $scriptNote = stripslashes($scriptNote);
816
 
817
  if ($scriptNote === '' && isset($existingList['scripts'][$globalKey][$scriptHandle])) {
818
  unset($existingList['scripts'][$globalKey][$scriptHandle]);
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: pagespeed, page speed, dequeue, minify css, performance
4
  Donate link: https://gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
5
  Requires at least: 4.4
6
  Tested up to: 5.2.2
7
- Stable tag: 1.3.3.4
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl.html
10
 
@@ -157,6 +157,14 @@ With the recently released "Test Mode" feature, you can safely unload assets on
157
  4. Homepage CSS & JS Management (List sorted by location)
158
 
159
  == Changelog ==
 
 
 
 
 
 
 
 
160
  = 1.3.3.4 =
161
  * Preload CSS/JS Compatibility Update: If "WP Fastest Cache" is enabled with "Minify CSS" or "Minify JS" option, Asset CleanUp preloading works fine with the new (cached) URLs
162
  * New Option in "Assets List Layout": Sort assets by their preload status (preloaded or not)
4
  Donate link: https://gabelivan.com/items/wp-asset-cleanup-pro/?utm_source=wp_org_lite&utm_medium=donate
5
  Requires at least: 4.4
6
  Tested up to: 5.2.2
7
+ Stable tag: 1.3.3.5
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl.html
10
 
157
  4. Homepage CSS & JS Management (List sorted by location)
158
 
159
  == Changelog ==
160
+ = 1.3.3.5 =
161
+ * New Option To Conveniently Site-Wide Unload Gutenberg CSS Library Block in "Settings" -> "Site-Wide Common Unloads"
162
+ * Better way to clear cached files as the system doesn't just check the version number of the enqueued file, but also the contents of the file in case an update is made for a CSS/JS file on the server, and the developer(s) forgot to update the version number
163
+ * When CSS/JS caching is cleared, the previously cached assets older than (X) days (set in "Settings" -> "Plugin Usage Preferences") are deleted from the server to free up space
164
+ * New Information was added to "Tools" -> "Storage Info" about the total number of cached assets and their total size
165
+ * Prevent specific already minified CSS files (based on their handle name) from various plugins from being minified again by Asset CleanUp (to save resources)
166
+ * Bug Fix: When the asset's note was saved, any quotes from the text were saved with backslashes that kept increasing on every save action
167
+
168
  = 1.3.3.4 =
169
  * Preload CSS/JS Compatibility Update: If "WP Fastest Cache" is enabled with "Minify CSS" or "Minify JS" option, Asset CleanUp preloading works fine with the new (cached) URLs
170
  * New Option in "Assets List Layout": Sort assets by their preload status (preloaded or not)
templates/_admin-page-settings-plugin-areas/_common-files-unload.php CHANGED
@@ -77,11 +77,32 @@ $styleTabContent = ($selectedTabArea === $tabIdArea) ? 'style="display: table-ce
77
  name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[disable_dashicons_for_guests]"
78
  value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
79
  &nbsp;
80
- <?php echo sprintf(__('This will unload %s for guests (non logged-in users)', 'wp-asset-clean-up'), 'Dashicons'); ?> -&gt; <em>/wp-includes/css/dashicons.min.css</em> (46KB + the size of the actual font file loaded based on the browser)
81
  <p style="margin-top: 10px;"><?php _e('This is a CSS file that loads the official icon font of the WordPress admin as of 3.8. While needed for showing up the icons loaded within the top admin bar and in the styling of other plugins such as Query Monitor, it is sometimes loaded site-wide for guests (non logged-in users) when it is not needed.', 'wp-asset-clean-up'); ?></p>
82
  </td>
83
  </tr>
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  <tr valign="top">
86
  <th scope="row">
87
  <label for="wpacu_disable_jquery_migrate"><?php echo sprintf(__('Disable %s Site-Wide', 'wp-asset-clean-up'), 'jQuery Migrate'); ?> <span style="color: #cc0000;" class="dashicons dashicons-warning wordpress-core-file"><span class="wpacu-tooltip">WordPress Core File<br />Not sure if needed or not? In this case, it's better to leave it loaded to avoid breaking the website.</span></span></label>
77
  name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[disable_dashicons_for_guests]"
78
  value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
79
  &nbsp;
80
+ <?php echo sprintf(__('This will unload %s for guests (non logged-in users)', 'wp-asset-clean-up'), 'Dashicons'); ?> -&gt; <em>/wp-includes/css/dashicons.min.css</em> (46 KB + the size of the actual font file loaded based on the browser)
81
  <p style="margin-top: 10px;"><?php _e('This is a CSS file that loads the official icon font of the WordPress admin as of 3.8. While needed for showing up the icons loaded within the top admin bar and in the styling of other plugins such as Query Monitor, it is sometimes loaded site-wide for guests (non logged-in users) when it is not needed.', 'wp-asset-clean-up'); ?></p>
82
  </td>
83
  </tr>
84
 
85
+ <tr valign="top">
86
+ <th scope="row">
87
+ <label for="wpacu_disable_wp_block_library"><?php echo sprintf(__('Disable %s Site-Wide', 'wp-asset-clean-up'), 'Gutenberg CSS Block Library'); ?> <span style="color: #cc0000;" class="dashicons dashicons-warning wordpress-core-file"><span class="wpacu-tooltip">WordPress Core File<br />Not sure if needed or not? In this case, it's better to leave it loaded to avoid breaking the website.</span></span></label>
88
+ </th>
89
+ <td>
90
+ <label class="wpacu_switch">
91
+ <input id="wpacu_disable_wp_block_library" type="checkbox"
92
+ <?php echo (($data['disable_wp_block_library'] == 1) ? 'checked="checked"' : ''); ?>
93
+ name="<?php echo WPACU_PLUGIN_ID . '_global_unloads'; ?>[disable_wp_block_library]"
94
+ value="1" /> <span class="wpacu_slider wpacu_round"></span> </label>
95
+ &nbsp;
96
+ <?php echo sprintf(__('This will unload %s', 'wp-asset-clean-up'), 'Gutenberg Blocks CSS file'); ?> -&gt; (<em>/wp-includes/css/dist/block-library/style.min.css</em>) (25 KB)
97
+ <p style="margin-top: 10px;"><?php _e('If you\'re not using Gutenberg blocks in your posts/page (e.g. you prefer the Classic Editor), then you can unload this file site-wide to avoid an extra render-blocking external CSS file load.', 'wp-asset-clean-up'); ?></p>
98
+ <?php
99
+ if ($extraTip = \WpAssetCleanUp\Tips::ceGutenbergCssLibraryBlockTip()) {
100
+ echo '<p class="wpacu-warning" style="font-size: 100%;"><strong>Extra Tip:</strong> '.$extraTip.'</p>';
101
+ }
102
+ ?>
103
+ </td>
104
+ </tr>
105
+
106
  <tr valign="top">
107
  <th scope="row">
108
  <label for="wpacu_disable_jquery_migrate"><?php echo sprintf(__('Disable %s Site-Wide', 'wp-asset-clean-up'), 'jQuery Migrate'); ?> <span style="color: #cc0000;" class="dashicons dashicons-warning wordpress-core-file"><span class="wpacu-tooltip">WordPress Core File<br />Not sure if needed or not? In this case, it's better to leave it loaded to avoid breaking the website.</span></span></label>
templates/_admin-page-settings-plugin-areas/_plugin-usage-settings.php CHANGED
@@ -301,6 +301,20 @@ $availableForPro = '<a class="go-pro-link-no-style" target="_blank" href="' . WP
301
  Allow Asset CleanUp to anonymously track plugin usage in order to help us make the plugin better? No sensitive or personal data is collected. <span style="color: #004567;" class="dashicons dashicons-info"></span> <a id="wpacu-show-tracked-data-list-modal-target" href="#wpacu-show-tracked-data-list-modal">What kind of data will be sent for the tracking?</a>
302
  </td>
303
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  </table>
305
  </div>
306
 
301
  Allow Asset CleanUp to anonymously track plugin usage in order to help us make the plugin better? No sensitive or personal data is collected. <span style="color: #004567;" class="dashicons dashicons-info"></span> <a id="wpacu-show-tracked-data-list-modal-target" href="#wpacu-show-tracked-data-list-modal">What kind of data will be sent for the tracking?</a>
302
  </td>
303
  </tr>
304
+ <tr valign="top">
305
+ <th scope="row">
306
+ <label for="wpacu_clear_cached_files_after"><?php _e('Clear previously cached CSS/JS files older than (x) days', 'wp-asset-clean-up'); ?></label>
307
+ </th>
308
+ <td>
309
+ <input id="wpacu_clear_cached_files_after"
310
+ type="number"
311
+ min="0"
312
+ style="width: 60px; margin-bottom: 10px;"
313
+ name="<?php echo WPACU_PLUGIN_ID . '_settings'; ?>[clear_cached_files_after]"
314
+ value="<?php echo $data['clear_cached_files_after']; ?>" /> days <small>(setting the value to 0 will result in all the previously cached CSS/JS files to be deleted).</small>
315
+ <br />This is relevant only if any of the options from the following tabs are enabled: "Minify CSS & JS Files" &amp; "Combine CSS & JS Files"). When the caching is cleared, the previously cached CSS/JS files stored in <code><?php echo \WpAssetCleanUp\OptimiseAssets\OptimizeCommon::getRelPathPluginCacheDir(); ?></code> that are older than (X) days will be deleted as they are outdated and likely not referenced anymore in any source code (e.g. old cached pages, Google Search cached version etc.). <span style="color: #004567;" class="dashicons dashicons-info"></span> <a href="https://assetcleanup.com/docs/?p=237" target="_blank">Read more</a>
316
+ </td>
317
+ </tr>
318
  </table>
319
  </div>
320
 
templates/admin-page-tools.php CHANGED
@@ -96,6 +96,22 @@ do_action('wpacu_admin_notices');
96
  $currentStorageDirFull = WP_CONTENT_DIR . $currentStorageDirRel;
97
  $currentStorageDirIsWritable = is_writable($currentStorageDirFull);
98
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  <p><?php _e('If either of the Minify &amp; Combine CSS/JS features is enabled, a storage directory of the minified &amp; concatenated files is needed.', 'wp-asset-clean-up'); ?></p>
100
  <p><?php echo sprintf(__('On certain hosting platforms such as Pantheon, the number of writable directories is limited, in this case you have to change it to %s', 'wp-asset-clean-up'), '<code><strong>/uploads/asset-cleanup/</strong></code>'); ?></p>
101
  <p>
@@ -111,14 +127,7 @@ do_action('wpacu_admin_notices');
111
  __('Note that the relative path is appended to %s', 'wp-asset-clean-up'),
112
  '<em>'.WP_CONTENT_DIR.'/</em>'
113
  ); ?></p>
114
- <hr/>
115
- <p>
116
- <?php _e('Current storage directory', 'wp-asset-clean-up'); ?>: <code><?php echo WP_CONTENT_DIR; ?><strong><?php echo $currentStorageDirRel; ?></strong></code>
117
- &nbsp; <?php if ($currentStorageDirIsWritable) {
118
- echo '<span style="color: green;"><span class="dashicons dashicons-yes"></span> '.__('writable', 'wp-asset-clean-up').'</span>';
119
- } ?>
120
- </p>
121
- <?php
122
  if (! $currentStorageDirIsWritable) {
123
  ?>
124
  <div class="wpacu-warning" style="width: 98%;">
96
  $currentStorageDirFull = WP_CONTENT_DIR . $currentStorageDirRel;
97
  $currentStorageDirIsWritable = is_writable($currentStorageDirFull);
98
  ?>
99
+ <p>
100
+ <?php _e('Current storage directory', 'wp-asset-clean-up'); ?>: <code><?php echo WP_CONTENT_DIR; ?><strong><?php echo $currentStorageDirRel; ?></strong></code>
101
+ &nbsp; <?php if ($currentStorageDirIsWritable) {
102
+ echo '<span style="color: green;"><span class="dashicons dashicons-yes"></span> '.__('writable', 'wp-asset-clean-up').'</span>';
103
+ } ?>
104
+ </p>
105
+ <?php
106
+ $storageStats = \WpAssetCleanUp\OptimiseAssets\OptimizeCommon::getStorageStats();
107
+
108
+ if (isset($storageStats['total_size'], $storageStats['total_files'])) {
109
+ ?>
110
+ <p><?php _e('Total cached CSS/JS files', 'wp-asset-clean-up'); ?>: <strong><?php echo $storageStats['total_files']; ?></strong>, <?php echo $storageStats['total_size']; ?></p>
111
+ <?php
112
+ }
113
+ ?>
114
+ <hr />
115
  <p><?php _e('If either of the Minify &amp; Combine CSS/JS features is enabled, a storage directory of the minified &amp; concatenated files is needed.', 'wp-asset-clean-up'); ?></p>
116
  <p><?php echo sprintf(__('On certain hosting platforms such as Pantheon, the number of writable directories is limited, in this case you have to change it to %s', 'wp-asset-clean-up'), '<code><strong>/uploads/asset-cleanup/</strong></code>'); ?></p>
117
  <p>
127
  __('Note that the relative path is appended to %s', 'wp-asset-clean-up'),
128
  '<em>'.WP_CONTENT_DIR.'/</em>'
129
  ); ?></p>
130
+ <?php
 
 
 
 
 
 
 
131
  if (! $currentStorageDirIsWritable) {
132
  ?>
133
  <div class="wpacu-warning" style="width: 98%;">
templates/meta-box-loaded-assets/_asset-script-single-row.php CHANGED
@@ -378,7 +378,7 @@ $jqueryIconHtmlDepends = '<img src="'.WPACU_PLUGIN_URL.'/assets/icons/handles/ic
378
  <textarea id="wpacu_handle_note_script_<?php echo $data['row']['obj']->handle; ?>"
379
  rows="3"
380
  placeholder="<?php echo esc_attr('Add your note here about this JavaScript file', 'wp-asset-clean-up'); ?>"
381
- name="wpacu_handle_notes[scripts][<?php echo $data['row']['obj']->handle; ?>]"><?php echo (isset($data['handle_notes']['scripts'][$data['row']['obj']->handle]) ? $data['handle_notes']['scripts'][$data['row']['obj']->handle] : ''); ?></textarea>
382
  </div>
383
  </div>
384
  <img style="display: none;" class="wpacu-ajax-loader" src="<?php echo WPACU_PLUGIN_URL; ?>/assets/icons/icon-ajax-loading-spinner.svg" alt="" />
378
  <textarea id="wpacu_handle_note_script_<?php echo $data['row']['obj']->handle; ?>"
379
  rows="3"
380
  placeholder="<?php echo esc_attr('Add your note here about this JavaScript file', 'wp-asset-clean-up'); ?>"
381
+ name="wpacu_handle_notes[scripts][<?php echo $data['row']['obj']->handle; ?>]"><?php echo esc_textarea($handleNote); ?></textarea>
382
  </div>
383
  </div>
384
  <img style="display: none;" class="wpacu-ajax-loader" src="<?php echo WPACU_PLUGIN_URL; ?>/assets/icons/icon-ajax-loading-spinner.svg" alt="" />
templates/meta-box-loaded-assets/_asset-style-single-row.php CHANGED
@@ -352,7 +352,7 @@ sort($childHandles);
352
  <textarea id="wpacu_handle_note_style_<?php echo $data['row']['obj']->handle; ?>"
353
  rows="3"
354
  placeholder="<?php echo esc_attr('Add your note here about this stylesheet file', 'wp-asset-clean-up'); ?>"
355
- name="wpacu_handle_notes[styles][<?php echo $data['row']['obj']->handle; ?>]"><?php echo $handleNote; ?></textarea>
356
  </div>
357
  </div>
358
  <img style="display: none;" class="wpacu-ajax-loader" src="<?php echo WPACU_PLUGIN_URL; ?>/assets/icons/icon-ajax-loading-spinner.svg" alt="" />
352
  <textarea id="wpacu_handle_note_style_<?php echo $data['row']['obj']->handle; ?>"
353
  rows="3"
354
  placeholder="<?php echo esc_attr('Add your note here about this stylesheet file', 'wp-asset-clean-up'); ?>"
355
+ name="wpacu_handle_notes[styles][<?php echo $data['row']['obj']->handle; ?>]"><?php echo esc_textarea($handleNote); ?></textarea>
356
  </div>
357
  </div>
358
  <img style="display: none;" class="wpacu-ajax-loader" src="<?php echo WPACU_PLUGIN_URL; ?>/assets/icons/icon-ajax-loading-spinner.svg" alt="" />
wpacu.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  * Plugin Name: Asset CleanUp: Page Speed Booster
4
  * Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
5
- * Version: 1.3.3.4
6
  * Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
7
  * Author: Gabriel Livan
8
  * Author URI: http://gabelivan.com/
@@ -12,7 +12,7 @@
12
 
13
  // Is the Pro version triggered before the Lite one and are both plugins active?
14
  if (! defined('WPACU_PLUGIN_VERSION')) {
15
- define('WPACU_PLUGIN_VERSION', '1.3.3.4');
16
  }
17
 
18
  // Exit if accessed directly
2
  /*
3
  * Plugin Name: Asset CleanUp: Page Speed Booster
4
  * Plugin URI: https://wordpress.org/plugins/wp-asset-clean-up/
5
+ * Version: 1.3.3.5
6
  * Description: Unload Chosen Scripts & Styles from Posts/Pages to reduce HTTP Requests, Combine/Minify CSS/JS files
7
  * Author: Gabriel Livan
8
  * Author URI: http://gabelivan.com/
12
 
13
  // Is the Pro version triggered before the Lite one and are both plugins active?
14
  if (! defined('WPACU_PLUGIN_VERSION')) {
15
+ define('WPACU_PLUGIN_VERSION', '1.3.3.5');
16
  }
17
 
18
  // Exit if accessed directly