I am implementing some special search options that should exclude anything not of the type post
. The Events Calendar is interfering and modifying the query on the fly anyway.
My query mod just looks like:
$query->post_type
And I am doing this before the query in question:
remove_action(
'pre_get_posts',
[ 'Tribe__Events__Query', 'pre_get_posts' ],
50
);
remove_action(
'parse_query',
[ 'Tribe__Events__Query', 'parse_query' ],
50
);
...and restoring the actions afterward to resume normal operation.
So with this debug code:
add_filter('query', function($sql) {
global $wp_query;
if (isset($_GET['s']) && strpos($sql, $_GET['s']) !== false) {
debug($wp_query->post_type);
debug($wp_query->tax_query);
debug($sql);
}
return $sql;
});
...I can see that the post_type on the query object itself is getting set correctly, and the tax_query
is at the default setting (no events calendar stuff). But by the time WordPress's query
filter runs, the actual SQL that runs is:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts
WHERE 1=1
AND (((wp_posts.post_title LIKE '%persian%') OR (wp_posts.post_excerpt LIKE '%persian%') OR (wp_posts.post_content LIKE '%persian%')))
AND (wp_posts.post_password = '')
AND wp_posts.post_type IN ('post', 'page', 'attachment', 'tribe_venue', 'tribe_events', 'tribe-ea-record', 'service', 'facility')
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled'
OR wp_posts.post_status = 'tribe-ea-success'
OR wp_posts.post_status = 'tribe-ea-failed'
OR wp_posts.post_status = 'tribe-ea-schedule'
OR wp_posts.post_status = 'tribe-ea-pending'
OR wp_posts.post_status = 'tribe-ea-draft')
ORDER BY wp_posts.post_title LIKE '%persian%'
DESC, wp_posts.post_date DESC LIMIT 0, 6
Edit 1
Here's the full WP_Query
object dump:
WP_Query::__set_state(array(
'query' =>
array (
's' => 'persian',
),
'query_vars' =>
array (
's' => 'persian',
'error' => '',
'm' => '',
'p' => 0,
'post_parent' => '',
'subpost' => '',
'subpost_id' => '',
'attachment' => '',
'attachment_id' => 0,
'name' => '',
'static' => '',
'pagename' => '',
'page_id' => 0,
'second' => '',
'minute' => '',
'hour' => '',
'day' => 0,
'monthnum' => 0,
'year' => 0,
'w' => 0,
'category_name' => '',
'tag' => '',
'cat' => '',
'tag_id' => '',
'author' => '',
'author_name' => '',
'feed' => '',
'tb' => '',
'paged' => 0,
'meta_key' => '',
'meta_value' => '',
'preview' => '',
'sentence' => '',
'title' => '',
'fields' => '',
'menu_order' => '',
'embed' => '',
'category__in' =>
array (
),
'category__not_in' =>
array (
),
'category__and' =>
array (
),
'post__in' =>
array (
),
'post__not_in' =>
array (
),
'post_name__in' =>
array (
),
'tag__in' =>
array (
),
'tag__not_in' =>
array (
),
'tag__and' =>
array (
),
'tag_slug__in' =>
array (
),
'tag_slug__and' =>
array (
),
'post_parent__in' =>
array (
),
'post_parent__not_in' =>
array (
),
'author__in' =>
array (
),
'author__not_in' =>
array (
),
'ignore_sticky_posts' => false,
'suppress_filters' => false,
'cache_results' => true,
'update_post_term_cache' => true,
'lazy_load_term_meta' => true,
'update_post_meta_cache' => true,
'post_type' => 'any',
'posts_per_page' => 6,
'nopaging' => false,
'comments_per_page' => '50',
'no_found_rows' => false,
'search_terms_count' => 1,
'search_terms' =>
array (
0 => 'persian',
),
'search_orderby_title' =>
array (
0 => 'wp_posts.post_title LIKE \'%persian%\'',
),
'order' => 'DESC',
),
'tax_query' =>
WP_Tax_Query::__set_state(array(
'queries' =>
array (
),
'relation' => 'AND',
'table_aliases' =>
array (
),
'queried_terms' =>
array (
),
'primary_table' => 'wp_posts',
'primary_id_column' => 'ID',
)),
'meta_query' =>
WP_Meta_Query::__set_state(array(
'queries' =>
array (
),
'relation' => NULL,
'meta_table' => NULL,
'meta_id_column' => NULL,
'primary_table' => NULL,
'primary_id_column' => NULL,
'table_aliases' =>
array (
),
'clauses' =>
array (
),
'has_or_relation' => false,
)),
'date_query' => false,
'post_count' => 0,
'current_post' => -1,
'in_the_loop' => false,
'comment_count' => 0,
'current_comment' => -1,
'found_posts' => 0,
'max_num_pages' => 0,
'max_num_comment_pages' => 0,
'is_single' => false,
'is_preview' => false,
'is_page' => false,
'is_archive' => false,
'is_date' => false,
'is_year' => false,
'is_month' => false,
'is_day' => false,
'is_time' => false,
'is_author' => false,
'is_category' => false,
'is_tag' => false,
'is_tax' => false,
'is_search' => true,
'is_feed' => false,
'is_comment_feed' => false,
'is_trackback' => false,
'is_home' => false,
'is_404' => false,
'is_embed' => false,
'is_paged' => false,
'is_admin' => false,
'is_attachment' => false,
'is_singular' => false,
'is_robots' => false,
'is_posts_page' => false,
'is_post_type_archive' => false,
'query_vars_hash' => '1b23d8a973f2ad41269c66f71f8365d4',
'query_vars_changed' => false,
'thumbnails_cached' => false,
'stopwords' =>
array (
0 => 'about',
1 => 'an',
2 => 'are',
3 => 'as',
4 => 'at',
5 => 'be',
6 => 'by',
7 => 'com',
8 => 'for',
9 => 'from',
10 => 'how',
11 => 'in',
12 => 'is',
13 => 'it',
14 => 'of',
15 => 'on',
16 => 'or',
17 => 'that',
18 => 'the',
19 => 'this',
20 => 'to',
21 => 'was',
22 => 'what',
23 => 'when',
24 => 'where',
25 => 'who',
26 => 'will',
27 => 'with',
28 => 'www',
),
'compat_fields' =>
array (
0 => 'query_vars_hash',
1 => 'query_vars_changed',
),
'compat_methods' =>
array (
0 => 'init_query_flags',
1 => 'parse_tax_query',
),
'tribe_is_event' => false,
'tribe_is_multi_posttype' => false,
'tribe_is_event_category' => false,
'tribe_is_event_venue' => false,
'tribe_is_event_organizer' => false,
'tribe_is_event_query' => false,
'tribe_is_past' => false,
'post_type' => 'post',
'request' => 'SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND (((wp_posts.post_title LIKE \'%persian%\') OR (wp_posts.post_excerpt LIKE \'%persian%\') OR (wp_posts.post_content LIKE \'%persian%\'))) AND (wp_posts.post_password = \'\') AND wp_posts.post_type IN (\'post\', \'page\', \'attachment\', \'tribe_venue\', \'tribe_events\', \'tribe-ea-record\', \'service\', \'facility\') AND (wp_posts.post_status = \'publish\' OR wp_posts.post_status = \'acf-disabled\' OR wp_posts.post_status = \'tribe-ea-success\' OR wp_posts.post_status = \'tribe-ea-failed\' OR wp_posts.post_status = \'tribe-ea-schedule\' OR wp_posts.post_status = \'tribe-ea-pending\' OR wp_posts.post_status = \'tribe-ea-draft\') ORDER BY wp_posts.post_title LIKE \'%persian%\' DESC, wp_posts.post_date DESC LIMIT 0, 6',
'posts' => NULL,
))
From this I see that the extra tribe-* clauses are already in there. Not totally sure where they're coming from or how to get rid of them.
Edit 2
To give a bit more detail, I'm trying to implement a dropdown that gives users the ability to specify what I'm calling a search type, which include:
- All - default search behavior
- Blog posts - type
post
only - Classes - posts of type
tribe_events
in theclasses
category - Club Events - posts of type
tribe_events
in theclub-events
category
Here's an outline of what I have so far:
In functions.php
add_action( 'pre_get_posts', function( WP_Query $query ) {
$searchType = isset($_GET['search_type']) ? $_GET['search_type'] : '';
SearchFilter\AbstractBase::filter_results_by_search_type($query, $searchType);
});
SearchFilter/AbstractBase.php
namespace SearchFilter;
use WP_Query;
use Timber;
abstract class AbstractBase {
/**
* Supported search_types and the specific class responsible for modifying the query for each type
*/
protected static $SUPPORTED_TYPES = [
'post' => 'wac\SearchFilter\PostFilter',
'tribe_events_category_classes' => 'wac\SearchFilter\ClassFilter',
'tribe_events_category_club_events' => 'wac\SearchFilter\ClubEventFilter',
];
/**
* The instance of SearchFilter\AbstractBase to pull queries from
*/
protected static $filteredSearchQuery;
/**
* Modify $query to limit search results to the specified $type.
* Supported types are enumerated in the $SUPPORTED_TYPES property.
*/
public static function filter_results_by_search_type(WP_Query $query, $type = '') {
// only affect general search queries
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
// figure out what type of search this is
if (isset(static::$SUPPORTED_TYPES[$type])) {
$class = static::$SUPPORTED_TYPES[$type];
$filter = new $class($query);
} else {
$filter = new DefaultFilter($query);
}
$filter->modify_query();
static::$filteredSearchQuery = $filter;
}
}
/**
* Constructor
* @param WP_Query $query the WP_Query object to modify
*/
protected function __construct(WP_Query $query) {
$this->query = $query;
}
/**
* Returns the modified query
*/
abstract public function modify_query();
public function get_posts() {
$this->override_tribe_hooks();
$posts = Timber::get_posts();
$this->restore_tribe_hooks();
return $posts;
}
protected function hide_recurring_events() {
$this->query->set( 'tribeHideRecurrence', true );
$this->query->set( 'eventDisplay', 'upcoming' );
$this->query->tribe_is_multi_posttype = true;
$this->query->set('meta_query', array(
'relation' => 'OR',
array(
'key' => '_EventStartDate',
'value' => date('Y-m-d h:i:s'),
'compare' => '>=',
'type' => 'DATE'
),
array(
'key' => '_EventEndDate',
'value' => date('Y-m-d h:i:s'),
'compare' => '>',
'type' => 'DATE'
),
array(
'relation' => 'AND',
array(
'key' => '_EventStartDate',
'compare' => 'NOT EXISTS',
'type' => 'DATE'
),
array(
'key' => '_EventEndDate',
'compare' => 'NOT EXISTS',
'type' => 'DATE'
)
)
));
}
/**
* Remove default The Events Calendar hook for querying events
*/
protected function override_tribe_hooks() {
remove_action(
'pre_get_posts',
[ 'Tribe__Events__Query', 'pre_get_posts' ],
static::TRIBE_ACTION_PRIORITY
);
remove_action(
'parse_query',
[ 'Tribe__Events__Query', 'parse_query' ],
static::TRIBE_ACTION_PRIORITY
);
}
protected function restore_tribe_hooks() {
add_action(
'pre_get_posts',
[ 'Tribe__Events__Query', 'pre_get_posts' ],
static::TRIBE_ACTION_PRIORITY
);
add_action(
'parse_query',
[ 'Tribe__Events__Query', 'parse_query' ],
static::TRIBE_ACTION_PRIORITY
);
}
SearchFilter/DefaultFilter.php
namespace SearchFilter;
use Timber;
class DefaultFilter extends AbstractBase {
public function modify_query() {
$this->hide_recurring_events();
}
public function get_posts() {
return Timber::get_posts();
}
}
SearchFilter/PostFilter.php
namespace SearchFilter;
use WP_Query;
class PostFilter extends AbstractBase {
public function modify_query() {
$this->query->query_vars->post_type = ['post'];
}
}
search.php
$data['posts'] = SearchFilter\AbstractBase::get_filtered_query()->get_posts();
// render posts
BTW, Timber is a low-level plugin that provides a more OO-friendly interface around get_posts
and the like. I've used it on tons of WP projects and it never gets in the way like this, so I don't think it's the issue here.
What am I missing?