[ 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 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 250 $data = $this->add_additional_fields_to_object( $data, $request ); 251 $data = $this->filter_response_by_context( $data, $context ); 252 253 // Wrap the data in a response object. 254 $response = rest_ensure_response( $data ); 255 256 if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { 257 $response->add_links( $this->prepare_links( $post_type ) ); 258 } 259 260 /** 261 * Filters a post type returned from the REST API. 262 * 263 * Allows modification of the post type data right before it is returned. 264 * 265 * @since 4.7.0 266 * 267 * @param WP_REST_Response $response The response object. 268 * @param WP_Post_Type $post_type The original post type object. 269 * @param WP_REST_Request $request Request used to generate the response. 270 */ 271 return apply_filters( 'rest_prepare_post_type', $response, $post_type, $request ); 272 } 273 274 /** 275 * Prepares links for the request. 276 * 277 * @since 6.1.0 278 * 279 * @param WP_Post_Type $post_type The post type. 280 * @return array Links for the given post type. 281 */ 282 protected function prepare_links( $post_type ) { 283 return array( 284 'collection' => array( 285 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), 286 ), 287 'https://api.w.org/items' => array( 288 'href' => rest_url( rest_get_route_for_post_type_items( $post_type->name ) ), 289 ), 290 ); 291 } 292 293 /** 294 * Retrieves the post type's schema, conforming to JSON Schema. 295 * 296 * @since 4.7.0 297 * @since 4.8.0 The `supports` property was added. 298 * @since 5.9.0 The `visibility` and `rest_namespace` properties were added. 299 * @since 6.1.0 The `icon` property was added. 300 * 301 * @return array Item schema data. 302 */ 303 public function get_item_schema() { 304 if ( $this->schema ) { 305 return $this->add_additional_fields_schema( $this->schema ); 306 } 307 308 $schema = array( 309 '$schema' => 'http://json-schema.org/draft-04/schema#', 310 'title' => 'type', 311 'type' => 'object', 312 'properties' => array( 313 'capabilities' => array( 314 'description' => __( 'All capabilities used by the post type.' ), 315 'type' => 'object', 316 'context' => array( 'edit' ), 317 'readonly' => true, 318 ), 319 'description' => array( 320 'description' => __( 'A human-readable description of the post type.' ), 321 'type' => 'string', 322 'context' => array( 'view', 'edit' ), 323 'readonly' => true, 324 ), 325 'hierarchical' => array( 326 'description' => __( 'Whether or not the post type should have children.' ), 327 'type' => 'boolean', 328 'context' => array( 'view', 'edit' ), 329 'readonly' => true, 330 ), 331 'viewable' => array( 332 'description' => __( 'Whether or not the post type can be viewed.' ), 333 'type' => 'boolean', 334 'context' => array( 'edit' ), 335 'readonly' => true, 336 ), 337 'labels' => array( 338 'description' => __( 'Human-readable labels for the post type for various contexts.' ), 339 'type' => 'object', 340 'context' => array( 'edit' ), 341 'readonly' => true, 342 ), 343 'name' => array( 344 'description' => __( 'The title for the post type.' ), 345 'type' => 'string', 346 'context' => array( 'view', 'edit', 'embed' ), 347 'readonly' => true, 348 ), 349 'slug' => array( 350 'description' => __( 'An alphanumeric identifier for the post type.' ), 351 'type' => 'string', 352 'context' => array( 'view', 'edit', 'embed' ), 353 'readonly' => true, 354 ), 355 'supports' => array( 356 'description' => __( 'All features, supported by the post type.' ), 357 'type' => 'object', 358 'context' => array( 'edit' ), 359 'readonly' => true, 360 ), 361 'has_archive' => array( 362 '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.' ), 363 'type' => array( 'string', 'boolean' ), 364 'context' => array( 'view', 'edit' ), 365 'readonly' => true, 366 ), 367 'taxonomies' => array( 368 'description' => __( 'Taxonomies associated with post type.' ), 369 'type' => 'array', 370 'items' => array( 371 'type' => 'string', 372 ), 373 'context' => array( 'view', 'edit' ), 374 'readonly' => true, 375 ), 376 'rest_base' => array( 377 'description' => __( 'REST base route for the post type.' ), 378 'type' => 'string', 379 'context' => array( 'view', 'edit', 'embed' ), 380 'readonly' => true, 381 ), 382 'rest_namespace' => array( 383 'description' => __( 'REST route\'s namespace for the post type.' ), 384 'type' => 'string', 385 'context' => array( 'view', 'edit', 'embed' ), 386 'readonly' => true, 387 ), 388 'visibility' => array( 389 'description' => __( 'The visibility settings for the post type.' ), 390 'type' => 'object', 391 'context' => array( 'edit' ), 392 'readonly' => true, 393 'properties' => array( 394 'show_ui' => array( 395 'description' => __( 'Whether to generate a default UI for managing this post type.' ), 396 'type' => 'boolean', 397 ), 398 'show_in_nav_menus' => array( 399 'description' => __( 'Whether to make the post type available for selection in navigation menus.' ), 400 'type' => 'boolean', 401 ), 402 ), 403 ), 404 'icon' => array( 405 'description' => __( 'The icon for the post type.' ), 406 'type' => array( 'string', 'null' ), 407 'context' => array( 'view', 'edit', 'embed' ), 408 'readonly' => true, 409 ), 410 ), 411 ); 412 413 $this->schema = $schema; 414 415 return $this->add_additional_fields_schema( $this->schema ); 416 } 417 418 /** 419 * Retrieves the query params for collections. 420 * 421 * @since 4.7.0 422 * 423 * @return array Collection parameters. 424 */ 425 public function get_collection_params() { 426 return array( 427 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 428 ); 429 } 430 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Fri Mar 29 08:20:02 2024 | Cross-referenced by PHPXref |