Phân tách từ tìm kiếm cho wp_postmeta.meta_value phần 2 (ok)

// === Phân tách các từ ra để tìm kiếm ===
if(!class_exists('parse_search_custom')) {
	global $test;
	class parse_search_custom {
		function parse_search($s) {
			$q = array();
			$q['s'] = $s;
		  global $wpdb;
		  $search = '';
		  // Added slashes screw with quote grouping when done early, so done later.
		  $q['s'] = stripslashes($q['s']);
		  if (empty($_GET['s']) && is_main_query()) {
		    $q['s'] = urldecode($q['s']);
		  }
		  // There are no line breaks in <input /> fields.
		  $q['s']                  = str_replace(array("\r", "\n"), '', $q['s']);
		  $q['search_terms_count'] = 1;
		  if (!empty($q['sentence'])) {
		    $q['search_terms'] = array($q['s']);
		  } else {
		    if (preg_match_all('/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $q['s'], $matches)) {
		      $q['search_terms_count'] = count($matches[0]);
		      $q['search_terms']       = $this->parse_search_terms($matches[0]);
		      // If the search string has only short terms or stopwords, or is 10+ terms long, match it as sentence.
		      if (empty($q['search_terms']) || count($q['search_terms']) > 9) {
		        $q['search_terms'] = array($q['s']);
		      }
		    } else {
		      $q['search_terms'] = array($q['s']);
		    }
		  }
		  $n                         = !empty($q['exact']) ? '' : '%';
		  $searchand                 = '';
		  $q['search_orderby_title'] = array();
		  /**
		   * Filters the prefix that indicates that a search term should be excluded from results.
		   *
		   * @since 4.7.0
		   *
		   * @param string $exclusion_prefix The prefix. Default '-'. Returning
		   *                                 an empty value disables exclusions.
		   */
		  $exclusion_prefix = apply_filters('wp_query_search_exclusion_prefix', '-');
		  foreach ($q['search_terms'] as $term) {
		    // If there is an $exclusion_prefix, terms prefixed with it should be excluded.
		    $exclude = $exclusion_prefix && (substr($term, 0, 1) === $exclusion_prefix);
		    if ($exclude) {
		      $like_op  = 'NOT LIKE';
		      $andor_op = 'AND';
		      $term     = substr($term, 1);
		    } else {
		      $like_op  = 'LIKE';
		      $andor_op = 'OR';
		    }
		    if ($n && !$exclude) {
		      $like                        = '%' . $wpdb->esc_like($term) . '%';
		      $q['search_orderby_title'][] = $wpdb->prepare("{$wpdb->postmeta}.meta_value LIKE %s", $like);
		    }
		    $like = $n . $wpdb->esc_like($term) . $n;
		    $search .= $wpdb->prepare("{$searchand}(({$wpdb->postmeta}.meta_value $like_op %s) AND {$wpdb->posts}.post_status = 'publish' )", $like);
		    $searchand = ' AND ';
		  }
		  return $search;
		}
		function parse_search_terms($terms) {
		  $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
		  $checked    = array();
		  $stopwords = $this->get_search_stopwords();
		  foreach ($terms as $term) {
		    // Keep before/after spaces when term is for exact match.
		    if (preg_match('/^".+"$/', $term)) {
		      $term = trim($term, "\"'");
		    } else {
		      $term = trim($term, "\"' ");
		    }
		    // Avoid single A-Z and single dashes.
		    if (!$term || (1 === strlen($term) && preg_match('/^[a-z\-]$/i', $term))) {
		      continue;
		    }
		    if (in_array(call_user_func($strtolower, $term), $stopwords, true)) {
		      continue;
		    }
		    $checked[] = $term;
		  }
		  return $checked;
		}
		function get_search_stopwords() {
		  /*
		   * translators: This is a comma-separated list of very common words that should be excluded from a search,
		   * like a, an, and the. These are usually called "stopwords". You should not simply translate these individual
		   * words into your language. Instead, look for and provide commonly accepted stopwords in your language.
		   */
		  $words = explode(
		    ',',_x('about,an,are,as,at,be,by,com,for,from,how,in,is,it,of,on,or,that,the,this,to,was,what,when,where,who,will,with,www','Comma-separated list of search stopwords in your language')
		  );
		  $stopwords = array();
		  foreach ($words as $word) {
		    $word = trim($word, "\r\n\t ");
		    if ($word) {
		      $stopwords[] = $word;
		    }
		  }
		  /**
		   * Filters stopwords used when parsing search terms.
		   *
		   * @since 3.7.0
		   *
		   * @param string[] $stopwords Array of stopwords.
		   */
		  $stopwords = apply_filters('wp_search_stopwords_ct', $stopwords);
		  return $stopwords;
		}
	}
	$test = new parse_search_custom();
}
add_filter( 'posts_where' , 'posts_where',10,2 );
function posts_where( $where, $query ) {
  global $wpdb, $test;
  if($query->is_search && !$query->is_admin) {
  	$string = $query->query_vars['s'];
  	$tests = $test->parse_search($string);
	  $where .= " OR ($tests) ";
  }
  return $where;
}
function custom_posts_join($join){
  global $wpdb;
	$join .= " LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id ";
  return $join;
}
add_filter( 'posts_join' , 'custom_posts_join');
add_filter( 'posts_groupby', 'my_posts_groupby' );
function my_posts_groupby($groupby) {
  global $wpdb;
  $groupby = " {$wpdb->posts}.ID ";
  return $groupby;
}

Last updated