REST API/Editor: Support post formats in Query Block & Posts API.

Introduces post format support for both the Query Block with the new parameter `format`. In the `build_query_vars_from_query_block()` function, this is converted to a `post_format` taxonomy query passed to `WP_Query`.

Also introduces the `format` parameter to the REST API's Posts controller to support the feature in the Query block. The parameter type is an enumerated  string accepted the post formats supported by each post type.

Props poena, mukesh27, mamaduka, noisysocks, TimothyBlynJacobs.
Fixes #62014.

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


git-svn-id: http://core.svn.wordpress.org/trunk@58511 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Peter Wilson 2024-09-30 01:19:16 +00:00
parent 8838465b5e
commit 998a74eb6f
3 changed files with 142 additions and 7 deletions

View File

@ -2335,6 +2335,7 @@ function wp_migrate_old_typography_shape( $metadata ) {
* *
* @since 5.8.0 * @since 5.8.0
* @since 6.1.0 Added `query_loop_block_query_vars` filter and `parents` support in query. * @since 6.1.0 Added `query_loop_block_query_vars` filter and `parents` support in query.
* @since 6.7.0 Added support for the `format` property in query.
* *
* @param WP_Block $block Block instance. * @param WP_Block $block Block instance.
* @param int $page Current query's page. * @param int $page Current query's page.
@ -2347,6 +2348,7 @@ function build_query_vars_from_query_block( $block, $page ) {
'order' => 'DESC', 'order' => 'DESC',
'orderby' => 'date', 'orderby' => 'date',
'post__not_in' => array(), 'post__not_in' => array(),
'tax_query' => array(),
); );
if ( isset( $block->context['query'] ) ) { if ( isset( $block->context['query'] ) ) {
@ -2396,35 +2398,103 @@ function build_query_vars_from_query_block( $block, $page ) {
} }
// Migrate `categoryIds` and `tagIds` to `tax_query` for backwards compatibility. // Migrate `categoryIds` and `tagIds` to `tax_query` for backwards compatibility.
if ( ! empty( $block->context['query']['categoryIds'] ) || ! empty( $block->context['query']['tagIds'] ) ) { if ( ! empty( $block->context['query']['categoryIds'] ) || ! empty( $block->context['query']['tagIds'] ) ) {
$tax_query = array(); $tax_query_back_compat = array();
if ( ! empty( $block->context['query']['categoryIds'] ) ) { if ( ! empty( $block->context['query']['categoryIds'] ) ) {
$tax_query[] = array( $tax_query_back_compat[] = array(
'taxonomy' => 'category', 'taxonomy' => 'category',
'terms' => array_filter( array_map( 'intval', $block->context['query']['categoryIds'] ) ), 'terms' => array_filter( array_map( 'intval', $block->context['query']['categoryIds'] ) ),
'include_children' => false, 'include_children' => false,
); );
} }
if ( ! empty( $block->context['query']['tagIds'] ) ) { if ( ! empty( $block->context['query']['tagIds'] ) ) {
$tax_query[] = array( $tax_query_back_compat[] = array(
'taxonomy' => 'post_tag', 'taxonomy' => 'post_tag',
'terms' => array_filter( array_map( 'intval', $block->context['query']['tagIds'] ) ), 'terms' => array_filter( array_map( 'intval', $block->context['query']['tagIds'] ) ),
'include_children' => false, 'include_children' => false,
); );
} }
$query['tax_query'] = $tax_query; $query['tax_query'] = array_merge( $query['tax_query'], $tax_query_back_compat );
} }
if ( ! empty( $block->context['query']['taxQuery'] ) ) { if ( ! empty( $block->context['query']['taxQuery'] ) ) {
$query['tax_query'] = array(); $tax_query = array();
foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) { foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) {
if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) { if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {
$query['tax_query'][] = array( $tax_query[] = array(
'taxonomy' => $taxonomy, 'taxonomy' => $taxonomy,
'terms' => array_filter( array_map( 'intval', $terms ) ), 'terms' => array_filter( array_map( 'intval', $terms ) ),
'include_children' => false, 'include_children' => false,
); );
} }
} }
$query['tax_query'] = array_merge( $query['tax_query'], $tax_query );
} }
if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
$formats = $block->context['query']['format'];
/*
* Validate that the format is either `standard` or a supported post format.
* - First, add `standard` to the array of valid formats.
* - Then, remove any invalid formats.
*/
$valid_formats = array_merge( array( 'standard' ), get_post_format_slugs() );
$formats = array_intersect( $formats, $valid_formats );
/*
* The relation needs to be set to `OR` since the request can contain
* two separate conditions. The user may be querying for items that have
* either the `standard` format or a specific format.
*/
$formats_query = array( 'relation' => 'OR' );
/*
* The default post format, `standard`, is not stored in the database.
* If `standard` is part of the request, the query needs to exclude all post items that
* have a format assigned.
*/
if ( in_array( 'standard', $formats, true ) ) {
$formats_query[] = array(
'taxonomy' => 'post_format',
'field' => 'slug',
'operator' => 'NOT EXISTS',
);
// Remove the `standard` format, since it cannot be queried.
unset( $formats[ array_search( 'standard', $formats, true ) ] );
}
// Add any remaining formats to the formats query.
if ( ! empty( $formats ) ) {
// Add the `post-format-` prefix.
$terms = array_map(
static function ( $format ) {
return "post-format-$format";
},
$formats
);
$formats_query[] = array(
'taxonomy' => 'post_format',
'field' => 'slug',
'terms' => $terms,
'operator' => 'IN',
);
}
/*
* Add `$formats_query` to `$query`, as long as it contains more than one key:
* If `$formats_query` only contains the initial `relation` key, there are no valid formats to query,
* and the query should not be modified.
*/
if ( count( $formats_query ) > 1 ) {
// Enable filtering by both post formats and other taxonomies by combining them with `AND`.
if ( empty( $query['tax_query'] ) ) {
$query['tax_query'] = $formats_query;
} else {
$query['tax_query'] = array(
'relation' => 'AND',
$query['tax_query'],
$formats_query,
);
}
}
}
if ( if (
isset( $block->context['query']['order'] ) && isset( $block->context['query']['order'] ) &&
in_array( strtoupper( $block->context['query']['order'] ), array( 'ASC', 'DESC' ), true ) in_array( strtoupper( $block->context['query']['order'] ), array( 'ASC', 'DESC' ), true )

View File

@ -346,6 +346,59 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
$args = $this->prepare_tax_query( $args, $request ); $args = $this->prepare_tax_query( $args, $request );
if ( ! empty( $request['format'] ) ) {
$formats = $request['format'];
/*
* The relation needs to be set to `OR` since the request can contain
* two separate conditions. The user may be querying for items that have
* either the `standard` format or a specific format.
*/
$formats_query = array( 'relation' => 'OR' );
/*
* The default post format, `standard`, is not stored in the database.
* If `standard` is part of the request, the query needs to exclude all post items that
* have a format assigned.
*/
if ( in_array( 'standard', $formats, true ) ) {
$formats_query[] = array(
'taxonomy' => 'post_format',
'field' => 'slug',
'operator' => 'NOT EXISTS',
);
// Remove the `standard` format, since it cannot be queried.
unset( $formats[ array_search( 'standard', $formats, true ) ] );
}
// Add any remaining formats to the formats query.
if ( ! empty( $formats ) ) {
// Add the `post-format-` prefix.
$terms = array_map(
static function ( $format ) {
return "post-format-$format";
},
$formats
);
$formats_query[] = array(
'taxonomy' => 'post_format',
'field' => 'slug',
'terms' => $terms,
'operator' => 'IN',
);
}
// Enable filtering by both post formats and other taxonomies by combining them with `AND`.
if ( isset( $args['tax_query'] ) ) {
$args['tax_query'][] = array(
'relation' => 'AND',
$formats_query,
);
} else {
$args['tax_query'] = $formats_query;
}
}
// Force the post_type argument, since it's not a user input variable. // Force the post_type argument, since it's not a user input variable.
$args['post_type'] = $this->post_type; $args['post_type'] = $this->post_type;
@ -2992,6 +3045,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
); );
} }
if ( post_type_supports( $this->post_type, 'post-formats' ) ) {
$query_params['format'] = array(
'description' => __( 'Limit result set to items assigned one or more given formats.' ),
'type' => 'array',
'uniqueItems' => true,
'items' => array(
'enum' => array_values( get_post_format_slugs() ),
'type' => 'string',
),
);
}
/** /**
* Filters collection parameters for the posts controller. * Filters collection parameters for the posts controller.
* *

View File

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