Make WordPress Core


Ignore:
Timestamp:
02/02/2021 07:23:08 PM (4 years ago)
Author:
TimothyBlynJacobs
Message:

REST API: Allow for the posts endpoint include/exclude terms query to include_children.

For example the categories or categories_exclude parameters can now optionally accept an object with a terms property that accepts the list of term ids and a new include_children property which controls the Tax Query include_children field.

Props jason_the_adams, jnylen0, birgire, dlh.
Fixes #39494.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

    r50024 r50157  
    281281        }
    282282
    283         $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
    284 
    285         if ( ! empty( $request['tax_relation'] ) ) {
    286             $args['tax_query'] = array( 'relation' => $request['tax_relation'] );
    287         }
    288 
    289         foreach ( $taxonomies as $taxonomy ) {
    290             $base        = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
    291             $tax_exclude = $base . '_exclude';
    292 
    293             if ( ! empty( $request[ $base ] ) ) {
    294                 $args['tax_query'][] = array(
    295                     'taxonomy'         => $taxonomy->name,
    296                     'field'            => 'term_id',
    297                     'terms'            => $request[ $base ],
    298                     'include_children' => false,
    299                 );
    300             }
    301 
    302             if ( ! empty( $request[ $tax_exclude ] ) ) {
    303                 $args['tax_query'][] = array(
    304                     'taxonomy'         => $taxonomy->name,
    305                     'field'            => 'term_id',
    306                     'terms'            => $request[ $tax_exclude ],
    307                     'include_children' => false,
    308                     'operator'         => 'NOT IN',
    309                 );
    310             }
    311         }
     283        $args = $this->prepare_tax_query( $args, $request );
    312284
    313285        // Force the post_type argument, since it's not a user input variable.
     
    28002772        );
    28012773
    2802         $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
    2803 
    2804         if ( ! empty( $taxonomies ) ) {
    2805             $query_params['tax_relation'] = array(
    2806                 'description' => __( 'Limit result set based on relationship between multiple taxonomies.' ),
    2807                 'type'        => 'string',
    2808                 'enum'        => array( 'AND', 'OR' ),
    2809             );
    2810         }
    2811 
    2812         foreach ( $taxonomies as $taxonomy ) {
    2813             $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
    2814 
    2815             $query_params[ $base ] = array(
    2816                 /* translators: %s: Taxonomy name. */
    2817                 'description' => sprintf( __( 'Limit result set to all items that have the specified term assigned in the %s taxonomy.' ), $base ),
    2818                 'type'        => 'array',
    2819                 'items'       => array(
    2820                     'type' => 'integer',
    2821                 ),
    2822                 'default'     => array(),
    2823             );
    2824 
    2825             $query_params[ $base . '_exclude' ] = array(
    2826                 /* translators: %s: Taxonomy name. */
    2827                 'description' => sprintf( __( 'Limit result set to all items except those that have the specified term assigned in the %s taxonomy.' ), $base ),
    2828                 'type'        => 'array',
    2829                 'items'       => array(
    2830                     'type' => 'integer',
    2831                 ),
    2832                 'default'     => array(),
    2833             );
    2834         }
     2774        $query_params = $this->prepare_taxonomy_limit_schema( $query_params );
    28352775
    28362776        if ( 'post' === $this->post_type ) {
     
    29002840        return $statuses;
    29012841    }
     2842
     2843    /**
     2844     * Prepares the 'tax_query' for a collection of posts.
     2845     *
     2846     * @since 5.7.0
     2847     *
     2848     * @param array           $args    WP_Query arguments.
     2849     * @param WP_REST_Request $request Full details about the request.
     2850     * @return array Updated query arguments.
     2851     */
     2852    private function prepare_tax_query( array $args, WP_REST_Request $request ) {
     2853        $relation = $request['tax_relation'];
     2854
     2855        if ( $relation ) {
     2856            $args['tax_query'] = array( 'relation' => $relation );
     2857        }
     2858
     2859        $taxonomies = wp_list_filter(
     2860            get_object_taxonomies( $this->post_type, 'objects' ),
     2861            array( 'show_in_rest' => true )
     2862        );
     2863
     2864        foreach ( $taxonomies as $taxonomy ) {
     2865            $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
     2866
     2867            $tax_include = $request[ $base ];
     2868            $tax_exclude = $request[ $base . '_exclude' ];
     2869
     2870            if ( $tax_include ) {
     2871                $terms            = array();
     2872                $include_children = false;
     2873
     2874                if ( rest_is_array( $tax_include ) ) {
     2875                    $terms = $tax_include;
     2876                } elseif ( rest_is_object( $tax_include ) ) {
     2877                    $terms            = empty( $tax_include['terms'] ) ? array() : $tax_include['terms'];
     2878                    $include_children = ! empty( $tax_include['include_children'] );
     2879                }
     2880
     2881                if ( $terms ) {
     2882                    $args['tax_query'][] = array(
     2883                        'taxonomy'         => $taxonomy->name,
     2884                        'field'            => 'term_id',
     2885                        'terms'            => $terms,
     2886                        'include_children' => $include_children,
     2887                    );
     2888                }
     2889            }
     2890
     2891            if ( $tax_exclude ) {
     2892                $terms            = array();
     2893                $include_children = false;
     2894
     2895                if ( rest_is_array( $tax_exclude ) ) {
     2896                    $terms = $tax_exclude;
     2897                } elseif ( rest_is_object( $tax_exclude ) ) {
     2898                    $terms            = empty( $tax_exclude['terms'] ) ? array() : $tax_exclude['terms'];
     2899                    $include_children = ! empty( $tax_exclude['include_children'] );
     2900                }
     2901
     2902                if ( $terms ) {
     2903                    $args['tax_query'][] = array(
     2904                        'taxonomy'         => $taxonomy->name,
     2905                        'field'            => 'term_id',
     2906                        'terms'            => $terms,
     2907                        'include_children' => $include_children,
     2908                        'operator'         => 'NOT IN',
     2909                    );
     2910                }
     2911            }
     2912        }
     2913
     2914        return $args;
     2915    }
     2916
     2917    /**
     2918     * Prepares the collection schema for including and excluding items by terms.
     2919     *
     2920     * @since 5.7.0
     2921     *
     2922     * @param array $query_params Collection schema.
     2923     * @return array Updated schema.
     2924     */
     2925    private function prepare_taxonomy_limit_schema( array $query_params ) {
     2926        $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
     2927
     2928        if ( ! $taxonomies ) {
     2929            return $query_params;
     2930        }
     2931
     2932        $query_params['tax_relation'] = array(
     2933            'description' => __( 'Limit result set based on relationship between multiple taxonomies.' ),
     2934            'type'        => 'string',
     2935            'enum'        => array( 'AND', 'OR' ),
     2936        );
     2937
     2938        $limit_schema = array(
     2939            'type'  => array( 'object', 'array' ),
     2940            'oneOf' => array(
     2941                array(
     2942                    'title'       => __( 'Term ID List' ),
     2943                    'description' => __( 'Match terms with the listed IDs.' ),
     2944                    'type'        => 'array',
     2945                    'items'       => array(
     2946                        'type' => 'integer',
     2947                    ),
     2948                ),
     2949                array(
     2950                    'title'                => __( 'Term ID Taxonomy Query' ),
     2951                    'description'          => __( 'Perform an advanced term query.' ),
     2952                    'type'                 => 'object',
     2953                    'properties'           => array(
     2954                        'terms'            => array(
     2955                            'description' => __( 'Term IDs.' ),
     2956                            'type'        => 'array',
     2957                            'items'       => array(
     2958                                'type' => 'integer',
     2959                            ),
     2960                            'default'     => array(),
     2961                        ),
     2962                        'include_children' => array(
     2963                            'description' => __( 'Whether to include child terms in the terms limiting the result set.' ),
     2964                            'type'        => 'boolean',
     2965                            'default'     => false,
     2966                        ),
     2967                    ),
     2968                    'additionalProperties' => false,
     2969                ),
     2970            ),
     2971        );
     2972
     2973        $include_schema = array_merge(
     2974            array(
     2975                /* translators: %s: Taxonomy name. */
     2976                'description' => __( 'Limit result set to items with specific terms assigned in the %s taxonomy.' ),
     2977            ),
     2978            $limit_schema
     2979        );
     2980        $exclude_schema = array_merge(
     2981            array(
     2982                /* translators: %s: Taxonomy name. */
     2983                'description' => __( 'Limit result set to items except those with specific terms assigned in the %s taxonomy.' ),
     2984            ),
     2985            $limit_schema
     2986        );
     2987
     2988        foreach ( $taxonomies as $taxonomy ) {
     2989            $base         = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
     2990            $base_exclude = $base . '_exclude';
     2991
     2992            $query_params[ $base ]                = $include_schema;
     2993            $query_params[ $base ]['description'] = sprintf( $query_params[ $base ]['description'], $base );
     2994
     2995            $query_params[ $base_exclude ]                = $exclude_schema;
     2996            $query_params[ $base_exclude ]['description'] = sprintf( $query_params[ $base_exclude ]['description'], $base );
     2997
     2998            if ( ! $taxonomy->hierarchical ) {
     2999                unset( $query_params[ $base ]['oneOf'][1]['properties']['include_children'] );
     3000                unset( $query_params[ $base_exclude ]['oneOf'][1]['properties']['include_children'] );
     3001            }
     3002        }
     3003
     3004        return $query_params;
     3005    }
    29023006}
Note: See TracChangeset for help on using the changeset viewer.