PluginProbe
Image Optimizer – Compress Images and Convert to WebP or AVIF / 1.7.7
Image Optimizer – Compress Images and Convert to WebP or AVIF v1.7.7
1.7.7 1.7.6 1.7.5 1.7.4 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.3.0 1.4.0 1.4.1 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 All 33 releases
← All changes | classes/client/client.php +86 -19 1.4.11.7.7 View file →
@@ -2,14 +2,15 @@
2 2
3 3 namespace ImageOptimization\Classes\Client;
4 4
5 5 use ImageOptimization\Classes\Exceptions\Client_Exception;
6 +use ImageOptimization\Classes\File_Utils;
6 7 use ImageOptimization\Classes\Image\Image;
7 -use ImageOptimization\Modules\Oauth\{
8 - Classes\Data,
9 - Components\Connect
10 -};
8 +use ImageOptimization\Classes\Logger;
9 +use ImageOptimization\Modules\Connect\Module as Connect_Module;
10 +use ImageOptimization\Modules\Optimization\Classes\Optimize_Image;
11 11 use ImageOptimization\Modules\Stats\Classes\Optimization_Stats;
12 +use Throwable;
12 13 use WP_Error;
13 14
14 15 use ImageOptimization\Plugin;
15 16
@@ -21,9 +22,13 @@
21 22 * Class Client
22 23 */
23 24 class Client {
24 25 const BASE_URL = 'https://my.elementor.com/api/v2/image-optimizer/';
25 - const STATUS_CHECK = 'status/check';
26 + const BASE_URL_FEEDBACK = 'https://feedback-api.prod.apps.elementor.red/apps/api/v1/';
27 + const SITE_INFO = 'site/info';
28 + const SITE_INFO_TRANSIENT = 'image_optimizer_site_info';
29 + const SITE_INFO_TRANSIENT_ERROR = 'image_optimizer_site_info_error';
30 + const ERROR_CACHE_DURATION = MINUTE_IN_SECONDS * 5;
26 31
27 32 private bool $refreshed = false;
28 33
29 34 public static ?Client $instance = null;
@@ -35,13 +40,14 @@
35 40 public static function get_instance(): ?Client {
36 41 if ( ! self::$instance ) {
37 42 self::$instance = new self();
38 43 }
44 +
39 45 return self::$instance;
40 46 }
41 47
42 - public static function get_site_info(): array {
43 - return [
48 + public static function get_site_info( $endpoint = null ): array {
49 + $data = [
44 50 // Which API version is used.
45 51 'app_version' => IMAGE_OPTIMIZATION_VERSION,
46 52 // Which language to return.
47 53 'site_lang' => get_bloginfo( 'language' ),
@@ -48,13 +54,54 @@
48 54 // site to connect
49 55 'site_url' => trailingslashit( home_url() ),
50 56 // current user
51 57 'local_id' => get_current_user_id(),
58 +
59 + ];
60 +
61 + if ( Optimize_Image::IMAGE_OPTIMIZE_ENDPOINT === $endpoint ) {
52 62 // Media library stats
53 - 'media_data' => base64_encode( wp_json_encode( self::get_request_stats() ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
54 - ];
63 + $data['media_data'] = base64_encode( wp_json_encode( self::get_request_stats() ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
64 + }
65 +
66 + return $data;
55 67 }
56 68
69 + /**
70 + * Get site info
71 + * @return mixed|WP_Error|null
72 + */
73 + public static function get_subscription_info() {
74 + $cached_info = get_transient( self::SITE_INFO_TRANSIENT );
75 +
76 + if ( $cached_info ) {
77 + return $cached_info;
78 + }
79 +
80 + $cached_error = get_transient( self::SITE_INFO_TRANSIENT_ERROR );
81 +
82 + if ( $cached_error ) {
83 + Logger::debug( 'Status check skipped due to recent error: ' . $cached_error );
84 + return null;
85 + }
86 +
87 + try {
88 + $info = self::get_instance()->make_request( 'POST', self::SITE_INFO );
89 + } catch ( Throwable $t ) {
90 + $error_message = $t->getMessage();
91 +
92 + Logger::error( 'Cannot get site info response from service: ' . $error_message );
93 +
94 + set_transient( self::SITE_INFO_TRANSIENT_ERROR, $error_message, self::ERROR_CACHE_DURATION );
95 +
96 + return null;
97 + }
98 +
99 + set_transient( self::SITE_INFO_TRANSIENT, $info, DAY_IN_SECONDS );
100 +
101 + return $info;
102 + }
103 +
57 104 private static function get_request_stats(): array {
58 105 $optimization_stats = Optimization_Stats::get_image_stats();
59 106 $image_sizes = [];
60 107
@@ -81,9 +128,9 @@
81 128 $headers,
82 129 $this->is_connected() ? $this->generate_authentication_headers( $endpoint ) : []
83 130 );
84 131
85 - $body = array_replace_recursive( $body, $this->get_site_info() );
132 + $body = array_replace_recursive( $body, $this->get_site_info( $endpoint ) );
86 133
87 134 try {
88 135 if ( $file ) {
89 136 $boundary = wp_generate_password( 24, false );
@@ -98,9 +145,9 @@
98 145 $response = $this->request(
99 146 $method,
100 147 $endpoint,
101 148 [
102 - 'timeout' => 100,
149 + 'timeout' => 50,
103 150 'headers' => $headers,
104 151 'body' => $body,
105 152 ]
106 153 );
@@ -107,10 +154,20 @@
107 154
108 155 return ( new Client_Response( $response ) )->handle();
109 156 }
110 157
158 + public static function get_feedback_base_url() {
159 + return apply_filters( 'image_optimizer_feedback_base_url', self::BASE_URL_FEEDBACK );
160 + }
161 +
111 162 private static function get_remote_url( $endpoint ): string {
112 - return self::BASE_URL . $endpoint;
163 + $base_url = apply_filters( 'image_optimizer_client_get_base_url', self::BASE_URL );
164 +
165 + if ( strpos( $endpoint, 'feedback/' ) !== false ) {
166 + return self::get_feedback_base_url() . $endpoint;
167 + }
168 +
169 + return $base_url . $endpoint;
113 170 }
114 171
115 172 protected function is_connected(): bool {
116 173 return Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance->is_connected();
@@ -116,9 +173,8 @@
116 173 return Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance->is_connected();
117 174 }
118 175
119 176 protected function generate_authentication_headers( $endpoint ): array {
120 -
121 177 $connect_instance = Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance;
122 178
123 179 if ( ! $connect_instance->get_is_connect_on_fly() ) {
124 180 $headers = [
@@ -188,9 +244,15 @@
188 244 return $this->request( $method, $endpoint, $args );
189 245 }
190 246 }
191 247
192 - if ( 200 !== $response_code ) {
248 + // If there is mismatch then trigger the mismatch flow explicitly.
249 + if ( ! $this->refreshed && ! empty( $body->message ) && ( false !== strpos( $body->message, 'site url mismatch' ) ) ) {
250 + Connect_Module::get_connect()->data()->set_home_url( 'https://wrongurl' );
251 + return new WP_Error( 401, 'site url mismatch' );
252 + }
253 +
254 + if ( ! in_array( $response_code, [ 200, 201 ], true ) ) {
193 255 // In case $as_array = true.
194 256 $message = $body->message ?? wp_remote_retrieve_response_message( $response );
195 257 $message = is_array( $message ) ? join( ', ', $message ) : $message;
196 258 $code = isset( $body->code ) ? (int) $body->code : $response_code;
@@ -217,11 +279,12 @@
217 279 * @param string $file_name
218 280 *
219 281 * @return string
220 282 * @throws Client_Exception
221 -*/
283 + */
222 284 private function get_upload_request_body( array $body, $file, string $boundary, string $file_name = '' ): string {
223 285 $payload = '';
286 +
224 287 // add all body fields as standard POST fields:
225 288 foreach ( $body as $name => $value ) {
226 289 $payload .= '--' . $boundary;
227 290 $payload .= "\r\n";
@@ -236,10 +299,13 @@
236 299 }
237 300 } else {
238 301 $image_mime = image_type_to_mime_type( exif_imagetype( $file ) );
239 302
240 - if ( ! in_array( $image_mime, Image::get_supported_mime_types(), true ) ) {
241 - throw new Client_Exception( "Unsupported mime type `$image_mime`" );
303 + if (
304 + ! in_array( $image_mime, Image::get_supported_mime_types(), true ) &&
305 + ( 'application/octet-stream' === $image_mime && 'avif' !== File_Utils::get_extension( $file ) )
306 + ) {
307 + throw new Client_Exception( esc_html( "Unsupported mime type `$image_mime`" ) );
242 308 }
243 309
244 310 if ( empty( $file_name ) ) {
245 311 $file_name = basename( $file );
@@ -262,15 +328,16 @@
262 328 * @return string
263 329 */
264 330 private function get_file_payload( string $filename, string $file_type, string $file_path, string $boundary ): string {
265 331 $name = $filename ?? basename( $file_path );
266 - $mine_type = 'image' === $file_type ? image_type_to_mime_type( exif_imagetype( $file_path ) ) : $file_type;
332 + $mime_type = 'image' === $file_type ? image_type_to_mime_type( exif_imagetype( $file_path ) ) : $file_type;
267 333 $payload = '';
334 +
268 335 // Upload the file
269 336 $payload .= '--' . $boundary;
270 337 $payload .= "\r\n";
271 338 $payload .= 'Content-Disposition: form-data; name="' . esc_attr( $name ) . '"; filename="' . esc_attr( $name ) . '"' . "\r\n";
272 - $payload .= 'Content-Type: ' . $mine_type . "\r\n";
339 + $payload .= 'Content-Type: ' . $mime_type . "\r\n";
273 340 $payload .= "\r\n";
274 341 $payload .= file_get_contents( $file_path );
275 342 $payload .= "\r\n";
276 343