wp/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     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 the objects of the controller.
       
    31 	 *
       
    32 	 * @since 4.7.0
       
    33 	 *
       
    34 	 * @see register_rest_route()
       
    35 	 */
       
    36 	public function register_routes() {
       
    37 
       
    38 		register_rest_route( $this->namespace, '/' . $this->rest_base, array(
       
    39 			array(
       
    40 				'methods'         => WP_REST_Server::READABLE,
       
    41 				'callback'        => array( $this, 'get_items' ),
       
    42 				'permission_callback' => array( $this, 'get_items_permissions_check' ),
       
    43 				'args'            => $this->get_collection_params(),
       
    44 			),
       
    45 			'schema' => array( $this, 'get_public_item_schema' ),
       
    46 		) );
       
    47 
       
    48 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<taxonomy>[\w-]+)', array(
       
    49 			'args' => array(
       
    50 				'taxonomy' => array(
       
    51 					'description'  => __( 'An alphanumeric identifier for the taxonomy.' ),
       
    52 					'type'         => 'string',
       
    53 				),
       
    54 			),
       
    55 			array(
       
    56 				'methods'         => WP_REST_Server::READABLE,
       
    57 				'callback'        => array( $this, 'get_item' ),
       
    58 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
       
    59 				'args'            => array(
       
    60 					'context'     => $this->get_context_param( array( 'default' => 'view' ) ),
       
    61 				),
       
    62 			),
       
    63 			'schema' => array( $this, 'get_public_item_schema' ),
       
    64 		) );
       
    65 	}
       
    66 
       
    67 	/**
       
    68 	 * Checks whether a given request has permission to read taxonomies.
       
    69 	 *
       
    70 	 * @since 4.7.0
       
    71 	 *
       
    72 	 * @param WP_REST_Request $request Full details about the request.
       
    73 	 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
       
    74 	 */
       
    75 	public function get_items_permissions_check( $request ) {
       
    76 		if ( 'edit' === $request['context'] ) {
       
    77 			if ( ! empty( $request['type'] ) ) {
       
    78 				$taxonomies = get_object_taxonomies( $request['type'], 'objects' );
       
    79 			} else {
       
    80 				$taxonomies = get_taxonomies( '', 'objects' );
       
    81 			}
       
    82 			foreach ( $taxonomies as $taxonomy ) {
       
    83 				if ( ! empty( $taxonomy->show_in_rest ) && current_user_can( $taxonomy->cap->assign_terms ) ) {
       
    84 					return true;
       
    85 				}
       
    86 			}
       
    87 			return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to manage terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) );
       
    88 		}
       
    89 		return true;
       
    90 	}
       
    91 
       
    92 	/**
       
    93 	 * Retrieves all public taxonomies.
       
    94 	 *
       
    95 	 * @since 4.7.0
       
    96 	 *
       
    97 	 * @param WP_REST_Request $request Full details about the request.
       
    98 	 * @return WP_REST_Response Response object on success, or WP_Error object on failure.
       
    99 	 */
       
   100 	public function get_items( $request ) {
       
   101 
       
   102 		// Retrieve the list of registered collection query parameters.
       
   103 		$registered = $this->get_collection_params();
       
   104 
       
   105 		if ( isset( $registered['type'] ) && ! empty( $request['type'] ) ) {
       
   106 			$taxonomies = get_object_taxonomies( $request['type'], 'objects' );
       
   107 		} else {
       
   108 			$taxonomies = get_taxonomies( '', 'objects' );
       
   109 		}
       
   110 		$data = array();
       
   111 		foreach ( $taxonomies as $tax_type => $value ) {
       
   112 			if ( empty( $value->show_in_rest ) || ( 'edit' === $request['context'] && ! current_user_can( $value->cap->assign_terms ) ) ) {
       
   113 				continue;
       
   114 			}
       
   115 			$tax = $this->prepare_item_for_response( $value, $request );
       
   116 			$tax = $this->prepare_response_for_collection( $tax );
       
   117 			$data[ $tax_type ] = $tax;
       
   118 		}
       
   119 
       
   120 		if ( empty( $data ) ) {
       
   121 			// Response should still be returned as a JSON object when it is empty.
       
   122 			$data = (object) $data;
       
   123 		}
       
   124 
       
   125 		return rest_ensure_response( $data );
       
   126 	}
       
   127 
       
   128 	/**
       
   129 	 * Checks if a given request has access to a taxonomy.
       
   130 	 *
       
   131 	 * @since 4.7.0
       
   132 	 *
       
   133 	 * @param  WP_REST_Request $request Full details about the request.
       
   134 	 * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
       
   135 	 */
       
   136 	public function get_item_permissions_check( $request ) {
       
   137 
       
   138 		$tax_obj = get_taxonomy( $request['taxonomy'] );
       
   139 
       
   140 		if ( $tax_obj ) {
       
   141 			if ( empty( $tax_obj->show_in_rest ) ) {
       
   142 				return false;
       
   143 			}
       
   144 			if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->assign_terms ) ) {
       
   145 				return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) );
       
   146 			}
       
   147 		}
       
   148 
       
   149 		return true;
       
   150 	}
       
   151 
       
   152 	/**
       
   153 	 * Retrieves a specific taxonomy.
       
   154 	 *
       
   155 	 * @since 4.7.0
       
   156 	 *
       
   157 	 * @param WP_REST_Request $request Full details about the request.
       
   158 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
       
   159 	 */
       
   160 	public function get_item( $request ) {
       
   161 		$tax_obj = get_taxonomy( $request['taxonomy'] );
       
   162 		if ( empty( $tax_obj ) ) {
       
   163 			return new WP_Error( 'rest_taxonomy_invalid', __( 'Invalid taxonomy.' ), array( 'status' => 404 ) );
       
   164 		}
       
   165 		$data = $this->prepare_item_for_response( $tax_obj, $request );
       
   166 		return rest_ensure_response( $data );
       
   167 	}
       
   168 
       
   169 	/**
       
   170 	 * Prepares a taxonomy object for serialization.
       
   171 	 *
       
   172 	 * @since 4.7.0
       
   173 	 *
       
   174 	 * @param stdClass        $taxonomy Taxonomy data.
       
   175 	 * @param WP_REST_Request $request  Full details about the request.
       
   176 	 * @return WP_REST_Response Response object.
       
   177 	 */
       
   178 	public function prepare_item_for_response( $taxonomy, $request ) {
       
   179 		$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
       
   180 
       
   181 		$fields = $this->get_fields_for_response( $request );
       
   182 		$data   = array();
       
   183 
       
   184 		if ( in_array( 'name', $fields, true ) ) {
       
   185 			$data['name'] = $taxonomy->label;
       
   186 		}
       
   187 
       
   188 		if ( in_array( 'slug', $fields, true ) ) {
       
   189 			$data['slug'] = $taxonomy->name;
       
   190 		}
       
   191 
       
   192 		if ( in_array( 'capabilities', $fields, true ) ) {
       
   193 			$data['capabilities'] = $taxonomy->cap;
       
   194 		}
       
   195 
       
   196 		if ( in_array( 'description', $fields, true ) ) {
       
   197 			$data['description'] = $taxonomy->description;
       
   198 		}
       
   199 
       
   200 		if ( in_array( 'labels', $fields, true ) ) {
       
   201 			$data['labels'] = $taxonomy->labels;
       
   202 		}
       
   203 
       
   204 		if ( in_array( 'types', $fields, true ) ) {
       
   205 			$data['types'] = $taxonomy->object_type;
       
   206 		}
       
   207 
       
   208 		if ( in_array( 'show_cloud', $fields, true ) ) {
       
   209 			$data['show_cloud'] = $taxonomy->show_tagcloud;
       
   210 		}
       
   211 
       
   212 		if ( in_array( 'hierarchical', $fields, true ) ) {
       
   213 			$data['hierarchical'] = $taxonomy->hierarchical;
       
   214 		}
       
   215 
       
   216 		if ( in_array( 'rest_base', $fields, true ) ) {
       
   217 			$data['rest_base'] = $base;
       
   218 		}
       
   219 
       
   220 		if ( in_array( 'visibility', $fields, true ) ) {
       
   221 			$data['visibility'] = array(
       
   222 				'public'             => (bool) $taxonomy->public,
       
   223 				'publicly_queryable' => (bool) $taxonomy->publicly_queryable,
       
   224 				'show_admin_column'  => (bool) $taxonomy->show_admin_column,
       
   225 				'show_in_nav_menus'  => (bool) $taxonomy->show_in_nav_menus,
       
   226 				'show_in_quick_edit' => (bool) $taxonomy->show_in_quick_edit,
       
   227 				'show_ui'            => (bool) $taxonomy->show_ui,
       
   228 			);
       
   229 		}
       
   230 
       
   231 		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
       
   232 		$data = $this->add_additional_fields_to_object( $data, $request );
       
   233 		$data = $this->filter_response_by_context( $data, $context );
       
   234 
       
   235 		// Wrap the data in a response object.
       
   236 		$response = rest_ensure_response( $data );
       
   237 
       
   238 		$response->add_links( array(
       
   239 			'collection'                => array(
       
   240 				'href'                  => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
       
   241 			),
       
   242 			'https://api.w.org/items'   => array(
       
   243 				'href'                  => rest_url( sprintf( 'wp/v2/%s', $base ) ),
       
   244 			),
       
   245 		) );
       
   246 
       
   247 		/**
       
   248 		 * Filters a taxonomy returned from the REST API.
       
   249 		 *
       
   250 		 * Allows modification of the taxonomy data right before it is returned.
       
   251 		 *
       
   252 		 * @since 4.7.0
       
   253 		 *
       
   254 		 * @param WP_REST_Response $response The response object.
       
   255 		 * @param object           $item     The original taxonomy object.
       
   256 		 * @param WP_REST_Request  $request  Request used to generate the response.
       
   257 		 */
       
   258 		return apply_filters( 'rest_prepare_taxonomy', $response, $taxonomy, $request );
       
   259 	}
       
   260 
       
   261 	/**
       
   262 	 * Retrieves the taxonomy's schema, conforming to JSON Schema.
       
   263 	 *
       
   264 	 * @since 4.7.0
       
   265 	 *
       
   266 	 * @return array Item schema data.
       
   267 	 */
       
   268 	public function get_item_schema() {
       
   269 		$schema = array(
       
   270 			'$schema'              => 'http://json-schema.org/draft-04/schema#',
       
   271 			'title'                => 'taxonomy',
       
   272 			'type'                 => 'object',
       
   273 			'properties'           => array(
       
   274 				'capabilities'     => array(
       
   275 					'description'  => __( 'All capabilities used by the taxonomy.' ),
       
   276 					'type'         => 'object',
       
   277 					'context'      => array( 'edit' ),
       
   278 					'readonly'     => true,
       
   279 				),
       
   280 				'description'      => array(
       
   281 					'description'  => __( 'A human-readable description of the taxonomy.' ),
       
   282 					'type'         => 'string',
       
   283 					'context'      => array( 'view', 'edit' ),
       
   284 					'readonly'     => true,
       
   285 				),
       
   286 				'hierarchical'     => array(
       
   287 					'description'  => __( 'Whether or not the taxonomy should have children.' ),
       
   288 					'type'         => 'boolean',
       
   289 					'context'      => array( 'view', 'edit' ),
       
   290 					'readonly'     => true,
       
   291 				),
       
   292 				'labels'           => array(
       
   293 					'description'  => __( 'Human-readable labels for the taxonomy for various contexts.' ),
       
   294 					'type'         => 'object',
       
   295 					'context'      => array( 'edit' ),
       
   296 					'readonly'     => true,
       
   297 				),
       
   298 				'name'             => array(
       
   299 					'description'  => __( 'The title for the taxonomy.' ),
       
   300 					'type'         => 'string',
       
   301 					'context'      => array( 'view', 'edit', 'embed' ),
       
   302 					'readonly'     => true,
       
   303 				),
       
   304 				'slug'             => array(
       
   305 					'description'  => __( 'An alphanumeric identifier for the taxonomy.' ),
       
   306 					'type'         => 'string',
       
   307 					'context'      => array( 'view', 'edit', 'embed' ),
       
   308 					'readonly'     => true,
       
   309 				),
       
   310 				'show_cloud'       => array(
       
   311 					'description'  => __( 'Whether or not the term cloud should be displayed.' ),
       
   312 					'type'         => 'boolean',
       
   313 					'context'      => array( 'edit' ),
       
   314 					'readonly'     => true,
       
   315 				),
       
   316 				'types'            => array(
       
   317 					'description'  => __( 'Types associated with the taxonomy.' ),
       
   318 					'type'         => 'array',
       
   319 					'items'        => array(
       
   320 						'type' => 'string',
       
   321 					),
       
   322 					'context'      => array( 'view', 'edit' ),
       
   323 					'readonly'     => true,
       
   324 				),
       
   325 				'rest_base'            => array(
       
   326 					'description'  => __( 'REST base route for the taxonomy.' ),
       
   327 					'type'         => 'string',
       
   328 					'context'      => array( 'view', 'edit', 'embed' ),
       
   329 					'readonly'     => true,
       
   330 				),
       
   331 			),
       
   332 		);
       
   333 		return $this->add_additional_fields_schema( $schema );
       
   334 	}
       
   335 
       
   336 	/**
       
   337 	 * Retrieves the query params for collections.
       
   338 	 *
       
   339 	 * @since 4.7.0
       
   340 	 *
       
   341 	 * @return array Collection parameters.
       
   342 	 */
       
   343 	public function get_collection_params() {
       
   344 		$new_params = array();
       
   345 		$new_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
       
   346 		$new_params['type'] = array(
       
   347 			'description'  => __( 'Limit results to taxonomies associated with a specific post type.' ),
       
   348 			'type'         => 'string',
       
   349 		);
       
   350 		return $new_params;
       
   351 	}
       
   352 
       
   353 }