PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 2.5.5
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v2.5.5
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / inc / rest.php

rest.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 2.5.5, at inc/rest.php

693 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Optimole Rest related actions.
4 *
5 * @package Optimole/Inc
6 * @copyright Copyright (c) 2017, Marius Cristea
7 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8 */
9
10 /**
11 * Class Optml_Rest
12 *
13 * @codeCoverageIgnore
14 */
15 class Optml_Rest {
16 /**
17 * Rest api namespace.
18 *
19 * @var string Namespace.
20 */
21 private $namespace;
22
23 /**
24 * Optml_Rest constructor.
25 */
26 public function __construct() {
27 $this->namespace = OPTML_NAMESPACE . '/v1';
28 add_action( 'rest_api_init', array( $this, 'register' ) );
29 }
30
31 /**
32 * Register rest routes.
33 */
34 public function register() {
35
36 $this->register_service_routes();
37
38 register_rest_route(
39 $this->namespace,
40 '/update_option',
41 array(
42 array(
43 'methods' => \WP_REST_Server::CREATABLE,
44 'permission_callback' => function () {
45 return current_user_can( 'manage_options' );
46 },
47 'callback' => array( $this, 'update_option' ),
48 ),
49 )
50 );
51
52 register_rest_route(
53 $this->namespace,
54 '/request_update',
55 array(
56 array(
57 'methods' => \WP_REST_Server::READABLE,
58 'permission_callback' => function () {
59 return current_user_can( 'manage_options' );
60 },
61 'callback' => array( $this, 'request_update' ),
62 ),
63 )
64 );
65 register_rest_route(
66 $this->namespace,
67 '/check_redirects',
68 array(
69 array(
70 'methods' => \WP_REST_Server::EDITABLE,
71 'permission_callback' => function () {
72 return current_user_can( 'manage_options' );
73 },
74 'callback' => array( $this, 'check_redirects' ),
75 'args' => array(
76 'images' => array(
77 'type' => 'Array',
78 'required' => true,
79 ),
80 ),
81 ),
82 )
83 );
84
85 $this->register_image_routes();
86 $this->register_watermark_routes();
87 $this->register_conflict_routes();
88 $this->register_cache_routes();
89 }
90
91 /**
92 * Method to register service specific routes.
93 */
94 public function register_service_routes() {
95 register_rest_route(
96 $this->namespace,
97 '/connect',
98 array(
99 array(
100 'methods' => \WP_REST_Server::CREATABLE,
101 'permission_callback' => function () {
102 return current_user_can( 'manage_options' );
103 },
104 'callback' => array( $this, 'connect' ),
105 'args' => array(
106 'api_key' => array(
107 'type' => 'string',
108 'required' => true,
109 ),
110 ),
111 ),
112 )
113 );
114 register_rest_route(
115 $this->namespace,
116 '/register',
117 array(
118 array(
119 'methods' => \WP_REST_Server::CREATABLE,
120 'permission_callback' => function () {
121 return current_user_can( 'manage_options' );
122 },
123 'callback' => array( $this, 'register_service' ),
124 'args' => array(
125 'email' => array(
126 'type' => 'string',
127 'required' => true,
128 ),
129 ),
130 ),
131 )
132 );
133 register_rest_route(
134 $this->namespace,
135 '/disconnect',
136 array(
137 array(
138 'methods' => \WP_REST_Server::READABLE,
139 'permission_callback' => function () {
140 return current_user_can( 'manage_options' );
141 },
142 'callback' => array( $this, 'disconnect' ),
143 ),
144 )
145 );
146 }
147
148 /**
149 * Method to register image specific routes.
150 */
151 public function register_image_routes() {
152 register_rest_route(
153 $this->namespace,
154 '/poll_optimized_images',
155 array(
156 array(
157 'methods' => \WP_REST_Server::READABLE,
158 'permission_callback' => function () {
159 return current_user_can( 'manage_options' );
160 },
161 'callback' => array( $this, 'poll_optimized_images' ),
162 ),
163 )
164 );
165 register_rest_route(
166 $this->namespace,
167 '/images-sample-rate',
168 array(
169 array(
170 'methods' => \WP_REST_Server::CREATABLE,
171 'permission_callback' => function () {
172 return current_user_can( 'manage_options' );
173 },
174 'callback' => array( $this, 'get_sample_rate' ),
175 ),
176 )
177 );
178 }
179
180 /**
181 * Method to register watermark specific routes.
182 */
183 public function register_watermark_routes() {
184 register_rest_route(
185 $this->namespace,
186 '/poll_watermarks',
187 array(
188 array(
189 'methods' => \WP_REST_Server::READABLE,
190 'permission_callback' => function () {
191 return current_user_can( 'manage_options' );
192 },
193 'callback' => array( $this, 'poll_watermarks' ),
194 ),
195 )
196 );
197 register_rest_route(
198 $this->namespace,
199 '/add_watermark',
200 array(
201 array(
202 'methods' => \WP_REST_Server::CREATABLE,
203 'permission_callback' => function () {
204 return current_user_can( 'manage_options' );
205 },
206 'callback' => array( $this, 'add_watermark' ),
207 ),
208 )
209 );
210 register_rest_route(
211 $this->namespace,
212 '/remove_watermark',
213 array(
214 array(
215 'methods' => \WP_REST_Server::CREATABLE,
216 'permission_callback' => function () {
217 return current_user_can( 'manage_options' );
218 },
219 'callback' => array( $this, 'remove_watermark' ),
220 ),
221 )
222 );
223 }
224
225 /**
226 * Method to register conflicts specific routes.
227 */
228 public function register_conflict_routes() {
229 register_rest_route(
230 $this->namespace,
231 '/poll_conflicts',
232 array(
233 array(
234 'methods' => \WP_REST_Server::READABLE,
235 'permission_callback' => function () {
236 return current_user_can( 'manage_options' );
237 },
238 'callback' => array( $this, 'poll_conflicts' ),
239 ),
240 )
241 );
242 register_rest_route(
243 $this->namespace,
244 '/dismiss_conflict',
245 array(
246 array(
247 'methods' => \WP_REST_Server::CREATABLE,
248 'permission_callback' => function () {
249 return current_user_can( 'manage_options' );
250 },
251 'callback' => array( $this, 'dismiss_conflict' ),
252 ),
253 )
254 );
255 }
256
257 /**
258 * Method to register cache specific routes.
259 */
260 public function register_cache_routes() {
261 register_rest_route(
262 $this->namespace,
263 '/clear_cache',
264 array(
265 array(
266 'methods' => \WP_REST_Server::CREATABLE,
267 'permission_callback' => function () {
268 return current_user_can( 'manage_options' );
269 },
270 'callback' => array( $this, 'clear_cache_request' ),
271 ),
272 )
273 );
274 }
275
276 /**
277 * Clear Cache request.
278 *
279 * @param WP_REST_Request $request clear cache rest request.
280 *
281 * @return WP_Error|WP_REST_Response
282 */
283 public function clear_cache_request( WP_REST_Request $request ) {
284 $settings = new Optml_Settings();
285 $token = $settings->get( 'cache_buster' );
286 $request = new Optml_Api();
287 $data = $request->get_cache_token( $token );
288 if ( $data === false || is_wp_error( $data ) || empty( $data ) || ! isset( $data['token'] ) ) {
289 $extra = '';
290 if ( is_wp_error( $data ) ) {
291 /**
292 * Error from api.
293 *
294 * @var WP_Error $data Error object.
295 */
296 $extra = sprintf( __( '. ERROR details: %s', 'optimole-wp' ), $data->get_error_message() );
297 }
298 wp_send_json_error( __( 'Can not get new token from Optimole service', 'optimole-wp' ) . $extra );
299 }
300
301 set_transient( 'optml_cache_lock', 'yes', 5 * MINUTE_IN_SECONDS );
302 $settings->update( 'cache_buster', $data['token'] );
303
304 return $this->response( $data['token'], '200' );
305 }
306
307 /**
308 * Connect to optimole service.
309 *
310 * @param WP_REST_Request $request connect rest request.
311 *
312 * @return WP_Error|WP_REST_Response
313 */
314 public function connect( WP_REST_Request $request ) {
315 $api_key = $request->get_param( 'api_key' );
316 $request = new Optml_Api();
317 $data = $request->get_user_data( $api_key );
318 if ( $data === false || is_wp_error( $data ) ) {
319 $extra = '';
320 if ( is_wp_error( $data ) ) {
321 /**
322 * Error from api.
323 *
324 * @var WP_Error $data Error object.
325 */
326 $extra = sprintf( __( '. ERROR details: %s', 'optimole-wp' ), $data->get_error_message() );
327 }
328 wp_send_json_error( __( 'Can not connect to Optimole service', 'optimole-wp' ) . $extra );
329 }
330 $settings = new Optml_Settings();
331 $settings->update( 'service_data', $data );
332 $settings->update( 'api_key', $api_key );
333
334 return $this->response( $data );
335 }
336
337 /**
338 * Wrapper for api response.
339 *
340 * @param mixed $data data from api.
341 *
342 * @return WP_REST_Response
343 */
344 private function response( $data, $code = 'success' ) {
345 return new WP_REST_Response( array( 'data' => $data, 'code' => $code ), 200 );
346 }
347
348 /**
349 * Connect to optimole service.
350 *
351 * @param WP_REST_Request $request connect rest request.
352 *
353 * @return WP_Error|WP_REST_Response
354 */
355 public function register_service( WP_REST_Request $request ) {
356 $email = $request->get_param( 'email' );
357 $api = new Optml_Api();
358 $user = $api->create_account( $email );
359 if ( $user === false ) {
360 return new WP_REST_Response(
361 array(
362 'data' => null,
363 'message' => __( 'Error creating account.', 'optimole-wp' ),
364 'code' => 'error',
365 ),
366 200
367 );
368
369 }
370
371 return $this->response( $user );
372 }
373
374 /**
375 * Return image samples.
376 *
377 * @param WP_REST_Request $request Rest request.
378 *
379 * @return WP_REST_Response Image urls.
380 */
381 public function get_sample_rate( WP_REST_Request $request ) {
382
383 add_filter( 'optml_dont_replace_url', '__return_true' );
384 $image_sample = get_transient( 'optimole_sample_image' );
385 if ( $image_sample === false || $request->get_param( 'force' ) === 'yes' ) {
386 $image_sample = $this->fetch_sample_image();
387 set_transient( 'optimole_sample_image', $image_sample );
388 }
389 $image = array( 'id' => $image_sample['id'] );
390
391 $image['original'] = $image_sample['url'];
392
393 remove_filter( 'optml_dont_replace_url', '__return_true' );
394
395 $image['optimized'] = apply_filters(
396 'optml_replace_image',
397 $image['original'],
398 array(
399 'width' => $image_sample['width'],
400 'height' => $image_sample['height'],
401 'quality' => $request->get_param( 'quality' ),
402 )
403 );
404
405 $optimized = wp_remote_get(
406 $image['optimized'],
407 array(
408 'timeout' => 10,
409 'headers' => array(
410 'Accept' => 'text/html,application/xhtml+xml,image/webp,image/apng ',
411 ),
412 )
413 );
414
415 $original = wp_remote_get( $image['original'] );
416
417 $image['optimized_size'] = (int) wp_remote_retrieve_header( $optimized, 'content-length' );
418 $image['original_size'] = (int) wp_remote_retrieve_header( $original, 'content-length' );
419
420 return $this->response( $image );
421 }
422
423 /**
424 * Return sample image data.
425 *
426 * @return array Image data.
427 */
428 private function fetch_sample_image() {
429 $accepted_mimes = array( 'image/jpeg' );
430 $args = array(
431 'post_type' => 'attachment',
432 'post_status' => 'any',
433 'number' => '5',
434 'no_found_rows' => true,
435 'fields' => 'ids',
436 'post_mime_type' => $accepted_mimes,
437 'post_parent__not_in' => array( 0 ),
438 );
439 $image_result = new WP_Query( $args );
440 if ( empty( $image_result->posts ) ) {
441 $rand_id = rand( 1, 3 );
442 $original_image_url = OPTML_URL . 'assets/img/' . $rand_id . '.jpg';
443
444 return array(
445 'url' => $original_image_url,
446 'width' => '700',
447 'height' => '465',
448 'id' => - 1,
449 );
450 }
451 $attachment_id = $image_result->posts[ array_rand( $image_result->posts, 1 ) ];
452
453 $original_image_url = wp_get_attachment_image_url( $attachment_id, 'full' );
454
455 $metadata = wp_get_attachment_metadata( $attachment_id );
456
457 $width = 'auto';
458 $height = 'auto';
459 $size = 'full';
460 if ( isset( $metadata['sizes'] ) && isset( $metadata['sizes'][ $size ] ) ) {
461 $width = $metadata['sizes'][ $size ]['width'];
462 $height = $metadata['sizes'][ $size ]['height'];
463 }
464
465 return array(
466 'url' => $original_image_url,
467 'id' => $attachment_id,
468 'width' => $width,
469 'height' => $height,
470 );
471 }
472
473 /**
474 * Disconnect from optimole service.
475 *
476 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
477 * @param WP_REST_Request $request disconnect rest request.
478 */
479 public function disconnect( WP_REST_Request $request ) {
480 $settings = new Optml_Settings();
481 $settings->reset();
482 wp_send_json_success( 'Disconnected' );
483 }
484
485 /**
486 * Get optimized images from API.
487 *
488 * @param WP_REST_Request $request rest request.
489 *
490 * @return WP_REST_Response
491 */
492 public function poll_optimized_images( WP_REST_Request $request ) {
493 $api_key = $request->get_param( 'api_key' );
494 $request = new Optml_Api();
495 $images = $request->get_optimized_images( $api_key );
496 if ( ! isset( $images['list'] ) || empty( $images['list'] ) ) {
497 return $this->response( array() );
498 }
499
500 $final_images = array_splice( $images['list'], 0, 10 );
501
502 return $this->response( $final_images );
503 }
504
505 /**
506 * Get watermarks from API.
507 *
508 * @param WP_REST_Request $request rest request.
509 *
510 * @return WP_REST_Response
511 */
512 public function poll_watermarks( WP_REST_Request $request ) {
513 $api_key = $request->get_param( 'api_key' );
514 $request = new Optml_Api();
515 $watermarks = $request->get_watermarks( $api_key );
516 if ( ! isset( $watermarks['watermarks'] ) || empty( $watermarks['watermarks'] ) ) {
517 return $this->response( array() );
518 }
519 $final_images = array_splice( $watermarks['watermarks'], 0, 10 );
520
521 return $this->response( $final_images );
522 }
523
524 /**
525 * Add watermark.
526 *
527 * @param WP_REST_Request $request rest request.
528 *
529 * @return WP_REST_Response
530 */
531 public function add_watermark( WP_REST_Request $request ) {
532 $file = $request->get_file_params();
533 $request = new Optml_Api();
534 $response = $request->add_watermark( $file );
535 if ( $response === false ) {
536 return $this->response( __( 'Error uploading image. Please try again.', 'optimole-wp' ), 'error' );
537 }
538
539 return $this->response( __( 'Watermark image uploaded succesfully ! ', 'optimole-wp' ) );
540 }
541
542 /**
543 * Remove watermark.
544 *
545 * @param WP_REST_Request $request rest request.
546 *
547 * @return WP_REST_Response
548 */
549 public function remove_watermark( WP_REST_Request $request ) {
550 $post_id = $request->get_param( 'postID' );
551 $api_key = $request->get_param( 'api_key' );
552 $request = new Optml_Api();
553
554 return $this->response( $request->remove_watermark( $post_id, $api_key ) );
555 }
556
557 /**
558 * Get conflicts from API.
559 *
560 * @param WP_REST_Request $request rest request.
561 *
562 * @return WP_REST_Response
563 */
564 public function poll_conflicts( WP_REST_Request $request ) {
565 $conflicts_to_register = apply_filters( 'optml_register_conflicts', array() );
566 $manager = new Optml_Conflict_Manager( $conflicts_to_register );
567
568 return $this->response(
569 array(
570 'count' => $manager->get_conflict_count(),
571 'conflicts' => $manager->get_conflict_list(),
572 )
573 );
574 }
575
576 /**
577 * Dismiss conflict.
578 *
579 * @param WP_REST_Request $request rest request.
580 *
581 * @return WP_REST_Response
582 */
583 public function dismiss_conflict( WP_REST_Request $request ) {
584 $conflict_id = $request->get_param( 'conflictID' );
585 $conflicts_to_register = apply_filters( 'optml_register_conflicts', array() );
586 $manager = new Optml_Conflict_Manager( $conflicts_to_register );
587 $manager->dismiss_conflict( $conflict_id );
588
589 return $this->response(
590 array(
591 'count' => $manager->get_conflict_count(),
592 'conflicts' => $manager->get_conflict_list(),
593 )
594 );
595 }
596
597 /**
598 * Request stats update for app.
599 *
600 * @param WP_REST_Request $request rest request.
601 *
602 * @return WP_REST_Response
603 */
604 public function request_update( WP_REST_Request $request ) {
605 do_action( 'optml_daily_sync' );
606 $settings = new Optml_Settings();
607
608 return $this->response( $settings->get( 'service_data' ) );
609 }
610
611 /**
612 * Update options method.
613 *
614 * @param WP_REST_Request $request option update rest request.
615 *
616 * @return WP_REST_Response
617 */
618 public function update_option( WP_REST_Request $request ) {
619 $new_settings = $request->get_param( 'settings' );
620
621 if ( empty( $new_settings ) ) {
622 wp_send_json_error( 'No option key set.' );
623 }
624
625 $settings = new Optml_Settings();
626 $sanitized = $settings->parse_settings( $new_settings );
627
628 return $this->response( $sanitized );
629 }
630
631 /**
632 * Update options method.
633 *
634 * @param WP_REST_Request $request option update rest request.
635 *
636 * @return WP_REST_Response
637 */
638 public function check_redirects( WP_REST_Request $request ) {
639 if ( empty( $request->get_param( 'images' ) ) ) {
640 return $this->response( __( 'No images available on the current page.' ), 'noImagesFound' );
641 }
642 // 'ok' if no issues found, 'log' is there are issues we need to notify, 'deactivated' if the user's account is disabled
643 $status = 'ok';
644 $result = '';
645 foreach ( $request->get_param( 'images' ) as $domain => $value ) {
646 $args = array(
647 'method' => 'GET',
648 'redirection' => 0,
649 );
650 $processed_images = 0;
651 if ( isset( $value['src'] ) ) {
652 $processed_images = count( $value['src'] );
653 }
654 if ( isset( $value['ignoredUrls'] ) && $value['ignoredUrls'] > $processed_images ) {
655 $result .= '<li>❌ ' . sprintf( __( 'The images from: %1$s are not optimized by Optimole. If you would like to do so, you can follow this: %2$sWhy Optimole does not optimize all the images from my site?%3$s.', 'optimole-wp' ), $domain, '<a target="_blank" href="https://docs.optimole.com/article/1290-how-to-optimize-images-using-optimole-from-my-domain">', '</a>' ) . '</li>';
656 $status = 'log';
657 continue;
658 }
659
660 if ( $processed_images > 0 ) {
661 $response = wp_remote_get( $value['src'][ rand( 0, $processed_images - 1 ) ], $args );
662 if ( is_array( $response ) && ! is_wp_error( $response ) ) {
663 $headers = $response['headers']; // array of http header lines
664 $status_code = $response['response']['code'];
665 if ( $status_code === 301 ) {
666 $status = 'deactivated';
667 $result = '<li>❌ ' . sprintf( __( 'Your account is currently disabled due to exceeding quota and Optimole is no longer able to optimize the images. In order to fix this you will need to %1$supgrade%2$s.', 'optimole-wp' ), '<a target="_blank" href="https://optimole.com/pricing">', '</a>' ) . '</li>';
668 break;
669 }
670 if ( $status_code === 302 ) {
671 if ( isset( $headers['x-redirect-o'] ) ) {
672 $optimole_code = (int) $headers['x-redirect-o'];
673 if ( $optimole_code === 1 ) {
674 $status = 'log';
675 $result .= '<li>❌ ' . sprintf( __( 'The domain: %1$s is not allowed to optimize images using your Optimole account. You can add this to the allowed list %2$shere%3$s.', 'optimole-wp' ), '<b>' . $domain . '</b>', '<a target="_blank" href="https://dashboard.optimole.com/whitelist">', '</a>' ) . '</li>';
676 }
677 if ( $optimole_code === 4 ) {
678 $status = 'log';
679 $result .= '<li>❌ ' . sprintf( __( 'We are not able to download the images from %1$s. Please check %2$sthis%3$s document for a more advanced guide on how to solve this. ', 'optimole-wp' ), '<b>' . $domain . '</b>', '<a target="_blank" href="https://docs.optimole.com/article/1291-why-optimole-is-not-able-to-download-the-images-from-my-site">', '</a>' ) . '<br />' . '</li>';
680 }
681 }
682 }
683 }
684 }
685 }
686 if ( $result === '' ) {
687 $result = __( 'No issues detected, everything is running smoothly.', 'optimole-wp' );
688 }
689
690 return $this->response( '<ul>' . $result . '</ul>', $status );
691 }
692 }
693