PluginProbe
Image Optimizer – Compress Images and Convert to WebP or AVIF / 1.7.4
Image Optimizer – Compress Images and Convert to WebP or AVIF v1.7.4
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
image-optimization / vendor / elementor / wp-one-package / src / Admin / Services / Client.php

Client.php in Image Optimizer – Compress Images and Convert to WebP or AVIF 1.7.4, at vendor/elementor/wp-one-package/src/Admin/Services/Client.php

173 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ElementorOne\Admin\Services;
4
5 use ElementorOne\Admin\Config;
6 use ElementorOne\Admin\Exceptions\ClientException;
7 use ElementorOne\Admin\Helpers\Utils;
8 use ElementorOne\Connect\Classes\GrantTypes;
9 use ElementorOne\Logger;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly
13 }
14
15 /**
16 * Class Client
17 */
18 class Client {
19
20 const BASE_URL = 'https://my.elementor.com';
21
22 /**
23 * Logger instance
24 * @var Logger
25 */
26 private Logger $logger;
27
28 /**
29 * Instance
30 * @var Client|null
31 */
32 private static ?Client $instance = null;
33
34 /**
35 * Get instance
36 * @return Client|null
37 */
38 public static function instance(): ?Client {
39 if ( ! self::$instance ) {
40 self::$instance = new self();
41 }
42 return self::$instance;
43 }
44
45 /**
46 * Constructor
47 */
48 private function __construct() {
49 $this->logger = new Logger( self::class );
50 }
51
52 /**
53 * Refreshed flag
54 * @var bool
55 */
56 private bool $refreshed = false;
57
58 /**
59 * Check if JWT token is expired
60 * @param string $token
61 * @return bool
62 */
63 private function token_expired( string $token ): bool {
64 try {
65 $payload = Utils::decode_jwt( $token );
66
67 if ( ! isset( $payload['exp'] ) ) {
68 return false; // No expiration claim, let the regular flow handle it
69 }
70
71 // Check if token is expired (with 60 second buffer to account for clock skew)
72 return ( $payload['exp'] - MINUTE_IN_SECONDS ) < time();
73 } catch ( \Throwable $th ) {
74 $this->logger->error( 'Error checking token expiration: ' . $th->getMessage() );
75 return false; // On error, let the regular flow handle it
76 }
77 }
78
79 /**
80 * Refresh access token
81 * @param string $grant_type
82 * @return self
83 * @throws ClientException
84 */
85 private function refresh_access_token( string $grant_type ): self {
86 $this->refreshed = true;
87
88 try {
89 Utils::get_one_connect()->service()->renew_access_token( $grant_type );
90 } catch ( \Throwable $th ) {
91 throw new ClientException( $th->getMessage(), \WP_Http::UNAUTHORIZED );
92 }
93
94 return $this;
95 }
96
97 /**
98 * Request
99 * @param string $url
100 * @param array $args
101 * @param int $valid_response_code
102 * @return mixed
103 * @throws ClientException
104 */
105 public function request(
106 string $url,
107 array $args,
108 ?callable $callback = null,
109 string $grant_type = GrantTypes::REFRESH_TOKEN,
110 int $valid_response_code = \WP_Http::OK
111 ) {
112 $access_token = Utils::get_access_token( $grant_type );
113
114 // Decode and check token expiration
115 if ( ! $this->refreshed && $this->token_expired( $access_token ) ) {
116 $this->refresh_access_token( $grant_type );
117 $access_token = Utils::get_access_token( $grant_type );
118 }
119
120 $args['timeout'] = 30;
121 $args['headers'] = array_merge( $args['headers'] ?? [], [
122 'Content-Type' => 'application/json',
123 'Authorization' => "Bearer {$access_token}",
124 'x-elementor-app-type' => Config::APP_TYPE,
125 ] );
126
127 $response = wp_remote_request( $url, $args );
128
129 // If the response is an error, throw an error.
130 if ( is_wp_error( $response ) ) {
131 $this->logger->error( $response->get_error_message() );
132
133 throw new ClientException( $response->get_error_message() );
134 }
135
136 $response_body = wp_remote_retrieve_body( $response );
137 $response_code = wp_remote_retrieve_response_code( $response );
138
139 // If the response body is not valid, throw an error.
140 if ( ! empty( $response_body ) && null === json_decode( $response_body ) ) {
141 throw new ClientException( esc_html( $response_body ), $response_code );
142 }
143
144 // If the token is invalid, refresh it and try again once only.
145 if ( ! $this->refreshed && \WP_Http::UNAUTHORIZED === $response_code ) {
146 return $this->refresh_access_token( $grant_type )
147 ->request( $url, $args, $callback, $grant_type, $valid_response_code );
148 }
149
150 // If the response code is not valid, throw an error.
151 if ( $response_code !== $valid_response_code ) {
152 $this->logger->error( 'Invalid status code ' . wp_remote_retrieve_response_code( $response ) );
153
154 throw new ClientException( json_decode( $response_body )->message ?? $response_body, $response_code );
155 }
156
157 // If a callback is provided, call it.
158 if ( $callback ) {
159 return call_user_func( $callback, $response_body );
160 }
161
162 return json_decode( $response_body, true );
163 }
164
165 /**
166 * Get client base URL
167 * @return string
168 */
169 public static function get_client_base_url() {
170 return apply_filters( 'elementor_one/get_client_base_url', self::BASE_URL );
171 }
172 }
173