PluginProbe
Elementor Website Builder – more than just a page builder / 3.25.7
Elementor Website Builder – more than just a page builder v3.25.7
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 / base / controller.php

controller.php in Elementor Website Builder – more than just a page builder 3.25.7, at data/base/controller.php

347 lines 8.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\Base;
3
4 use Elementor\Data\Manager;
5 use Elementor\Plugin;
6 use WP_REST_Controller;
7 use WP_REST_Server;
8
9 abstract class Controller extends WP_REST_Controller {
10 /**
11 * Loaded endpoint(s).
12 *
13 * @var \Elementor\Data\Base\Endpoint[]
14 */
15 public $endpoints = [];
16
17 /**
18 * Loaded processor(s).
19 *
20 * @var \Elementor\Data\Base\Processor[][]
21 */
22 public $processors = [];
23
24 /**
25 * Controller constructor.
26 *
27 * Register endpoints on 'rest_api_init'.
28 *
29 */
30 public function __construct() {
31 // TODO: Controllers and endpoints can have common interface.
32
33 // TODO: Uncomment when native 3rd plugins uses V2.
34 //$this->deprecated();
35
36 $this->namespace = Manager::ROOT_NAMESPACE . '/v' . Manager::VERSION;
37 $this->rest_base = Manager::REST_BASE . $this->get_name();
38
39 add_action( 'rest_api_init', function () {
40 $this->register(); // Because 'register' is protected.
41 } );
42
43 /**
44 * Since all actions were removed for custom internal REST server.
45 * Re-add the actions.
46 */
47 add_action( 'elementor_rest_api_before_init', function () {
48 add_action( 'rest_api_init', function() {
49 $this->register();
50 } );
51 } );
52 }
53
54 /**
55 * Get controller name.
56 *
57 * @return string
58 */
59 abstract public function get_name();
60
61 /**
62 * Get controller namespace.
63 *
64 * @return string
65 */
66 public function get_namespace() {
67 return $this->namespace;
68 }
69
70 /**
71 * Get controller reset base.
72 *
73 * @return string
74 */
75 public function get_rest_base() {
76 return $this->rest_base;
77 }
78
79 /**
80 * Get controller route.
81 *
82 * @return string
83 */
84 public function get_controller_route() {
85 return $this->get_namespace() . '/' . $this->get_rest_base();
86 }
87
88 /**
89 * Retrieves the index for a controller.
90 *
91 * @return \WP_REST_Response|\WP_Error
92 */
93 public function get_controller_index() {
94 $server = rest_get_server();
95 $routes = $server->get_routes();
96
97 $endpoints = array_intersect_key( $server->get_routes(), $routes );
98
99 $controller_route = $this->get_controller_route();
100
101 array_walk( $endpoints, function ( &$item, $endpoint ) use ( &$endpoints, $controller_route ) {
102 if ( ! strstr( $endpoint, $controller_route ) ) {
103 unset( $endpoints[ $endpoint ] );
104 }
105 } );
106
107 $data = [
108 'namespace' => $this->get_namespace(),
109 'controller' => $controller_route,
110 'routes' => $server->get_data_for_routes( $endpoints ),
111 ];
112
113 $response = rest_ensure_response( $data );
114
115 // Link to the root index.
116 $response->add_link( 'up', rest_url( '/' ) );
117
118 return $response;
119 }
120
121 /**
122 * Get processors.
123 *
124 * @param string $command
125 *
126 * @return \Elementor\Data\Base\Processor[]
127 */
128 public function get_processors( $command ) {
129 $result = [];
130
131 if ( isset( $this->processors[ $command ] ) ) {
132 $result = $this->processors[ $command ];
133 }
134
135 return $result;
136 }
137
138 public function get_items( $request ) {
139 return $this->get_controller_index();
140 }
141
142 /**
143 * Creates multiple items.
144 *
145 * @param \WP_REST_Request $request Full data about the request.
146 *
147 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
148 */
149 public function create_items( $request ) {
150 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
151 }
152
153 /**
154 * Updates multiple items.
155 *
156 * @param \WP_REST_Request $request Full data about the request.
157 *
158 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
159 */
160 public function update_items( $request ) {
161 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
162 }
163
164 /**
165 * Delete multiple items.
166 *
167 * @param \WP_REST_Request $request Full data about the request.
168 *
169 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure.
170 */
171 public function delete_items( $request ) {
172 return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] );
173 }
174
175 /**
176 * Register endpoints.
177 */
178 abstract public function register_endpoints();
179
180 /**
181 * Register processors.
182 */
183 public function register_processors() {
184 }
185
186 /**
187 * Register internal endpoints.
188 */
189 protected function register_internal_endpoints() {
190 register_rest_route( $this->get_namespace(), '/' . $this->get_rest_base(), [
191 [
192 'methods' => WP_REST_Server::READABLE,
193 'callback' => array( $this, 'get_items' ),
194 'args' => [],
195 'permission_callback' => function ( $request ) {
196 return $this->get_permission_callback( $request );
197 },
198 ],
199 ] );
200 }
201
202 /**
203 * Register endpoint.
204 *
205 * @param string $endpoint_class
206 *
207 * @return \Elementor\Data\Base\Endpoint
208 */
209 protected function register_endpoint( $endpoint_class ) {
210 $endpoint_instance = new $endpoint_class( $this );
211
212 // TODO: Validate instance like in register_sub_endpoint().
213
214 $endpoint_route = $this->get_name() . '/' . $endpoint_instance->get_name();
215
216 $this->endpoints[ $endpoint_route ] = $endpoint_instance;
217
218 $command = $endpoint_route;
219 $format = $endpoint_instance::get_format();
220
221 if ( $command ) {
222 $format = $command . '/' . $format;
223 } else {
224 $format = $format . $command;
225 }
226
227 // `$e.data.registerFormat()`.
228 Manager::instance()->register_endpoint_format( $command, $format );
229
230 return $endpoint_instance;
231 }
232
233 /**
234 * Register a processor.
235 *
236 * That will be later attached to the endpoint class.
237 *
238 * @param string $processor_class
239 *
240 * @return \Elementor\Data\Base\Processor $processor_instance
241 */
242 protected function register_processor( $processor_class ) {
243 $processor_instance = new $processor_class( $this );
244
245 // TODO: Validate processor instance.
246
247 $command = $processor_instance->get_command();
248
249 if ( ! isset( $this->processors[ $command ] ) ) {
250 $this->processors[ $command ] = [];
251 }
252
253 $this->processors[ $command ] [] = $processor_instance;
254
255 return $processor_instance;
256 }
257
258 /**
259 * Register.
260 *
261 * Endpoints & processors.
262 */
263 protected function register() {
264 $this->register_internal_endpoints();
265 $this->register_endpoints();
266
267 // Aka hooks.
268 $this->register_processors();
269 }
270
271 /**
272 * Retrieves a recursive collection of all endpoint(s), items.
273 *
274 * Get items recursive, will run overall endpoints of the current controller.
275 * For each endpoint it will run `$endpoint->getItems( $request ) // the $request passed in get_items_recursive`.
276 * Will skip $skip_endpoints endpoint(s).
277 *
278 * Example, scenario:
279 * Controller 'test-controller'.
280 * Controller endpoints: 'endpoint1', 'endpoint2'.
281 * Endpoint2 get_items method: `get_items() { return 'test' }`.
282 * Call `Controller.get_items_recursive( ['endpoint1'] )`, result: [ 'endpoint2' => 'test' ];
283 *
284 * @param array $skip_endpoints
285 *
286 * @return array
287 */
288 public function get_items_recursive( $skip_endpoints = [] ) {
289 $response = [];
290
291 foreach ( $this->endpoints as $endpoint ) {
292 // Skip self.
293 if ( in_array( $endpoint, $skip_endpoints, true ) ) {
294 continue;
295 }
296
297 $response[ $endpoint->get_name() ] = $endpoint->get_items( null );
298 }
299
300 return $response;
301 }
302
303 /**
304 * Get permission callback.
305 *
306 * Default controller permission callback.
307 * By default endpoint will inherit the permission callback from the controller.
308 * By default permission is `current_user_can( 'administrator' );`.
309 *
310 * @param \WP_REST_Request $request
311 *
312 * @return bool
313 */
314 public function get_permission_callback( $request ) {
315 // The function is public since endpoint need to access it.
316 switch ( $request->get_method() ) {
317 case 'GET':
318 case 'POST':
319 case 'UPDATE':
320 case 'PUT':
321 case 'DELETE':
322 case 'PATCH':
323 return current_user_can( 'administrator' );
324 }
325
326 return false;
327 }
328
329 private static $notify_deprecated = true;
330
331 private function deprecated() {
332 add_action( 'elementor/init', function () {
333 if ( ! self::$notify_deprecated ) {
334 return;
335 }
336
337 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function(
338 'Elementor\Data\Manager',
339 '3.5.0',
340 'Elementor\Data\V2\Manager'
341 );
342
343 self::$notify_deprecated = false;
344 } );
345 }
346 }
347