PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | minify/class-wp-optimize-minify-commands.php +278 -30 3.2.5 → 4.7.0 View file →
@@ -15,10 +15,9 @@
15 15 * @param array $data - The $_POST data
16 16 * @return array
17 17 */
18 18 public function get_minify_cached_files($data = array()) {
19 - if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
20 - $stamp = isset($data['stamp']) ? $data['stamp'] : 0;
19 + $stamp = $data['stamp'] ?? 0;
21 20 $files = WP_Optimize_Minify_Cache_Functions::get_cached_files($stamp, false);
22 21 $files['js'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['js']);
23 22 $files['css'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['css']);
24 23 return $files;
@@ -30,18 +29,16 @@
30 29 *
31 30 * @return array
32 31 */
33 32 public function purge_all_minify_cache() {
34 - if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
35 33 WP_Optimize_Minify_Cache_Functions::purge();
36 34 WP_Optimize_Minify_Cache_Functions::cache_increment();
37 35 $others = WP_Optimize_Minify_Cache_Functions::purge_others();
38 36 $files = $this->get_minify_cached_files();
39 - $message = array(
40 - __('The minification cache was deleted.', 'wp-optimize'),
41 - strip_tags($others, '<strong>'),
42 - );
43 - $message = array_filter($message);
37 +
38 + $message = array_merge(array(esc_html__('The minification cache was deleted.', 'wp-optimize')), $others);
39 + $message = WP_Optimize_Minify_Functions::apply_strip_tags_for_messages_array($message, '');
40 +
44 41 return array(
45 42 'success' => true,
46 43 'message' => implode("\n", $message),
47 44 'files' => $files
@@ -53,9 +50,8 @@
53 50 *
54 51 * @return array
55 52 */
56 53 public function minify_increment_cache() {
57 - if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
58 54 WP_Optimize_Minify_Cache_Functions::cache_increment();
59 55 $files = $this->get_minify_cached_files();
60 56 return array(
61 57 'success' => true,
@@ -68,12 +64,15 @@
68 64 *
69 65 * @return array
70 66 */
71 67 public function purge_minify_cache() {
72 - if (!WPO_MINIFY_PHP_VERSION_MET) return array('error' => __('WP-Optimize Minify requires a higher PHP version', 'wp-optimize'));
73 - if (!WP_Optimize()->can_purge_the_cache()) return array('error' => __('You do not have permission to purge the cache', 'wp-optimize'));
68 + if (!WP_Optimize()->get_minify()->can_purge_cache() && !(defined('WP_CLI') && WP_CLI)) {
69 + return array(
70 + 'error' => __('You do not have permission to purge the cache', 'wp-optimize')
71 + );
72 + }
74 73
75 - // deletes temp files and old caches incase CRON isn't working
74 + // deletes temp files and old caches in case CRON isn't working
76 75 WP_Optimize_Minify_Cache_Functions::cache_increment();
77 76 if (wp_optimize_minify_config()->always_purge_everything()) {
78 77 WP_Optimize_Minify_Cache_Functions::purge();
79 78 $state = array();
@@ -84,18 +83,17 @@
84 83 }
85 84 $others = WP_Optimize_Minify_Cache_Functions::purge_others();
86 85 $files = $this->get_minify_cached_files();
87 86
88 - $notice = array(
89 - __('All caches from WP-Optimize Minify have been purged.', 'wp-optimize'),
90 - strip_tags($others, '<strong>'),
91 - );
92 - $notice = array_filter($notice);
93 - $notice = json_encode($notice); // encode
87 + $notice = array_merge(array(esc_html__('All caches from WP-Optimize Minify have been purged.', 'wp-optimize')), $others);
88 +
89 + $notice = WP_Optimize_Minify_Functions::apply_strip_tags_for_messages_array($notice, '');
94 90
91 + $notice = wp_json_encode($notice); // encode
92 +
95 93 return array(
96 94 'result' => 'caches cleared',
97 - 'others' => $others,
95 + 'others' => implode("\n", $others),
98 96 'state' => $state,
99 97 'message' => $notice,
100 98 'old' => $old,
101 99 'files' => $files
@@ -102,8 +100,72 @@
102 100 );
103 101 }
104 102
105 103 /**
104 + * Delete minify cache file
105 + *
106 + * @param string $filename
107 + * @return array
108 + */
109 + public function delete_minify_cache_file($filename) {
110 + if (!WP_Optimize()->get_minify()->can_purge_cache()) return array('error' => __('You do not have permission to purge the cache', 'wp-optimize'), 'result' => '', 'files' => '');
111 +
112 + $response = array(
113 + 'result' => __('Cache file was not found.', 'wp-optimize'),
114 + 'files' => '',
115 + 'error' => '',
116 + );
117 +
118 + if (empty($filename)) return $response;
119 +
120 + $is_valid_filename = $this->is_valid_filename($filename);
121 +
122 + if (!$is_valid_filename) {
123 + return $response;
124 + } else {
125 + $filename = pathinfo($filename, PATHINFO_BASENAME);
126 +
127 + $data = $this->get_file_data($filename);
128 +
129 + if (empty($data)) return $response;
130 + $this->fetch_and_remove_temp_minify_cache_files($data);
131 +
132 + $files = $this->get_minify_cached_files();
133 + return array(
134 + 'result' => __('Cache deleted.', 'wp-optimize'),
135 + 'files' => $files,
136 + 'error' => '',
137 + );
138 + }
139 + }
140 +
141 + /**
142 + * Fetch and remove the temp and minify js/css cache files.
143 + *
144 + * @param array $data file data
145 + */
146 + public function fetch_and_remove_temp_minify_cache_files($data) {
147 + $filename = $data['filename'];
148 + $log = $data['log'];
149 +
150 + // get cache directories and urls
151 + $cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
152 + $tmp_dir = $cache_path['tmpdir'];
153 + $cache_dir = $cache_path['cachedir'];
154 +
155 + $ext_to_delete = array('', '.json', '.gz');
156 + foreach ($ext_to_delete as $ext) {
157 + $this->check_and_delete($cache_dir . '/' . $filename . $ext);
158 + }
159 +
160 + if (empty($log->files)) return;
161 + foreach ($log->files as $key => $value) {
162 + $transient_file = $this->get_transient_file($key, $value, $filename);
163 + $this->check_and_delete($tmp_dir.'/'.$transient_file);
164 + }
165 + }
166 +
167 + /**
106 168 * Save options to the config
107 169 *
108 170 * @param array $data
109 171 * @return array
@@ -108,9 +170,8 @@
108 170 * @param array $data
109 171 * @return array
110 172 */
111 173 public function save_minify_settings($data) {
112 -
113 174 $new_data = array();
114 175 foreach ($data as $key => $value) {
115 176 if ('true' === $value) {
116 177 $new_data[$key] = true;
@@ -116,9 +177,9 @@
116 177 $new_data[$key] = true;
117 178 } elseif ('false' === $value) {
118 179 $new_data[$key] = false;
119 180 } else {
120 - $new_data[$key] = $value;
181 + $new_data[$key] = is_string($value) ? trim($value) : $value;
121 182 }
122 183 }
123 184
124 185 if (isset($data['minify_advanced_tab'])) {
@@ -142,26 +203,84 @@
142 203 $working = wp_optimize_minify_config()->update($new_data);
143 204 if (!$working) {
144 205 return array(
145 206 'success' => false,
146 - 'error' => 'failed to save'
207 + 'error' => 'failed to save minify settings'
147 208 );
148 209 }
149 210 $purged = $this->purge_minify_cache();
150 211 return array(
151 212 'success' => true,
152 - 'files' => $purged['files']
213 + 'files' => $purged['files'] ?? array(),
153 214 );
154 215 }
155 216
156 217 /**
157 - * Hide the information notice for the current user
218 + * Toggle (hide or show) the information notice for the current user.
158 219 *
159 - * @return array
220 + * @param array $params {type:(js|css|minify), merging_enabled:(true|false), force_hide:(true|false)}
221 + * @return array {success:(true|false), hide:(true|false), message:(string)}
160 222 */
161 - public function hide_minify_notice() {
223 + public function toggle_minify_notice($params) {
224 + if (empty($params['type'])) {
225 + return array(
226 + 'success' => false,
227 + 'message' => __('The request did not include a notice type.', 'wp-optimize')
228 + );
229 + }
230 +
231 + $notice_types = array(
232 + 'js' => 'wpo_hide_js_merging_notice',
233 + 'css' => 'wpo_hide_css_merging_notice',
234 + 'minify' => 'wpo-hide-minify-information-notice'
235 + );
236 +
237 + if (!isset($notice_types[$params['type']])) {
238 + return array(
239 + 'success' => false,
240 + 'message' => __('The specified notice type is invalid.', 'wp-optimize')
241 + );
242 + }
243 +
244 + $current_user_id = get_current_user_id();
245 + if (!$current_user_id) {
246 + return array(
247 + 'success' => false,
248 + 'message' => __('Invalid user context.', 'wp-optimize')
249 + );
250 + }
251 +
252 + $meta_key = $notice_types[$params['type']];
253 + $should_hide_notice = isset($params['force_hide']) ? filter_var($params['force_hide'], FILTER_VALIDATE_BOOLEAN) : true;
254 + if (!$should_hide_notice) {
255 + $merging_enabled = isset($params['merging_enabled']) ? filter_var($params['merging_enabled'], FILTER_VALIDATE_BOOLEAN) : true;
256 + $is_http1 = WP_Optimize_Utils::is_request_protocol_http1();
257 + $should_hide_notice = (($is_http1 && $merging_enabled) || (!$is_http1 && !$merging_enabled));
258 + }
259 +
260 + $updated = update_user_meta($current_user_id, $meta_key, $should_hide_notice);
261 + $success = true;
262 +
263 + if (false === $updated) {
264 + /**
265 + * Function update_user_meta() returns false when:
266 + * the value is unchanged or the update failed.
267 + *
268 + * We verify by reading the stored value. If it matches the intended value,
269 + * treat it as a success; otherwise, treat it as a failure.
270 + */
271 + $existing = get_user_meta($current_user_id, $meta_key, true);
272 +
273 + /**
274 + * Loose comparison (==) is intentional because user meta-values are
275 + * stored as strings ('1', '0'), not booleans.
276 + */
277 + $success = ($existing == $should_hide_notice);
278 + }
279 +
162 280 return array(
163 - 'success' => update_user_meta(get_current_user_id(), 'wpo-hide-minify-information-notice', true)
281 + 'success' => $success,
282 + 'hide' => $should_hide_notice,
164 283 );
165 284 }
166 285
167 286 /**
@@ -182,9 +301,9 @@
182 301
183 302 /**
184 303 * Run minify preload action.
185 304 *
186 - * @return void|array - Doesn't return anything if run() is successfull (Run() prints a JSON object and closed browser connection) or an array if failed.
305 + * @return array|true[]|null - Doesn't return anything if run() is successful (Run() prints a JSON object and closed browser connection) or an array if failed.
187 306 */
188 307 public function run_minify_preload() {
189 308 return WP_Optimize_Minify_Preloader::instance()->run('manual');
190 309 }
@@ -191,9 +310,9 @@
191 310
192 311 /**
193 312 * Cancel minify preload action.
194 313 *
195 - * @return array
314 + * @return mixed
196 315 */
197 316 public function cancel_minify_preload() {
198 317 WP_Optimize_Minify_Preloader::instance()->cancel_preload();
199 318 return WP_Optimize_Minify_Preloader::instance()->get_status_info();
@@ -201,10 +320,139 @@
201 320
202 321 /**
203 322 * Get status of minify preload.
204 323 *
205 - * @return array
324 + * @return mixed
206 325 */
207 326 public function get_minify_preload_status() {
208 327 return WP_Optimize_Minify_Preloader::instance()->get_status_info();
328 + }
329 +
330 + /**
331 + * Returns the combined json of all available meta.json files
332 + *
333 + * @return array
334 + */
335 + public function get_minify_meta_files() {
336 + $enabled = wp_optimize_minify_config()->get('enabled');
337 + if (!$enabled) return array(
338 + 'success' => false,
339 + 'error' => __('Minify not enabled', 'wp-optimize'),
340 + );
341 + $combined_metas = array(
342 + 'meta_logs' => array()
343 + );
344 +
345 + // loop through wpo-minify cache directory and get the meta.json files, combine into a single json file
346 + if (is_dir(WPO_CACHE_MIN_FILES_DIR) && wp_is_writable(dirname(WPO_CACHE_MIN_FILES_DIR))) {
347 + if ($handle = opendir(WPO_CACHE_MIN_FILES_DIR)) {
348 + while (false !== ($d = readdir($handle))) {
349 + if (0 === strcmp($d, '.') || 0 === strcmp($d, '..') || !is_numeric($d)) {
350 + continue;
351 + }
352 + $cache_min_folder = WPO_CACHE_MIN_FILES_DIR.'/'.$d;
353 + if ($cache_min_folder_handle = opendir($cache_min_folder)) {
354 + while (false !== ($maybe_file = readdir($cache_min_folder_handle))) {
355 + if (0 === strcmp($maybe_file, '.') || 0 === strcmp($maybe_file, '..')) {
356 + continue;
357 + }
358 + $maybe_file_path = $cache_min_folder . '/' . $maybe_file;
359 + if (is_file($maybe_file_path) && 'meta.json' === basename($maybe_file_path)) {
360 + $combined_metas['meta_logs'][$d] = json_decode(file_get_contents($maybe_file_path));
361 + }
362 + }
363 + closedir($cache_min_folder_handle);
364 + }
365 + }
366 + closedir($handle);
367 + }
368 + }
369 +
370 + if (0 === count($combined_metas['meta_logs'])) {
371 + return array(
372 + 'success' => false,
373 + 'error' => __('No file was found', 'wp-optimize'),
374 + );
375 + } else {
376 + return array(
377 + 'success' => true,
378 + 'combined_metas' => $combined_metas
379 + );
380 + }
381 + }
382 +
383 + /**
384 + * Get minify file data.
385 + *
386 + * @param string $filename
387 + * @return array
388 + */
389 + private function get_file_data($filename) {
390 + $log = false;
391 + $data = array();
392 + $cache_path = WP_Optimize_Minify_Cache_Functions::cache_path();
393 + $cache_dir = $cache_path['cachedir'];
394 + $file = $cache_dir.'/'.$filename;
395 +
396 + if (file_exists($file.'.json')) {
397 + $log = json_decode(file_get_contents($file.'.json'));
398 + $data['filename'] = $filename;
399 + $data['log'] = $log;
400 + }
401 +
402 + return $data;
403 + }
404 +
405 + /**
406 + * Check minify file exists and delete it.
407 + *
408 + * @param string $file
409 + */
410 + private function check_and_delete($file) {
411 + if (file_exists($file)) {
412 + wp_delete_file($file);
413 + }
414 + }
415 +
416 + /**
417 + * Get transient file.
418 + *
419 + * @param string $key
420 + * @param mixed $value
421 + * @param string $filename
422 + * @return string
423 + */
424 + private function get_transient_file($key, $value, $filename) {
425 + $url = $value->url;
426 + $file_url = site_url().$url;
427 + $file_ext = $this->get_file_extension($filename);
428 +
429 + $href = WP_Optimize_Minify_Functions::get_hurl($file_url);
430 + $transient_key = $file_ext.'-'.hash('adler32', $key.$href).'.'.$file_ext;
431 + return $transient_key.'.transient';
432 + }
433 +
434 + /**
435 + * Get file extension.
436 + *
437 + * @param string $filename
438 + * @return string
439 + */
440 + private function get_file_extension($filename) {
441 + $file_info = pathinfo($filename);
442 + return $file_info['extension'];
443 + }
444 +
445 + /**
446 + * Check for valid filename.
447 + * For file name pattern see here, the function 'process_header_css' in the file 'class-wp-optimize-minify-front-end.php' where the file name is constructed. You can find' WP_Optimize_Minify_Print::write_combined_asset' and go to the passed $file variable where it's defined or constructed.
448 + *
449 + * @param string $filename
450 + * @return bool
451 + */
452 + private function is_valid_filename($filename) {
453 + if (preg_match('/^[a-zA-Z0-9.-]*$/', $filename)) {
454 + return true;
455 + }
456 + return false;
209 457 }
210 458 }