Добавляем название таксономии (термина) в поиск по записям

Задача: к стандартному поиску по товарам нужно добавить поиск и по названию атрибута товара. Другими словами нужно к дефолтному поиску товаров добавить товары, которые относятся к атрибуту "Производитель" из поисковой фразы.

Логика работы такая:

  • Ищем в таксономии (атрибуте) "Производитель" термины по поисковой фразе
  • Запрашиваем все записи, относящиеся к найденным производителям
  • Добавляем найденные записи в общий пул записей, что были найдены стандартно

Данный механизм можно использовать и для поиска по любым типам записей и таксономиям - измените в коде их на желаемые.

// init
new Post_Search_With_Terms( [
	'post_type' => 'product',
	'taxonomy'  => 'pa_izgotovitel'
] );

/**
 * Extends default posts search in order to search by terms titles too.
 *
 * @version: 1.0
 */
final class Post_Search_With_Terms {

	private $post_type;
	private $taxonomy;

	/**
	 * @param array $args {
	 *     Arguments to retreive posts.
	 *
	 *     @type string $post_type Default: post
	 *     @type string $taxonomy  Default: post_tag
	 * }
	 */
	public function __construct( $args = [] ) {

		$args = (object) array_merge( [
			'post_type' => 'post',
			'taxonomy'  => 'post_tag'
		], $args );

		foreach( $args as $key => $val ){
			$this->$key = $val;
		}

		add_filter( 'pre_get_posts', [ $this, 'extends_search_query' ] );
	}

	/**
	 * @param WP_Query $wp_query
	 */
	public function extends_search_query( $wp_query ) {

		// Только для основного запроса
		if ( ! $wp_query->is_main_query() ) {
			return;
		}

		// Только для указанного типа поста
		if ( ! $wp_query->is_post_type_archive( $this->post_type ) ) {
			return;
		}

		// Для поиска во фронте
		if ( ! is_admin() && $wp_query->is_search() ) {
			add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
		}

		// Для поиска в админке
		if ( is_admin() ) {
			add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
		}
	}

	/**
	 * Возвращает термины указанной таксономии на основе поискового запроса.
	 *
	 * @return WP_Term[]|array Empty array if no terms found.
	 */
	private function search_terms() {

		$search_query = filter_input( INPUT_GET, 's' );

		if ( empty( $search_query ) ) {
			return [];
		}

		$terms = get_terms( [
			'taxonomy'   => $this->taxonomy,
			'name__like' => $search_query,
		] );

		return is_wp_error( $terms ) ? [] : $terms;
	}

	/**
	 * Добавляет в базовый запрос условия расширенной выборки по указанной таксономии.
	 *
	 * @param string $where
	 *
	 * @return string
	 */
	public function add_tax_query( $where ) {
		global $wpdb;

		$terms = $this->search_terms();

		if ( $terms ) {
			$ids = implode( ',', wp_list_pluck( $terms, 'term_id' ) );

			$where .= " OR ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ($ids) )";
		}

		// Отменяем фильтр, чтобы он не применялся к другим запросам
		remove_filter( 'posts_where', [ $this, __FUNCTION__ ] );

		return $where;
	}
}