PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 4.2.13
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v4.2.13
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
← All changes | inc/api.php +280 -74 2.5.64.2.13 View file →
@@ -15,14 +15,25 @@
15 15 * @var string Api root.
16 16 */
17 17 private $api_root = 'https://dashboard.optimole.com/api/';
18 18 /**
19 + * Optimole onboard api root url.
20 + *
21 + * @var string Api root.
22 + */
23 + private $onboard_api_root = 'https://onboard.i.optimole.com/onboard_api/';
24 + /**
25 + * Optimole offload conflicts api root url.
26 + *
27 + * @var string Api root.
28 + */
29 + private $upload_conflicts_api = 'https://conflicts.i.optimole.com/offload_api/';
30 + /**
19 31 * Hold the user api key.
20 32 *
21 33 * @var string Api key.
22 34 */
23 35 private $api_key;
24 -
25 36 /**
26 37 * Optml_Api constructor.
27 38 */
28 39 public function __construct() {
@@ -27,79 +38,147 @@
27 38 */
28 39 public function __construct() {
29 40 $settings = new Optml_Settings();
30 41 $this->api_key = $settings->get( 'api_key' );
42 + if ( defined( 'OPTIML_API_ROOT' ) ) {
43 + $this->api_root = constant( 'OPTIML_API_ROOT' );
44 + }
45 + if ( defined( 'OPTIML_ONBOARD_API_ROOT' ) ) {
46 + $this->onboard_api_root = constant( 'OPTIML_ONBOARD_API_ROOT' );
47 + }
48 + if ( defined( 'OPTIML_UPLOAD_CONFLICTS_API_ROOT' ) ) {
49 + $this->upload_conflicts_api = constant( 'OPTIML_UPLOAD_CONFLICTS_API_ROOT' );
50 + }
31 51 }
32 52
33 53 /**
54 + * Connect to the service.
55 + *
56 + * @param string $api_key Api key.
57 + *
58 + * @return array|bool|WP_Error
59 + */
60 + public function connect( $api_key = '' ) {
61 + if ( ! empty( $api_key ) ) {
62 + $this->api_key = $api_key;
63 + }
64 +
65 + return $this->request( '/optml/v2/account/connect', 'POST', [ 'sample_image' => $this->get_sample_image() ] );
66 + }
67 +
68 + /**
69 + * Get sample image.
70 + *
71 + * @return string
72 + */
73 + private function get_sample_image() {
74 + $accepted_mimes = [ 'image/jpeg', 'image/png', 'image/webp' ];
75 + $args = [
76 + 'post_type' => 'attachment',
77 + 'post_status' => 'any',
78 + 'number' => '1',
79 + 'no_found_rows' => true,
80 + 'fields' => 'ids',
81 + 'post_mime_type' => $accepted_mimes,
82 + 'post_parent__not_in' => [ 0 ],
83 + ];
84 + $image_result = new WP_Query( $args );
85 + $original_image_url = 'none';
86 + if ( ! empty( $image_result->posts ) ) {
87 + $original_image_url = wp_get_attachment_image_url( $image_result->posts[0], 'full' );
88 + }
89 +
90 + return $original_image_url;
91 + }
92 + /**
34 93 * Get user data from service.
35 94 *
36 - * @return array|bool User data.
95 + * @return array|string|bool|WP_Error User data.
37 96 */
38 - public function get_user_data( $api_key = '' ) {
97 + public function get_user_data( $api_key = '', $application = '' ) {
39 98 if ( ! empty( $api_key ) ) {
40 99 $this->api_key = $api_key;
41 100 }
42 101
43 - return $this->request( '/optml/v1/image/details', 'POST' );
102 + return $this->request( '/optml/v2/account/details', 'POST', [ 'application' => $application ] );
44 103 }
45 104
46 105 /**
106 + * Toggle the extra visits.
107 + *
108 + * @param string $api_key Api key.
109 + * @param string $status Status of the visits toggle.
110 + *
111 + * @return array|bool|string
112 + */
113 + public function update_extra_visits( $api_key = '', $status = 'enabled', $application = '' ) {
114 + if ( ! empty( $api_key ) ) {
115 + $this->api_key = $api_key;
116 + }
117 +
118 + return $this->request( '/optml/v2/account/extra_visits', 'POST', [ 'extra_visits' => $status, 'application' => $application ] );
119 + }
120 +
121 + /**
47 122 * Get cache token from service.
48 123 *
49 - * @return array|bool User data.
124 + * @return array|bool|WP_Error User data.
50 125 */
51 - public function get_cache_token( $token = '', $api_key = '' ) {
126 + public function get_cache_token( $token = '', $type = '', $api_key = '' ) {
52 127 if ( ! empty( $api_key ) ) {
53 128 $this->api_key = $api_key;
54 129 }
55 - $lock = get_transient( 'optml_cache_lock' );
130 + $lock = '';
131 + if ( empty( $type ) || $type === 'images' ) {
132 + $lock = get_transient( 'optml_cache_lock' );
133 + } elseif ( $type === 'assets' ) {
134 + $lock = get_transient( 'optml_cache_lock_assets' );
135 + } else {
136 + $type = 'images';
137 + }
138 +
56 139 if ( $lock === 'yes' ) {
57 140 return new WP_Error( 'cache_throttle', __( 'You can clear cache only once per 5 minutes.', 'optimole-wp' ) );
58 141 }
59 - return $this->request( '/optml/v1/cache/tokens', 'POST', array( 'token' => $token ) );
142 + return $this->request( '/optml/v1/cache/tokens', 'POST', [ 'token' => $token, 'type' => $type ] );
60 143 }
61 144
62 145 /**
63 146 * Request constructor.
64 147 *
65 - * @param string $path The request url.
66 - * @param string $method The request method type.
67 - * @param array $params The request method type.
148 + * @param string $path The request url.
149 + * @param string $method The request method type.
150 + * @param array|string $params The request method type.
68 151 *
69 - * @return array|boolean Api data.
152 + * @return array|string|boolean|WP_Error Api data.
70 153 */
71 - private function request( $path, $method = 'GET', $params = array(), $extra_headers = [] ) {
154 + public function request( $path, $method = 'GET', $params = [], $extra_headers = [] ) {
72 155
73 - // Grab the url to which we'll be making the request.
74 - $url = $this->api_root;
75 - $headers = array(
156 + $headers = [
76 157 'Optml-Site' => get_home_url(),
77 - );
158 + ];
159 + update_option( 'optimole_wp_logger_flag', 'yes' );
78 160 if ( ! empty( $this->api_key ) ) {
79 161 $headers['Authorization'] = 'Bearer ' . $this->api_key;
80 162 }
81 - if ( ! empty( $headers ) && is_array( $headers ) ) {
82 - $headers = array_merge( $headers, $extra_headers );
83 - }
84 -
163 + $headers = array_merge( $headers, $extra_headers );
164 + $url = trailingslashit( $this->api_root ) . ltrim( $path, '/' );
85 165 // If there is a extra, add that as a url var.
86 166 if ( 'GET' === $method && ! empty( $params ) ) {
87 167 foreach ( $params as $key => $val ) {
88 - $url = add_query_arg( array( $key => $val ), $url );
168 + $url = add_query_arg( [ $key => $val ], $url );
89 169 }
90 170 }
91 - $url = trailingslashit( $this->api_root ) . ltrim( $path, '/' );
171 + $url = tsdk_translate_link( $url, 'query' );
172 +
92 173 $args = $this->build_args( $method, $url, $headers, $params );
93 174
94 175 $response = wp_remote_request( $url, $args );
95 -
96 176 if ( is_wp_error( $response ) ) {
97 177 return $response;
98 178 }
99 179
100 180 $response = wp_remote_retrieve_body( $response );
101 -
102 181 if ( empty( $response ) ) {
103 182 return false;
104 183 }
105 184 $response = json_decode( $response, true );
@@ -109,34 +188,68 @@
109 188 }
110 189 if ( ! isset( $response['code'] ) ) {
111 190 return false;
112 191 }
192 +
113 193 if ( intval( $response['code'] ) !== 200 ) {
114 - return false;
194 + if ( isset( $response['error'] ) && $response['error'] === 'domain_not_accessible' ) {
195 + return new WP_Error( 'domain_not_accessible', sprintf( /* translators: 1 start of the italic tag, 2 is the end of italic tag, 3 is starting anchor tag, 4 is the ending anchor tag. */ __( 'It seems Optimole is having trouble reaching your website. This issue often occurs if your website is private, local, or protected by a firewall. But don\'t stress – it\'s an easy fix! Ensure your website is live and accessible to the public. If a firewall is in place, just tweak the settings to allow the %1$sOptimole(1.0)%2$s user agent access to your website. %3$sLearn More%4$s', 'optimole-wp' ), '<i>', '</i>', '<a href="https://docs.optimole.com/article/1976-resolving-optimole-access-to-your-website" target="_blank">', '</a>' ) );
196 + }
197 + if ( $path === 'optml/v2/account/complete_register_remote' && isset( $response['error'] ) ) {
198 + if ( strpos( $response['error'], 'This email address is already registered.' ) !== false ) {
199 + return 'email_registered';
200 + }
201 +
202 + if ( $response['error'] === 'ERROR: Site already whitelisted.' ) {
203 + return 'site_exists';
204 + }
205 + }
206 +
207 + if ( $path === '/optml/v2/account/details'
208 + && isset( $response['code'] ) && $response['code'] === 'not_allowed' ) {
209 + return 'disconnect';
210 + }
211 +
212 + if ( $path === '/optml/v2/account/details'
213 + && isset( $response['error'] ) && $response['error'] === 'whitelist_limit_reached' ) {
214 + return 'disconnect';
215 + }
216 +
217 + return isset( $response['error'] ) ? new WP_Error(
218 + 'api_error',
219 + wp_kses(
220 + $response['error'],
221 + [
222 + 'a' => [
223 + 'href' => [],
224 + 'target' => [],
225 + ],
226 + ]
227 + )
228 + ) : false;
115 229 }
116 230
117 231 return $response['data'];
118 -
119 232 }
120 233
121 234 /**
122 235 * Builds Request arguments array.
123 236 *
124 - * @param string $method Request method (GET | POST | PUT | UPDATE | DELETE).
125 - * @param string $url Request URL.
126 - * @param array $headers Headers Array.
127 - * @param array $params Additional params for the Request.
237 + * @param string $method Request method (GET | POST | PUT | UPDATE | DELETE).
238 + * @param string $url Request URL.
239 + * @param array $headers Headers Array.
240 + * @param array|string $params Additional params for the Request.
128 241 *
129 242 * @return array
130 243 */
131 244 private function build_args( $method, $url, $headers, $params ) {
132 - $args = array(
245 + $args = [
133 246 'method' => $method,
134 247 'timeout' => 45,
135 248 'user-agent' => 'Optimle WP (v' . OPTML_VERSION . ') ',
136 249 'sslverify' => false,
137 250 'headers' => $headers,
138 - );
251 + ];
139 252 if ( $method !== 'GET' ) {
140 253 $args['body'] = $params;
141 254 }
142 255
@@ -143,23 +256,82 @@
143 256 return $args;
144 257 }
145 258
146 259 /**
260 + * Check if the optimized url is available.
261 + *
262 + * @param string $url The optimized url to check.
263 + * @return bool Whether or not the url is valid.
264 + */
265 + public function check_optimized_url( $url ) {
266 + $response = wp_remote_get( $url, [ 'timeout' => 30 ] );
267 +
268 + if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 || ! empty( wp_remote_retrieve_header( $response, 'x-not-found-o' ) ) ) {
269 + $this->log_offload_error( $response );
270 + return false;
271 + }
272 + return true;
273 + }
274 +
275 + /**
276 + * Send a list of images to upload.
277 + *
278 + * @param array $images List of Images.
279 + * @return array
280 + */
281 + public function call_onboard_api( $images = [] ) {
282 + $settings = new Optml_Settings();
283 + $token_images = $settings->get( 'cache_buster_images' );
284 +
285 + $body = [
286 + 'secret' => Optml_Config::$secret,
287 + 'userKey' => Optml_Config::$key,
288 + 'images' => $images,
289 + 'cache_buster' => $token_images,
290 + ];
291 + $body = wp_json_encode( $body );
292 +
293 + $options = [
294 + 'body' => $body,
295 + 'headers' => [
296 + 'Content-Type' => 'application/json',
297 + ],
298 + 'timeout' => 60,
299 + 'blocking' => true,
300 + 'sslverify' => false,
301 + 'data_format' => 'body',
302 + ];
303 + return wp_remote_post( $this->onboard_api_root, $options );
304 + }
305 +
306 +
307 + /**
308 + * Send a list of images with alt/title values to update.
309 + *
310 + * @param array $images List of images.
311 + * @return array
312 + */
313 + public function call_data_enrich_api( $images = [] ) {
314 + return $this->request( 'optml/v2/media/add_data', 'POST', [ 'images' => $images, 'key' => Optml_Config::$key ] );
315 + }
316 + /**
147 317 * Register user remotely on optimole.com.
148 318 *
149 319 * @param string $email User email.
150 320 *
151 - * @return array|bool Api response.
321 + * @return array|bool|string|WP_Error Api response.
152 322 */
153 323 public function create_account( $email ) {
154 324 return $this->request(
155 - 'optml/v1/user/register-remote',
325 + 'optml/v2/account/complete_register_remote',
156 326 'POST',
157 - array(
327 + [
158 328 'email' => $email,
159 329 'version' => OPTML_VERSION,
330 + 'sample_image' => $this->get_sample_image(),
160 331 'site' => get_home_url(),
161 - )
332 + 'reference' => get_option( 'optimole_reference_key', '' ),
333 + ]
162 334 );
163 335 }
164 336
165 337 /**
@@ -166,69 +338,103 @@
166 338 * Get the optimized images from API.
167 339 *
168 340 * @param string $api_key the api key.
169 341 *
170 - * @return array|bool
342 + * @return array|bool|WP_Error
171 343 */
172 344 public function get_optimized_images( $api_key = '' ) {
173 345 if ( ! empty( $api_key ) ) {
174 346 $this->api_key = $api_key;
175 347 }
176 -
177 - return $this->request( '/optml/v1/stats/images' );
348 + $app_key = '';
349 + $settings = new Optml_Settings();
350 + $service_data = $settings->get( 'service_data' );
351 + if ( isset( $service_data['cdn_key'] ) ) {
352 + $app_key = $service_data['cdn_key'];
353 + }
354 + return $this->request( '/optml/v1/stats/images', 'GET', [], [ 'application' => $app_key ] );
178 355 }
179 356
180 357 /**
181 - * Get the watermarks from API.
358 + * Call the images endpoint.
182 359 *
183 - * @param string $api_key The API key.
184 - *
185 - * @return array|bool
360 + * @param integer $page Page used to advance the search.
361 + * @param array $domains Domains to filter by.
362 + * @param string $search The string to search inside the originURL.
363 + * @return mixed The decoded json response from the api.
186 364 */
187 - public function get_watermarks( $api_key = '' ) {
188 - if ( ! empty( $api_key ) ) {
189 - $this->api_key = $api_key;
365 + public function get_cloud_images( $page = 0, $domains = [], $search = '' ) {
366 +
367 + $params = [ 'key' => Optml_Config::$key ];
368 + $params['page'] = $page;
369 + $params['size'] = 40;
370 + if ( $search !== '' ) {
371 + $params['search'] = $search;
190 372 }
191 373
192 - return $this->request( '/optml/v1/settings/watermark' );
374 + if ( ! empty( $domains ) ) {
375 + $params['domains'] = implode( ',', $domains );
376 + }
377 + return $this->request( 'optml/v2/media/browser', 'GET', $params );
193 378 }
194 -
195 379 /**
196 - * Remove the watermark from the API.
380 + * Get offload conflicts.
197 381 *
198 - * @param integer $post_id The watermark post ID.
199 - * @param string $api_key The API key.
382 + * @return array The decoded conflicts list.
383 + */
384 + public function get_offload_conflicts() {
385 + $conflicts_list = wp_remote_retrieve_body( wp_remote_get( $this->upload_conflicts_api ) );
386 + return json_decode( $conflicts_list, true );
387 + }
388 + /**
389 + * Get offload conflicts.
200 390 *
201 - * @return array|bool
391 + * @param array $error_response The error to send as a string.
202 392 */
203 - public function remove_watermark( $post_id, $api_key = '' ) {
204 - if ( ! empty( $api_key ) ) {
205 - $this->api_key = $api_key;
393 + public function log_offload_error( $error_response ) {
394 +
395 + $headers = wp_remote_retrieve_headers( $error_response );
396 + $body = wp_remote_retrieve_body( $error_response );
397 +
398 + $headers_to_log = 'no_headers_returned';
399 + if ( ! empty( $headers ) ) {
400 + $headers_to_log = wp_json_encode( $headers->getAll() );
206 401 }
207 -
208 - return $this->request( '/optml/v1/settings/watermark', 'DELETE', array( 'watermark' => $post_id ) );
402 + wp_remote_post(
403 + $this->upload_conflicts_api,
404 + [
405 + 'headers' => [ 'Content-Type' => 'application/json' ],
406 + 'timeout' => 15,
407 + 'blocking' => true,
408 + 'sslverify' => false,
409 + 'data_format' => 'body',
410 + 'body' => [
411 + 'error_body' => wp_json_encode( $body ),
412 + 'error_headers' => $headers_to_log,
413 + 'error_site' => wp_json_encode( get_home_url() ),
414 + ],
415 + ]
416 + );
209 417 }
210 418
211 419 /**
212 - * Add watermark.
420 + * Send Offloading Logs
213 421 *
214 - * @param array $file The file to be uploaded.
422 + * @param string $type Type of log (offload/rollback).
423 + * @param string $message Log message.
215 424 *
216 - * @return array|bool|mixed|object
425 + * @return mixed
217 426 */
218 - public function add_watermark( $file ) {
219 -
220 - $headers = [
221 - 'Content-Disposition' => 'attachment; filename=' . $file['file']['name'],
222 - ];
223 -
224 - $response = $this->request( 'wp/v2/media', 'POST', file_get_contents( $file['file']['tmp_name'] ), $headers );
225 -
226 - if ( $response === false ) {
227 - return false;
228 - }
229 -
230 - return $response;
427 + public function send_log( $type, $message ) {
428 + return $this->request(
429 + 'optml/v2/logs',
430 + 'POST',
431 + [
432 + 'type' => $type,
433 + 'message' => $message,
434 + 'site' => get_home_url(),
435 + ]
436 + );
231 437 }
232 438
233 439 /**
234 440 * Throw error on object clone