????
Current Path : /proc/self/cwd/wp-content/plugins/elementor/modules/global-classes/ |
Current File : //proc/self/cwd/wp-content/plugins/elementor/modules/global-classes/global-classes-rest-api.php |
<?php namespace Elementor\Modules\GlobalClasses; use Elementor\Core\Utils\Collection; use Elementor\Modules\AtomicWidgets\Styles\Style_Schema; use Elementor\Modules\AtomicWidgets\Parsers\Style_Parser; use Elementor\Modules\GlobalClasses\Utils\Error_Builder; use Elementor\Modules\GlobalClasses\Utils\Response_Builder; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } class Global_Classes_REST_API { const API_NAMESPACE = 'elementor/v1'; const API_BASE = 'global-classes'; private $repository = null; public function register_hooks() { add_action( 'rest_api_init', fn() => $this->register_routes() ); } private function get_repository() { if ( ! $this->repository ) { $this->repository = new Global_Classes_Repository(); } return $this->repository; } /** * TODO: Add sanitization when implemented on prop types [EDS-574] */ private function register_routes() { register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [ [ 'methods' => 'GET', 'callback' => fn() => $this->route_wrapper( fn() => $this->all() ), 'permission_callback' => fn() => current_user_can( 'manage_options' ), ], ] ); register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [ [ 'methods' => 'PUT', 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->put( $request ) ), 'permission_callback' => fn() => current_user_can( 'manage_options' ), 'args' => [ 'items' => [ 'required' => true, 'type' => 'object', 'additionalProperties' => false, 'patternProperties' => [ '^g-[a-z0-9]+$' => [ 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'string', 'pattern' => '^g-[a-z0-9]+$', 'required' => true, ], 'variants' => [ 'type' => 'array', 'required' => true, ], 'type' => [ 'type' => 'string', 'enum' => [ 'class' ], 'required' => true, ], 'label' => [ 'type' => 'string', 'required' => true, ], ], ], ], ], 'order' => [ 'required' => true, 'type' => 'array', 'items' => [ 'type' => 'string', 'pattern' => '^g-[a-z0-9]+$', ], ], ], ], ] ); } private function all() { $classes = $this->get_repository()->all(); return Response_Builder::make( (object) $classes->get_items()->all() ) ->set_meta( [ 'order' => $classes->get_order()->all() ] ) ->build(); } private function put( \WP_REST_Request $request ) { $items = $request->get_param( 'items' ); [$is_valid, $sanitized_items, $errors] = $this->sanitize_items( $items ); if ( ! $is_valid ) { return Error_Builder::make( 'invalid_items' ) ->set_status( 400 ) ->set_message( 'Invalid items: ' . join( ', ', array_keys( $errors ) ) ) ->build(); } $order = $request->get_param( 'order' ); if ( ! $this->is_valid_order( $order, $sanitized_items ) ) { return Error_Builder::make( 'invalid_order' ) ->set_status( 400 ) ->set_message( 'Invalid order' ) ->build(); } $this->get_repository()->put( $sanitized_items, $order ); return Response_Builder::make()->no_content()->build(); } private function sanitize_items( array $items ) { $errors = []; $sanitized_items = []; foreach ( $items as $item_id => $item ) { [$is_item_valid, $sanitized_item, $item_errors] = Style_Parser::make( Style_Schema::get() )->parse( $item ); if ( ! $is_item_valid ) { $errors[ $item_id ] = $item_errors; continue; } if ( $item_id !== $sanitized_item['id'] ) { $errors[ $item_id ] = [ 'id' ]; continue; } $sanitized_items[ $sanitized_item['id'] ] = $sanitized_item; } $is_valid = count( $errors ) === 0; return [ $is_valid, $sanitized_items, $errors ]; } private function is_valid_order( array $order, array $items ) { $existing_ids = array_keys( $items ); $excess_ids = Collection::make( $order )->diff( $existing_ids ); $missing_ids = Collection::make( $existing_ids )->diff( $order ); $has_duplications = Collection::make( $order )->unique()->all() !== $order; return ( $excess_ids->is_empty() && $missing_ids->is_empty() && ! $has_duplications ); } private function route_wrapper( callable $cb ) { try { $response = $cb(); } catch ( \Exception $e ) { return Error_Builder::make( 'unexpected_error' ) ->set_message( __( 'Something went wrong', 'elementor' ) ) ->build(); } return $response; } }