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 +81 -14 1.5.31.7.7 View file →
@@ -4,9 +4,13 @@
4 4
5 5 use ImageOptimization\Classes\Exceptions\Client_Exception;
6 6 use ImageOptimization\Classes\File_Utils;
7 7 use ImageOptimization\Classes\Image\Image;
8 +use ImageOptimization\Classes\Logger;
9 +use ImageOptimization\Modules\Connect\Module as Connect_Module;
10 +use ImageOptimization\Modules\Optimization\Classes\Optimize_Image;
8 11 use ImageOptimization\Modules\Stats\Classes\Optimization_Stats;
12 +use Throwable;
9 13 use WP_Error;
10 14
11 15 use ImageOptimization\Plugin;
12 16
@@ -18,9 +22,13 @@
18 22 * Class Client
19 23 */
20 24 class Client {
21 25 const BASE_URL = 'https://my.elementor.com/api/v2/image-optimizer/';
22 - 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;
23 31
24 32 private bool $refreshed = false;
25 33
26 34 public static ?Client $instance = null;
@@ -32,13 +40,14 @@
32 40 public static function get_instance(): ?Client {
33 41 if ( ! self::$instance ) {
34 42 self::$instance = new self();
35 43 }
44 +
36 45 return self::$instance;
37 46 }
38 47
39 - public static function get_site_info(): array {
40 - return [
48 + public static function get_site_info( $endpoint = null ): array {
49 + $data = [
41 50 // Which API version is used.
42 51 'app_version' => IMAGE_OPTIMIZATION_VERSION,
43 52 // Which language to return.
44 53 'site_lang' => get_bloginfo( 'language' ),
@@ -45,13 +54,54 @@
45 54 // site to connect
46 55 'site_url' => trailingslashit( home_url() ),
47 56 // current user
48 57 'local_id' => get_current_user_id(),
58 +
59 + ];
60 +
61 + if ( Optimize_Image::IMAGE_OPTIMIZE_ENDPOINT === $endpoint ) {
49 62 // Media library stats
50 - 'media_data' => base64_encode( wp_json_encode( self::get_request_stats() ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
51 - ];
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;
52 67 }
53 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 +
54 104 private static function get_request_stats(): array {
55 105 $optimization_stats = Optimization_Stats::get_image_stats();
56 106 $image_sizes = [];
57 107
@@ -78,9 +128,9 @@
78 128 $headers,
79 129 $this->is_connected() ? $this->generate_authentication_headers( $endpoint ) : []
80 130 );
81 131
82 - $body = array_replace_recursive( $body, $this->get_site_info() );
132 + $body = array_replace_recursive( $body, $this->get_site_info( $endpoint ) );
83 133
84 134 try {
85 135 if ( $file ) {
86 136 $boundary = wp_generate_password( 24, false );
@@ -95,9 +145,9 @@
95 145 $response = $this->request(
96 146 $method,
97 147 $endpoint,
98 148 [
99 - 'timeout' => 100,
149 + 'timeout' => 50,
100 150 'headers' => $headers,
101 151 'body' => $body,
102 152 ]
103 153 );
@@ -104,10 +154,20 @@
104 154
105 155 return ( new Client_Response( $response ) )->handle();
106 156 }
107 157
158 + public static function get_feedback_base_url() {
159 + return apply_filters( 'image_optimizer_feedback_base_url', self::BASE_URL_FEEDBACK );
160 + }
161 +
108 162 private static function get_remote_url( $endpoint ): string {
109 - 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;
110 170 }
111 171
112 172 protected function is_connected(): bool {
113 173 return Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance->is_connected();
@@ -113,9 +173,8 @@
113 173 return Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance->is_connected();
114 174 }
115 175
116 176 protected function generate_authentication_headers( $endpoint ): array {
117 -
118 177 $connect_instance = Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance;
119 178
120 179 if ( ! $connect_instance->get_is_connect_on_fly() ) {
121 180 $headers = [
@@ -185,9 +244,15 @@
185 244 return $this->request( $method, $endpoint, $args );
186 245 }
187 246 }
188 247
189 - 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 ) ) {
190 255 // In case $as_array = true.
191 256 $message = $body->message ?? wp_remote_retrieve_response_message( $response );
192 257 $message = is_array( $message ) ? join( ', ', $message ) : $message;
193 258 $code = isset( $body->code ) ? (int) $body->code : $response_code;
@@ -214,11 +279,12 @@
214 279 * @param string $file_name
215 280 *
216 281 * @return string
217 282 * @throws Client_Exception
218 -*/
283 + */
219 284 private function get_upload_request_body( array $body, $file, string $boundary, string $file_name = '' ): string {
220 285 $payload = '';
286 +
221 287 // add all body fields as standard POST fields:
222 288 foreach ( $body as $name => $value ) {
223 289 $payload .= '--' . $boundary;
224 290 $payload .= "\r\n";
@@ -237,9 +303,9 @@
237 303 if (
238 304 ! in_array( $image_mime, Image::get_supported_mime_types(), true ) &&
239 305 ( 'application/octet-stream' === $image_mime && 'avif' !== File_Utils::get_extension( $file ) )
240 306 ) {
241 - throw new Client_Exception( "Unsupported mime type `$image_mime`" );
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