Skip to content

Commit 45e2aee

Browse files
committed
Editor: Update build_query_vars_from_query_block to handle new taxQuery structure.
The Query Loop block's `taxQuery` attribute now supports an include/exclude structure for term filtering. This updates the server-side query building to handle both the old format (e.g. `{"category":[4]}`) and the new format (e.g. `{"include":{"category":[4]},"exclude":{"post_tag":[5]}}`). Props ntsekouras, westonruter, peterwilsoncc, mcsf. Fixes #64416. git-svn-id: https://develop.svn.wordpress.org/trunk@61650 602fd350-edb4-49c9-b593-d223f7449a82
1 parent eef6fb2 commit 45e2aee

2 files changed

Lines changed: 149 additions & 10 deletions

File tree

src/wp-includes/blocks.php

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,6 +2660,7 @@ function wp_migrate_old_typography_shape( $metadata ) {
26602660
* @since 5.8.0
26612661
* @since 6.1.0 Added `query_loop_block_query_vars` filter and `parents` support in query.
26622662
* @since 6.7.0 Added support for the `format` property in query.
2663+
* @since 7.0.0 Updated `taxQuery` structure.
26632664
*
26642665
* @param WP_Block $block Block instance.
26652666
* @param int $page Current query's page.
@@ -2741,18 +2742,60 @@ function build_query_vars_from_query_block( $block, $page ) {
27412742
}
27422743
$query['tax_query'] = array_merge( $query['tax_query'], $tax_query_back_compat );
27432744
}
2744-
if ( ! empty( $block->context['query']['taxQuery'] ) ) {
2745-
$tax_query = array();
2746-
foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) {
2747-
if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {
2748-
$tax_query[] = array(
2749-
'taxonomy' => $taxonomy,
2750-
'terms' => array_filter( array_map( 'intval', $terms ) ),
2751-
'include_children' => false,
2752-
);
2745+
2746+
if ( ! empty( $block->context['query']['taxQuery'] ) && is_array( $block->context['query']['taxQuery'] ) ) {
2747+
$tax_query_input = $block->context['query']['taxQuery'];
2748+
$tax_query = array();
2749+
// If there are keys other than include/exclude, it's the old
2750+
// format e.g. "taxQuery":{"category":[4]}
2751+
if ( ! empty( array_diff( array_keys( $tax_query_input ), array( 'include', 'exclude' ) ) ) ) {
2752+
foreach ( $block->context['query']['taxQuery'] as $taxonomy => $terms ) {
2753+
if ( is_taxonomy_viewable( $taxonomy ) && ! empty( $terms ) ) {
2754+
$tax_query[] = array(
2755+
'taxonomy' => $taxonomy,
2756+
'terms' => array_filter( array_map( 'intval', $terms ) ),
2757+
'include_children' => false,
2758+
);
2759+
}
27532760
}
2761+
} else {
2762+
// This is the new format e.g. "taxQuery":{"include":{"category":[4]},"exclude":{"post_tag":[5]}}
2763+
2764+
// Helper function to build tax_query conditions from taxonomy terms.
2765+
$build_conditions = static function ( $terms, string $operator = 'IN' ): array {
2766+
$terms = (array) $terms;
2767+
$conditions = array();
2768+
foreach ( $terms as $taxonomy => $tax_terms ) {
2769+
if ( ! empty( $tax_terms ) && is_taxonomy_viewable( $taxonomy ) ) {
2770+
$conditions[] = array(
2771+
'taxonomy' => $taxonomy,
2772+
'terms' => array_filter( array_map( 'intval', $tax_terms ) ),
2773+
'operator' => $operator,
2774+
'include_children' => false,
2775+
);
2776+
}
2777+
}
2778+
return $conditions;
2779+
};
2780+
2781+
// Separate exclude from include terms.
2782+
$exclude_terms = isset( $tax_query_input['exclude'] ) && is_array( $tax_query_input['exclude'] )
2783+
? $tax_query_input['exclude']
2784+
: array();
2785+
$include_terms = isset( $tax_query_input['include'] ) && is_array( $tax_query_input['include'] )
2786+
? $tax_query_input['include']
2787+
: array();
2788+
2789+
$tax_query = array_merge(
2790+
$build_conditions( $include_terms ),
2791+
$build_conditions( $exclude_terms, 'NOT IN' )
2792+
);
2793+
}
2794+
2795+
if ( ! empty( $tax_query ) ) {
2796+
// Merge with any existing `tax_query` conditions.
2797+
$query['tax_query'] = array_merge( $query['tax_query'], $tax_query );
27542798
}
2755-
$query['tax_query'] = array_merge( $query['tax_query'], $tax_query );
27562799
}
27572800
if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
27582801
$formats = $block->context['query']['format'];

tests/phpunit/tests/blocks/wpBlock.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,102 @@ public function test_build_query_vars_from_query_block() {
837837
);
838838
}
839839

840+
/**
841+
* @ticket 64416
842+
*/
843+
public function test_build_query_vars_from_query_block_tax_query_old_format() {
844+
$this->registry->register(
845+
'core/example',
846+
array( 'uses_context' => array( 'query' ) )
847+
);
848+
849+
$parsed_blocks = parse_blocks( '<!-- wp:example {"ok":true} -->a<!-- wp:example /-->b<!-- /wp:example -->' );
850+
$parsed_block = $parsed_blocks[0];
851+
$context = array(
852+
'query' => array(
853+
'taxQuery' => array(
854+
'category' => array( 1, 2, 3 ),
855+
'post_tag' => array( 10, 20 ),
856+
),
857+
),
858+
);
859+
$block = new WP_Block( $parsed_block, $context, $this->registry );
860+
$query = build_query_vars_from_query_block( $block, 1 );
861+
862+
$this->assertSame(
863+
array(
864+
'post_type' => 'post',
865+
'order' => 'DESC',
866+
'orderby' => 'date',
867+
'post__not_in' => array(),
868+
'tax_query' => array(
869+
array(
870+
'taxonomy' => 'category',
871+
'terms' => array( 1, 2, 3 ),
872+
'include_children' => false,
873+
),
874+
array(
875+
'taxonomy' => 'post_tag',
876+
'terms' => array( 10, 20 ),
877+
'include_children' => false,
878+
),
879+
),
880+
),
881+
$query
882+
);
883+
}
884+
885+
/**
886+
* @ticket 64416
887+
*/
888+
public function test_build_query_vars_from_query_block_tax_query_include_exclude() {
889+
$this->registry->register(
890+
'core/example',
891+
array( 'uses_context' => array( 'query' ) )
892+
);
893+
894+
$parsed_blocks = parse_blocks( '<!-- wp:example {"ok":true} -->a<!-- wp:example /-->b<!-- /wp:example -->' );
895+
$parsed_block = $parsed_blocks[0];
896+
$context = array(
897+
'query' => array(
898+
'taxQuery' => array(
899+
'include' => array(
900+
'category' => array( 1, 2, 3 ),
901+
),
902+
'exclude' => array(
903+
'post_tag' => array( 15 ),
904+
),
905+
),
906+
),
907+
);
908+
$block = new WP_Block( $parsed_block, $context, $this->registry );
909+
$query = build_query_vars_from_query_block( $block, 1 );
910+
911+
$this->assertSame(
912+
array(
913+
'post_type' => 'post',
914+
'order' => 'DESC',
915+
'orderby' => 'date',
916+
'post__not_in' => array(),
917+
'tax_query' => array(
918+
array(
919+
'taxonomy' => 'category',
920+
'terms' => array( 1, 2, 3 ),
921+
'operator' => 'IN',
922+
'include_children' => false,
923+
),
924+
array(
925+
'taxonomy' => 'post_tag',
926+
'terms' => array( 15 ),
927+
'operator' => 'NOT IN',
928+
'include_children' => false,
929+
),
930+
),
931+
),
932+
$query
933+
);
934+
}
935+
840936
/**
841937
* @ticket 62014
842938
*/

0 commit comments

Comments
 (0)