PluginProbe
WPGet API – Connect to any external REST API / 1.4.6
WPGet API – Connect to any external REST API v1.4.6
1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.10 2.2.2 2.2.3 All 97 releases
wpgetapi / lib / cmb2 / includes / shim / WP_REST_Controller.php

WP_REST_Controller.php in WPGet API – Connect to any external REST API 1.4.6, at lib/cmb2/includes/shim/WP_REST_Controller.php

542 lines 15.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3
4 abstract class WP_REST_Controller {
5
6 /**
7 * The namespace of this controller's route.
8 *
9 * @var string
10 */
11 protected $namespace;
12
13 /**
14 * The base of this controller's route.
15 *
16 * @var string
17 */
18 protected $rest_base;
19
20 /**
21 * Register the routes for the objects of the controller.
22 */
23 public function register_routes() {
24 /* translators: %s: register_routes() */
25 _doing_it_wrong( 'WP_REST_Controller::register_routes', sprintf( __( "Method '%s' must be overridden." ), __METHOD__ ), '4.7' );
26 }
27
28 /**
29 * Check if a given request has access to get items.
30 *
31 * @param WP_REST_Request $request Full data about the request.
32 * @return WP_Error|boolean
33 */
34 public function get_items_permissions_check( $request ) {
35 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
36 'status' => 405,
37 ) );
38 }
39
40 /**
41 * Get a collection of items.
42 *
43 * @param WP_REST_Request $request Full data about the request.
44 * @return WP_Error|WP_REST_Response
45 */
46 public function get_items( $request ) {
47 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
48 'status' => 405,
49 ) );
50 }
51
52 /**
53 * Check if a given request has access to get a specific item.
54 *
55 * @param WP_REST_Request $request Full data about the request.
56 * @return WP_Error|boolean
57 */
58 public function get_item_permissions_check( $request ) {
59 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
60 'status' => 405,
61 ) );
62 }
63
64 /**
65 * Get one item from the collection.
66 *
67 * @param WP_REST_Request $request Full data about the request.
68 * @return WP_Error|WP_REST_Response
69 */
70 public function get_item( $request ) {
71 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
72 'status' => 405,
73 ) );
74 }
75
76 /**
77 * Check if a given request has access to create items.
78 *
79 * @param WP_REST_Request $request Full data about the request.
80 * @return WP_Error|boolean
81 */
82 public function create_item_permissions_check( $request ) {
83 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
84 'status' => 405,
85 ) );
86 }
87
88 /**
89 * Create one item from the collection.
90 *
91 * @param WP_REST_Request $request Full data about the request.
92 * @return WP_Error|WP_REST_Response
93 */
94 public function create_item( $request ) {
95 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
96 'status' => 405,
97 ) );
98 }
99
100 /**
101 * Check if a given request has access to update a specific item.
102 *
103 * @param WP_REST_Request $request Full data about the request.
104 * @return WP_Error|boolean
105 */
106 public function update_item_permissions_check( $request ) {
107 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
108 'status' => 405,
109 ) );
110 }
111
112 /**
113 * Update one item from the collection.
114 *
115 * @param WP_REST_Request $request Full data about the request.
116 * @return WP_Error|WP_REST_Response
117 */
118 public function update_item( $request ) {
119 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
120 'status' => 405,
121 ) );
122 }
123
124 /**
125 * Check if a given request has access to delete a specific item.
126 *
127 * @param WP_REST_Request $request Full data about the request.
128 * @return WP_Error|boolean
129 */
130 public function delete_item_permissions_check( $request ) {
131 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
132 'status' => 405,
133 ) );
134 }
135
136 /**
137 * Delete one item from the collection.
138 *
139 * @param WP_REST_Request $request Full data about the request.
140 * @return WP_Error|WP_REST_Response
141 */
142 public function delete_item( $request ) {
143 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
144 'status' => 405,
145 ) );
146 }
147
148 /**
149 * Prepare the item for create or update operation.
150 *
151 * @param WP_REST_Request $request Request object.
152 * @return WP_Error|object $prepared_item
153 */
154 protected function prepare_item_for_database( $request ) {
155 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
156 'status' => 405,
157 ) );
158 }
159
160 /**
161 * Prepare the item for the REST response.
162 *
163 * @param mixed $item WordPress representation of the item.
164 * @param WP_REST_Request $request Request object.
165 * @return WP_REST_Response $response
166 */
167 public function prepare_item_for_response( $item, $request ) {
168 return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass." ), __METHOD__ ), array(
169 'status' => 405,
170 ) );
171 }
172
173 /**
174 * Prepare a response for inserting into a collection.
175 *
176 * @param WP_REST_Response $response Response object.
177 * @return array Response data, ready for insertion into collection data.
178 */
179 public function prepare_response_for_collection( $response ) {
180 if ( ! ( $response instanceof WP_REST_Response ) ) {
181 return $response;
182 }
183
184 $data = (array) $response->get_data();
185 $server = rest_get_server();
186
187 if ( method_exists( $server, 'get_compact_response_links' ) ) {
188 $links = call_user_func( array( $server, 'get_compact_response_links' ), $response );
189 } else {
190 $links = call_user_func( array( $server, 'get_response_links' ), $response );
191 }
192
193 if ( ! empty( $links ) ) {
194 $data['_links'] = $links;
195 }
196
197 return $data;
198 }
199
200 /**
201 * Filter a response based on the context defined in the schema.
202 *
203 * @param array $data
204 * @param string $context
205 * @return array
206 */
207 public function filter_response_by_context( $data, $context ) {
208
209 $schema = $this->get_item_schema();
210 foreach ( $data as $key => $value ) {
211 if ( empty( $schema['properties'][ $key ] ) || empty( $schema['properties'][ $key ]['context'] ) ) {
212 continue;
213 }
214
215 if ( ! in_array( $context, $schema['properties'][ $key ]['context'] ) ) {
216 unset( $data[ $key ] );
217 continue;
218 }
219
220 if ( 'object' === $schema['properties'][ $key ]['type'] && ! empty( $schema['properties'][ $key ]['properties'] ) ) {
221 foreach ( $schema['properties'][ $key ]['properties'] as $attribute => $details ) {
222 if ( empty( $details['context'] ) ) {
223 continue;
224 }
225 if ( ! in_array( $context, $details['context'] ) ) {
226 if ( isset( $data[ $key ][ $attribute ] ) ) {
227 unset( $data[ $key ][ $attribute ] );
228 }
229 }
230 }
231 }
232 }
233
234 return $data;
235 }
236
237 /**
238 * Get the item's schema, conforming to JSON Schema.
239 *
240 * @return array
241 */
242 public function get_item_schema() {
243 return $this->add_additional_fields_schema( array() );
244 }
245
246 /**
247 * Get the item's schema for display / public consumption purposes.
248 *
249 * @return array
250 */
251 public function get_public_item_schema() {
252
253 $schema = $this->get_item_schema();
254
255 foreach ( $schema['properties'] as &$property ) {
256 if ( isset( $property['arg_options'] ) ) {
257 unset( $property['arg_options'] );
258 }
259 }
260
261 return $schema;
262 }
263
264 /**
265 * Get the query params for collections.
266 *
267 * @return array
268 */
269 public function get_collection_params() {
270 return array(
271 'context' => $this->get_context_param(),
272 'page' => array(
273 'description' => __( 'Current page of the collection.' ),
274 'type' => 'integer',
275 'default' => 1,
276 'sanitize_callback' => 'absint',
277 'validate_callback' => 'rest_validate_request_arg',
278 'minimum' => 1,
279 ),
280 'per_page' => array(
281 'description' => __( 'Maximum number of items to be returned in result set.' ),
282 'type' => 'integer',
283 'default' => 10,
284 'minimum' => 1,
285 'maximum' => 100,
286 'sanitize_callback' => 'absint',
287 'validate_callback' => 'rest_validate_request_arg',
288 ),
289 'search' => array(
290 'description' => __( 'Limit results to those matching a string.' ),
291 'type' => 'string',
292 'sanitize_callback' => 'sanitize_text_field',
293 'validate_callback' => 'rest_validate_request_arg',
294 ),
295 );
296 }
297
298 /**
299 * Get the magical context param.
300 *
301 * Ensures consistent description between endpoints, and populates enum from schema.
302 *
303 * @param array $args
304 * @return array
305 */
306 public function get_context_param( $args = array() ) {
307 $param_details = array(
308 'description' => __( 'Scope under which the request is made; determines fields present in response.' ),
309 'type' => 'string',
310 'sanitize_callback' => 'sanitize_key',
311 'validate_callback' => 'rest_validate_request_arg',
312 );
313 $schema = $this->get_item_schema();
314 if ( empty( $schema['properties'] ) ) {
315 return array_merge( $param_details, $args );
316 }
317 $contexts = array();
318 foreach ( $schema['properties'] as $attributes ) {
319 if ( ! empty( $attributes['context'] ) ) {
320 $contexts = array_merge( $contexts, $attributes['context'] );
321 }
322 }
323 if ( ! empty( $contexts ) ) {
324 $param_details['enum'] = array_unique( $contexts );
325 rsort( $param_details['enum'] );
326 }
327 return array_merge( $param_details, $args );
328 }
329
330 /**
331 * Add the values from additional fields to a data object.
332 *
333 * @param array $object
334 * @param WP_REST_Request $request
335 * @return array modified object with additional fields.
336 */
337 protected function add_additional_fields_to_object( $object, $request ) {
338
339 $additional_fields = $this->get_additional_fields();
340
341 foreach ( $additional_fields as $field_name => $field_options ) {
342
343 if ( ! $field_options['get_callback'] ) {
344 continue;
345 }
346
347 $object[ $field_name ] = call_user_func( $field_options['get_callback'], $object, $field_name, $request, $this->get_object_type() );
348 }
349
350 return $object;
351 }
352
353 /**
354 * Update the values of additional fields added to a data object.
355 *
356 * @param array $object
357 * @param WP_REST_Request $request
358 */
359 protected function update_additional_fields_for_object( $object, $request ) {
360
361 $additional_fields = $this->get_additional_fields();
362
363 foreach ( $additional_fields as $field_name => $field_options ) {
364
365 if ( ! $field_options['update_callback'] ) {
366 continue;
367 }
368
369 // Don't run the update callbacks if the data wasn't passed in the request.
370 if ( ! isset( $request[ $field_name ] ) ) {
371 continue;
372 }
373
374 call_user_func( $field_options['update_callback'], $request[ $field_name ], $object, $field_name, $request, $this->get_object_type() );
375 }
376 }
377
378 /**
379 * Add the schema from additional fields to an schema array.
380 *
381 * The type of object is inferred from the passed schema.
382 *
383 * @param array $schema Schema array.
384 */
385 protected function add_additional_fields_schema( $schema ) {
386 if ( empty( $schema['title'] ) ) {
387 return $schema;
388 }
389
390 /**
391 * Can't use $this->get_object_type otherwise we cause an inf loop.
392 */
393 $object_type = $schema['title'];
394
395 $additional_fields = $this->get_additional_fields( $object_type );
396
397 foreach ( $additional_fields as $field_name => $field_options ) {
398 if ( ! $field_options['schema'] ) {
399 continue;
400 }
401
402 $schema['properties'][ $field_name ] = $field_options['schema'];
403 }
404
405 return $schema;
406 }
407
408 /**
409 * Get all the registered additional fields for a given object-type.
410 *
411 * @param string $object_type
412 * @return array
413 */
414 protected function get_additional_fields( $object_type = null ) {
415
416 if ( ! $object_type ) {
417 $object_type = $this->get_object_type();
418 }
419
420 if ( ! $object_type ) {
421 return array();
422 }
423
424 global $wp_rest_additional_fields;
425
426 if ( ! $wp_rest_additional_fields || ! isset( $wp_rest_additional_fields[ $object_type ] ) ) {
427 return array();
428 }
429
430 return $wp_rest_additional_fields[ $object_type ];
431 }
432
433 /**
434 * Get the object type this controller is responsible for managing.
435 *
436 * @return string
437 */
438 protected function get_object_type() {
439 $schema = $this->get_item_schema();
440
441 if ( ! $schema || ! isset( $schema['title'] ) ) {
442 return null;
443 }
444
445 return $schema['title'];
446 }
447
448 /**
449 * Get an array of endpoint arguments from the item schema for the controller.
450 *
451 * @param string $method HTTP method of the request. The arguments
452 * for `CREATABLE` requests are checked for required
453 * values and may fall-back to a given default, this
454 * is not done on `EDITABLE` requests. Default is
455 * WP_REST_Server::CREATABLE.
456 * @return array $endpoint_args
457 */
458 public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) {
459
460 $schema = $this->get_item_schema();
461 $schema_properties = ! empty( $schema['properties'] ) ? $schema['properties'] : array();
462 $endpoint_args = array();
463
464 foreach ( $schema_properties as $field_id => $params ) {
465
466 // Arguments specified as `readonly` are not allowed to be set.
467 if ( ! empty( $params['readonly'] ) ) {
468 continue;
469 }
470
471 $endpoint_args[ $field_id ] = array(
472 'validate_callback' => 'rest_validate_request_arg',
473 'sanitize_callback' => 'rest_sanitize_request_arg',
474 );
475
476 if ( isset( $params['description'] ) ) {
477 $endpoint_args[ $field_id ]['description'] = $params['description'];
478 }
479
480 if ( WP_REST_Server::CREATABLE === $method && isset( $params['default'] ) ) {
481 $endpoint_args[ $field_id ]['default'] = $params['default'];
482 }
483
484 if ( WP_REST_Server::CREATABLE === $method && ! empty( $params['required'] ) ) {
485 $endpoint_args[ $field_id ]['required'] = true;
486 }
487
488 foreach ( array( 'type', 'format', 'enum' ) as $schema_prop ) {
489 if ( isset( $params[ $schema_prop ] ) ) {
490 $endpoint_args[ $field_id ][ $schema_prop ] = $params[ $schema_prop ];
491 }
492 }
493
494 // Merge in any options provided by the schema property.
495 if ( isset( $params['arg_options'] ) ) {
496
497 // Only use required / default from arg_options on CREATABLE endpoints.
498 if ( WP_REST_Server::CREATABLE !== $method ) {
499 $params['arg_options'] = array_diff_key( $params['arg_options'], array(
500 'required' => '',
501 'default' => '',
502 ) );
503 }
504
505 $endpoint_args[ $field_id ] = array_merge( $endpoint_args[ $field_id ], $params['arg_options'] );
506 }
507 }// End foreach().
508
509 return $endpoint_args;
510 }
511
512 /**
513 * Retrieves post data given a post ID or post object.
514 *
515 * This is a subset of the functionality of the `get_post()` function, with
516 * the additional functionality of having `the_post` action done on the
517 * resultant post object. This is done so that plugins may manipulate the
518 * post that is used in the REST API.
519 *
520 * @see get_post()
521 * @global WP_Query $wp_query
522 *
523 * @param int|WP_Post $post Post ID or post object. Defaults to global $post.
524 * @return WP_Post|null A `WP_Post` object when successful.
525 */
526 public function get_post( $post ) {
527 $post_obj = get_post( $post );
528
529 /**
530 * Filter the post.
531 *
532 * Allows plugins to filter the post object as returned by `\WP_REST_Controller::get_post()`.
533 *
534 * @param WP_Post|null $post_obj The post object as returned by `get_post()`.
535 * @param int|WP_Post $post The original value used to obtain the post object.
536 */
537 $post = apply_filters( 'rest_the_post', $post_obj, $post );
538
539 return $post;
540 }
541 }
542