WP_Query OR clause for tax_query and keywords

Here’s a little experiment:

You can try the following setup:

$args = array(
    'wpse_search_or_tax_query'      => true,    // <-- New parameter!
    's'                             => 'some search text',
    'tax_query'                     => array(
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => array( 'some-category-slug' ),
            'operator' => 'IN',
        ),
    ),      
);
$query = new WP_Query( $args );

where we introduce the custom wpse_search_or_tax_query parameter to activate the query modifications.

This is supported by the following demo plugin:

<?php
/**
 * Plugin Name: Modify the WP_Query to use OR between the search and tax query parts.
 * Description: Activation through the boolean 'wpse_search_or_tax_query' parameter.
 * Plugin URI:  http://wordpress.stackexchange.com/a/174221/26350
 * Author:      Birgir Erlendsson (birgire)
 * Version:     0.0.2
 */

add_action( 'init', function()
{   
    if( ! is_admin() && class_exists( 'WPSE_Modify_Query' ) )
    {
        $o = new WPSE_Modify_Query;
        $o->activate();
    }
});


class WPSE_Modify_Query
{
    private $search="";

    public function activate()
    {
        add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
    }

    public function pre_get_posts( WP_Query $q )
    {
        if( filter_var( 
                $q->get( 'wpse_search_or_tax_query' ), 
                FILTER_VALIDATE_BOOLEAN 
             ) 
             && $q->get( 'tax_query' ) 
             && $q->get( 's' )
        )
        {                                                           
            add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );
            add_filter( 'posts_search', array( $this, 'posts_search' ), 10, 2 );
        }
    }

    public function posts_clauses( $clauses, \WP_Query $q )
    {
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );

        // Generate the tax query:
        $tq = new WP_Tax_Query( $q->query_vars['tax_query'] );

        // Get the generated taxonomy clauses:
        global $wpdb;
        $tc = $tq->get_sql( $wpdb->posts, 'ID' );

        // Remove the search part:
        $clauses['where'] = str_ireplace( 
            $this->search, 
            ' ', 
            $clauses['where'] 
        );

        // Remove the taxonomy part:
        $clauses['where'] = str_ireplace( 
            $tc['where'], 
            ' ', 
            $clauses['where'] 
        );

        // Add the search OR taxonomy part:
        $clauses['where'] .= sprintf( 
            " AND ( ( 1=1 %s ) OR ( 1=1 %s ) ) ", 
            $tc['where'],
            $this->search
        );

        return $clauses;
    }

    public function posts_search( $search, \WP_Query $q )
    {
        remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
        $this->search = $search;
        return $search;
    }

} // end class

Hopefully you can adjust this further to your needs.

Leave a Comment