PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.2
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.2
6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 5.6.2 All 33 releases
automatorwp / libraries / cmb2 / includes / rest-api / CMB2_REST_Controller.php

CMB2_REST_Controller.php in AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI 6.0.2, at libraries/cmb2/includes/rest-api/CMB2_REST_Controller.php

452 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if( !defined( 'ABSPATH' ) ) exit;
4
5 if ( ! class_exists( 'WP_REST_Controller' ) ) {
6 // Shim the WP_REST_Controller class if wp-api plugin not installed, & not in core.
7 require_once cmb2_dir( 'includes/shim/WP_REST_Controller.php' );
8 }
9
10 /**
11 * Creates CMB2 objects/fields endpoint for WordPress REST API.
12 * Allows access to fields registered to a specific post type and more.
13 *
14 * @todo Add better documentation.
15 * @todo Research proper schema.
16 *
17 * @since 2.2.3
18 *
19 * @category WordPress_Plugin
20 * @package CMB2
21 * @author CMB2 team
22 * @license GPL-2.0+
23 * @link https://cmb2.io
24 */
25 abstract class CMB2_REST_Controller extends WP_REST_Controller {
26
27 /**
28 * The namespace of this controller's route.
29 *
30 * @var string
31 */
32 protected $namespace = CMB2_REST::NAME_SPACE;
33
34 /**
35 * The base of this controller's route.
36 *
37 * @var string
38 */
39 protected $rest_base;
40
41 /**
42 * The current request object
43 *
44 * @var WP_REST_Request $request
45 * @since 2.2.3
46 */
47 public $request;
48
49 /**
50 * The current server object
51 *
52 * @var WP_REST_Server $server
53 * @since 2.2.3
54 */
55 public $server;
56
57 /**
58 * Box object id
59 *
60 * @var mixed
61 * @since 2.2.3
62 */
63 public $object_id = null;
64
65 /**
66 * Box object type
67 *
68 * @var string
69 * @since 2.2.3
70 */
71 public $object_type = '';
72
73 /**
74 * CMB2 Instance
75 *
76 * @var CMB2_REST
77 */
78 protected $rest_box;
79
80 /**
81 * CMB2_Field Instance
82 *
83 * @var CMB2_Field
84 */
85 protected $field;
86
87 /**
88 * The initial route
89 *
90 * @var string
91 * @since 2.2.3
92 */
93 protected static $route = '';
94
95 /**
96 * Defines which endpoint the initial request is.
97 *
98 * @var string $request_type
99 * @since 2.2.3
100 */
101 protected static $request_type = '';
102
103 /**
104 * Constructor
105 *
106 * @since 2.2.3
107 */
108 public function __construct( WP_REST_Server $wp_rest_server ) {
109 $this->server = $wp_rest_server;
110 }
111
112 /**
113 * A wrapper for `apply_filters` which checks for box/field properties to hook to the filter.
114 *
115 * Checks if a CMB object callback property exists, and if it does,
116 * hook it to the permissions filter.
117 *
118 * @since 2.2.3
119 *
120 * @param string $filter The name of the filter to apply.
121 * @param bool $default_access The default access for this request.
122 *
123 * @return void
124 */
125 public function maybe_hook_callback_and_apply_filters( $filter, $default_access ) {
126 if ( ! $this->rest_box && $this->request->get_param( 'cmb_id' ) ) {
127 $this->rest_box = CMB2_REST::get_rest_box( $this->request->get_param( 'cmb_id' ) );
128 }
129
130 $default_access = $this->maybe_hook_registered_callback( $filter, $default_access );
131
132 /**
133 * Apply the permissions check filter.
134 *
135 * @since 2.2.3
136 *
137 * @param bool $default_access Whether this CMB2 endpoint can be accessed.
138 * @param object $controller This CMB2_REST_Controller object.
139 */
140 $default_access = apply_filters( $filter, $default_access, $this );
141
142 $this->maybe_unhook_registered_callback( $filter );
143
144 return $default_access;
145 }
146
147 /**
148 * Checks if the CMB2 box has any registered callback parameters for the given filter.
149 *
150 * The registered handlers will have a property name which matches the filter, except:
151 * - The 'cmb2_api' prefix will be removed
152 * - A '_cb' suffix will be added (to stay inline with other '*_cb' parameters).
153 *
154 * @since 2.2.3
155 *
156 * @param string $filter The filter name.
157 * @param bool $default_val The default filter value.
158 *
159 * @return bool The possibly-modified filter value (if the '*_cb' param is non-callable).
160 */
161 public function maybe_hook_registered_callback( $filter, $default_val ) {
162 if ( ! $this->rest_box || is_wp_error( $this->rest_box ) ) {
163 return $default_val;
164 }
165
166 // Hook box specific filter callbacks.
167 $val = $this->rest_box->cmb->maybe_hook_parameter( $filter, $default_val );
168 if ( null !== $val ) {
169 $default_val = $val;
170 }
171
172 return $default_val;
173 }
174
175 /**
176 * Unhooks any CMB2 box registered callback parameters for the given filter.
177 *
178 * @since 2.2.3
179 *
180 * @param string $filter The filter name.
181 *
182 * @return void
183 */
184 public function maybe_unhook_registered_callback( $filter ) {
185 if ( ! $this->rest_box || is_wp_error( $this->rest_box ) ) {
186 return;
187 }
188
189 // Unhook box specific filter callbacks.
190 $this->rest_box->cmb->maybe_hook_parameter( $filter, null, 'remove_filter' );
191 }
192
193 /**
194 * Prepare a CMB2 object for serialization
195 *
196 * @since 2.2.3
197 *
198 * @param mixed $data
199 * @return array $data
200 */
201 public function prepare_item( $data ) {
202 return $this->prepare_item_for_response( $data, $this->request );
203 }
204
205 /**
206 * Output buffers a callback and returns the results.
207 *
208 * @since 2.2.3
209 *
210 * @param mixed $cb Callable function/method.
211 * @return mixed Results of output buffer after calling function/method.
212 */
213 public function get_cb_results( $cb ) {
214 $args = func_get_args();
215 array_shift( $args ); // ignore $cb
216 ob_start();
217 call_user_func_array( $cb, $args );
218
219 return ob_get_clean();
220 }
221
222 /**
223 * Prepare the CMB2 item for the REST response.
224 *
225 * @since 2.2.3
226 *
227 * @param mixed $item WordPress representation of the item.
228 * @param WP_REST_Request $request Request object.
229 * @return WP_REST_Response $response
230 */
231 public function prepare_item_for_response( $data, $request = null ) {
232 $data = $this->filter_response_by_context( $data, $this->request['context'] );
233
234 /**
235 * Filter the prepared CMB2 item response.
236 *
237 * @since 2.2.3
238 *
239 * @param mixed $data Prepared data
240 * @param object $request The WP_REST_Request object
241 * @param object $cmb2_endpoints This endpoints object
242 */
243 return apply_filters( 'cmb2_rest_prepare', rest_ensure_response( $data ), $this->request, $this );
244 }
245
246 /**
247 * Initiates the request property and the rest_box property if box is readable.
248 *
249 * @since 2.2.3
250 *
251 * @param WP_REST_Request $request Request object.
252 * @param string $request_type A description of the type of request being made.
253 *
254 * @return void
255 */
256 protected function initiate_rest_read_box( $request, $request_type ) {
257 $this->initiate_rest_box( $request, $request_type );
258
259 if ( ! is_wp_error( $this->rest_box ) && ! $this->rest_box->rest_read ) {
260 $this->rest_box = new WP_Error( 'cmb2_rest_no_read_error', __( 'This box does not have read permissions.', 'cmb2' ), array(
261 'status' => 403,
262 ) );
263 }
264 }
265
266 /**
267 * Initiates the request property and the rest_box property if box is writeable.
268 *
269 * @since 2.2.3
270 *
271 * @param WP_REST_Request $request Request object.
272 * @param string $request_type A description of the type of request being made.
273 *
274 * @return void
275 */
276 protected function initiate_rest_edit_box( $request, $request_type ) {
277 $this->initiate_rest_box( $request, $request_type );
278
279 if ( ! is_wp_error( $this->rest_box ) && ! $this->rest_box->rest_edit ) {
280 $this->rest_box = new WP_Error( 'cmb2_rest_no_write_error', __( 'This box does not have write permissions.', 'cmb2' ), array(
281 'status' => 403,
282 ) );
283 }
284 }
285
286 /**
287 * Initiates the request property and the rest_box property.
288 *
289 * @since 2.2.3
290 *
291 * @param WP_REST_Request $request Request object.
292 * @param string $request_type A description of the type of request being made.
293 *
294 * @return void
295 */
296 protected function initiate_rest_box( $request, $request_type ) {
297 $this->initiate_request( $request, $request_type );
298
299 $this->rest_box = CMB2_REST::get_rest_box( $this->request->get_param( 'cmb_id' ) );
300
301 if ( ! $this->rest_box ) {
302
303 $this->rest_box = new WP_Error( 'cmb2_rest_box_not_found_error', __( 'No box found by that id. A box needs to be registered with the "show_in_rest" parameter configured.', 'cmb2' ), array(
304 'status' => 403,
305 ) );
306
307 } else {
308
309 if ( isset( $this->request['object_id'] ) ) {
310 $this->rest_box->cmb->object_id( sanitize_text_field( $this->request['object_id'] ) );
311 }
312
313 if ( isset( $this->request['object_type'] ) ) {
314 $this->rest_box->cmb->object_type( sanitize_text_field( $this->request['object_type'] ) );
315 }
316 }
317 }
318
319 /**
320 * Initiates the request property and sets up the initial static properties.
321 *
322 * @since 2.2.3
323 *
324 * @param WP_REST_Request $request Request object.
325 * @param string $request_type A description of the type of request being made.
326 *
327 * @return void
328 */
329 public function initiate_request( $request, $request_type ) {
330 $this->request = $request;
331
332 if ( ! isset( $this->request['context'] ) || empty( $this->request['context'] ) ) {
333 $this->request['context'] = 'view';
334 }
335
336 if ( ! self::$request_type ) {
337 self::$request_type = $request_type;
338 }
339
340 if ( ! self::$route ) {
341 self::$route = $this->request->get_route();
342 }
343 }
344
345 /**
346 * Useful when getting `_embed`-ed items
347 *
348 * @since 2.2.3
349 *
350 * @return string Initial requested type.
351 */
352 public static function get_intial_request_type() {
353 return self::$request_type;
354 }
355
356 /**
357 * Useful when getting `_embed`-ed items
358 *
359 * @since 2.2.3
360 *
361 * @return string Initial requested route.
362 */
363 public static function get_intial_route() {
364 return self::$route;
365 }
366
367 /**
368 * Get CMB2 fields schema, conforming to JSON Schema
369 *
370 * @since 2.2.3
371 *
372 * @return array
373 */
374 public function get_item_schema() {
375 $schema = array(
376 '$schema' => 'http://json-schema.org/draft-04/schema#',
377 'title' => 'CMB2',
378 'type' => 'object',
379 'properties' => array(
380 'description' => array(
381 'description' => __( 'A human-readable description of the object.', 'cmb2' ),
382 'type' => 'string',
383 'context' => array(
384 'view',
385 ),
386 ),
387 'name' => array(
388 'description' => __( 'The id for the object.', 'cmb2' ),
389 'type' => 'integer',
390 'context' => array(
391 'view',
392 ),
393 ),
394 'name' => array(
395 'description' => __( 'The title for the object.', 'cmb2' ),
396 'type' => 'string',
397 'context' => array(
398 'view',
399 ),
400 ),
401 ),
402 );
403
404 return $this->add_additional_fields_schema( $schema );
405 }
406
407 /**
408 * Return an array of contextual links for endpoint/object
409 *
410 * @link http://v2.wp-api.org/extending/linking/
411 * @link http://www.iana.org/assignments/link-relations/link-relations.xhtml
412 *
413 * @since 2.2.3
414 *
415 * @param mixed $object Object to build links from.
416 *
417 * @return array Array of links
418 */
419 abstract protected function prepare_links( $object );
420
421 /**
422 * Get whitelisted query strings from URL for appending to link URLS.
423 *
424 * @since 2.2.3
425 *
426 * @return string URL query stringl
427 */
428 public function get_query_string() {
429 $defaults = array(
430 'object_id' => 0,
431 'object_type' => '',
432 '_rendered' => '',
433 // '_embed' => '',
434 );
435
436 $query_string = '';
437
438 foreach ( $defaults as $key => $value ) {
439 if ( isset( $this->request[ $key ] ) ) {
440 $query_string .= $query_string ? '&' : '?';
441 $query_string .= $key;
442 if ( $value = sanitize_text_field( $this->request[ $key ] ) ) {
443 $query_string .= '=' . $value;
444 }
445 }
446 }
447
448 return $query_string;
449 }
450
451 }
452