Adding taxonomy (term) to post search

Task: To the standard product search, it is necessary to add search by the product attribute name. In other words, it is necessary to add products related to the "Manufacturer" attribute to the default product search results.

The logic is as follows:

  • Search for terms in the "Manufacturer" taxonomy based on the search query
  • Retrieve all posts related to the found manufacturers
  • Add the retrieved posts to the overall pool of posts that were found by default

This mechanism can also be used for searching any types of posts and taxonomies - modify them in the code as desired.

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

/**
 * 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 retrieve 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 ) {

		// Only for the main query
		if ( ! $wp_query->is_main_query() ) {
			return;
		}

		// Only for the specified post type
		if ( ! $wp_query->is_post_type_archive( $this->post_type ) ) {
			return;
		}

		// For front-end search
		if ( ! is_admin() && $wp_query->is_search() ) {
			add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
		}

		// For admin search
		if ( is_admin() ) {
			add_filter( 'posts_where', [ $this, 'add_tax_query' ] );
		}
	}

	/**
	 * Returns terms of the specified taxonomy based on the search 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;
	}

	/**
	 * Adds conditions for extended selection by the specified taxonomy to the base query.
	 *
	 * @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 the filter so it does not apply to other queries
		remove_filter( 'posts_where', [ $this, __FUNCTION__ ] );

		return $where;
	}
}