angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-rest-post-types-controller.php (10037B)


      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 	 *
    172 	 * @param WP_Post_Type    $post_type Post type object.
    173 	 * @param WP_REST_Request $request   Full details about the request.
    174 	 * @return WP_REST_Response Response object.
    175 	 */
    176 	public function prepare_item_for_response( $post_type, $request ) {
    177 		$taxonomies = wp_list_filter( get_object_taxonomies( $post_type->name, 'objects' ), array( 'show_in_rest' => true ) );
    178 		$taxonomies = wp_list_pluck( $taxonomies, 'name' );
    179 		$base       = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
    180 		$supports   = get_all_post_type_supports( $post_type->name );
    181 
    182 		$fields = $this->get_fields_for_response( $request );
    183 		$data   = array();
    184 
    185 		if ( in_array( 'capabilities', $fields, true ) ) {
    186 			$data['capabilities'] = $post_type->cap;
    187 		}
    188 
    189 		if ( in_array( 'description', $fields, true ) ) {
    190 			$data['description'] = $post_type->description;
    191 		}
    192 
    193 		if ( in_array( 'hierarchical', $fields, true ) ) {
    194 			$data['hierarchical'] = $post_type->hierarchical;
    195 		}
    196 
    197 		if ( in_array( 'viewable', $fields, true ) ) {
    198 			$data['viewable'] = is_post_type_viewable( $post_type );
    199 		}
    200 
    201 		if ( in_array( 'labels', $fields, true ) ) {
    202 			$data['labels'] = $post_type->labels;
    203 		}
    204 
    205 		if ( in_array( 'name', $fields, true ) ) {
    206 			$data['name'] = $post_type->label;
    207 		}
    208 
    209 		if ( in_array( 'slug', $fields, true ) ) {
    210 			$data['slug'] = $post_type->name;
    211 		}
    212 
    213 		if ( in_array( 'supports', $fields, true ) ) {
    214 			$data['supports'] = $supports;
    215 		}
    216 
    217 		if ( in_array( 'taxonomies', $fields, true ) ) {
    218 			$data['taxonomies'] = array_values( $taxonomies );
    219 		}
    220 
    221 		if ( in_array( 'rest_base', $fields, true ) ) {
    222 			$data['rest_base'] = $base;
    223 		}
    224 
    225 		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
    226 		$data    = $this->add_additional_fields_to_object( $data, $request );
    227 		$data    = $this->filter_response_by_context( $data, $context );
    228 
    229 		// Wrap the data in a response object.
    230 		$response = rest_ensure_response( $data );
    231 
    232 		$response->add_links(
    233 			array(
    234 				'collection'              => array(
    235 					'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
    236 				),
    237 				'https://api.w.org/items' => array(
    238 					'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
    239 				),
    240 			)
    241 		);
    242 
    243 		/**
    244 		 * Filters a post type returned from the REST API.
    245 		 *
    246 		 * Allows modification of the post type data right before it is returned.
    247 		 *
    248 		 * @since 4.7.0
    249 		 *
    250 		 * @param WP_REST_Response $response  The response object.
    251 		 * @param WP_Post_Type     $post_type The original post type object.
    252 		 * @param WP_REST_Request  $request   Request used to generate the response.
    253 		 */
    254 		return apply_filters( 'rest_prepare_post_type', $response, $post_type, $request );
    255 	}
    256 
    257 	/**
    258 	 * Retrieves the post type's schema, conforming to JSON Schema.
    259 	 *
    260 	 * @since 4.7.0
    261 	 *
    262 	 * @return array Item schema data.
    263 	 */
    264 	public function get_item_schema() {
    265 		if ( $this->schema ) {
    266 			return $this->add_additional_fields_schema( $this->schema );
    267 		}
    268 
    269 		$schema = array(
    270 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
    271 			'title'      => 'type',
    272 			'type'       => 'object',
    273 			'properties' => array(
    274 				'capabilities' => array(
    275 					'description' => __( 'All capabilities used by the post type.' ),
    276 					'type'        => 'object',
    277 					'context'     => array( 'edit' ),
    278 					'readonly'    => true,
    279 				),
    280 				'description'  => array(
    281 					'description' => __( 'A human-readable description of the post type.' ),
    282 					'type'        => 'string',
    283 					'context'     => array( 'view', 'edit' ),
    284 					'readonly'    => true,
    285 				),
    286 				'hierarchical' => array(
    287 					'description' => __( 'Whether or not the post type should have children.' ),
    288 					'type'        => 'boolean',
    289 					'context'     => array( 'view', 'edit' ),
    290 					'readonly'    => true,
    291 				),
    292 				'viewable'     => array(
    293 					'description' => __( 'Whether or not the post type can be viewed.' ),
    294 					'type'        => 'boolean',
    295 					'context'     => array( 'edit' ),
    296 					'readonly'    => true,
    297 				),
    298 				'labels'       => array(
    299 					'description' => __( 'Human-readable labels for the post type for various contexts.' ),
    300 					'type'        => 'object',
    301 					'context'     => array( 'edit' ),
    302 					'readonly'    => true,
    303 				),
    304 				'name'         => array(
    305 					'description' => __( 'The title for the post type.' ),
    306 					'type'        => 'string',
    307 					'context'     => array( 'view', 'edit', 'embed' ),
    308 					'readonly'    => true,
    309 				),
    310 				'slug'         => array(
    311 					'description' => __( 'An alphanumeric identifier for the post type.' ),
    312 					'type'        => 'string',
    313 					'context'     => array( 'view', 'edit', 'embed' ),
    314 					'readonly'    => true,
    315 				),
    316 				'supports'     => array(
    317 					'description' => __( 'All features, supported by the post type.' ),
    318 					'type'        => 'object',
    319 					'context'     => array( 'edit' ),
    320 					'readonly'    => true,
    321 				),
    322 				'taxonomies'   => array(
    323 					'description' => __( 'Taxonomies associated with post type.' ),
    324 					'type'        => 'array',
    325 					'items'       => array(
    326 						'type' => 'string',
    327 					),
    328 					'context'     => array( 'view', 'edit' ),
    329 					'readonly'    => true,
    330 				),
    331 				'rest_base'    => array(
    332 					'description' => __( 'REST base route for the post type.' ),
    333 					'type'        => 'string',
    334 					'context'     => array( 'view', 'edit', 'embed' ),
    335 					'readonly'    => true,
    336 				),
    337 			),
    338 		);
    339 
    340 		$this->schema = $schema;
    341 
    342 		return $this->add_additional_fields_schema( $this->schema );
    343 	}
    344 
    345 	/**
    346 	 * Retrieves the query params for collections.
    347 	 *
    348 	 * @since 4.7.0
    349 	 *
    350 	 * @return array Collection parameters.
    351 	 */
    352 	public function get_collection_params() {
    353 		return array(
    354 			'context' => $this->get_context_param( array( 'default' => 'view' ) ),
    355 		);
    356 	}
    357 
    358 }