PluginProbe
Elementor Website Builder – more than just a page builder / 3.27.0-dev2
Elementor Website Builder – more than just a page builder v3.27.0-dev2
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / global-classes / global-classes-rest-api.php

global-classes-rest-api.php in Elementor Website Builder – more than just a page builder 3.27.0-dev2, at modules/global-classes/global-classes-rest-api.php

201 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\GlobalClasses;
4
5 use Elementor\Core\Utils\Collection;
6 use Elementor\Modules\AtomicWidgets\Styles\Style_Schema;
7 use Elementor\Modules\AtomicWidgets\Parsers\Style_Parser;
8 use Elementor\Plugin;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly.
12 }
13
14 class Global_Classes_REST_API {
15 const API_NAMESPACE = 'elementor/v1';
16 const API_BASE = 'global-classes';
17
18 private $repository = null;
19
20 public function register_hooks() {
21 add_action( 'rest_api_init', fn() => $this->register_routes() );
22 }
23
24 private function get_repository() {
25 if ( ! $this->repository ) {
26 $this->repository = new Global_Classes_Repository();
27 }
28
29 return $this->repository;
30 }
31
32 // TODO: Add sanitization when implemented on prop types [EDS-574]
33 private function register_routes() {
34 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
35 [
36 'methods' => 'GET',
37 'callback' => fn() => $this->route_wrapper( fn() => $this->all() ),
38 'permission_callback' => fn() => current_user_can( 'manage_options' ),
39 ],
40 ] );
41
42 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/(?P<id>[\w-]+)', [
43 [
44 'methods' => 'GET',
45 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->get( $request ) ),
46 'args' => [
47 'id' => [
48 'type' => 'string',
49 'required' => true,
50 ],
51 ],
52 'permission_callback' => fn() => current_user_can( 'manage_options' ),
53 ],
54 ] );
55
56 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/(?P<id>[\w-]+)', [
57 [
58 'methods' => 'DELETE',
59 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->delete( $request ) ),
60 'args' => [
61 'id' => [
62 'type' => 'string',
63 'required' => true,
64 ],
65 ],
66 'permission_callback' => fn() => current_user_can( 'manage_options' ),
67 ],
68 ] );
69
70 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/(?P<id>[\w-]+)', [
71 [
72 'methods' => 'PUT',
73 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->put( $request ) ),
74 'permission_callback' => fn() => current_user_can( 'manage_options' ),
75 ],
76 ] );
77
78 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
79 [
80 'methods' => 'POST',
81 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->create( $request ) ),
82 'permission_callback' => fn() => current_user_can( 'manage_options' ),
83 ],
84 ] );
85
86 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '-order', [
87 [
88 'methods' => 'PUT',
89 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->arrange( $request ) ),
90 'validate_callback' => function( \WP_REST_Request $request ) {
91 $order = $request->get_params();
92
93 if ( ! is_array( $order ) ) {
94 return false;
95 }
96
97 $classes = $this->get_repository()->all();
98
99 $missing_items = Collection::make( $classes->get_items()->keys() )->diff( $order );
100 $extra_items = Collection::make( $order )->diff( $classes->get_items()->keys() );
101
102 return $missing_items->is_empty() && $extra_items->is_empty();
103 },
104 'permission_callback' => fn() => current_user_can( 'manage_options' ),
105 ],
106 ] );
107 }
108
109 private function all() {
110 $classes = $this->get_repository()->all();
111
112 return $classes->get();
113 }
114
115 private function get( \WP_REST_Request $request ) {
116 $id = $request->get_param( 'id' );
117 $class = $this->get_repository()->get( $id );
118
119 if ( null === $class ) {
120 return new \WP_Error( 'entity_not_found', __( 'Global class not found', 'elementor' ), [ 'status' => 404 ] );
121 }
122
123 return $class;
124 }
125
126 private function delete( \WP_REST_Request $request ) {
127 $id = $request->get_param( 'id' );
128 $class = $this->get_repository()->get( $id );
129
130 if ( null === $class ) {
131 return new \WP_Error( 'entity_not_found', __( 'Global class not found', 'elementor' ), [ 'status' => 404 ] );
132 }
133
134 $this->get_repository()->delete( $id );
135
136 return new \WP_REST_Response( null, 204 );
137 }
138
139 private function put( \WP_REST_Request $request ) {
140 $id = $request->get_param( 'id' );
141 $values = $request->get_params();
142
143 // Ignore id to simplify the patch, and allow passing the entity as it is
144 unset( $values['id'] );
145
146 $class = $this->get_repository()->get( $id );
147
148 if ( null === $class ) {
149 return new \WP_Error( 'entity_not_found', __( 'Global class not found', 'elementor' ), [ 'status' => 404 ] );
150 }
151
152 [$is_valid, $parsed, $errors] = Style_Parser::make( Style_Schema::get() )
153 ->without_id()
154 ->parse( $values );
155
156 if ( ! $is_valid ) {
157 return $this->fail_with_validation_errors( $errors );
158 }
159
160 $values = $this->get_repository()->put( $id, $parsed );
161
162 return new \WP_REST_Response( $values, 200 );
163 }
164
165 private function create( \WP_REST_Request $request ) {
166 $class = $request->get_params();
167 [$is_valid, $parsed, $errors] = Style_Parser::make( Style_Schema::get() )
168 ->without_id()
169 ->parse( $class );
170
171 if ( ! $is_valid ) {
172 return $this->fail_with_validation_errors( $errors );
173 }
174
175 $new = $this->get_repository()->create( $parsed );
176
177 return new \WP_REST_Response( $new, 201 );
178 }
179
180 private function arrange( \WP_REST_Request $request ) {
181 $order = $request->get_params();
182 $updated = $this->get_repository()->arrange( $order );
183
184 return new \WP_REST_Response( $updated, 200 );
185 }
186
187 private function route_wrapper( callable $cb ) {
188 try {
189 $response = $cb();
190 } catch ( \Exception $e ) {
191 return new \WP_Error( 'unexpected_error', __( 'Something went wrong', 'elementor' ), [ 'status' => 500 ] );
192 }
193
194 return $response;
195 }
196
197 private function fail_with_validation_errors( array $errors ) {
198 return new \WP_Error( 'Invalid data: ', join( ', ', $errors ), [ 'status' => 400 ] );
199 }
200 }
201