Site icon Hip-Hop Website Design and Development

Post API tax_relation field doesn’t work

I’m trying to query posts that contain ALL the supplied tags, with a URL like this:

/wp-json/wp/v2/posts?tags=22,23&tax_relation=AND

However, it still returns posts with any of the tags, not all of them.

I dug into WP’s code and found this from wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php:

private function prepare_tax_query( array $args, WP_REST_Request $request ) {
    $relation = $request['tax_relation'];

    if ( $relation ) {
        $args['tax_query'] = array( 'relation' => $relation );
    }

    $taxonomies = wp_list_filter(
        get_object_taxonomies( $this->post_type, 'objects' ),
        array( 'show_in_rest' => true )
    );

    foreach ( $taxonomies as $taxonomy ) {
        $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;

        $tax_include = $request[ $base ];
        $tax_exclude = $request[ $base . '_exclude' ];

        if ( $tax_include ) {
            $terms            = array();
            $include_children = false;
            $operator         = 'IN';

            if ( rest_is_array( $tax_include ) ) {
                $terms = $tax_include;
            } elseif ( rest_is_object( $tax_include ) ) {
                $terms            = empty( $tax_include['terms'] ) ? array() : $tax_include['terms'];
                $include_children = ! empty( $tax_include['include_children'] );

                if ( isset( $tax_include['operator'] ) && 'AND' === $tax_include['operator'] ) {
                    $operator = 'AND';
                }
            }

The bit that should be applying the AND clause is this bit:

if ( isset( $tax_include['operator'] ) && 'AND' === $tax_include['operator'] ) {
    $operator = 'AND';
}

But a few lines up it does this:

$tax_include = $request[ $base ];

And if I dump out the value of $tax_include, I get this:

Array
(
    [0] => 22
    [1] => 23
)

So I don’t see how half of WP’s code here is supposed to work? The terms and include_children and operator keys will never exist on $tax_include as it’s just an array of IDs from the request.

If I manually add this in after the initial code chunk:

$operator = 'AND';

It works fine and matches all the tags.

Surely this is a bug in WP and just flat out doesn’t work, or am I misunderstanding something here?