PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 1.7
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v1.7
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / inc / classes / class-imagify.php

class-imagify.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 1.7, at inc/classes/class-imagify.php

521 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
3
4 /**
5 * Imagify.io API for WordPress.
6 */
7 class Imagify extends Imagify_Deprecated {
8
9 /**
10 * Class version.
11 *
12 * @var string
13 */
14 const VERSION = '1.1';
15 /**
16 * The Imagify API endpoint.
17 *
18 * @var string
19 */
20 const API_ENDPOINT = 'https://app.imagify.io/api/';
21
22 /**
23 * The Imagify API key.
24 *
25 * @var string
26 */
27 private $api_key = '';
28
29 /**
30 * HTTP headers. Each http call must fill it (even if it's with an empty array).
31 *
32 * @var array
33 */
34 private $headers = array();
35
36 /**
37 * All (default) HTTP headers. They must not be modified once the class is instanciated, or it will affect any following HTTP calls.
38 *
39 * @var array
40 */
41 private $all_headers = array();
42
43 /**
44 * The single instance of the class.
45 *
46 * @access protected
47 *
48 * @var object
49 */
50 protected static $_instance;
51
52 /**
53 * The constructor.
54 */
55 protected function __construct() {
56 $this->api_key = get_imagify_option( 'api_key' );
57
58 $this->all_headers['Accept'] = 'Accept: application/json';
59 $this->all_headers['Content-Type'] = 'Content-Type: application/json';
60 $this->all_headers['Authorization'] = 'Authorization: token ' . $this->api_key;
61 }
62
63 /**
64 * Get the main Instance.
65 *
66 * @access public
67 * @since 1.6.5
68 * @author Grégory Viguier
69 *
70 * @return object Main instance.
71 */
72 public static function get_instance() {
73 if ( ! isset( self::$_instance ) ) {
74 self::$_instance = new self();
75 }
76
77 return self::$_instance;
78 }
79
80 /**
81 * Get your Imagify account infos.
82 *
83 * @access public
84 * @since 1.6.5
85 *
86 * @return object
87 */
88 public function get_user() {
89 static $user;
90
91 if ( ! isset( $user ) ) {
92 $this->headers = $this->all_headers;
93
94 $user = $this->http_call( 'users/me/', array(
95 'timeout' => 10,
96 ) );
97 }
98
99 return $user;
100 }
101
102 /**
103 * Create a user on your Imagify account.
104 *
105 * @access public
106 * @since 1.6.5
107 *
108 * @param array $data All user data.
109 * @return object
110 */
111 public function create_user( $data ) {
112 $this->headers = array();
113 $data = array_merge( $data, array(
114 'from_plugin' => true,
115 'partner' => imagify_get_partner(),
116 ) );
117
118 if ( ! $data['partner'] ) {
119 unset( $data['partner'] );
120 }
121
122 $response = $this->http_call( 'users/', array(
123 'method' => 'POST',
124 'post_data' => $data,
125 ) );
126
127 if ( ! is_wp_error( $response ) ) {
128 imagify_delete_partner();
129 }
130
131 return $response;
132 }
133
134 /**
135 * Update an existing user on your Imagify account.
136 *
137 * @access public
138 * @since 1.6.5
139 *
140 * @param string $data All user data.
141 * @return object
142 */
143 public function update_user( $data ) {
144 $this->headers = $this->all_headers;
145
146 return $this->http_call( 'users/me/', array(
147 'method' => 'PUT',
148 'post_data' => $data,
149 'timeout' => 10,
150 ) );
151 }
152
153 /**
154 * Check your Imagify API key status.
155 *
156 * @access public
157 * @since 1.6.5
158 *
159 * @param string $data The license key.
160 * @return object
161 */
162 public function get_status( $data ) {
163 static $status = array();
164
165 if ( isset( $status[ $data ] ) ) {
166 return $status[ $data ];
167 }
168
169 $this->headers = array(
170 'Authorization' => 'Authorization: token ' . $data,
171 );
172
173 $uri = 'status/';
174 $partner = imagify_get_partner();
175
176 if ( $partner ) {
177 $uri .= '?partner=' . $partner;
178 }
179
180 $status[ $data ] = $this->http_call( $uri, array(
181 'timeout' => 10,
182 ) );
183
184 return $status[ $data ];
185 }
186
187 /**
188 * Get the Imagify API version.
189 *
190 * @access public
191 * @since 1.6.5
192 *
193 * @return object
194 */
195 public function get_api_version() {
196 static $api_version;
197
198 if ( ! isset( $api_version ) ) {
199 $this->headers = array(
200 'Authorization' => $this->all_headers['Authorization'],
201 );
202
203 $api_version = $this->http_call( 'version/', array(
204 'timeout' => 5,
205 ) );
206 }
207
208 return $api_version;
209 }
210
211 /**
212 * Get Public Info.
213 *
214 * @access public
215 * @since 1.6.5
216 *
217 * @return object
218 */
219 public function get_public_info() {
220 $this->headers = $this->all_headers;
221
222 return $this->http_call( 'public-info' );
223 }
224
225 /**
226 * Optimize an image from its binary content.
227 *
228 * @access public
229 * @since 1.6.5
230 * @since 1.6.7 $data['image'] can contain the file path (prefered) or the result of `curl_file_create()`.
231 *
232 * @param string $data All options.
233 * @return object
234 */
235 public function upload_image( $data ) {
236 $this->headers = array(
237 'Authorization' => $this->all_headers['Authorization'],
238 );
239
240 return $this->http_call( 'upload/', array(
241 'method' => 'POST',
242 'post_data' => $data,
243 ) );
244 }
245
246 /**
247 * Optimize an image from its URL.
248 *
249 * @access public
250 * @since 1.6.5
251 *
252 * @param string $data All options. Details here: --.
253 * @return object
254 */
255 public function fetch_image( $data ) {
256 $this->headers = $this->all_headers;
257
258 return $this->http_call( 'fetch/', array(
259 'method' => 'POST',
260 'post_data' => wp_json_encode( $data ),
261 ) );
262 }
263
264 /**
265 * Get prices for plans.
266 *
267 * @access public
268 * @since 1.6.5
269 *
270 * @return object
271 */
272 public function get_plans_prices() {
273 $this->headers = $this->all_headers;
274
275 return $this->http_call( 'pricing/plan/' );
276 }
277
278 /**
279 * Get prices for packs (One Time).
280 *
281 * @access public
282 * @since 1.6.5
283 *
284 * @return object
285 */
286 public function get_packs_prices() {
287 $this->headers = $this->all_headers;
288
289 return $this->http_call( 'pricing/pack/' );
290 }
291
292 /**
293 * Get all prices (packs & plans included).
294 *
295 * @access public
296 * @since 1.6.5
297 *
298 * @return object
299 */
300 public function get_all_prices() {
301 $this->headers = $this->all_headers;
302
303 return $this->http_call( 'pricing/all/' );
304 }
305
306 /**
307 * Get all prices (packs & plans included).
308 *
309 * @access public
310 * @since 1.6.5
311 *
312 * @param string $coupon A coupon code.
313 * @return object
314 */
315 public function check_coupon_code( $coupon ) {
316 $this->headers = $this->all_headers;
317
318 return $this->http_call( 'coupons/' . $coupon . '/' );
319 }
320
321 /**
322 * Get information about current discount.
323 *
324 * @access public
325 * @since 1.6.5
326 *
327 * @return object
328 */
329 public function check_discount() {
330 $this->headers = $this->all_headers;
331
332 return $this->http_call( 'pricing/discount/' );
333 }
334
335 /**
336 * Make an HTTP call using curl.
337 *
338 * @access private
339 * @since 1.6.5
340 * @since 1.6.7 Use `wp_remote_request()` when possible (when we don't need to send an image).
341 *
342 * @param string $url The URL to call.
343 * @param array $args The request args.
344 * @return object
345 */
346 private function http_call( $url, $args = array() ) {
347 $args = array_merge( array(
348 'method' => 'GET',
349 'post_data' => null,
350 'timeout' => 45,
351 ), $args );
352
353 $endpoint = trim( $url, '/' );
354 /**
355 * Filter the timeout value for any request to the API.
356 *
357 * @since 1.6.7
358 * @author Grégory Viguier
359 *
360 * @param int $timeout Timeout value in seconds.
361 * @param string $endpoint The targetted endpoint. It's basically URI without heading nor trailing slash.
362 */
363 $args['timeout'] = apply_filters( 'imagify_api_http_request_timeout', $args['timeout'], $endpoint );
364
365 // We need to send an image: we must use cURL directly.
366 if ( isset( $args['post_data']['image'] ) ) {
367 return $this->curl_http_call( $url, $args );
368 }
369
370 $args = array_merge( array(
371 'headers' => array(),
372 'body' => $args['post_data'],
373 'sslverify' => apply_filters( 'https_ssl_verify', false ),
374 ), $args );
375
376 unset( $args['post_data'] );
377
378 if ( $this->headers ) {
379 foreach ( $this->headers as $name => $value ) {
380 $value = explode( ':', $value, 2 );
381 $value = end( $value );
382
383 $args['headers'][ $name ] = trim( $value );
384 }
385 }
386
387 $response = wp_remote_request( self::API_ENDPOINT . $url, $args );
388
389 if ( is_wp_error( $response ) ) {
390 return $response;
391 }
392
393 $http_code = wp_remote_retrieve_response_code( $response );
394 $response = wp_remote_retrieve_body( $response );
395
396 return $this->handle_response( $response, $http_code );
397 }
398
399 /**
400 * Make an HTTP call using curl.
401 *
402 * @access private
403 * @since 1.6.7
404 * @author Grégory Viguier
405 *
406 * @param string $url The URL to call.
407 * @param array $args The request arguments.
408 * @return object
409 */
410 private function curl_http_call( $url, $args = array() ) {
411 // Check if php-curl is enabled.
412 if ( ! function_exists( 'curl_init' ) || ! function_exists( 'curl_exec' ) ) {
413 return new WP_Error( 'curl', 'cURL isn\'t installed on the server.' );
414 }
415
416 $url = self::API_ENDPOINT . $url;
417
418 try {
419 $ch = curl_init();
420
421 if ( isset( $args['post_data']['image'] ) && is_string( $args['post_data']['image'] ) && file_exists( $args['post_data']['image'] ) ) {
422 $args['post_data']['image'] = curl_file_create( $args['post_data']['image'] );
423 }
424
425 if ( 'POST' === $args['method'] ) {
426 curl_setopt( $ch, CURLOPT_POST, true );
427 curl_setopt( $ch, CURLOPT_POSTFIELDS, $args['post_data'] );
428 } elseif ( 'PUT' === $args['method'] ) {
429 curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'PUT' );
430 curl_setopt( $ch, CURLOPT_POSTFIELDS, $args['post_data'] );
431 }
432
433 curl_setopt( $ch, CURLOPT_URL, $url );
434 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
435 curl_setopt( $ch, CURLOPT_HTTPHEADER, $this->headers );
436 curl_setopt( $ch, CURLOPT_TIMEOUT, $args['timeout'] );
437 @curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
438 curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
439 curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
440
441 $response = curl_exec( $ch );
442 $error = curl_error( $ch );
443 $http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
444
445 curl_close( $ch );
446 } catch ( Exception $e ) {
447 $args['headers'] = $this->headers;
448 /**
449 * Fires after a failed curl request.
450 *
451 * @since 1.6.9
452 * @author Grégory Viguier
453 *
454 * @param string $url The requested URL.
455 * @param array $args The request arguments.
456 * @param object $e The raised Exception.
457 */
458 do_action( 'imagify_curl_http_response', $url, $args, $e );
459
460 return new WP_Error( 'curl', 'Unknown error occurred' );
461 } // End try().
462
463 $args['headers'] = $this->headers;
464
465 /**
466 * Fires after a successful curl request.
467 *
468 * @since 1.6.9
469 * @author Grégory Viguier
470 *
471 * @param string $url The requested URL.
472 * @param array $args The request arguments.
473 * @param string $response The request response.
474 * @param int $http_code The request HTTP code.
475 * @param string $error An error message.
476 */
477 do_action( 'imagify_curl_http_response', $url, $args, $response, $http_code, $error );
478
479 return $this->handle_response( $response, $http_code, $error );
480 }
481
482 /**
483 * Handle the request response and maybe trigger an error.
484 *
485 * @access private
486 * @since 1.6.7
487 * @author Grégory Viguier
488 *
489 * @param string $response The request response.
490 * @param int $http_code The request HTTP code.
491 * @param string $error An error message.
492 * @return object
493 */
494 private function handle_response( $response, $http_code, $error = '' ) {
495 $response = json_decode( $response );
496
497 if ( 200 !== $http_code && ! empty( $response->code ) ) {
498 if ( ! empty( $response->detail ) ) {
499 return new WP_Error( $http_code, $response->detail );
500 }
501 if ( ! empty( $response->image ) ) {
502 $error = (array) $response->image;
503 $error = reset( $error );
504 return new WP_Error( $http_code, $error );
505 }
506 }
507
508 if ( 413 === $http_code ) {
509 return new WP_Error( $http_code, 'Your image is too big to be uploaded on our server.' );
510 }
511
512 if ( 200 !== $http_code ) {
513 $error = trim( (string) $error );
514 $error = '' !== $error ? ' - ' . htmlentities( $error ) : '';
515 return new WP_Error( $http_code, "Unknown error occurred ({$http_code}{$error})" );
516 }
517
518 return $response;
519 }
520 }
521