+ $this->query_vars_hash = md5( serialize( $this->query_vars ) );
+ $this->query_vars_changed = false;
+
+ do_action_ref_array('parse_query', array(&$this));
+ }
+
+ /**
+ * Parses various taxonomy related query vars.
+ *
+ * @access protected
+ * @since 3.1.0
+ *
+ * @param array &$q The query variables
+ */
+ function parse_tax_query( &$q ) {
+ if ( ! empty( $q['tax_query'] ) && is_array( $q['tax_query'] ) ) {
+ $tax_query = $q['tax_query'];
+ } else {
+ $tax_query = array();
+ }
+
+ if ( !empty($q['taxonomy']) && !empty($q['term']) ) {
+ $tax_query[] = array(
+ 'taxonomy' => $q['taxonomy'],
+ 'terms' => array( $q['term'] ),
+ 'field' => 'slug',
+ );
+ }
+
+ foreach ( get_taxonomies( array() , 'objects' ) as $taxonomy => $t ) {
+ if ( 'post_tag' == $taxonomy )
+ continue; // Handled further down in the $q['tag'] block
+
+ if ( $t->query_var && !empty( $q[$t->query_var] ) ) {
+ $tax_query_defaults = array(
+ 'taxonomy' => $taxonomy,
+ 'field' => 'slug',
+ );
+
+ if ( isset( $t->rewrite['hierarchical'] ) && $t->rewrite['hierarchical'] ) {
+ $q[$t->query_var] = wp_basename( $q[$t->query_var] );
+ }
+
+ $term = $q[$t->query_var];
+
+ if ( strpos($term, '+') !== false ) {
+ $terms = preg_split( '/[+]+/', $term );
+ foreach ( $terms as $term ) {
+ $tax_query[] = array_merge( $tax_query_defaults, array(
+ 'terms' => array( $term )
+ ) );
+ }
+ } else {
+ $tax_query[] = array_merge( $tax_query_defaults, array(
+ 'terms' => preg_split( '/[,]+/', $term )
+ ) );
+ }
+ }
+ }
+
+ // Category stuff
+ if ( ! empty( $q['cat'] ) && ! $this->is_singular ) {
+ $cat_in = $cat_not_in = array();
+
+ $cat_array = preg_split( '/[,\s]+/', urldecode( $q['cat'] ) );
+ $cat_array = array_map( 'intval', $cat_array );
+ $q['cat'] = implode( ',', $cat_array );
+
+ foreach ( $cat_array as $cat ) {
+ if ( $cat > 0 )
+ $cat_in[] = $cat;
+ elseif ( $cat < 0 )
+ $cat_not_in[] = abs( $cat );
+ }
+
+ if ( ! empty( $cat_in ) ) {
+ $tax_query[] = array(
+ 'taxonomy' => 'category',
+ 'terms' => $cat_in,
+ 'field' => 'term_id',
+ 'include_children' => true
+ );
+ }
+
+ if ( ! empty( $cat_not_in ) ) {
+ $tax_query[] = array(
+ 'taxonomy' => 'category',
+ 'terms' => $cat_not_in,
+ 'field' => 'term_id',
+ 'operator' => 'NOT IN',
+ 'include_children' => true
+ );
+ }
+ unset( $cat_array, $cat_in, $cat_not_in );
+ }
+
+ if ( ! empty( $q['category__and'] ) && 1 === count( (array) $q['category__and'] ) ) {
+ $q['category__and'] = (array) $q['category__and'];
+ if ( ! isset( $q['category__in'] ) )
+ $q['category__in'] = array();
+ $q['category__in'][] = absint( reset( $q['category__and'] ) );
+ unset( $q['category__and'] );
+ }
+
+ if ( ! empty( $q['category__in'] ) ) {
+ $q['category__in'] = array_map( 'absint', array_unique( (array) $q['category__in'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'category',
+ 'terms' => $q['category__in'],
+ 'field' => 'term_id',
+ 'include_children' => false
+ );
+ }
+
+ if ( ! empty($q['category__not_in']) ) {
+ $q['category__not_in'] = array_map( 'absint', array_unique( (array) $q['category__not_in'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'category',
+ 'terms' => $q['category__not_in'],
+ 'operator' => 'NOT IN',
+ 'include_children' => false
+ );
+ }
+
+ if ( ! empty($q['category__and']) ) {
+ $q['category__and'] = array_map( 'absint', array_unique( (array) $q['category__and'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'category',
+ 'terms' => $q['category__and'],
+ 'field' => 'term_id',
+ 'operator' => 'AND',
+ 'include_children' => false
+ );
+ }
+
+ // Tag stuff
+ if ( '' != $q['tag'] && !$this->is_singular && $this->query_vars_changed ) {
+ if ( strpos($q['tag'], ',') !== false ) {
+ $tags = preg_split('/[,\r\n\t ]+/', $q['tag']);
+ foreach ( (array) $tags as $tag ) {
+ $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
+ $q['tag_slug__in'][] = $tag;
+ }
+ } else if ( preg_match('/[+\r\n\t ]+/', $q['tag']) || !empty($q['cat']) ) {
+ $tags = preg_split('/[+\r\n\t ]+/', $q['tag']);
+ foreach ( (array) $tags as $tag ) {
+ $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
+ $q['tag_slug__and'][] = $tag;
+ }
+ } else {
+ $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
+ $q['tag_slug__in'][] = $q['tag'];
+ }
+ }
+
+ if ( !empty($q['tag_id']) ) {
+ $q['tag_id'] = absint( $q['tag_id'] );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag_id']
+ );
+ }
+
+ if ( !empty($q['tag__in']) ) {
+ $q['tag__in'] = array_map('absint', array_unique( (array) $q['tag__in'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag__in']
+ );
+ }
+
+ if ( !empty($q['tag__not_in']) ) {
+ $q['tag__not_in'] = array_map('absint', array_unique( (array) $q['tag__not_in'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag__not_in'],
+ 'operator' => 'NOT IN'
+ );
+ }
+
+ if ( !empty($q['tag__and']) ) {
+ $q['tag__and'] = array_map('absint', array_unique( (array) $q['tag__and'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag__and'],
+ 'operator' => 'AND'
+ );
+ }
+
+ if ( !empty($q['tag_slug__in']) ) {
+ $q['tag_slug__in'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__in'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag_slug__in'],
+ 'field' => 'slug'
+ );
+ }
+
+ if ( !empty($q['tag_slug__and']) ) {
+ $q['tag_slug__and'] = array_map('sanitize_title_for_query', array_unique( (array) $q['tag_slug__and'] ) );
+ $tax_query[] = array(
+ 'taxonomy' => 'post_tag',
+ 'terms' => $q['tag_slug__and'],
+ 'field' => 'slug',
+ 'operator' => 'AND'
+ );
+ }
+
+ $this->tax_query = new WP_Tax_Query( $tax_query );
+
+ do_action( 'parse_tax_query', $this );
+ }
+
+ /**
+ * Generate SQL for the WHERE clause based on passed search terms.
+ *
+ * @since 3.7.0
+ *
+ * @global wpdb $wpdb
+ * @param array $q Query variables.
+ * @return string WHERE clause.
+ */
+ protected function parse_search( &$q ) {
+ global $wpdb;
+
+ $search = '';
+
+ // added slashes screw with quote grouping when done early, so done later
+ $q['s'] = stripslashes( $q['s'] );
+ if ( empty( $_GET['s'] ) && $this->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();
+ foreach ( $q['search_terms'] as $term ) {
+ $term = like_escape( esc_sql( $term ) );
+ if ( $n )
+ $q['search_orderby_title'][] = "$wpdb->posts.post_title LIKE '%$term%'";
+
+ $search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}'))";
+ $searchand = ' AND ';
+ }
+
+ if ( ! empty( $search ) ) {
+ $search = " AND ({$search}) ";
+ if ( ! is_user_logged_in() )
+ $search .= " AND ($wpdb->posts.post_password = '') ";
+ }
+
+ return $search;