PluginProbe
Image Optimizer – Compress Images and Convert to WebP or AVIF / 1.1.0
Image Optimizer – Compress Images and Convert to WebP or AVIF v1.1.0
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 / modules / oauth / components / connect.php

connect.php in Image Optimizer – Compress Images and Convert to WebP or AVIF 1.1.0, at modules/oauth/components/connect.php

341 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ImageOptimization\Modules\Oauth\Components;
4
5 use ImageOptimization\Modules\Oauth\{
6 Classes\Route_Base,
7 Components\Exceptions\Auth_Error,
8 Classes\Data,
9 };
10 use ImageOptimization\Classes\Logger;
11 use ImageOptimization\Classes\Utils;
12 use ImageOptimization\Modules\Settings\Module as Settings_Module;
13
14 use Throwable;
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit if accessed directly.
18 }
19
20 /**
21 * Class Connect
22 */
23 class Connect {
24 const API_URL = 'https://my.elementor.com/api/connect/v1';
25
26 /**
27 * is_connected
28 * @return bool
29 */
30 public static function is_connected(): bool {
31 return ! empty( Data::get_connect_data()['access_token'] );
32 }
33
34 /**
35 * is_activated
36 * @return bool
37 */
38 public static function is_activated(): bool {
39 return ! empty( Data::get_activation_state() );
40 }
41
42 /**
43 * maybe_handle_admin_connect_page
44 * @return bool
45 */
46 public static function maybe_handle_admin_connect_page(): bool {
47 if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), 'nonce_actionget_token' ) ) {
48 return false;
49 }
50
51 $args = [
52 'page' => 'elementor-connect',
53 'app' => 'library',
54 'action' => 'get_token',
55 'state' => Data::get_connect_state(),
56 ];
57
58 foreach ( $args as $key => $value ) {
59 if ( ! isset( $_GET[ $key ] ) || $_GET[ $key ] !== $value ) {
60 return false;
61 }
62 }
63
64 if ( ! isset( $_GET['nonce'] ) || ! isset( $_GET['code'] ) ) {
65 return false;
66 }
67
68 return true;
69 }
70
71 /**
72 * handle_elementor_connect_admin
73 */
74 public function handle_elementor_connect_admin(): void {
75 // validate args
76 if ( ! self::maybe_handle_admin_connect_page() ) {
77 return;
78 }
79
80 // validate nonce
81 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), 'nonce_actionget_token' ) ) {
82 wp_die( 'Nonce verification failed', 'image-optimization' );
83 }
84
85 $token_response = wp_remote_request( self::API_URL . '/get_token', [
86 'method' => 'POST',
87 'body' => [
88 'app' => 'library',
89 'grant_type' => 'authorization_code',
90 'client_id' => Data::get_client_id(),
91 'code' => sanitize_text_field( $_GET['code'] ),
92 ],
93 ] );
94
95 if ( is_wp_error( $token_response ) ) {
96 wp_die( $token_response->get_error_message(), 'image-optimization' );
97 }
98
99 $data = json_decode( wp_remote_retrieve_body( $token_response ), true );
100 Data::set_connect_data( $data );
101
102 do_action( Checkpoint::ON_CONNECT );
103
104 // cleanup
105 Data::delete_connect_state();
106
107 wp_redirect( add_query_arg( [
108 'page' => Settings_Module::SETTING_BASE_SLUG,
109 'connected' => 'true',
110 ], admin_url( 'admin.php' ) ) );
111 die();
112 }
113
114 /**
115 * Gets required connection data from the service and generates a connect link.
116 *
117 * @return string User connect link
118 *
119 * @throws Auth_Error
120 */
121 public static function initialize_connect(): string {
122 try {
123 $response = wp_remote_request(
124 self::API_URL . '/library/get_client_id',
125 [
126 'method' => 'POST',
127 'body' => [
128 'local_id' => get_current_user_id(),
129 'site_key' => Data::get_site_key(),
130 'app' => 'library',
131 'home_url' => trailingslashit( home_url() ),
132 'source' => 'image-optimizer',
133 ],
134 ]
135 );
136 } catch ( Throwable $t ) {
137 Logger::log(
138 Logger::LEVEL_ERROR,
139 'Error while sending connection initialization request: ' . $t->getMessage()
140 );
141
142 throw new Auth_Error( $t->getMessage() );
143 }
144
145 $data = json_decode( wp_remote_retrieve_body( $response ) );
146
147 if ( ! isset( $data->client_id ) || ! isset( $data->auth_secret ) ) {
148 Logger::log(
149 Logger::LEVEL_ERROR,
150 'Invalid response from server: client id or auth secret are undefined'
151 );
152
153 throw new Auth_Error( esc_html__( 'Invalid response from server', 'image-optimization' ) );
154 }
155
156 Data::set_client_data( $data->client_id, $data->auth_secret );
157
158 return add_query_arg( [
159 'utm_source' => 'image-optimizer-panel',
160 'utm_campaign' => 'image-optimizer',
161 'utm_medium' => 'wp-dash',
162 'source' => 'generic',
163 'action' => 'authorize',
164 'response_type' => 'code',
165 'client_id' => $data->client_id,
166 'auth_secret' => $data->auth_secret,
167 'state' => Data::get_connect_state( true ),
168 'redirect_uri' => rawurlencode( add_query_arg( [
169 'page' => 'elementor-connect',
170 'app' => 'library',
171 'action' => 'get_token',
172 'nonce' => wp_create_nonce( 'nonce_action' . 'get_token' ),
173 ], admin_url( 'admin.php' ) ) ),
174 'may_share_data' => 0,
175 'reconnect_nonce' => wp_create_nonce( 'nonce_action' . 'reconnect' ),
176 ], Route_Base::SITE_URL . 'library' );
177 }
178
179 /**
180 * Disconnects a user and removes connection data from the DB.
181 */
182 public static function disconnect() {
183 Data::reset();
184
185 do_action( Checkpoint::ON_DISCONNECT );
186
187 try {
188 return wp_remote_request( self::API_URL . '/disconnect', [
189 'method' => 'POST',
190 'body' => [
191 'app' => 'library',
192 'home_url' => trailingslashit( home_url() ),
193 'client_id' => Data::get_client_id(),
194 'access_token' => Data::get_access_token(),
195 ],
196 ] );
197 } catch ( Throwable $t ) {
198 Logger::log( Logger::LEVEL_ERROR, 'Error while sending disconnection request: ' . $t->getMessage() );
199
200 throw new Auth_Error( $t->getMessage() );
201 }
202 }
203
204 /**
205 * Sends an activation request and stores activation data in the DB.
206 *
207 * @param $license_key string License key to activate with.
208 * @return mixed
209 *
210 * @throws Auth_Error
211 */
212 public static function activate( string $license_key ) {
213 try {
214 $response = Utils::get_api_client()->make_request(
215 'POST',
216 'activation/activate',
217 [],
218 [ 'key' => $license_key ]
219 );
220 } catch ( Throwable $t ) {
221 Logger::log( Logger::LEVEL_ERROR, 'Error while sending activation request: ' . $t->getMessage() );
222
223 throw new Auth_Error( $t->getMessage() );
224 }
225
226 if ( ! isset( $response->id ) ) {
227 Logger::log( Logger::LEVEL_ERROR, 'Invalid response from server' );
228
229 throw new Auth_Error( esc_html__( 'Invalid response from server', 'image-optimization' ) );
230 }
231
232 Data::set_activation_state( $license_key );
233
234 do_action( Checkpoint::ON_ACTIVATE, $license_key );
235
236 return $response;
237 }
238
239 /**
240 * Deactivate specific license and remove activation data from the DB.
241 *
242 * @param $license_key string License key to deactivate.
243 *
244 * @return mixed
245 *
246 * @throws Auth_Error
247 */
248 public static function deactivate( string $license_key ) {
249 Data::delete_activation_state();
250
251 do_action( Checkpoint::ON_DEACTIVATE, $license_key );
252
253 try {
254 $response = Utils::get_api_client()->make_request(
255 'POST',
256 'activation/deactivate',
257 [
258 'key' => $license_key,
259 ]
260 );
261 } catch ( Throwable $t ) {
262 Logger::log( Logger::LEVEL_ERROR, 'Error while sending deactivation request: ' . $t->getMessage() );
263
264 throw new Auth_Error( $t->getMessage() );
265 }
266
267 if ( ! isset( $response->id ) ) {
268 Logger::log( Logger::LEVEL_ERROR, 'Invalid response from server' );
269
270 throw new Auth_Error( esc_html__( 'Invalid response from server', 'image-optimization' ) );
271 }
272
273 return $response;
274 }
275
276 /**
277 * Fetches and returns a list of available licenses for a specific user.
278 *
279 * @return array Available subscriptions or an empty array
280 *
281 * @throws Auth_Error
282 */
283 public static function get_subscriptions(): array {
284 try {
285 $response = Utils::get_api_client()->make_request(
286 'POST',
287 'activation/get-subscriptions'
288 );
289 } catch ( Throwable $t ) {
290 Logger::log( Logger::LEVEL_ERROR, 'Error while fetching subscriptions: ' . $t->getMessage() );
291
292 throw new Auth_Error( $t->getMessage() );
293 }
294
295 if ( ! isset( $response->subscriptions ) ) {
296 Logger::log( Logger::LEVEL_ERROR, 'Invalid response from server' );
297
298 throw new Auth_Error( esc_html__( 'Invalid response from server', 'image-optimization' ) );
299 }
300
301 return $response->subscriptions;
302 }
303
304 public static function check_connect_status() {
305 if ( ! self::is_connected() ) {
306 Logger::log( Logger::LEVEL_INFO, 'Status check error. Reason: User is not connected' );
307
308 return null;
309 }
310
311 try {
312 $response = Utils::get_api_client()->make_request(
313 'POST',
314 'status/check'
315 );
316 } catch ( Throwable $t ) {
317 Logger::log(
318 Logger::LEVEL_ERROR,
319 'Status check error. Reason: ' . $t->getMessage()
320 );
321
322 return null;
323 }
324
325 if ( ! isset( $response->status ) ) {
326 Logger::log( Logger::LEVEL_ERROR, 'Invalid response from server' );
327
328 return null;
329 }
330
331 return $response;
332 }
333
334 public function __construct() {
335 // handle connect if elementor is active
336 add_action( 'load-elementor_page_elementor-connect', [ $this, 'handle_elementor_connect_admin' ], 9 );
337 // handle connect if elementor is not active
338 add_action( '_admin_menu', [ $this, 'handle_elementor_connect_admin' ] );
339 }
340 }
341