PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.0-dev1
Elementor Website Builder – more than just a page builder v3.6.0-dev1
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 / data / v2 / base / controller.php

controller.php in Elementor Website Builder – more than just a page builder 3.6.0-dev1, at data/v2/base/controller.php

410 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Data\V2\Base;
3
4 use Elementor\Data\V2\Manager;
5 use WP_REST_Controller;
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit; // Exit if accessed directly
9 }
10
11 /**
12 * TODO: Utilize 'WP_REST_Controller' as much as possible.
13 */
14 abstract class Controller extends WP_REST_Controller {
15 /**
16 * Loaded endpoint(s).
17 *
18 * @var \Elementor\Data\V2\Base\Endpoint[]
19 */
20 public $endpoints = [];
21
22 /**
23 * Index endpoint.
24 *
25 * @var \Elementor\Data\V2\Base\Endpoint\Index
26 */
27 public $index_endpoint = null;
28
29 /**
30 * Loaded processor(s).
31 *
32 * @var \Elementor\Data\V2\Base\Processor[][]
33 */
34 public $processors = [];
35
36 /**
37 * @var \Elementor\Data\V2\Base\Controller|null
38 */
39 private $parent = null;
40
41 /**
42 * @var \Elementor\Data\V2\Base\Controller[]
43 */
44 private $sub_controllers = [];
45
46 public static function get_default_namespace() {
47 return Manager::ROOT_NAMESPACE;
48 }
49
50 public static function get_default_version() {
51 return Manager::VERSION;
52 }
53
54 /**
55 * Controller constructor.
56 *
57 * Register endpoints on 'rest_api_init'.
58 */
59 public function __construct() {
60 $this->namespace = static::get_default_namespace() . '/v' . static::get_default_version();
61 $this->rest_base = $this->get_name();
62
63 add_action( 'rest_api_init', function () {
64 $this->register(); // Because 'register' is protected.
65 } );
66
67 /**
68 * Since all actions were removed for custom internal REST server.
69 * Re-add the actions.
70 */
71 add_action( 'elementor_rest_api_before_init', function () {
72 add_action( 'rest_api_init', function() {
73 $this->register();
74 } );
75 } );
76
77 $parent_name = $this->get_parent_name();
78 if ( $parent_name ) {
79 $this->act_as_sub_controller( $parent_name );
80 }
81 }
82
83 /**
84 * Get controller name.
85 *
86 * @return string
87 */
88 abstract public function get_name();
89
90 /**
91 * Register endpoints.
92 */
93 public function register_endpoints() {}
94
95 /**
96 * Get parent controller name.
97 *
98 * @note: If `get_parent_name()` provided, controller will work as sub-controller.
99 *
100 * @returns null|string
101 */
102 public function get_parent_name() {
103 return null;
104 }
105
106 /**
107 * Get full controller name.
108 *
109 * The method exist to handle situations when parent exist, to include the parent name.
110 *
111 * @return string
112 */
113 public function get_full_name() {
114 if ( ! $this->parent ) {
115 return $this->get_name();
116 }
117
118 return $this->parent->get_name() . '/' . $this->get_name();
119 }
120
121 /**
122 * Get controller namespace.
123 *
124 * @return string
125 */
126 public function get_namespace() {
127 return $this->namespace;
128 }
129
130 /**
131 * Get controller reset base.
132 *
133 * @return string
134 */
135 public function get_base_route() {
136 if ( ! $this->parent ) {
137 return $this->rest_base;
138 }
139
140 return $this->parent->get_base_route() . '/' . $this->get_name();
141 }
142
143 /**
144 * Get controller route.
145 *
146 * @return string
147 */
148 public function get_controller_route() {
149 return $this->get_namespace() . '/' . $this->get_base_route();
150 }
151
152 /**
153 * Retrieves rest route(s) index for current controller.
154 *
155 * @return \WP_REST_Response|\WP_Error
156 */
157 public function get_controller_index() {
158 $server = rest_get_server();
159 $routes = $server->get_routes();
160
161 $endpoints = array_intersect_key( $server->get_routes(), $routes );
162
163 $controller_route = $this->get_controller_route();
164
165 array_walk( $endpoints, function ( &$item, $endpoint ) use ( &$endpoints, $controller_route ) {
166 if ( ! strstr( $endpoint, $controller_route ) ) {
167 unset( $endpoints[ $endpoint ] );
168 }
169 } );
170
171 $data = [
172 'namespace' => $this->get_namespace(),
173 'controller' => $controller_route,
174 'routes' => $server->get_data_for_routes( $endpoints ),
175 ];
176
177 $response = rest_ensure_response( $data );
178
179 // Link to the root index.
180 $response->add_link( 'up', rest_url( '/' ) );
181
182 return $response;
183 }
184
185 /**
186 * Get items args for specific endpoint.
187 *
188 * @param string $methods
189 *
190 * @return array
191 */
192 public function get_items_args( $methods ) {
193 if ( \WP_REST_Server::READABLE === $methods ) {
194 return $this->get_collection_params();
195 }
196
197 return [];
198 }
199
200 /**
201 * Get permission callback.
202 *
203 * Default controller permission callback.
204 * By default endpoint will inherit the permission callback from the controller.
205 * By default permission is `current_user_can( 'administrator' );`.
206 *
207 * @param \WP_REST_Request $request
208 *
209 * @return bool
210 */
211 public function get_permission_callback( $request ) {
212 // The function is public since endpoint need to access it.
213 switch ( $request->get_method() ) {
214 case 'GET':
215 case 'POST':
216 case 'UPDATE':
217 case 'PUT':
218 case 'DELETE':
219 case 'PATCH':
220 return current_user_can( 'administrator' );
221 }
222
223 return false;
224 }
225
226 public function get_items( $request ) {
227 return $this->get_controller_index();
228 }
229
230 /**
231 * Creates multiple items.
232 *
233 * @param \WP_REST_Request $request Full data about the request.
234 *
235 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
236 */
237 public function create_items( $request ) {
238 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
239 }
240
241 /**
242 * Updates multiple items.
243 *
244 * @param \WP_REST_Request $request Full data about the request.
245 *
246 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
247 */
248 public function update_items( $request ) {
249 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
250 }
251
252 /**
253 * Delete multiple items.
254 *
255 * @param \WP_REST_Request $request Full data about the request.
256 *
257 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
258 */
259 public function delete_items( $request ) {
260 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
261 }
262
263 /**
264 * Get the parent controller.
265 *
266 * @return \Elementor\Data\V2\Base\Controller|null
267 */
268 public function get_parent() {
269 return $this->parent;
270 }
271
272 /**
273 * Get sub controller(s).
274 *
275 * @return \Elementor\Data\V2\Base\Controller[]
276 */
277 public function get_sub_controllers() {
278 return $this->sub_controllers;
279 }
280
281 /**
282 * Get processors.
283 *
284 * @param string $command
285 *
286 * @return \Elementor\Data\V2\Base\Processor[]
287 */
288 public function get_processors( $command ) {
289 $result = [];
290
291 if ( isset( $this->processors[ $command ] ) ) {
292 $result = $this->processors[ $command ];
293 }
294
295 return $result;
296 }
297
298 /**
299 * Register processors.
300 */
301 public function register_processors() {
302 }
303
304 /**
305 * Register index endpoint.
306 */
307 protected function register_index_endpoint() {
308 if ( ! $this->parent ) {
309 $this->register_endpoint( new Endpoint\Index( $this ) );
310 return;
311 }
312
313 $this->register_endpoint( new Endpoint\Index\Sub_Index_Endpoint( $this ) );
314 }
315
316 /**
317 * Register endpoint.
318 *
319 * @param \Elementor\Data\V2\Base\Endpoint $endpoint
320 *
321 * @return \Elementor\Data\V2\Base\Endpoint
322 */
323 protected function register_endpoint( Endpoint $endpoint ) {
324 $command = $endpoint->get_full_command();
325
326 if ( $endpoint instanceof Endpoint\Index ) {
327 $this->index_endpoint = $endpoint;
328 } else {
329 $this->endpoints[ $command ] = $endpoint;
330 }
331
332 $format = $endpoint->get_format();
333
334 // `$e.data.registerFormat()`.
335 Manager::instance()->register_endpoint_format( $command, $format );
336
337 return $endpoint;
338 }
339
340 /**
341 * Register a processor.
342 *
343 * That will be later attached to the endpoint class.
344 *
345 * @param Processor $processor
346 *
347 * @return \Elementor\Data\V2\Base\Processor $processor_instance
348 */
349 protected function register_processor( Processor $processor ) {
350 $command = $processor->get_command();
351
352 if ( ! isset( $this->processors[ $command ] ) ) {
353 $this->processors[ $command ] = [];
354 }
355
356 $this->processors[ $command ] [] = $processor;
357
358 return $processor;
359 }
360
361 /**
362 * Register.
363 *
364 * Endpoints & processors.
365 */
366 protected function register() {
367 $this->register_index_endpoint();
368 $this->register_endpoints();
369
370 // Aka hooks.
371 $this->register_processors();
372 }
373
374 /**
375 * Get collection params by 'additionalProperties' context.
376 *
377 * @param string $context
378 *
379 * @return array
380 */
381 protected function get_collection_params_by_additional_props_context( $context ) {
382 $result = [];
383
384 $collection_params = $this->get_collection_params();
385
386 foreach ( $collection_params as $collection_param_key => $collection_param ) {
387 if ( isset( $collection_param['additionalProperties']['context'] ) && $context === $collection_param['additionalProperties']['context'] ) {
388 $result[ $collection_param_key ] = $collection_param;
389 }
390 }
391
392 return $result;
393 }
394
395 /**
396 * When `$this->get_parent_name` is extended, the controller will have a parent, and will know to behave like a sub-controller.
397 *
398 * @param string $parent_name
399 */
400 private function act_as_sub_controller( $parent_name ) {
401 $this->parent = Manager::instance()->get_controller( $parent_name );
402
403 if ( ! $this->parent ) {
404 trigger_error( "Cannot find parent controller: '$parent_name'", E_USER_ERROR ); // phpcs:ignore
405 }
406
407 $this->parent->sub_controllers [] = $this;
408 }
409 }
410