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
image-optimization / vendor / elementor / wp-one-package / src / Admin / Controllers / Plugins.php

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

466 lines 13.4 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\Controllers;
4
5 use ElementorOne\Admin\Config;
6 use ElementorOne\Admin\Exceptions\MigrationException;
7 use ElementorOne\Admin\Helpers\Utils;
8 use ElementorOne\Admin\Services\Editor;
9 use ElementorOne\Admin\Services\Migration;
10 use ElementorOne\Common\RestError;
11 use ElementorOne\Common\SupportedPlugins;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly
15 }
16
17 /**
18 * Class Plugins
19 * Extends WordPress's built-in REST Plugins Controller
20 * Handles all plugin-related REST API endpoints
21 */
22 class Plugins extends \WP_REST_Plugins_Controller {
23
24 /**
25 * Constructor
26 */
27 public function __construct() {
28 $this->namespace = Config::APP_REST_NAMESPACE;
29 $this->rest_base = 'plugins';
30
31 add_action( 'rest_api_init', [ $this, 'register_routes' ] );
32 }
33
34 /**
35 * Register all plugin-related routes
36 * @return void
37 */
38 public function register_routes() {
39 // GET /plugins - List all plugins
40 register_rest_route(
41 $this->namespace,
42 '/' . $this->rest_base,
43 [
44 [
45 'methods' => \WP_REST_Server::READABLE,
46 'callback' => [ $this, 'get_items' ],
47 'permission_callback' => [ $this, 'get_items_permissions_check' ],
48 'args' => $this->get_collection_params(),
49 ],
50 ]
51 );
52
53 // POST /plugins - Install plugin
54 register_rest_route(
55 $this->namespace,
56 '/' . $this->rest_base,
57 [
58 [
59 'methods' => \WP_REST_Server::CREATABLE,
60 'callback' => [ $this, 'install_plugin' ],
61 'permission_callback' => [ $this, 'create_item_permissions_check' ],
62 'args' => [
63 'slug' => [
64 'type' => 'string',
65 'required' => true,
66 'description' => 'WordPress.org plugin directory slug.',
67 'enum' => SupportedPlugins::get_values(),
68 ],
69 'status' => [
70 'description' => 'The plugin activation status.',
71 'type' => 'string',
72 'enum' => [ 'inactive', 'active' ],
73 'default' => 'inactive',
74 ],
75 ],
76 ],
77 ]
78 );
79
80 // POST /plugins/{slug}/activate
81 register_rest_route(
82 $this->namespace,
83 '/' . $this->rest_base . '/(?P<slug>[\w\-]+)/activate',
84 [
85 [
86 'methods' => \WP_REST_Server::CREATABLE,
87 'callback' => [ $this, 'activate_plugin' ],
88 'permission_callback' => [ $this, 'user_can_manage_plugin_status' ],
89 'args' => [
90 'slug' => [
91 'type' => 'string',
92 'required' => true,
93 'description' => 'WordPress.org plugin directory slug.',
94 'enum' => SupportedPlugins::get_values(),
95 ],
96 ],
97 ],
98 ]
99 );
100
101 // POST /plugins/{slug}/deactivate
102 register_rest_route(
103 $this->namespace,
104 '/' . $this->rest_base . '/(?P<slug>[\w\-]+)/deactivate',
105 [
106 [
107 'methods' => \WP_REST_Server::CREATABLE,
108 'callback' => [ $this, 'deactivate_plugin' ],
109 'permission_callback' => [ $this, 'user_can_manage_plugin_status' ],
110 'args' => [
111 'slug' => [
112 'type' => 'string',
113 'required' => true,
114 'description' => 'WordPress.org plugin directory slug.',
115 'enum' => SupportedPlugins::get_values(),
116 ],
117 ],
118 ],
119 ]
120 );
121
122 // POST /plugins/{slug}/upgrade
123 register_rest_route(
124 $this->namespace,
125 '/' . $this->rest_base . '/(?P<slug>[\w\-]+)/upgrade',
126 [
127 [
128 'methods' => \WP_REST_Server::CREATABLE,
129 'callback' => [ $this, 'upgrade_plugin' ],
130 'permission_callback' => [ $this, 'update_item_permissions_check' ],
131 'args' => [
132 'slug' => [
133 'type' => 'string',
134 'required' => true,
135 'description' => 'WordPress.org plugin directory slug.',
136 'enum' => SupportedPlugins::get_values(),
137 ],
138 'status' => [
139 'description' => 'The plugin activation status.',
140 'type' => 'string',
141 'required' => false,
142 'enum' => [ 'active' ],
143 ],
144 ],
145 ],
146 ]
147 );
148
149 // POST /plugins/{slug}/migration/run
150 register_rest_route(
151 $this->namespace,
152 '/' . $this->rest_base . '/(?P<slug>[\w\-]+)/migration/run',
153 [
154 [
155 'methods' => \WP_REST_Server::CREATABLE,
156 'callback' => [ $this, 'run_migration' ],
157 'permission_callback' => [ $this, 'user_can_run_migration' ],
158 'args' => [
159 'slug' => [
160 'type' => 'string',
161 'required' => true,
162 'description' => 'WordPress.org plugin directory slug.',
163 'enum' => Migration::get_supported_plugins(),
164 ],
165 'force' => [
166 'type' => 'boolean',
167 'required' => false,
168 'default' => true,
169 'description' => 'Force migration even if the plugin is already connected.',
170 ],
171 ],
172 ],
173 ]
174 );
175
176 // POST /plugins/{slug}/migration/rollback
177 register_rest_route(
178 $this->namespace,
179 '/' . $this->rest_base . '/(?P<slug>[\w\-]+)/migration/rollback',
180 [
181 [
182 'methods' => \WP_REST_Server::CREATABLE,
183 'callback' => [ $this, 'rollback_migration' ],
184 'permission_callback' => [ $this, 'user_can_rollback_migration' ],
185 'args' => [
186 'slug' => [
187 'type' => 'string',
188 'required' => true,
189 'description' => 'WordPress.org plugin directory slug.',
190 'enum' => Migration::get_supported_plugins(),
191 ],
192 ],
193 ],
194 ]
195 );
196 }
197
198 /**
199 * Get all plugins - Override parent to add custom fields
200 * @param \WP_REST_Request $request
201 * @return \WP_REST_Response|\WP_Error
202 */
203 public function get_items( $request ) {
204 wp_update_plugins();
205
206 $plugins = [];
207 foreach ( SupportedPlugins::get_values() as $plugin_slug ) {
208 $plugin_response = $this->plugin_response( $plugin_slug )->get_data();
209 if ( ! empty( $plugin_response ) ) {
210 $plugins[] = $plugin_response;
211 }
212 }
213
214 return new \WP_REST_Response( $plugins );
215 }
216
217 /**
218 * Install plugin - Override parent to add custom logic
219 * @param \WP_REST_Request $request
220 * @return \WP_REST_Response|\WP_Error
221 */
222 public function install_plugin( $request ) {
223 // Filter plugins API result for Elementor Pro
224 if ( SupportedPlugins::ELEMENTOR_PRO === $request['slug'] ) {
225 add_filter( 'plugins_api', [ Editor::instance(), 'filter_plugins_api_result' ], 10 );
226 }
227
228 // Use parent's create_item functionality
229 $result = parent::create_item( $request );
230
231 if ( is_wp_error( $result ) ) {
232 return RestError::bad_request( $result->get_error_message(), $result->get_all_error_data() );
233 }
234
235 return $this->plugin_response( $request['slug'] );
236 }
237
238 /**
239 * Activate plugin
240 * @param \WP_REST_Request $request
241 * @return \WP_REST_Response|\WP_Error
242 */
243 public function activate_plugin( \WP_REST_Request $request ) {
244 $plugin_slug = $request->get_url_params()['slug'];
245
246 try {
247 $plugin_file = Utils::get_plugin_data( $plugin_slug )['_file'];
248 $result = activate_plugins( $plugin_file );
249
250 if ( is_wp_error( $result ) ) {
251 return RestError::bad_request( $result->get_error_message(), $result->get_all_error_data() );
252 }
253 } catch ( \Throwable $th ) {
254 return RestError::internal_server_error( $th->getMessage() );
255 }
256
257 return $this->plugin_response( $plugin_slug );
258 }
259
260 /**
261 * Deactivate plugin
262 * @param \WP_REST_Request $request
263 * @return \WP_REST_Response|\WP_Error
264 */
265 public function deactivate_plugin( \WP_REST_Request $request ) {
266 $plugin_slug = $request->get_url_params()['slug'];
267
268 try {
269 $plugin_file = Utils::get_plugin_data( $plugin_slug )['_file'];
270 deactivate_plugins( $plugin_file );
271 } catch ( \Throwable $th ) {
272 return RestError::internal_server_error( $th->getMessage() );
273 }
274
275 return $this->plugin_response( $plugin_slug );
276 }
277
278 /**
279 * Upgrade plugin
280 * @param \WP_REST_Request $request
281 * @return \WP_REST_Response|\WP_Error
282 */
283 public function upgrade_plugin( \WP_REST_Request $request ) {
284 $plugin_slug = $request->get_url_params()['slug'];
285
286 try {
287 require_once ABSPATH . 'wp-admin/includes/file.php';
288 require_once ABSPATH . 'wp-admin/includes/plugin.php';
289 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
290 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
291 require_once ABSPATH . 'wp-admin/includes/update.php';
292
293 $plugin_data = Utils::get_plugin_data( $plugin_slug );
294
295 if ( empty( $plugin_data ) ) {
296 return RestError::not_found( 'Plugin not found.' );
297 }
298
299 // Check if there's an update available
300 wp_update_plugins();
301
302 $skin = new \WP_Ajax_Upgrader_Skin();
303 $upgrader = new \Plugin_Upgrader( $skin );
304 $result = $upgrader->upgrade( $plugin_data['_file'] );
305
306 if ( is_wp_error( $result ) ) {
307 return RestError::bad_request( $result->get_error_message(), $result->get_all_error_data() );
308 }
309
310 if ( is_wp_error( $skin->result ) ) {
311 return RestError::bad_request( $skin->result->get_error_message(), $skin->result->get_all_error_data() );
312 }
313
314 if ( $skin->get_errors()->has_errors() ) {
315 return RestError::bad_request( $skin->get_errors()->get_error_message(), $skin->get_errors()->get_all_error_data() );
316 }
317
318 if ( false === $result ) {
319 return RestError::internal_server_error( 'Failed to update plugin for an unknown reason.' );
320 }
321
322 if ( 'active' === $request['status'] ) {
323 $can_change_status = $this->user_can_manage_plugin_status( $request );
324
325 if ( is_wp_error( $can_change_status ) ) {
326 return RestError::forbidden( $can_change_status->get_error_message(), $can_change_status->get_all_error_data() );
327 }
328
329 $result = activate_plugins( $plugin_data['_file'] );
330
331 if ( is_wp_error( $result ) ) {
332 return RestError::bad_request( $result->get_error_message(), $result->get_all_error_data() );
333 }
334 }
335 } catch ( \Throwable $th ) {
336 return RestError::internal_server_error( $th->getMessage() );
337 }
338
339 return $this->plugin_response( $plugin_slug );
340 }
341
342 /**
343 * Run migration
344 * @param \WP_REST_Request $request
345 * @return \WP_REST_Response|\WP_Error
346 */
347 public function run_migration( \WP_REST_Request $request ) {
348 $plugin_slug = $request->get_url_params()['slug'];
349
350 try {
351 Migration::instance()->run( $plugin_slug, $request['force'] );
352 } catch ( MigrationException $e ) {
353 return RestError::custom_error( 'migration_exception', $e->getMessage(), $e->getCode() );
354 } catch ( \Throwable $th ) {
355 return RestError::internal_server_error( $th->getMessage() );
356 }
357
358 return $this->plugin_response( $plugin_slug );
359 }
360
361 /**
362 * Rollback migration
363 * @param \WP_REST_Request $request
364 * @return \WP_REST_Response|\WP_Error
365 */
366 public function rollback_migration( \WP_REST_Request $request ) {
367 $plugin_slug = $request->get_url_params()['slug'];
368
369 try {
370 Migration::instance()->rollback( $plugin_slug );
371 } catch ( MigrationException $e ) {
372 return RestError::custom_error( 'migration_exception', $e->getMessage(), $e->getCode() );
373 } catch ( \Throwable $th ) {
374 return RestError::internal_server_error( $th->getMessage() );
375 }
376
377 return $this->plugin_response( $plugin_slug );
378 }
379
380 /**
381 * Create unified plugin response
382 * @param string $plugin_slug Plugin slug
383 * @return \WP_REST_Response
384 */
385 protected function plugin_response( string $plugin_slug ): \WP_REST_Response {
386 $plugin_data = Utils::get_plugin_data( $plugin_slug );
387
388 $response = is_null( $plugin_data ) ? null : [
389 'slug' => $plugin_slug,
390 'status' => is_plugin_active( $plugin_data['_file'] ) ? 'active' : 'inactive',
391 'version' => $plugin_data['Version'],
392 'newVersion' => Utils::get_plugin_new_version( $plugin_data['_file'] ),
393 'isMigrated' => Migration::is_migrated( $plugin_slug ),
394 'isConnected' => Utils::is_plugin_connected( $plugin_slug ),
395 'hasWpOnePackage' => (bool) Utils::get_package_version( $plugin_slug ),
396 ];
397
398 return new \WP_REST_Response( $response );
399 }
400
401 /**
402 * Check if the user has permission to manage the plugin status
403 * @param \WP_REST_Request $request
404 * @return true|\WP_Error
405 */
406 public function user_can_manage_plugin_status( \WP_REST_Request $request ) {
407 if ( ! current_user_can( 'manage_options' ) ) {
408 $authorization_required_code = rest_authorization_required_code();
409 return RestError::custom_error(
410 \WP_Http::UNAUTHORIZED === $authorization_required_code ? 'unauthorized' : 'forbidden',
411 'Sorry, you are not allowed to manage plugins for this site.',
412 $authorization_required_code
413 );
414 }
415
416 $plugin_slug = $request->get_url_params()['slug'];
417 $plugin_data = Utils::get_plugin_data( $plugin_slug );
418
419 if ( empty( $plugin_data ) ) {
420 return RestError::not_found( 'Plugin not found.' );
421 }
422
423 $current_status = is_plugin_active( $plugin_data['_file'] ) ? 'active' : 'inactive';
424
425 return $this->plugin_status_permission_check( $plugin_data['_file'], 'active', $current_status );
426 }
427
428 /**
429 * Check if the user has permission to run migration
430 * @param \WP_REST_Request $request
431 * @return true|\WP_Error
432 */
433 public function user_can_run_migration( \WP_REST_Request $request ) {
434 if ( ! current_user_can( 'manage_options' ) ) {
435 $authorization_required_code = rest_authorization_required_code();
436 return RestError::custom_error(
437 \WP_Http::UNAUTHORIZED === $authorization_required_code ? 'unauthorized' : 'forbidden',
438 'Sorry, you are not allowed to manage plugins for this site.',
439 $authorization_required_code
440 );
441 }
442
443 $plugin_slug = $request->get_url_params()['slug'];
444 $plugin_data = Utils::get_plugin_data( $plugin_slug );
445
446 if ( empty( $plugin_data ) ) {
447 return RestError::not_found( 'Plugin not found.' );
448 }
449
450 if ( ! is_plugin_active( $plugin_data['_file'] ) ) {
451 return RestError::bad_request( 'Plugin is not active.' );
452 }
453
454 return Utils::get_one_connect()->utils()->is_connected();
455 }
456
457 /**
458 * Check if the user has permission to rollback migration
459 * @param \WP_REST_Request $request
460 * @return true|\WP_Error
461 */
462 public function user_can_rollback_migration( \WP_REST_Request $request ) {
463 return $this->user_can_run_migration( $request );
464 }
465 }
466