View source
<?php
class apachesolr_views_query extends views_plugin_query implements Drupal_Solr_Query_Interface {
protected static $idCount = 0;
public $id;
protected $_facets = array();
protected $_query;
protected $_solr_service;
protected $_params = array(
'facet' => 'true',
'facet.mincount' => 1,
'facet.sort' => 'true',
);
protected $_used_fields = array(
'id',
'nid',
'url',
'uid',
);
protected $_query_template = '';
protected $_view_arguments = array();
protected $_view_filters = array();
protected $_base_path = '';
protected $_subqueries = array();
protected $_extra_query = array();
protected $_available_sorts = array();
protected $_sorts = array();
protected $_current_display = '';
protected $_current_views_name = '';
protected $_query_fields = array();
protected $_boost_functions = array();
protected $_boost_queries = array();
protected $base_table;
protected $sql_base_table;
protected $base_field;
protected $_db_query = NULL;
protected $has_sql_fields = FALSE;
public function init($base_table, $base_field, $options) {
$this->base_table = $base_table;
$this->base_field = $base_field;
$this->sql_base_table = substr($base_table, 11);
$this->_solr_service = apachesolr_get_solr();
module_load_include('inc', 'views', 'plugins/views_plugin_query_default');
$this->_db_query = new views_plugin_query_default();
$this->_db_query
->init($this->sql_base_table, $base_field, $options);
$this->id = ++self::$idCount;
$data = views_fetch_data($base_table);
foreach ($data as $field_name => $field) {
if (!empty($field['sort'])) {
$this->_available_sorts[$field_name] = array(
'name' => $field['title'],
'default' => 'asc',
);
}
}
}
public function __clone() {
$this->id = ++self::$idCount;
}
public function build(&$view) {
$view
->init_pager();
if ($this->pager
->use_pager()) {
$this->pager
->set_current_page($view->current_page);
}
$this->pager
->query();
if (empty($this->_query_template) || $this->_query_template == 'dismax') {
if (empty($this->_query_fields)) {
$qf = variable_get('apachesolr_search_query_fields', array());
foreach ($qf as $field_name => $boost) {
if (!empty($boost)) {
if ($field_name == 'body') {
$boost *= 40.0;
}
$this
->add_query_field($field_name, $boost);
}
}
}
if (empty($this->_boost_functions)) {
$this->_params['bf'] = array();
$solr = $this->_solr_service;
$total = 0;
if (isset($solr)) {
try {
$data = $solr
->getLuke();
} catch (Exception $e) {
watchdog('apachesolr_views', $e
->getMessage());
}
if (isset($data) && isset($data->index->numDocs)) {
$total = $data->index->numDocs;
}
}
if (empty($total)) {
$total = db_result(db_query("SELECT COUNT(nid) FROM {node}"));
}
$date_settings = variable_get('apachesolr_search_date_boost', '4:200.0');
list($date_steepness, $date_boost) = explode(':', $date_settings);
if (!empty($date_boost)) {
$values = array(
$date_steepness,
$total,
$total,
$date_boost,
);
$this
->add_boost_function("recip(rord(created),%f,%d,%d)^%f", $values);
}
$comment_settings = variable_get('apachesolr_search_comment_boost', '0:0');
list($comment_steepness, $comment_boost) = explode(':', $comment_settings);
if ($comment_boost) {
$values = array(
$comment_steepness,
$total,
$total,
$comment_boost,
);
$this
->add_boost_function("recip(rord(comment_count),%f,%d,%d)^%f", $values);
}
$changed_settings = variable_get('apachesolr_search_changed_boost', '0:0');
list($changed_steepness, $changed_boost) = explode(':', $changed_settings);
if ($changed_boost) {
$values = array(
$changed_steepness,
$total,
$total,
$changed_boost,
);
$this
->add_boost_function("recip(rord(last_comment_or_change),%f,%d,%d)^%f", $values);
}
}
if (empty($this->_boost_queries)) {
$sticky_boost = variable_get('apachesolr_search_sticky_boost', 0);
if ($sticky_boost) {
$this
->add_boost_query('sticky', 'true', $sticky_boost);
}
$promote_boost = variable_get('apachesolr_search_promote_boost', 0);
if ($promote_boost) {
$this
->add_boost_query('promote', 'true', $promote_boost);
}
$type_boosts = variable_get('apachesolr_search_type_boosts', array());
if (!empty($type_boosts)) {
foreach ($type_boosts as $type => $boost) {
if (!empty($boost)) {
$this
->add_boost_query('type', $type, $boost);
}
}
}
}
}
try {
apachesolr_search_add_facet_params($this->_params, $this);
if ($this->_query_template == 'dismax' || empty($this->_query_template)) {
$this->_params['qf'] = array();
foreach ($this->_query_fields as $field_name => $boost) {
$this->_params['qf'][] = "{$field_name}^{$boost}";
}
$this->_params['bf'] = $this->_boost_functions;
foreach ($this->_boost_queries as $field_name => $fields) {
foreach ($fields as $field_value => $boost) {
$this->_params['bq'][] = "{$field_name}:{$field_value}^{$boost}";
}
}
}
$this->_params['fq'] = $this
->rebuild_fq();
foreach ($this->_subqueries as $query_data) {
$sub_query_string = $query_data['query']
->get_query_basic();
if ($sub_query_string) {
$this->_query .= " {$query_data['q_op']} ({$sub_query_string})";
}
$subfq = $query_data['query']
->get_fq();
if (!empty($subfq)) {
$operator = $query_data['fq_op'];
$this->_params['fq'][] = "(" . implode(" {$operator} ", $subfq) . ")";
}
}
$this->_params['fl'] = implode(',', $this->_used_fields);
$sort_strings = array();
foreach ($this->_sorts as $name => $direction) {
$sort_strings[] = "{$name} {$direction}";
}
$this->_params['sort'] = implode(',', $sort_strings);
if (!empty($this->_query_template)) {
$this->_params['qt'] = $this->_query_template;
}
} catch (Exception $e) {
watchdog('apachesolr_views', $e
->getMessage());
}
}
public function alter(&$view) {
foreach (module_implements('apachesolr_modify_query') as $module) {
$function = $module . '_apachesolr_modify_query';
$function($this, $this->_params, 'apachesolr_views_query');
}
}
public function execute(&$view) {
$start_time = views_microtime();
$view->result = array();
$this->_view_arguments = $view->argument;
$this->_view_filters = $view->filter;
$this->_base_path = $view
->get_path();
$this->_current_display = $view->current_display;
$this->_current_views_name = $view->name;
$this->pager
->pre_execute($this->_query, $args);
try {
if (empty($this->_query)) {
watchdog('Apachesolr Views', 'Warning, no query string set');
}
$response = $this->_solr_service
->search($this->_query, $this->offset, $this->limit, $this->_params);
$view->total_rows = $total = $response->response->numFound;
if (!empty($this->_base_path)) {
apachesolr_static_response_cache($response);
apachesolr_has_searched(TRUE);
apachesolr_current_query($this);
}
if ($total > 0) {
$results = $response->response->docs;
$date_fields = array(
'created',
'changed',
);
foreach (array_values($date_fields) as $field) {
if (empty($this->_used_fields[$field])) {
unset($date_fields[$field]);
}
}
if (!empty($date_fields)) {
foreach ($results as $doc) {
foreach ($date_fields as $field) {
$doc->{$field} = strtotime($doc->{$field});
}
}
}
$base_fields = array();
foreach ($results as $doc) {
$base_fields[] = $doc->{$this->base_field};
}
if ($this->has_sql_fields) {
$sql_table = $this->_db_query
->ensure_table($this->sql_base_table);
$replace = array_fill(0, sizeof($base_fields), '%d');
$in = '(' . implode(", ", $replace) . ')';
$this->_db_query
->add_where(0, "{$sql_table}.{$this->base_field} IN {$in}", $base_fields);
$base_alias = $this->_db_query
->add_field($sql_table, $this->base_field);
$sql_query = $this->_db_query
->query();
$sql_args = $this->_db_query
->get_where_args();
$sql_result = db_query($sql_query, $sql_args);
while ($sql_row = db_fetch_object($sql_result)) {
foreach ($results as $key => $doc) {
if ($doc->{$this->base_field} == $sql_row->{$base_alias}) {
foreach ($sql_row as $field => $value) {
$results[$key]->{$field} = $value;
}
}
}
}
}
$view->result = $results;
}
} catch (Exception $e) {
watchdog('Apache Solr', $e
->getMessage(), NULL, WATCHDOG_ERROR);
apachesolr_failure(t('Solr search'), is_null($query) ? $this->_keys : $query
->get_query_basic());
}
$this->pager->total_items = $view->total_rows;
$this->pager
->update_page_info();
$this->pager
->post_execute($view->result);
$view->execute_time = views_microtime() - $start_time;
}
function set_limit($limit) {
$this->limit = $limit;
}
function set_offset($offset) {
$this->offset = $offset;
}
function set_keys($keys) {
$this->keys = $keys;
}
function get_keys() {
return $this->keys;
}
public function add_solr_field($field) {
if (!in_array($field, $this->_used_fields)) {
$this->_used_fields[] = $field;
}
return $field;
}
public function add_field($table, $field, $alias = '', $params = array()) {
$this->has_sql_fields = TRUE;
return $this->_db_query
->add_field($table, $field, $alias, $params);
}
public function ensure_table($table, $relationship) {
if ($table != $this->base_table) {
if (substr($table, 0, strlen($this->base_table)) == $this->base_table) {
$real_table = substr($table, strlen($this->base_table) + 1);
}
else {
$real_table = $table;
}
return $this->_db_query
->ensure_table($real_table, $relationship);
}
}
public function add_sort($field, $order, $single = FALSE) {
if ($single) {
$this->_sorts = array();
}
$this->_sorts[$field] = strtolower($order);
}
function get_param($param_name) {
return $this->_params[$param_name];
}
function set_param($param_name, $param_value) {
$this->_params[$param_name] = $param_value;
}
public function add_filter($type, $value, $exclude = FALSE) {
$this->_facets[$type][] = array(
'value' => $value,
'exclude' => $exclude,
);
}
public function set_query($query) {
return $this->_query = $query;
}
public function get_query_basic() {
return $this->_query;
}
public function remove_keys() {
$this->_query = '';
}
function has_filter($field, $value) {
if (isset($this->_facets[$field])) {
foreach ($this->_facets[$field] as $definition) {
if ($definition['value'] == $value && $definition['exclude'] == FALSE) {
return TRUE;
}
}
}
return FALSE;
}
function remove_filter($field, $value = NULL) {
if (!empty($value)) {
if (isset($this->_facets[$field])) {
$removal_key = FALSE;
foreach ($this->_facets[$field] as $key => $definition) {
if ($definition['value'] == $value) {
$removal_key = $key;
break;
}
}
if ($removal_key !== FALSE) {
unset($this->_facets[$field][$removal_key]);
}
}
}
else {
if (isset($this->_facets[$field])) {
unset($this->_facets[$field]);
}
}
}
function get_path($new_keys = NULL) {
if (isset($new_keys)) {
$this
->set_query($new_keys);
}
$wildcard_count = 0;
if (empty($this->_view_arguments)) {
return $this->_base_path;
}
foreach ($this->_view_arguments as $field => $argument) {
$path_part = $this
->part_of_facet_block($argument) ? $this
->argument_part($field) : $argument->argument;
if (!empty($path_part)) {
$path_parts[$argument->position + 1] = $path_part;
$wildcard_count = 0;
}
else {
$path_parts[$argument->position + 1] = $argument->options['wildcard'];
$wildcard_count++;
}
}
$arguments = explode('/', $this->_base_path);
$path = '';
foreach ($arguments as $arg) {
if ($arg == '%') {
$part = array_shift($path_parts);
}
else {
$part = $arg;
}
$path .= "/{$part}";
}
if (count($path_parts) && $wildcard_count != count($path_parts)) {
$path .= "/" . implode('/', array_slice($path_parts, 0, count($path_parts) - $wildcard_count));
}
$path = substr($path, 1);
if (trim($path) == trim(variable_get('site_frontpage', 'node'))) {
return '<front>';
}
return $path;
}
protected function argument_part($field) {
$argument_path = '';
if (empty($this->_facets[$field])) {
if ($field == 'text' && !empty($this->_query)) {
return $this->_query;
}
else {
return '';
}
}
foreach ($this->_facets[$field] as $defintion) {
if (!$defintion['exclude']) {
$argument_path .= ',' . $defintion['value'];
}
}
return drupal_substr($argument_path, 1);
}
protected function part_of_facet_block($argument) {
foreach (apachesolr_get_enabled_facets() as $module => $module_facets) {
foreach ($module_facets as $delta => $facet_field) {
$facet_arguments[] = $facet_field;
}
}
if (!empty($facet_arguments) && $argument->field == "tid") {
return true;
}
return in_array($argument->field, $facet_arguments);
}
function get_url_queryvalues() {
$query_values = array();
foreach ($this->_view_filters as $filter) {
if ($filter->options['exposed']) {
if ($filter->field == 'text' && !empty($this->_query)) {
$query_values[$filter->options['expose']['identifier']] = $this->_query;
}
elseif ($this->_facets[$filter->field]) {
$query_values[$filter->options['expose']['identifier']] = $this->_facets[$filter->field];
}
elseif (!empty($_GET[$filter->options['expose']['identifier']]) && $filter->field != 'text') {
$query_values[$filter->options['expose']['identifier']] = $_GET[$filter->options['expose']['identifier']];
}
}
}
foreach ($this->_extra_query as $field => $value) {
$query_values[$field] = $value;
}
return $query_values;
}
function set_solrsort($field, $direction) {
$this
->add_sort($field, $direction);
}
function get_solrsort() {
return $this->_sorts;
}
function get_filters($name = NULL) {
$filters = array();
foreach ($this->_facets as $type => $fields) {
foreach ($fields as $data) {
$filters[] = array(
'#name' => $data['exclude'] ? "NOT {$type}" : $type,
'#value' => $data['value'],
);
}
}
if (!empty($name)) {
foreach ($filters as $key => $filter) {
if ($filter['#name'] != $name) {
unset($filters[$key]);
}
}
}
return $filters;
}
function get_fq() {
return $this
->rebuild_fq();
}
function get_display_id() {
return $this->_current_display;
}
function get_views_name() {
return $this->_current_views_name;
}
function add_subquery(Drupal_Solr_Query_Interface $query, $fq_operator = 'OR', $q_operator = 'AND') {
$this->_subqueries[$query->id] = array(
'query' => $query,
'fq_op' => $fq_operator,
'q_op' => $q_operator,
);
}
public static function escape_term($term) {
$term = trim($term);
if (empty($term)) {
return '';
}
if ($term[0] == '"' && $term[strlen($term) - 1] == '"' || $term[0] == '(' && $term[strlen($term) - 1] == ')') {
return $term;
}
if (strpos($term, ' TO ') !== FALSE) {
return $term;
}
if (strpos($term, ' ') !== FALSE) {
return Drupal_Apache_Solr_Service::phrase($term);
}
return Drupal_Apache_Solr_Service::escape($term);
}
public function change_query_template($qt) {
$this->_query_template = $qt;
}
function add_url_query_param($field, $value) {
$this->_extra_query[$field] = $value;
}
public function get_available_sorts() {
return $this->_available_sorts;
}
function remove_subquery(Drupal_Solr_Query_Interface $query) {
unset($this->_subqueries[$query->id]);
}
function remove_subqueries() {
$this->_subqueries = array();
}
function set_available_sort($field, $sort) {
}
function add_query_field($field_name, $boost = 1.0) {
$this->_query_fields[$field_name] = $boost;
}
function remove_query_field($field_name) {
unset($this->_query_fields[$field_name]);
}
function add_boost_function($function, array $values) {
$this->_boost_functions[] = vsprintf($function, $values);
}
function add_boost_query($field_name, $field_value, $boost_value) {
$this->_boost_queries[$field_name][$field_value] = $boost_value;
}
function remove_boost_query($field_name, $field_value = NULL) {
if ($field_value) {
unset($this->_boost_queries[$field_name][$field_value]);
}
else {
unset($this->_boost_queries[$field_name]);
}
}
protected function rebuild_fq() {
$query_filters = array();
foreach ($this->_facets as $type => $facets) {
$filter_string = '';
foreach ($facets as $definition) {
if ($definition['exclude']) {
$type_string = "NOT {$type}";
}
else {
$type_string = $type;
}
$query_filters[] = "{$type_string}:" . $definition['value'];
}
}
$query_filters[] = "entity:" . $this->sql_base_table;
return $query_filters;
}
}