REST API: Support custom namespaces for taxonomies.

While a taxonomy can define a custom route by using the rest_base argument, a namespace of wp/v2 was assumed. This commit introduces support for a rest_namespace argument.

A new rest_get_route_for_taxonomy_items function has been introduced and the rest_get_route_for_term function updated to facilitate getting the correct route for taxonomies.

For maximum compatibility sticking with the default wp/v2 namespace is recommended until the API functions see wider use.

Props spacedmonkey.
Fixes #54267.
See [51962].

Built from https://develop.svn.wordpress.org/trunk@51964


git-svn-id: http://core.svn.wordpress.org/trunk@51553 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
TimothyBlynJacobs 2021-11-01 03:27:55 +00:00
parent 2c3205bb84
commit c0995319f4
7 changed files with 77 additions and 34 deletions

View File

@ -199,6 +199,14 @@ final class WP_Taxonomy {
*/
public $rest_base;
/**
* The namespace for this taxonomy's REST API endpoints.
*
* @since 5.9
* @var string|bool $rest_namespace
*/
public $rest_namespace;
/**
* The controller for this taxonomy's REST API endpoints.
*
@ -319,6 +327,7 @@ final class WP_Taxonomy {
'update_count_callback' => '',
'show_in_rest' => false,
'rest_base' => false,
'rest_namespace' => false,
'rest_controller_class' => false,
'default_term' => null,
'sort' => null,
@ -384,6 +393,11 @@ final class WP_Taxonomy {
$args['show_in_quick_edit'] = $args['show_ui'];
}
// If not set, default rest_namespace to wp/v2 if show_in_rest is true.
if ( false === $args['rest_namespace'] && ! empty( $args['show_in_rest'] ) ) {
$args['rest_namespace'] = 'wp/v2';
}
$default_caps = array(
'manage_terms' => 'manage_categories',
'edit_terms' => 'manage_categories',

View File

@ -3115,24 +3115,12 @@ function rest_get_route_for_term( $term ) {
return '';
}
$taxonomy = get_taxonomy( $term->taxonomy );
if ( ! $taxonomy ) {
$taxonomy_route = rest_get_route_for_taxonomy_items( $term->taxonomy );
if ( ! $taxonomy_route ) {
return '';
}
$controller = $taxonomy->get_rest_controller();
if ( ! $controller ) {
return '';
}
$route = '';
// The only controller that works is the Terms controller.
if ( $controller instanceof WP_REST_Terms_Controller ) {
$namespace = 'wp/v2';
$rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
$route = sprintf( '/%s/%s/%d', $namespace, $rest_base, $term->term_id );
}
$route = sprintf( '%s/%d', $taxonomy_route, $term->term_id );
/**
* Filters the REST API route for a term.
@ -3145,6 +3133,39 @@ function rest_get_route_for_term( $term ) {
return apply_filters( 'rest_route_for_term', $route, $term );
}
/**
* Gets the REST API route for a taxonomy.
*
* @since 5.9.0
*
* @param string $taxonomy Name of taxonomy.
* @return string The route path with a leading slash for the given taxonomy.
*/
function rest_get_route_for_taxonomy_items( $taxonomy ) {
$taxonomy = get_taxonomy( $taxonomy );
if ( ! $taxonomy ) {
return '';
}
if ( ! $taxonomy->show_in_rest ) {
return '';
}
$namespace = ! empty( $taxonomy->rest_namespace ) ? $taxonomy->rest_namespace : 'wp/v2';
$rest_base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
$route = sprintf( '/%s/%s', $namespace, $rest_base );
/**
* Filters the REST API route for a taxonomy.
*
* @since 5.9.0
*
* @param string $route The route path.
* @param WP_Taxonomy $taxonomy The taxonomy object.
*/
return apply_filters( 'rest_route_for_taxonomy_items', $route, $taxonomy );
}
/**
* Gets the REST route for the currently queried object.
*

View File

@ -2060,19 +2060,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
$links['https://api.w.org/term'] = array();
foreach ( $taxonomies as $tax ) {
$taxonomy_obj = get_taxonomy( $tax );
$taxonomy_route = rest_get_route_for_taxonomy_items( $tax );
// Skip taxonomies that are not public.
if ( empty( $taxonomy_obj->show_in_rest ) ) {
if ( empty( $taxonomy_route ) ) {
continue;
}
$tax_base = ! empty( $taxonomy_obj->rest_base ) ? $taxonomy_obj->rest_base : $tax;
$terms_url = add_query_arg(
'post',
$post->ID,
rest_url( 'wp/v2/' . $tax_base )
rest_url( $taxonomy_route )
);
$links['https://api.w.org/term'][] = array(

View File

@ -250,6 +250,10 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
$data['rest_base'] = $base;
}
if ( in_array( 'rest_namespace', $fields, true ) ) {
$data['rest_namespace'] = $taxonomy->rest_namespace;
}
if ( in_array( 'visibility', $fields, true ) ) {
$data['visibility'] = array(
'public' => (bool) $taxonomy->public,
@ -274,7 +278,7 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
),
'https://api.w.org/items' => array(
'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
'href' => rest_url( rest_get_route_for_taxonomy_items( $taxonomy->name ) ),
),
)
);
@ -310,49 +314,49 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
'title' => 'taxonomy',
'type' => 'object',
'properties' => array(
'capabilities' => array(
'capabilities' => array(
'description' => __( 'All capabilities used by the taxonomy.' ),
'type' => 'object',
'context' => array( 'edit' ),
'readonly' => true,
),
'description' => array(
'description' => array(
'description' => __( 'A human-readable description of the taxonomy.' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'hierarchical' => array(
'hierarchical' => array(
'description' => __( 'Whether or not the taxonomy should have children.' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'labels' => array(
'labels' => array(
'description' => __( 'Human-readable labels for the taxonomy for various contexts.' ),
'type' => 'object',
'context' => array( 'edit' ),
'readonly' => true,
),
'name' => array(
'name' => array(
'description' => __( 'The title for the taxonomy.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
'slug' => array(
'slug' => array(
'description' => __( 'An alphanumeric identifier for the taxonomy.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
'show_cloud' => array(
'show_cloud' => array(
'description' => __( 'Whether or not the term cloud should be displayed.' ),
'type' => 'boolean',
'context' => array( 'edit' ),
'readonly' => true,
),
'types' => array(
'types' => array(
'description' => __( 'Types associated with the taxonomy.' ),
'type' => 'array',
'items' => array(
@ -361,13 +365,19 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'rest_base' => array(
'rest_base' => array(
'description' => __( 'REST base route for the taxonomy.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
'visibility' => array(
'rest_namespace' => array(
'description' => __( 'REST namespace route for the taxonomy.' ),
'type' => 'string',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
'visibility' => array(
'description' => __( 'The visibility settings for the taxonomy.' ),
'type' => 'object',
'context' => array( 'edit' ),

View File

@ -57,9 +57,9 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
*/
public function __construct( $taxonomy ) {
$this->taxonomy = $taxonomy;
$this->namespace = 'wp/v2';
$tax_obj = get_taxonomy( $taxonomy );
$this->rest_base = ! empty( $tax_obj->rest_base ) ? $tax_obj->rest_base : $tax_obj->name;
$this->namespace = ! empty( $tax_obj->rest_namespace ) ? $tax_obj->rest_namespace : 'wp/v2';
$this->meta = new WP_REST_Term_Meta_Fields( $taxonomy );
}

View File

@ -387,6 +387,7 @@ function is_taxonomy_hierarchical( $taxonomy ) {
* @type bool $show_in_rest Whether to include the taxonomy in the REST API. Set this to true
* for the taxonomy to be available in the block editor.
* @type string $rest_base To change the base url of REST API route. Default is $taxonomy.
* @type string $rest_namespace To change the namespace URL of REST API route. Default is wp/v2.
* @type string $rest_controller_class REST API Controller class name. Default is 'WP_REST_Terms_Controller'.
* @type bool $show_tagcloud Whether to list the taxonomy in the Tag Cloud Widget controls. If not set,
* the default is inherited from `$show_ui` (default true).

View File

@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.9-alpha-51963';
$wp_version = '5.9-alpha-51964';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.