PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.22
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.22
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 / includes / class-wpo-ajax.php

class-wpo-ajax.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.22, at includes/class-wpo-ajax.php

381 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) die('Access denied.');
4
5 if (!class_exists('WPO_Ajax')) :
6
7 class WPO_Ajax {
8
9 private $nonce;
10
11 private $subaction;
12
13 private $data;
14
15 private $commands;
16
17 private $results;
18
19 /**
20 * Constructor
21 */
22 private function __construct() {
23 add_action('wp_ajax_wp_optimize_ajax', array($this, 'handle_ajax_requests'));
24 }
25
26 /**
27 * Return singleton instance
28 *
29 * @return WPO_Ajax Returns WPO_Ajax object
30 */
31 public static function get_instance() {
32 static $instance = null;
33 if (null === $instance) {
34 $instance = new self();
35 }
36 return $instance;
37 }
38
39 /**
40 * Handles ajax requests
41 *
42 * @return void
43 */
44 public function handle_ajax_requests() {
45 $this->set_nonce();
46 $this->set_subaction();
47 $this->set_data();
48
49 if (!$this->is_valid_request()) {
50 $this->send_security_check_failed_error_response();
51 }
52
53 if (!$this->is_user_capable()) {
54 $this->send_user_capability_error_response();
55 }
56
57 if (is_multisite() && !current_user_can('manage_network_options')) {
58 if (!$this->is_valid_multisite_command()) {
59 $this->send_invalid_multisite_command_error_response();
60 }
61 }
62
63 if ($this->is_subaction_a_dismissed_notice()) {
64 $this->handle_notice_dismissals();
65 } else {
66 $this->set_commands();
67 if ($this->is_invalid_command()) {
68 $this->add_invalid_command_error_log_entry();
69 $this->set_invalid_command_error_response();
70 } else {
71 $this->execute_command();
72 $this->maybe_fix_status_box_content();
73 $this->set_error_response_on_wp_error();
74 $this->maybe_set_results_as_null();
75 }
76 }
77
78 $this->json_encode_results();
79
80 $json_last_error = json_last_error();
81 if ($json_last_error) {
82 $this->set_error_response_on_json_encode_error($json_last_error);
83 }
84
85 echo $this->results;
86 die;
87 }
88
89 /**
90 * Sets nonce property value
91 */
92 private function set_nonce() {
93 $this->nonce = empty($_POST['nonce']) ? '' : $_POST['nonce'];
94 }
95
96 /**
97 * Sets subaction property value
98 */
99 private function set_subaction() {
100 $this->subaction = empty($_POST['subaction']) ? '' : stripcslashes($_POST['subaction']);
101 }
102
103 /**
104 * Sets data property value
105 */
106 private function set_data() {
107 $this->data = isset($_POST['data']) ? stripslashes_deep($_POST['data']) : null;
108 }
109
110 /**
111 * Checks whether the request is valid or not
112 *
113 * @return bool
114 */
115 private function is_valid_request() {
116 return wp_verify_nonce($this->nonce, 'wp-optimize-ajax-nonce') && !empty($this->subaction);
117 }
118
119 /**
120 * Send security check failed error response to browser and die
121 */
122 private function send_security_check_failed_error_response() {
123 wp_send_json(array(
124 'result' => false,
125 'error_code' => 'security_check',
126 'error_message' => __('The security check failed; try refreshing the page.', 'wp-optimize')
127 ));
128 }
129
130
131 /**
132 * Checks whether current user capable of doing this action or not
133 *
134 * @return bool
135 */
136 private function is_user_capable() {
137 return current_user_can(WP_Optimize()->capability_required());
138 }
139
140 /**
141 * Send user capability check failed error response to browser and die
142 */
143 private function send_user_capability_error_response() {
144 wp_send_json(array(
145 'result' => false,
146 'error_code' => 'security_check',
147 'error_message' => __('You are not allowed to run this command.', 'wp-optimize')
148 ));
149 }
150
151 /**
152 * Checks whether subaction is a valid multisite command
153 *
154 * @return bool
155 */
156 private function is_valid_multisite_command() {
157 /**
158 * Filters the commands allowed to the sub site admins. Other commands are only available to network admin. Only used in a multisite context.
159 */
160 $allowed_multisite_commands = apply_filters('wpo_multisite_allowed_commands', array('check_server_status', 'compress_single_image', 'restore_single_image'));
161 return in_array($this->subaction, $allowed_multisite_commands);
162 }
163
164 /**
165 * Send invalid multisite command error response to browser and die
166 */
167 private function send_invalid_multisite_command_error_response() {
168 wp_send_json(array(
169 'result' => false,
170 'error_code' => 'update_failed',
171 'error_message' => __('Options can only be saved by network admin', 'wp-optimize')
172 ));
173 }
174
175 /**
176 * Checks if subaction is a notice dismissal or not
177 *
178 * @return bool True for notice dismiss actions, false otherwise
179 */
180 private function is_subaction_a_dismissed_notice() {
181 $dismiss_actions = $this->get_dismiss_actions();
182 return in_array($this->subaction, $dismiss_actions);
183 }
184
185 /**
186 * Returns an array of notice dismiss action names
187 *
188 * @return array An array of notice dismiss actions
189 */
190 private function get_dismiss_actions() {
191 return array(
192 'dismiss_dash_notice_until',
193 'dismiss_season',
194 'dismiss_page_notice_until',
195 'dismiss_notice',
196 'dismiss_review_notice',
197 );
198 }
199
200 /**
201 * Handles notice dismissals
202 */
203 private function handle_notice_dismissals() {
204 $options = WP_Optimize()->get_options();
205 // Some commands that are available via AJAX only.
206 if (in_array($this->subaction, array('dismiss_dash_notice_until', 'dismiss_season'))) {
207 $options->update_option($this->subaction, (time() + 366 * 86400));
208 } elseif (in_array($this->subaction, array('dismiss_page_notice_until', 'dismiss_notice'))) {
209 $options->update_option($this->subaction, (time() + 84 * 86400));
210 } elseif ('dismiss_review_notice' == $this->subaction) {
211 if (empty($this->data['dismiss_forever'])) {
212 $options->update_option($this->subaction, time() + 84 * 86400);
213 } else {
214 $options->update_option($this->subaction, 100 * (365.25 * 86400));
215 }
216 }
217 }
218
219 /**
220 * Sets commands property value
221 */
222 private function set_commands() {
223 $this->commands = new WP_Optimize_Commands();
224
225 $minify_commands = $this->get_minify_commands();
226 if ($this->is_subaction_a_minify_command($minify_commands)) {
227 $this->commands = $minify_commands;
228 }
229
230 $cache_commands = $this->get_cache_commands();
231 if ($this->is_subaction_a_cache_command($cache_commands)) {
232 $this->commands = $cache_commands;
233 }
234 }
235
236 /**
237 * Gets minify commands
238 *
239 * @return WP_Optimize_Minify_Commands
240 */
241 private function get_minify_commands() {
242 return new WP_Optimize_Minify_Commands();
243 }
244
245 /**
246 * Gets cache commands
247 *
248 * @return WP_Optimize_Cache_Commands|WP_Optimize_Cache_Commands_Premium
249 */
250 private function get_cache_commands() {
251 if (WP_Optimize::is_premium()) {
252 $cache_commands = new WP_Optimize_Cache_Commands_Premium();
253 } else {
254 $cache_commands = new WP_Optimize_Cache_Commands();
255 }
256 return $cache_commands;
257 }
258
259 /**
260 * Checks if applied ajax command is a minify command or not
261 *
262 * @param WP_Optimize_Minify_Commands $minify_commands an instance of minify commands class
263 *
264 * @return bool Returns true if ajax command is a minify command, false otherwise
265 */
266 private function is_subaction_a_minify_command($minify_commands) {
267 return !is_callable(array($this->commands, $this->subaction)) && is_callable(array($minify_commands, $this->subaction));
268 }
269
270 /**
271 * Checks if applied ajax command is a cache command or not
272 *
273 * @param WP_Optimize_Cache_Commands|WP_Optimize_Cache_Commands_Premium $cache_commands an instance of cache commands
274 *
275 * @return bool Returns true if ajax command is a cache command, false otherwise
276 */
277 private function is_subaction_a_cache_command($cache_commands) {
278 return !is_callable(array($this->commands, $this->subaction)) && is_callable(array($cache_commands, $this->subaction));
279 }
280
281 /**
282 * Checks if applied ajax command is an invalid command or not
283 *
284 * @return bool Returns true if ajax command is an invalid command, false otherwise
285 */
286 private function is_invalid_command() {
287 return !is_callable(array($this->commands, $this->subaction));
288 }
289
290 /**
291 * Log an error message for invalid ajax command
292 */
293 private function add_invalid_command_error_log_entry() {
294 error_log("WP-Optimize: ajax_handler: no such command (" . $this->subaction . ")");
295 }
296
297 /**
298 * Set `results` property with error response array for invalid ajax command
299 *
300 * @return void
301 */
302 private function set_invalid_command_error_response() {
303 $this->results = array(
304 'result' => false,
305 'error_code' => 'command_not_found',
306 'error_message' => sprintf(__('The command "%s" was not found', 'wp-optimize'), $this->subaction)
307 );
308 }
309
310 /**
311 * Execute the ajax command
312 */
313 private function execute_command() {
314 $this->results = call_user_func(array($this->commands, $this->subaction), $this->data);
315 }
316
317 /**
318 * If status box content is present, fix it.
319 */
320 private function maybe_fix_status_box_content() {
321 // clean status box content, it broke json sometimes.
322 // Git commit wp-optimize/-/commit/c05686b39959b863f4e168af3fa54421c4870470
323 if (isset($this->results['status_box_contents'])) {
324 $this->results['status_box_contents'] = str_replace(array("\n", "\t"), '', $this->results['status_box_contents']);
325 }
326 }
327
328 /**
329 * Set `results` property with error message
330 */
331 private function set_error_response_on_wp_error() {
332 if (is_wp_error($this->results)) {
333 $this->results = array(
334 'result' => false,
335 'error_code' => $this->results->get_error_code(),
336 'error_message' => $this->results->get_error_message(),
337 'error_data' => $this->results->get_error_data(),
338 );
339 }
340 }
341
342 /**
343 * Set `results` property to null, if it is not yet set
344 */
345 private function maybe_set_results_as_null() {
346 // if nothing was returned for some reason, set as result null.
347 if (empty($this->results)) {
348 $this->results = array(
349 'result' => null
350 );
351 }
352 }
353
354 /**
355 * Sets `results` property with json encode error
356 *
357 * @param int $json_last_error
358 *
359 * @return void
360 */
361 private function set_error_response_on_json_encode_error($json_last_error) {
362 $this->results = array(
363 'result' => false,
364 'error_code' => $json_last_error,
365 'error_message' => 'json_encode error : ' . $json_last_error,
366 'error_data' => '',
367 );
368
369 $this->results = json_encode($this->results);
370 }
371
372 /**
373 * Json encode the `results` property value
374 */
375 private function json_encode_results() {
376 $this->results = json_encode($this->results);
377 }
378 }
379
380 endif;
381