PluginProbe
Elementor Website Builder – more than just a page builder / 4.2.0
Elementor Website Builder – more than just a page builder v4.2.0
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 4.2.0, at data/base/controller.php

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