Make WordPress Core

Changeset 61650


Ignore:
Timestamp:
02/16/2026 01:11:50 PM (5 months ago)
Author:
ntsekouras
Message:

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.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/blocks.php

    r61617 r61650  
    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.
     
    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                                }
    2754                         }
    2755                         $query['tax_query'] = array_merge( $query['tax_query'], $tax_query );
     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 );
     2798                        }
    27562799                }
    27572800                if ( ! empty( $block->context['query']['format'] ) && is_array( $block->context['query']['format'] ) ) {
  • trunk/tests/phpunit/tests/blocks/wpBlock.php

    r61519 r61650  
    839839
    840840        /**
     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
     936        /**
    841937         * @ticket 62014
    842938         */
Note: See TracChangeset for help on using the changeset viewer.