Exemplo n.º 1
0
 protected function parse_query($query)
 {
     $vars = array();
     // Taxonomy filters
     $terms = $this->get_valid_taxonomy_query_vars($query);
     if (!empty($terms)) {
         $vars['terms'] = $terms;
     }
     // Post type filters
     $searchable_post_types = sp_searchable_post_types();
     if ($query->get('post_type') && 'any' != $query->get('post_type')) {
         $post_types = (array) $query->get('post_type');
     } elseif (!empty($_GET['post_type'])) {
         $post_types = explode(',', $_GET['post_type']);
     } else {
         $post_types = false;
     }
     $vars['post_type'] = array();
     // Validate post types, making sure they exist and are not excluded from search
     if ($post_types) {
         foreach ((array) $post_types as $post_type) {
             if (in_array($post_type, $searchable_post_types)) {
                 $vars['post_type'][] = $post_type;
             }
         }
     }
     if (empty($vars['post_type'])) {
         $vars['post_type'] = $searchable_post_types;
     }
     return $vars;
 }
Exemplo n.º 2
0
 /**
  * Convert WP-style arguments to Elasticsearch arguments.
  * @static
  * @param  array $args {
  *     WordPress-style arguments for Elasticsearch.
  *     @type string $query Search phrase. Default null.
  *     @type array $query_fields Which fields to search (with boosting).
  *                              Default array(
  *                                  'post_title^3',
  *                                  'post_excerpt^2',
  *                                  'post_content',
  *                                  'post_author.display_name',
  *                                  'terms.category.name',
  *                                  'terms.post_tag.name'
  *                              ).
  *     @type string|array $post_type Which post type(s) to search.
  *                                   Default null.
  *     @type array $terms Taxonomy terms to search within. Default array().
  *                        The format is array( 'taxonomy' => 'slug' ), e.g.
  *                        array( 'post_tag' => 'wordpress' ). The "slug"
  *                        can be multiple terms, as WP would parse them if
  *                        they were in a URL. That is,
  *                        * Union (OR) 'slug-a,slug-b': Posts in slug-a OR slug-b.
  *                        * Intersection (AND) 'slug-a+slug-b': Posts in slug-a AND slug-b.
  *     @type int|array $author Search by author ID(s). Default null.
  *     @type int|array $author_name Search by author login(s).
  *                                  Default array().
  *     @type array $date_range Default null,    // array( 'field' => 'post_date', 'gt' => 'YYYY-MM-dd', 'lte' => 'YYYY-MM-dd' ); date formats: 'YYYY-MM-dd' or 'YYYY-MM-dd HH:MM:SS'
  *     @type string|array $orderby Set the order of the results. You can
  *                                 pass an array of multiple orders, e.g.
  *                                 array( 'field1' => 'asc', 'field2' => 'desc').
  *                                 If you pass an array, $order is ignored.
  *                                 Default is 'relevance' if $query is set,
  *                                 and 'date' otherwise.
  *     @type string $order Order for singular orderby clauses.
  *                                 Default 'desc'. Accepts 'asc' or 'desc'.
  *     @type int $posts_per_page Number of results. Default 10.
  *     @type int $offset Offset of results. Default null.
  *     @type int $paged Page of results. Default 1.
  *     @type array $facets Which facets, if any, we want with the results.
  *                         The format is "label" => array( "type" => $type, "count" => ## ).
  *                         The type can be taxonomy, post_type, or date_histogram.
  *                         If taxonomy, you must also pass "taxonomy" => $taxonomy.
  *                         If date_histogram, you must also pass "interval" => $interval,
  *                         where $interval is either "year", "month", or "day".
  *                         You can also pass "field" to date_histograms, specifying
  *                         any date field (e.g. post_modified). Default is post_date.
  *                         Examples:
  *                         array(
  *                             'Tags'       => array( 'type' => 'taxonomy', 'taxonomy' => 'post_tag', 'count' => 10 ),
  *                             'Post Types' => array( 'type' => 'post_type', 'count' => 10 ),
  *                             'Years'      => array( 'type' => 'date_histogram', 'interval' => 'year', 'field' => 'post_modified', 'count' => 10 )
  *                         )
  *     @type string|array $fields Which field(s) should be returned.
  *                                Default array( 'post_id' ).
  * }
  * @return array
  */
 public static function wp_to_es_args($args)
 {
     $defaults = array('query' => null, 'query_fields' => array('post_title^3', 'post_excerpt^2', 'post_content', 'post_author.display_name', 'terms.category.name', 'terms.post_tag.name'), 'post_type' => null, 'terms' => array(), 'author' => null, 'author_name' => array(), 'date_range' => null, 'orderby' => null, 'order' => 'desc', 'posts_per_page' => 10, 'offset' => null, 'paged' => 1, 'facets' => null, 'fields' => array('post_id'));
     $args = wp_parse_args($args, $defaults);
     // Posts per page
     $es_query_args = array('size' => absint($args['posts_per_page']));
     $filters = array();
     /**
      * Pagination
      *
      * @see trac ticket 18897
      *
      * Important: SearchPress currently emulates the (arguably broken)
      * behavior of core here. The above mentioned ticket would alter this
      * behavior, and should that happen, SearchPress would be updated to
      * reflect. In other words, presently, if offset is set, paged is
      * ignored. If core ever allows both to be set, so will SP.
      */
     if (!empty($args['offset'])) {
         $es_query_args['from'] = absint($args['offset']);
     } else {
         $es_query_args['from'] = max(0, (absint($args['paged']) - 1) * $es_query_args['size']);
     }
     // Post type
     if (!empty($args['post_type'])) {
         if ('any' == $args['post_type']) {
             $args['post_type'] = sp_searchable_post_types();
         }
         $filters[] = array('terms' => array('post_type.raw' => (array) $args['post_type']));
     }
     // Author
     // @todo Add support for comma-delim terms like wp_query
     if (!empty($args['author'])) {
         $filters[] = array('terms' => array('post_author.user_id' => (array) $args['author']));
     }
     if (!empty($args['author_name'])) {
         $filters[] = array('terms' => array('post_author.login' => (array) $args['author_name']));
     }
     // Date range
     if (!empty($args['date_range'])) {
         if (!empty($args['date_range']['field'])) {
             $field = $args['date_range']['field'];
             unset($args['date_range']['field']);
         } else {
             $field = 'post_date';
         }
         $filters[] = array('range' => array("{$field}.date" => $args['date_range']));
     }
     // Taxonomy terms
     if (!empty($args['terms'])) {
         foreach ((array) $args['terms'] as $tax => $terms) {
             if (strpos($terms, ',')) {
                 $terms = explode(',', $terms);
                 $comp = 'or';
             } else {
                 $terms = explode('+', $terms);
                 $comp = 'and';
             }
             $terms = array_map('sanitize_title', $terms);
             if (count($terms)) {
                 $tax_fld = 'terms.' . $tax . '.slug';
                 foreach ($terms as $term) {
                     if ('and' == $comp) {
                         $filters[] = array('term' => array($tax_fld => $term));
                     } else {
                         $or[] = array('term' => array($tax_fld => $term));
                     }
                 }
                 if ('or' == $comp) {
                     $filters[] = array('or' => $or);
                 }
             }
         }
     }
     if (!empty($filters)) {
         $es_query_args['filter'] = array('and' => $filters);
     }
     // Fill in the query
     //  todo: add auto phrase searching
     //  todo: add fuzzy searching to correct for spelling mistakes
     //  todo: boost title, tag, and category matches
     if (!empty($args['query'])) {
         $multi_match = array(array('multi_match' => array('query' => $args['query'], 'fields' => $args['query_fields'], 'type' => 'cross_fields', 'operator' => 'and')));
         $es_query_args['query']['bool']['must'] = $multi_match;
         if (!$args['orderby']) {
             $args['orderby'] = 'relevance';
         }
     } elseif (empty($args['orderby'])) {
         $args['orderby'] = 'date';
     }
     // Ordering
     $es_query_args['sort'] = array();
     if (is_string($args['orderby'])) {
         $args['order'] = 'asc' == strtolower($args['order']) ? 'asc' : 'desc';
         $args['orderby'] = array($args['orderby'] => $args['order']);
     }
     foreach ((array) $args['orderby'] as $orderby => $order) {
         $order = 'asc' == strtolower($order) ? 'asc' : 'desc';
         // Translate orderby from WP field to ES field
         switch (strtolower($orderby)) {
             case 'relevance':
                 $es_query_args['sort'][] = array('_score' => $order);
                 break;
             case 'date':
                 $es_query_args['sort'][] = array('post_date.date' => $order);
                 break;
             case 'modified':
                 $es_query_args['sort'][] = array('post_modified.date' => $order);
                 break;
             case 'id':
                 $es_query_args['sort'][] = array('post_id' => $order);
                 break;
             case 'author':
                 $es_query_args['sort'][] = array('post_author.user_id' => $order);
                 break;
             case 'name':
                 $es_query_args['sort'][] = array('post_name.raw' => $order);
                 break;
             case 'title':
                 $es_query_args['sort'][] = array('post_title.raw' => $order);
                 break;
             case 'menu_order':
                 $es_query_args['sort'][] = array('menu_order' => $order);
                 break;
             case 'parent':
                 $es_query_args['sort'][] = array('post_parent' => $order);
                 break;
         }
     }
     if (empty($es_query_args['sort'])) {
         unset($es_query_args['sort']);
     }
     // Facets
     if (!empty($args['facets'])) {
         foreach ((array) $args['facets'] as $label => $facet) {
             switch ($facet['type']) {
                 case 'taxonomy':
                     $es_query_args['aggregations'][$label] = array('terms' => array('field' => "terms.{$facet['taxonomy']}.slug", 'size' => $facet['count']));
                     break;
                 case 'post_type':
                     $es_query_args['aggregations'][$label] = array('terms' => array('field' => 'post_type', 'size' => $facet['count']));
                     break;
                 case 'date_histogram':
                     $es_query_args['aggregations'][$label] = array('date_histogram' => array('interval' => $facet['interval'], 'field' => !empty($facet['field']) ? "{$facet['field']}.date" : 'post_date.date'));
                     break;
             }
         }
         // If we have facets, we need to move our filters to a filtered
         // query, or else they won't have an effect on the facets.
         if (!empty($es_query_args['aggregations'])) {
             if (!empty($es_query_args['filter'])) {
                 if (!empty($es_query_args['query'])) {
                     $es_query = $es_query_args['query'];
                 }
                 $es_query_args['query'] = array('filtered' => array('filter' => $es_query_args['filter']));
                 unset($es_query_args['filter']);
                 if (!empty($es_query)) {
                     $es_query_args['query']['filtered']['query'] = $es_query;
                 }
             }
         }
     }
     // Fields
     if (!empty($args['fields'])) {
         $es_query_args['fields'] = (array) $args['fields'];
     }
     return $es_query_args;
 }
Exemplo n.º 3
0
 public function sync_post_types()
 {
     return apply_filters('sp_config_sync_post_types', sp_searchable_post_types());
 }
Exemplo n.º 4
0
 /**
  * Count the posts to index.
  *
  * @param  array  $args WP_Query args used for counting.
  * @return int Total number of posts to index.
  */
 public function count_posts($args = array())
 {
     if (false === $this->published_posts) {
         $args = wp_parse_args($args, array('post_type' => null, 'post_status' => 'publish', 'posts_per_page' => 1));
         if (empty($args['post_type'])) {
             $args['post_type'] = sp_searchable_post_types();
         }
         $args = apply_filters('searchpress_index_count_args', $args);
         $query = new WP_Query($args);
         $this->published_posts = $query->found_posts;
     }
     return $this->published_posts;
 }