WordPress

search — jak mogę zastąpić modyfikacje zapytania Kalendarza wydarzeń?

  • 8 lutego, 2017
  • 9 min read
search — jak mogę zastąpić modyfikacje zapytania Kalendarza wydarzeń?


Wdrażam specjalne opcje wyszukiwania, które powinny wykluczać wszystko, co nie jest tego typu post. Kalendarz wydarzeń i tak zakłóca i modyfikuje zapytanie w locie.

Mój mod zapytania wygląda po prostu tak:

$query->post_type

I robię to przed danym zapytaniem:

remove_action(
  'pre_get_posts',
  [ 'Tribe__Events__Query', 'pre_get_posts' ],
  50
);

remove_action(
  'parse_query',
  [ 'Tribe__Events__Query', 'parse_query' ],
  50
);

…i przywrócenie działań później, aby wznowić normalne działanie.

Więc z tym kodem debugowania:

    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;
    });

… Widzę, że typ post_type w samym obiekcie zapytania jest ustawiany poprawnie, a plik tax_query jest w ustawieniu domyślnym (brak elementów kalendarza wydarzeń). Ale do czasu WordPress query filter działa, rzeczywisty uruchomiony SQL to:

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

Edytuj 1

Oto całość WP_Query zrzut obiektu:

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,
))

Z tego widzę, że dodatkowe klauzule plemienia-* już tam są. Nie do końca wiadomo, skąd pochodzą i jak się ich pozbyć.

Warto przeczytać!  Niestandardowa taksonomia na łączu bezpośrednim — WordPress Development Stack Exchange

Edytuj 2

Aby podać nieco więcej szczegółów, próbuję zaimplementować listę rozwijaną, która daje użytkownikom możliwość określenia, co nazywam Typ wyszukiwaniaktóry zawiera:

  1. Wszystkie — domyślne zachowanie wyszukiwania
  2. Wpisy na blogu – typ post tylko
  3. Klasy – wpisy typu tribe_events w classes Kategoria
  4. Wydarzenia klubowe – wpisy typu tribe_events w club-events Kategoria

Oto zarys tego, co mam do tej pory:

W funkcjach.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'];
  }
}

szukaj.php

$data['posts'] = SearchFilter\AbstractBase::get_filtered_query()->get_posts();
// render posts

BTW, Timber to wtyczka niskiego poziomu, która zapewnia interfejs bardziej przyjazny dla OO get_posts i tym podobne. Użyłem go w wielu projektach WP i nigdy nie przeszkadza w ten sposób, więc nie sądzę, żeby to był problem.

Warto przeczytać!  Co nowego w WordPress 6.2 (funkcje i zrzuty ekranu)

czego mi brakuje?


Źródło