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

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