[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * REST API: WP_REST_Post_Types_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.7.0 8 */ 9 10 /** 11 * Core class to access post types via the REST API. 12 * 13 * @since 4.7.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Post_Types_Controller extends WP_REST_Controller { 18 19 /** 20 * Constructor. 21 * 22 * @since 4.7.0 23 */ 24 public function __construct() { 25 $this->namespace = 'wp/v2'; 26 $this->rest_base = 'types'; 27 } 28 29 /** 30 * Registers the routes for post types. 31 * 32 * @since 4.7.0 33 * 34 * @see register_rest_route() 35 */ 36 public function register_routes() { 37 38 register_rest_route( 39 $this->namespace, 40 '/' . $this->rest_base, 41 array( 42 array( 43 'methods' => WP_REST_Server::READABLE, 44 'callback' => array( $this, 'get_items' ), 45 'permission_callback' => array( $this, 'get_items_permissions_check' ), 46 'args' => $this->get_collection_params(), 47 ), 48 'schema' => array( $this, 'get_public_item_schema' ), 49 ) 50 ); 51 52 register_rest_route( 53 $this->namespace, 54 '/' . $this->rest_base . '/(?P<type>[\w-]+)', 55 array( 56 'args' => array( 57 'type' => array( 58 'description' => __( 'An alphanumeric identifier for the post type.' ), 59 'type' => 'string', 60 ), 61 ), 62 array( 63 'methods' => WP_REST_Server::READABLE, 64 'callback' => array( $this, 'get_item' ), 65 'permission_callback' => '__return_true', 66 'args' => array( 67 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 68 ), 69 ), 70 'schema' => array( $this, 'get_public_item_schema' ), 71 ) 72 ); 73 } 74 75 /** 76 * Checks whether a given request has permission to read types. 77 * 78 * @since 4.7.0 79 * 80 * @param WP_REST_Request $request Full details about the request. 81 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 82 */ 83 public function get_items_permissions_check( $request ) { 84 if ( 'edit' === $request['context'] ) { 85 $types = get_post_types( array( 'show_in_rest' => true ), 'objects' ); 86 87 foreach ( $types as $type ) { 88 if ( current_user_can( $type->cap->edit_posts ) ) { 89 return true; 90 } 91 } 92 93 return new WP_Error( 94 'rest_cannot_view', 95 __( 'Sorry, you are not allowed to edit posts in this post type.' ), 96 array( 'status' => rest_authorization_required_code() ) 97 ); 98 } 99 100 return true; 101 } 102 103 /** 104 * Retrieves all public post types. 105 * 106 * @since 4.7.0 107 * 108 * @param WP_REST_Request $request Full details about the request. 109 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 110 */ 111 public function get_items( $request ) { 112 $data = array(); 113 $types = get_post_types( array( 'show_in_rest' => true ), 'objects' ); 114 115 foreach ( $types as $type ) { 116 if ( 'edit' === $request['context'] && ! current_user_can( $type->cap->edit_posts ) ) { 117 continue; 118 } 119 120 $post_type = $this->prepare_item_for_response( $type, $request ); 121 $data[ $type->name ] = $this->prepare_response_for_collection( $post_type ); 122 } 123 124 return rest_ensure_response( $data ); 125 } 126 127 /** 128 * Retrieves a specific post type. 129 * 130 * @since 4.7.0 131 * 132 * @param WP_REST_Request $request Full details about the request. 133 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 134 */ 135 public function get_item( $request ) { 136 $obj = get_post_type_object( $request['type'] ); 137 138 if ( empty( $obj ) ) { 139 return new WP_Error( 140 'rest_type_invalid', 141 __( 'Invalid post type.' ), 142 array( 'status' => 404 ) 143 ); 144 } 145 146 if ( empty( $obj->show_in_rest ) ) { 147 return new WP_Error( 148 'rest_cannot_read_type', 149 __( 'Cannot view post type.' ), 150 array( 'status' => rest_authorization_required_code() ) 151 ); 152 } 153 154 if ( 'edit' === $request['context'] && ! current_user_can( $obj->cap->edit_posts ) ) { 155 return new WP_Error( 156 'rest_forbidden_context', 157 __( 'Sorry, you are not allowed to edit posts in this post type.' ), 158 array( 'status' => rest_authorization_required_code() ) 159 ); 160 } 161 162 $data = $this->prepare_item_for_response( $obj, $request ); 163 164 return rest_ensure_response( $data ); 165 } 166 167 /** 168 * Prepares a post type object for serialization. 169 * 170 * @since 4.7.0 171 * @since 5.9.0 Renamed `$post_type` to `$item` to match parent class for PHP 8 named parameter support. 172 * 173 * @param WP_Post_Type $item Post type object. 174 * @param WP_REST_Request $request Full details about the request. 175 * @return WP_REST_Response Response object. 176 */ 177 public function prepare_item_for_response( $item, $request ) { 178 // Restores the more descriptive, specific name for use within this method. 179 $post_type = $item; 180 181 $taxonomies = wp_list_filter( get_object_taxonomies( $post_type->name, 'objects' ), array( 'show_in_rest' => true ) ); 182 $taxonomies = wp_list_pluck( $taxonomies, 'name' ); 183 $base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name; 184 $namespace = ! empty( $post_type->rest_namespace ) ? $post_type->rest_namespace : 'wp/v2'; 185 $supports = get_all_post_type_supports( $post_type->name ); 186 187 $fields = $this->get_fields_for_response( $request ); 188 $data = array(); 189 190 if ( rest_is_field_included( 'capabilities', $fields ) ) { 191 $data['capabilities'] = $post_type->cap; 192 } 193 194 if ( rest_is_field_included( 'description', $fields ) ) { 195 $data['description'] = $post_type->description; 196 } 197 198 if ( rest_is_field_included( 'hierarchical', $fields ) ) { 199 $data['hierarchical'] = $post_type->hierarchical; 200 } 201 202 if ( rest_is_field_included( 'has_archive', $fields ) ) { 203 $data['has_archive'] = $post_type->has_archive; 204 } 205 206 if ( rest_is_field_included( 'visibility', $fields ) ) { 207 $data['visibility'] = array( 208 'show_in_nav_menus' => (bool) $post_type->show_in_nav_menus, 209 'show_ui' => (bool) $post_type->show_ui, 210 ); 211 } 212 213 if ( rest_is_field_included( 'viewable', $fields ) ) { 214 $data['viewable'] = is_post_type_viewable( $post_type ); 215 } 216 217 if ( rest_is_field_included( 'labels', $fields ) ) { 218 $data['labels'] = $post_type->labels; 219 } 220 221 if ( rest_is_field_included( 'name', $fields ) ) { 222 $data['name'] = $post_type->label; 223 } 224 225 if ( rest_is_field_included( 'slug', $fields ) ) { 226 $data['slug'] = $post_type->name; 227 } 228 229 if ( rest_is_field_included( 'icon', $fields ) ) { 230 $data['icon'] = $post_type->menu_icon; 231 } 232 233 if ( rest_is_field_included( 'supports', $fields ) ) { 234 $data['supports'] = $supports; 235 } 236 237 if ( rest_is_field_included( 'taxonomies', $fields ) ) { 238 $data['taxonomies'] = array_values( $taxonomies ); 239 } 240 241 if ( rest_is_field_included( 'rest_base', $fields ) ) { 242 $data['rest_base'] = $base; 243 } 244 245 if ( rest_is_field_included( 'rest_namespace', $fields ) ) { 246 $data['rest_namespace'] = $namespace; 247 } 248 249 if ( rest_is_field_included( 'template', $fields ) ) { 250 $data['template'] = $post_type->template ?? array(); 251 } 252 253 if ( rest_is_field_included( 'template_lock', $fields ) ) { 254 $data['template_lock'] = ! empty( $post_type->template_lock ) ? $post_type->template_lock : false; 255 } 256 257 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 258 $data = $this->add_additional_fields_to_object( $data, $request ); 259 $data = $this->filter_response_by_context( $data, $context ); 260 261 // Wrap the data in a response object. 262 $response = rest_ensure_response( $data ); 263 264 if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { 265 $response->add_links( $this->prepare_links( $post_type ) ); 266 } 267 268 /** 269 * Filters a post type returned from the REST API. 270 * 271 * Allows modification of the post type data right before it is returned. 272 * 273 * @since 4.7.0 274 * 275 * @param WP_REST_Response $response The response object. 276 * @param WP_Post_Type $post_type The original post type object. 277 * @param WP_REST_Request $request Request used to generate the response. 278 */ 279 return apply_filters( 'rest_prepare_post_type', $response, $post_type, $request ); 280 } 281 282 /** 283 * Prepares links for the request. 284 * 285 * @since 6.1.0 286 * 287 * @param WP_Post_Type $post_type The post type. 288 * @return array Links for the given post type. 289 */ 290 protected function prepare_links( $post_type ) { 291 return array( 292 'collection' => array( 293 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), 294 ), 295 'https://api.w.org/items' => array( 296 'href' => rest_url( rest_get_route_for_post_type_items( $post_type->name ) ), 297 ), 298 ); 299 } 300 301 /** 302 * Retrieves the post type's schema, conforming to JSON Schema. 303 * 304 * @since 4.7.0 305 * @since 4.8.0 The `supports` property was added. 306 * @since 5.9.0 The `visibility` and `rest_namespace` properties were added. 307 * @since 6.1.0 The `icon` property was added. 308 * 309 * @return array Item schema data. 310 */ 311 public function get_item_schema() { 312 if ( $this->schema ) { 313 return $this->add_additional_fields_schema( $this->schema ); 314 } 315 316 $schema = array( 317 '$schema' => 'http://json-schema.org/draft-04/schema#', 318 'title' => 'type', 319 'type' => 'object', 320 'properties' => array( 321 'capabilities' => array( 322 'description' => __( 'All capabilities used by the post type.' ), 323 'type' => 'object', 324 'context' => array( 'edit' ), 325 'readonly' => true, 326 ), 327 'description' => array( 328 'description' => __( 'A human-readable description of the post type.' ), 329 'type' => 'string', 330 'context' => array( 'view', 'edit' ), 331 'readonly' => true, 332 ), 333 'hierarchical' => array( 334 'description' => __( 'Whether or not the post type should have children.' ), 335 'type' => 'boolean', 336 'context' => array( 'view', 'edit' ), 337 'readonly' => true, 338 ), 339 'viewable' => array( 340 'description' => __( 'Whether or not the post type can be viewed.' ), 341 'type' => 'boolean', 342 'context' => array( 'edit' ), 343 'readonly' => true, 344 ), 345 'labels' => array( 346 'description' => __( 'Human-readable labels for the post type for various contexts.' ), 347 'type' => 'object', 348 'context' => array( 'edit' ), 349 'readonly' => true, 350 ), 351 'name' => array( 352 'description' => __( 'The title for the post type.' ), 353 'type' => 'string', 354 'context' => array( 'view', 'edit', 'embed' ), 355 'readonly' => true, 356 ), 357 'slug' => array( 358 'description' => __( 'An alphanumeric identifier for the post type.' ), 359 'type' => 'string', 360 'context' => array( 'view', 'edit', 'embed' ), 361 'readonly' => true, 362 ), 363 'supports' => array( 364 'description' => __( 'All features, supported by the post type.' ), 365 'type' => 'object', 366 'context' => array( 'edit' ), 367 'readonly' => true, 368 ), 369 'has_archive' => array( 370 'description' => __( 'If the value is a string, the value will be used as the archive slug. If the value is false the post type has no archive.' ), 371 'type' => array( 'string', 'boolean' ), 372 'context' => array( 'view', 'edit' ), 373 'readonly' => true, 374 ), 375 'taxonomies' => array( 376 'description' => __( 'Taxonomies associated with post type.' ), 377 'type' => 'array', 378 'items' => array( 379 'type' => 'string', 380 ), 381 'context' => array( 'view', 'edit' ), 382 'readonly' => true, 383 ), 384 'rest_base' => array( 385 'description' => __( 'REST base route for the post type.' ), 386 'type' => 'string', 387 'context' => array( 'view', 'edit', 'embed' ), 388 'readonly' => true, 389 ), 390 'rest_namespace' => array( 391 'description' => __( 'REST route\'s namespace for the post type.' ), 392 'type' => 'string', 393 'context' => array( 'view', 'edit', 'embed' ), 394 'readonly' => true, 395 ), 396 'visibility' => array( 397 'description' => __( 'The visibility settings for the post type.' ), 398 'type' => 'object', 399 'context' => array( 'edit' ), 400 'readonly' => true, 401 'properties' => array( 402 'show_ui' => array( 403 'description' => __( 'Whether to generate a default UI for managing this post type.' ), 404 'type' => 'boolean', 405 ), 406 'show_in_nav_menus' => array( 407 'description' => __( 'Whether to make the post type available for selection in navigation menus.' ), 408 'type' => 'boolean', 409 ), 410 ), 411 ), 412 'icon' => array( 413 'description' => __( 'The icon for the post type.' ), 414 'type' => array( 'string', 'null' ), 415 'context' => array( 'view', 'edit', 'embed' ), 416 'readonly' => true, 417 ), 418 'template' => array( 419 'type' => array( 'array' ), 420 'description' => __( 'The block template associated with the post type.' ), 421 'readonly' => true, 422 'context' => array( 'view', 'edit', 'embed' ), 423 ), 424 'template_lock' => array( 425 'type' => array( 'string', 'boolean' ), 426 'enum' => array( 'all', 'insert', 'contentOnly', false ), 427 'description' => __( 'The template_lock associated with the post type, or false if none.' ), 428 'readonly' => true, 429 'context' => array( 'view', 'edit', 'embed' ), 430 ), 431 ), 432 ); 433 434 $this->schema = $schema; 435 436 return $this->add_additional_fields_schema( $this->schema ); 437 } 438 439 /** 440 * Retrieves the query params for collections. 441 * 442 * @since 4.7.0 443 * 444 * @return array Collection parameters. 445 */ 446 public function get_collection_params() { 447 return array( 448 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 449 ); 450 } 451 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |