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
wp-optimize / minify / class-wp-optimize-minify-commands.php

class-wp-optimize-minify-commands.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.7.0, at minify/class-wp-optimize-minify-commands.php

459 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('No direct access allowed');
3
4 if (!class_exists('WP_Optimize_Minify_Config')) require_once(dirname(__FILE__) . '/class-wp-optimize-minify-config.php');
5 if (!class_exists('WP_Optimize_Minify_Preloader')) require_once(dirname(__FILE__) . '/class-wpo-minify-preloader.php');
6
7 /**
8 * All cache commands that are intended to be available for calling from any sort of control interface (e.g. wp-admin, UpdraftCentral) go in here. All public methods should either return the data to be returned, or a WP_Error with associated error code, message and error data.
9 */
10 class WP_Optimize_Minify_Commands {
11
12 /**
13 * List all cache files
14 *
15 * @param array $data - The $_POST data
16 * @return array
17 */
18 public function get_minify_cached_files($data = array()) {
19 $stamp = $data['stamp'] ?? 0;
20 $files = WP_Optimize_Minify_Cache_Functions::get_cached_files($stamp, false);
21 $files['js'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['js']);
22 $files['css'] = array_map(array('WP_Optimize_Minify_Cache_Functions', 'format_file_logs'), $files['css']);
23 return $files;
24 }
25
26 /**
27 * Removes the entire cache dir.
28 * Use with caution, as cached html may still reference those files.
29 *
30 * @return array
31 */
32 public function purge_all_minify_cache() {
33 WP_Optimize_Minify_Cache_Functions::purge();
34 WP_Optimize_Minify_Cache_Functions::cache_increment();
35 $others = WP_Optimize_Minify_Cache_Functions::purge_others();
36 $files = $this->get_minify_cached_files();
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
41 return array(
42 'success' => true,
43 'message' => implode("\n", $message),
44 'files' => $files
45 );
46 }
47
48 /**
49 * Forces a new Cache to be built
50 *
51 * @return array
52 */
53 public function minify_increment_cache() {
54 WP_Optimize_Minify_Cache_Functions::cache_increment();
55 $files = $this->get_minify_cached_files();
56 return array(
57 'success' => true,
58 'files' => $files
59 );
60 }
61
62 /**
63 * Purge the cache
64 *
65 * @return array
66 */
67 public function purge_minify_cache() {
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 }
73
74 // deletes temp files and old caches in case CRON isn't working
75 WP_Optimize_Minify_Cache_Functions::cache_increment();
76 if (wp_optimize_minify_config()->always_purge_everything()) {
77 WP_Optimize_Minify_Cache_Functions::purge();
78 $state = array();
79 $old = array();
80 } else {
81 $state = WP_Optimize_Minify_Cache_Functions::purge_temp_files();
82 $old = WP_Optimize_Minify_Cache_Functions::purge_old();
83 }
84 $others = WP_Optimize_Minify_Cache_Functions::purge_others();
85 $files = $this->get_minify_cached_files();
86
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, '');
90
91 $notice = wp_json_encode($notice); // encode
92
93 return array(
94 'result' => 'caches cleared',
95 'others' => implode("\n", $others),
96 'state' => $state,
97 'message' => $notice,
98 'old' => $old,
99 'files' => $files
100 );
101 }
102
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 /**
168 * Save options to the config
169 *
170 * @param array $data
171 * @return array
172 */
173 public function save_minify_settings($data) {
174 $new_data = array();
175 foreach ($data as $key => $value) {
176 if ('true' === $value) {
177 $new_data[$key] = true;
178 } elseif ('false' === $value) {
179 $new_data[$key] = false;
180 } else {
181 $new_data[$key] = is_string($value) ? trim($value) : $value;
182 }
183 }
184
185 if (isset($data['minify_advanced_tab'])) {
186 // Make sure that empty settings are still saved
187 if (!isset($new_data['ignore_list'])) $new_data['ignore_list'] = array();
188 if (!isset($new_data['blacklist'])) $new_data['blacklist'] = array();
189 }
190
191 /**
192 * Filters the data before saving it
193 *
194 * @param array $new_data - The original data
195 * @return array The data, altered or not
196 */
197 $new_data = apply_filters('wpo_save_minify_settings', $new_data);
198
199 if (!class_exists('WP_Optimize_Minify_Config')) return array(
200 'success' => false,
201 'message' => "WP_Optimize_Minify_Config class doesn't exist",
202 );
203 $working = wp_optimize_minify_config()->update($new_data);
204 if (!$working) {
205 return array(
206 'success' => false,
207 'error' => 'failed to save minify settings'
208 );
209 }
210 $purged = $this->purge_minify_cache();
211 return array(
212 'success' => true,
213 'files' => $purged['files'] ?? array(),
214 );
215 }
216
217 /**
218 * Toggle (hide or show) the information notice for the current user.
219 *
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)}
222 */
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
280 return array(
281 'success' => $success,
282 'hide' => $should_hide_notice,
283 );
284 }
285
286 /**
287 * Get the current status
288 *
289 * @return array
290 */
291 public function get_status() {
292 $config = wp_optimize_minify_config()->get();
293 return array(
294 'enabled' => $config['enabled'],
295 'js' => $config['enable_js'],
296 'css' => $config['enable_css'],
297 'html' => $config['html_minification'],
298 'stats' => $this->get_minify_cached_files()
299 );
300 }
301
302 /**
303 * Run minify preload action.
304 *
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.
306 */
307 public function run_minify_preload() {
308 return WP_Optimize_Minify_Preloader::instance()->run('manual');
309 }
310
311 /**
312 * Cancel minify preload action.
313 *
314 * @return mixed
315 */
316 public function cancel_minify_preload() {
317 WP_Optimize_Minify_Preloader::instance()->cancel_preload();
318 return WP_Optimize_Minify_Preloader::instance()->get_status_info();
319 }
320
321 /**
322 * Get status of minify preload.
323 *
324 * @return mixed
325 */
326 public function get_minify_preload_status() {
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;
457 }
458 }
459