ru-se.com

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

class-wp-rest-taxonomies-controller.php (12485B)


      1 <?php
      2 /**
      3  * REST API: WP_REST_Taxonomies_Controller class
      4  *
      5  * @package WordPress
      6  * @subpackage REST_API
      7  * @since 4.7.0
      8  */
      9 
     10 /**
     11  * Core class used to manage taxonomies via the REST API.
     12  *
     13  * @since 4.7.0
     14  *
     15  * @see WP_REST_Controller
     16  */
     17 class WP_REST_Taxonomies_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 = 'taxonomies';
     27 	}
     28 
     29 	/**
     30 	 * Registers the routes for taxonomies.
     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<taxonomy>[\w-]+)',
     55 			array(
     56 				'args'   => array(
     57 					'taxonomy' => array(
     58 						'description' => __( 'An alphanumeric identifier for the taxonomy.' ),
     59 						'type'        => 'string',
     60 					),
     61 				),
     62 				array(
     63 					'methods'             => WP_REST_Server::READABLE,
     64 					'callback'            => array( $this, 'get_item' ),
     65 					'permission_callback' => array( $this, 'get_item_permissions_check' ),
     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 taxonomies.
     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 			if ( ! empty( $request['type'] ) ) {
     86 				$taxonomies = get_object_taxonomies( $request['type'], 'objects' );
     87 			} else {
     88 				$taxonomies = get_taxonomies( '', 'objects' );
     89 			}
     90 
     91 			foreach ( $taxonomies as $taxonomy ) {
     92 				if ( ! empty( $taxonomy->show_in_rest ) && current_user_can( $taxonomy->cap->assign_terms ) ) {
     93 					return true;
     94 				}
     95 			}
     96 
     97 			return new WP_Error(
     98 				'rest_cannot_view',
     99 				__( 'Sorry, you are not allowed to manage terms in this taxonomy.' ),
    100 				array( 'status' => rest_authorization_required_code() )
    101 			);
    102 		}
    103 
    104 		return true;
    105 	}
    106 
    107 	/**
    108 	 * Retrieves all public taxonomies.
    109 	 *
    110 	 * @since 4.7.0
    111 	 *
    112 	 * @param WP_REST_Request $request Full details about the request.
    113 	 * @return WP_REST_Response Response object on success, or WP_Error object on failure.
    114 	 */
    115 	public function get_items( $request ) {
    116 
    117 		// Retrieve the list of registered collection query parameters.
    118 		$registered = $this->get_collection_params();
    119 
    120 		if ( isset( $registered['type'] ) && ! empty( $request['type'] ) ) {
    121 			$taxonomies = get_object_taxonomies( $request['type'], 'objects' );
    122 		} else {
    123 			$taxonomies = get_taxonomies( '', 'objects' );
    124 		}
    125 
    126 		$data = array();
    127 
    128 		foreach ( $taxonomies as $tax_type => $value ) {
    129 			if ( empty( $value->show_in_rest ) || ( 'edit' === $request['context'] && ! current_user_can( $value->cap->assign_terms ) ) ) {
    130 				continue;
    131 			}
    132 
    133 			$tax               = $this->prepare_item_for_response( $value, $request );
    134 			$tax               = $this->prepare_response_for_collection( $tax );
    135 			$data[ $tax_type ] = $tax;
    136 		}
    137 
    138 		if ( empty( $data ) ) {
    139 			// Response should still be returned as a JSON object when it is empty.
    140 			$data = (object) $data;
    141 		}
    142 
    143 		return rest_ensure_response( $data );
    144 	}
    145 
    146 	/**
    147 	 * Checks if a given request has access to a taxonomy.
    148 	 *
    149 	 * @since 4.7.0
    150 	 *
    151 	 * @param WP_REST_Request $request Full details about the request.
    152 	 * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
    153 	 */
    154 	public function get_item_permissions_check( $request ) {
    155 
    156 		$tax_obj = get_taxonomy( $request['taxonomy'] );
    157 
    158 		if ( $tax_obj ) {
    159 			if ( empty( $tax_obj->show_in_rest ) ) {
    160 				return false;
    161 			}
    162 
    163 			if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->assign_terms ) ) {
    164 				return new WP_Error(
    165 					'rest_forbidden_context',
    166 					__( 'Sorry, you are not allowed to manage terms in this taxonomy.' ),
    167 					array( 'status' => rest_authorization_required_code() )
    168 				);
    169 			}
    170 		}
    171 
    172 		return true;
    173 	}
    174 
    175 	/**
    176 	 * Retrieves a specific taxonomy.
    177 	 *
    178 	 * @since 4.7.0
    179 	 *
    180 	 * @param WP_REST_Request $request Full details about the request.
    181 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
    182 	 */
    183 	public function get_item( $request ) {
    184 		$tax_obj = get_taxonomy( $request['taxonomy'] );
    185 
    186 		if ( empty( $tax_obj ) ) {
    187 			return new WP_Error(
    188 				'rest_taxonomy_invalid',
    189 				__( 'Invalid taxonomy.' ),
    190 				array( 'status' => 404 )
    191 			);
    192 		}
    193 
    194 		$data = $this->prepare_item_for_response( $tax_obj, $request );
    195 
    196 		return rest_ensure_response( $data );
    197 	}
    198 
    199 	/**
    200 	 * Prepares a taxonomy object for serialization.
    201 	 *
    202 	 * @since 4.7.0
    203 	 *
    204 	 * @param WP_Taxonomy     $taxonomy Taxonomy data.
    205 	 * @param WP_REST_Request $request  Full details about the request.
    206 	 * @return WP_REST_Response Response object.
    207 	 */
    208 	public function prepare_item_for_response( $taxonomy, $request ) {
    209 		$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
    210 
    211 		$fields = $this->get_fields_for_response( $request );
    212 		$data   = array();
    213 
    214 		if ( in_array( 'name', $fields, true ) ) {
    215 			$data['name'] = $taxonomy->label;
    216 		}
    217 
    218 		if ( in_array( 'slug', $fields, true ) ) {
    219 			$data['slug'] = $taxonomy->name;
    220 		}
    221 
    222 		if ( in_array( 'capabilities', $fields, true ) ) {
    223 			$data['capabilities'] = $taxonomy->cap;
    224 		}
    225 
    226 		if ( in_array( 'description', $fields, true ) ) {
    227 			$data['description'] = $taxonomy->description;
    228 		}
    229 
    230 		if ( in_array( 'labels', $fields, true ) ) {
    231 			$data['labels'] = $taxonomy->labels;
    232 		}
    233 
    234 		if ( in_array( 'types', $fields, true ) ) {
    235 			$data['types'] = array_values( $taxonomy->object_type );
    236 		}
    237 
    238 		if ( in_array( 'show_cloud', $fields, true ) ) {
    239 			$data['show_cloud'] = $taxonomy->show_tagcloud;
    240 		}
    241 
    242 		if ( in_array( 'hierarchical', $fields, true ) ) {
    243 			$data['hierarchical'] = $taxonomy->hierarchical;
    244 		}
    245 
    246 		if ( in_array( 'rest_base', $fields, true ) ) {
    247 			$data['rest_base'] = $base;
    248 		}
    249 
    250 		if ( in_array( 'visibility', $fields, true ) ) {
    251 			$data['visibility'] = array(
    252 				'public'             => (bool) $taxonomy->public,
    253 				'publicly_queryable' => (bool) $taxonomy->publicly_queryable,
    254 				'show_admin_column'  => (bool) $taxonomy->show_admin_column,
    255 				'show_in_nav_menus'  => (bool) $taxonomy->show_in_nav_menus,
    256 				'show_in_quick_edit' => (bool) $taxonomy->show_in_quick_edit,
    257 				'show_ui'            => (bool) $taxonomy->show_ui,
    258 			);
    259 		}
    260 
    261 		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
    262 		$data    = $this->add_additional_fields_to_object( $data, $request );
    263 		$data    = $this->filter_response_by_context( $data, $context );
    264 
    265 		// Wrap the data in a response object.
    266 		$response = rest_ensure_response( $data );
    267 
    268 		$response->add_links(
    269 			array(
    270 				'collection'              => array(
    271 					'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
    272 				),
    273 				'https://api.w.org/items' => array(
    274 					'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
    275 				),
    276 			)
    277 		);
    278 
    279 		/**
    280 		 * Filters a taxonomy returned from the REST API.
    281 		 *
    282 		 * Allows modification of the taxonomy data right before it is returned.
    283 		 *
    284 		 * @since 4.7.0
    285 		 *
    286 		 * @param WP_REST_Response $response The response object.
    287 		 * @param WP_Taxonomy      $item     The original taxonomy object.
    288 		 * @param WP_REST_Request  $request  Request used to generate the response.
    289 		 */
    290 		return apply_filters( 'rest_prepare_taxonomy', $response, $taxonomy, $request );
    291 	}
    292 
    293 	/**
    294 	 * Retrieves the taxonomy's schema, conforming to JSON Schema.
    295 	 *
    296 	 * @since 4.7.0
    297 	 *
    298 	 * @return array Item schema data.
    299 	 */
    300 	public function get_item_schema() {
    301 		if ( $this->schema ) {
    302 			return $this->add_additional_fields_schema( $this->schema );
    303 		}
    304 
    305 		$schema = array(
    306 			'$schema'    => 'http://json-schema.org/draft-04/schema#',
    307 			'title'      => 'taxonomy',
    308 			'type'       => 'object',
    309 			'properties' => array(
    310 				'capabilities' => array(
    311 					'description' => __( 'All capabilities used by the taxonomy.' ),
    312 					'type'        => 'object',
    313 					'context'     => array( 'edit' ),
    314 					'readonly'    => true,
    315 				),
    316 				'description'  => array(
    317 					'description' => __( 'A human-readable description of the taxonomy.' ),
    318 					'type'        => 'string',
    319 					'context'     => array( 'view', 'edit' ),
    320 					'readonly'    => true,
    321 				),
    322 				'hierarchical' => array(
    323 					'description' => __( 'Whether or not the taxonomy should have children.' ),
    324 					'type'        => 'boolean',
    325 					'context'     => array( 'view', 'edit' ),
    326 					'readonly'    => true,
    327 				),
    328 				'labels'       => array(
    329 					'description' => __( 'Human-readable labels for the taxonomy for various contexts.' ),
    330 					'type'        => 'object',
    331 					'context'     => array( 'edit' ),
    332 					'readonly'    => true,
    333 				),
    334 				'name'         => array(
    335 					'description' => __( 'The title for the taxonomy.' ),
    336 					'type'        => 'string',
    337 					'context'     => array( 'view', 'edit', 'embed' ),
    338 					'readonly'    => true,
    339 				),
    340 				'slug'         => array(
    341 					'description' => __( 'An alphanumeric identifier for the taxonomy.' ),
    342 					'type'        => 'string',
    343 					'context'     => array( 'view', 'edit', 'embed' ),
    344 					'readonly'    => true,
    345 				),
    346 				'show_cloud'   => array(
    347 					'description' => __( 'Whether or not the term cloud should be displayed.' ),
    348 					'type'        => 'boolean',
    349 					'context'     => array( 'edit' ),
    350 					'readonly'    => true,
    351 				),
    352 				'types'        => array(
    353 					'description' => __( 'Types associated with the taxonomy.' ),
    354 					'type'        => 'array',
    355 					'items'       => array(
    356 						'type' => 'string',
    357 					),
    358 					'context'     => array( 'view', 'edit' ),
    359 					'readonly'    => true,
    360 				),
    361 				'rest_base'    => array(
    362 					'description' => __( 'REST base route for the taxonomy.' ),
    363 					'type'        => 'string',
    364 					'context'     => array( 'view', 'edit', 'embed' ),
    365 					'readonly'    => true,
    366 				),
    367 				'visibility'   => array(
    368 					'description' => __( 'The visibility settings for the taxonomy.' ),
    369 					'type'        => 'object',
    370 					'context'     => array( 'edit' ),
    371 					'readonly'    => true,
    372 					'properties'  => array(
    373 						'public'             => array(
    374 							'description' => __( 'Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.' ),
    375 							'type'        => 'boolean',
    376 						),
    377 						'publicly_queryable' => array(
    378 							'description' => __( 'Whether the taxonomy is publicly queryable.' ),
    379 							'type'        => 'boolean',
    380 						),
    381 						'show_ui'            => array(
    382 							'description' => __( 'Whether to generate a default UI for managing this taxonomy.' ),
    383 							'type'        => 'boolean',
    384 						),
    385 						'show_admin_column'  => array(
    386 							'description' => __( 'Whether to allow automatic creation of taxonomy columns on associated post-types table.' ),
    387 							'type'        => 'boolean',
    388 						),
    389 						'show_in_nav_menus'  => array(
    390 							'description' => __( 'Whether to make the taxonomy available for selection in navigation menus.' ),
    391 							'type'        => 'boolean',
    392 						),
    393 						'show_in_quick_edit' => array(
    394 							'description' => __( 'Whether to show the taxonomy in the quick/bulk edit panel.' ),
    395 							'type'        => 'boolean',
    396 						),
    397 
    398 					),
    399 				),
    400 			),
    401 		);
    402 
    403 		$this->schema = $schema;
    404 
    405 		return $this->add_additional_fields_schema( $this->schema );
    406 	}
    407 
    408 	/**
    409 	 * Retrieves the query params for collections.
    410 	 *
    411 	 * @since 4.7.0
    412 	 *
    413 	 * @return array Collection parameters.
    414 	 */
    415 	public function get_collection_params() {
    416 		$new_params            = array();
    417 		$new_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
    418 		$new_params['type']    = array(
    419 			'description' => __( 'Limit results to taxonomies associated with a specific post type.' ),
    420 			'type'        => 'string',
    421 		);
    422 		return $new_params;
    423 	}
    424 
    425 }