--- a/wp/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php Fri Sep 05 18:40:08 2025 +0200
@@ -145,12 +145,41 @@
}
/**
+ * Checks if the terms for a post can be read.
+ *
+ * @since 6.0.3
+ *
+ * @param WP_Post $post Post object.
+ * @param WP_REST_Request $request Full details about the request.
+ * @return bool Whether the terms for the post can be read.
+ */
+ public function check_read_terms_permission_for_post( $post, $request ) {
+ // If the requested post isn't associated with this taxonomy, deny access.
+ if ( ! is_object_in_taxonomy( $post->post_type, $this->taxonomy ) ) {
+ return false;
+ }
+
+ // Grant access if the post is publicly viewable.
+ if ( is_post_publicly_viewable( $post ) ) {
+ return true;
+ }
+
+ // Otherwise grant access if the post is readable by the logged in user.
+ if ( current_user_can( 'read_post', $post->ID ) ) {
+ return true;
+ }
+
+ // Otherwise, deny access.
+ return false;
+ }
+
+ /**
* Checks if a request has access to read terms in the specified taxonomy.
*
* @since 4.7.0
*
* @param WP_REST_Request $request Full details about the request.
- * @return true|WP_Error True if the request has read access, otherwise false or WP_Error object.
+ * @return bool|WP_Error True if the request has read access, otherwise false or WP_Error object.
*/
public function get_items_permissions_check( $request ) {
$tax_obj = get_taxonomy( $this->taxonomy );
@@ -167,6 +196,30 @@
);
}
+ if ( ! empty( $request['post'] ) ) {
+ $post = get_post( $request['post'] );
+
+ if ( ! $post ) {
+ return new WP_Error(
+ 'rest_post_invalid_id',
+ __( 'Invalid post ID.' ),
+ array(
+ 'status' => 400,
+ )
+ );
+ }
+
+ if ( ! $this->check_read_terms_permission_for_post( $post, $request ) ) {
+ return new WP_Error(
+ 'rest_forbidden_context',
+ __( 'Sorry, you are not allowed to view terms for this post.' ),
+ array(
+ 'status' => rest_authorization_required_code(),
+ )
+ );
+ }
+ }
+
return true;
}
@@ -295,15 +348,18 @@
// Store pagination values for headers.
$per_page = (int) $prepared_args['number'];
- $page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
+ $page = (int) ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
$response->header( 'X-WP-Total', (int) $total_terms );
- $max_pages = ceil( $total_terms / $per_page );
+ $max_pages = (int) ceil( $total_terms / $per_page );
+
+ $response->header( 'X-WP-TotalPages', $max_pages );
- $response->header( 'X-WP-TotalPages', (int) $max_pages );
+ $request_params = $request->get_query_params();
+ $collection_url = rest_url( rest_get_route_for_taxonomy_items( $this->taxonomy ) );
+ $base = add_query_arg( urlencode_deep( $request_params ), $collection_url );
- $base = add_query_arg( urlencode_deep( $request->get_query_params() ), rest_url( $this->namespace . '/' . $this->rest_base ) );
if ( $page > 1 ) {
$prev_page = $page - 1;
@@ -361,7 +417,7 @@
* @since 4.7.0
*
* @param WP_REST_Request $request Full details about the request.
- * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
+ * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object.
*/
public function get_item_permissions_check( $request ) {
$term = $this->get_term( $request['id'] );
@@ -751,7 +807,7 @@
* @return object Term object.
*/
public function prepare_item_for_database( $request ) {
- $prepared_term = new stdClass;
+ $prepared_term = new stdClass();
$schema = $this->get_item_schema();
if ( isset( $request['name'] ) && ! empty( $schema['properties']['name'] ) ) {
@@ -859,7 +915,9 @@
$response = rest_ensure_response( $data );
- $response->add_links( $this->prepare_links( $item ) );
+ if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
+ $response->add_links( $this->prepare_links( $item ) );
+ }
/**
* Filters the term data for a REST API response.
@@ -891,13 +949,12 @@
* @return array Links for the given term.
*/
protected function prepare_links( $term ) {
- $base = $this->namespace . '/' . $this->rest_base;
$links = array(
'self' => array(
- 'href' => rest_url( trailingslashit( $base ) . $term->term_id ),
+ 'href' => rest_url( rest_get_route_for_term( $term ) ),
),
'collection' => array(
- 'href' => rest_url( $base ),
+ 'href' => rest_url( rest_get_route_for_taxonomy_items( $this->taxonomy ) ),
),
'about' => array(
'href' => rest_url( sprintf( 'wp/v2/taxonomies/%s', $this->taxonomy ) ),
@@ -909,7 +966,7 @@
if ( $parent_term ) {
$links['up'] = array(
- 'href' => rest_url( trailingslashit( $base ) . $parent_term->term_id ),
+ 'href' => rest_url( rest_get_route_for_term( $parent_term ) ),
'embeddable' => true,
);
}