Skip to content

Commit

Permalink
Add apachesolr_views
Browse files Browse the repository at this point in the history
  • Loading branch information
sdboyer committed Oct 31, 2012
1 parent ded7dbd commit 248cd97
Show file tree
Hide file tree
Showing 11 changed files with 823 additions and 0 deletions.
339 changes: 339 additions & 0 deletions sites/all/modules/contrib/apachesolr_views/LICENSE.txt

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions sites/all/modules/contrib/apachesolr_views/apachesolr_views.info
@@ -0,0 +1,23 @@
name = Apache Solr Views Integration
description = Provides Views Integration with Views
package = Search Toolkit
core = "7.x"

dependencies[] = apachesolr
dependencies[] = views

files[] = apachesolr_views.views.inc
files[] = apachesolr_views_query.inc
files[] = apachesolr_views_solr_base_query.inc
files[] = handlers/apachesolr_views_handler_field.inc
files[] = handlers/apachesolr_views_handler_sort.inc
files[] = handlers/apachesolr_views_handler_filter.inc
files[] = handlers/apachesolr_views_keyword_handler_filter.inc
files[] = handlers/apachesolr_views_handler_argument.inc

; Information added by drupal.org packaging script on 2012-05-30
version = "7.x-1.0-beta1"
core = "7.x"
project = "apachesolr_views"
datestamp = "1338371748"

14 changes: 14 additions & 0 deletions sites/all/modules/contrib/apachesolr_views/apachesolr_views.module
@@ -0,0 +1,14 @@
<?php

/**
* @file
* Provides Views Implementation for the ApacheSolr Search Integration project
* drupal.org/project/apachesolr
*/

/**
* Implementation of hook_views_api().
*/
function apachesolr_views_views_api() {
return array('api' => '3.0');
}
104 changes: 104 additions & 0 deletions sites/all/modules/contrib/apachesolr_views/apachesolr_views.views.inc
@@ -0,0 +1,104 @@
<?php

/*
* Load files with base classes of the contained classes.
*/

/**
* Implementation of hook_views_plugins().
*/
function apachesolr_views_views_plugins() {
return array(
'module' => 'apachesolr_views',
'query' => array(
'apachesolr_views_query' => array(
'title' => t('Apache Solr Query'),
'help' => t('Query that allows you to search with Apache Solr.'),
'handler' => 'apachesolr_views_query',
'parent' => 'views_query',
),
),
);

}

/**
* Implementation of hook_views_data().
*/
function apachesolr_views_views_data() {
foreach (apachesolr_load_all_environments() as $env_id => $environment) {
$name = $environment['name'];
$apachesolr_base_table = 'apachesolr__' . $env_id;

$data[$apachesolr_base_table]['table']['group'] = t('Apache Solr');
$data[$apachesolr_base_table]['table']['base'] = array(
'query class' => 'apachesolr_views_query',
'title' => t('Apache Solr @name', array('@name' => $name)),
'help' => t('Searches the site with the Apache Solr search engine for @name', array('@name' => $name)),
);

// Get the list of the fields in index directly from Solr.
try {
$solr = apachesolr_get_solr($env_id);
$solr_fields = $solr->getFields(1);
}
catch (Exception $e) {
$solr_fields = array();
watchdog('Apache Solr Views', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
}

foreach ($solr_fields as $solr_field_name => $solr_field) {

// We do not allow to display 'sort_*' fields.
if (strpos($solr_field_name, 'sort_') === 0) {
continue;
}

$field_type = $solr_field->type;

$data[$apachesolr_base_table][$solr_field_name] = array(
'title' => $solr_field_name,
'help' => $solr_field_name,
'field' => array(
'handler' => 'apachesolr_views_handler_field',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'apachesolr_views_handler_filter',
),
'sort' => array(
'handler' => 'apachesolr_views_handler_sort',
),
'argument' => array(
'handler' => 'apachesolr_views_handler_argument',
),
);

// Default sort field for label.
$sort_field_name = ($solr_field_name == 'label') ? 'sort_label' : '';
// Check if corresponding sort_ field exists. We remove prefix from field
// name (for example prefix "ss_" from "ss_name") and check if "sort_*"
// field is available.
if (array_key_exists('sort_' . substr($solr_field_name, 2), $solr_fields)) {
$sort_field_name = 'sort_' . substr($solr_field_name, 2);
}
if (!empty($sort_field_name)) {
// Use the sort field for click sorting.
$data[$apachesolr_base_table][$solr_field_name]['field']['click sort field'] = $sort_field_name;
// And use the sort field for explicit sorts.
$data[$apachesolr_base_table][$solr_field_name]['sort']['real field'] = $sort_field_name;
}
}

// Keyword field.
$data[$apachesolr_base_table]['keyword'] = array(
'title' => t('Search'),
'help' => t('Fulltext search'),
'filter' => array(
'handler' => 'apachesolr_views_keyword_handler_filter',
),
);
}

return $data;
}
237 changes: 237 additions & 0 deletions sites/all/modules/contrib/apachesolr_views/apachesolr_views_query.inc
@@ -0,0 +1,237 @@
<?php

/**
* Class for handling a view that gets its data not from the database, but from
* a Solr server.
*/
class apachesolr_views_query extends views_plugin_query {

/**
* Array of parameters for Solr query.
*/
protected $params;

/**
* Array of all encountered errors. Each of these is fatal, meaning that a
* non-empty $errors property will result in an empty result being returned.
*
* @var array
*/
protected $errors;

/**
* Store results of apachesolr search.
*/
protected $apachesolr_results;

/**
* Array of where conditions.
*
* Neede for grouppin of query conditions.
*/
protected $where = array();

public function build(&$view) {
$view->init_pager();

// Let the pager modify the query to add limits.
$this->pager->query();

// Set aliases of the fields.
foreach ($view->field as $field_name => &$field) {
$field->field_alias = $field_name;
$field->aliases['entity_type'] = 'entity_type';
}

// Add fields to the query so they will be shown in solr document.
$this->params['fl'] = array_keys($view->field);
}

/**
* Executes the query and fills the associated view object with according
* values.
*
* Values to set: $view->result, $view->total_rows, $view->execute_time,
* $view->pager['current_page'].
*/
public function execute(&$view) {
try {
$start = microtime(TRUE);

// Execute the search.
$params = array();
if (isset($this->params['q'])) {
$params['q'] = $this->params['q'];
}

$params['rows'] = $this->pager->options['items_per_page'];
$params['start'] = $this->pager->current_page * $this->pager->options['items_per_page'];

// If we display all items without pager.
if ($params['rows'] == 0) {
$params['rows'] = 100000;
}

// Add fields.
$params['fl'] = array('id', 'entity_id');
if (isset($this->params['fl'])) {
$params['fl'] = array_merge($params['fl'], $this->params['fl']);
}
$params['fl'] = implode(',', $params['fl']);

// Add conditions to filter parameter.
$conditions = array('conditions' => $this->where, 'type' => $this->group_operator);
$conditions_string = $this->build_where_string($conditions);

if (!empty($conditions_string)) {
$params['fq'] = $conditions_string;
}

// Load search query.
// Get the Apache Solr "environment id".
if (strpos($view->base_table, 'apachesolr__') === 0) {
$env_id = substr($view->base_table, 12);
}
else {
$env_id = apachesolr_default_environment();
}

$solr = apachesolr_get_solr($env_id);
$query = new ApachesolrViewsSolrBaseQuery('apachesolr', $solr, $params, '', current_path());

// Add sorting.
if (isset($this->params['sort'])) {
$query->setAvailableSort($this->params['sort'][0], $this->params['sort'][1]);
$query->setSolrsort($this->params['sort'][0], $this->params['sort'][1]);
}

$query->page = $this->pager->current_page;

// Boost parameters if apachesolr_search module is available.
if (module_exists('apachesolr_search')) {
apachesolr_search_add_boost_params($query);
}

// Execute search.
list($final_query, $response) = apachesolr_do_query($query);
apachesolr_has_searched($solr->getId(), TRUE);

// Store results.
$view->result = $response->response->docs;

// Store apachesolr cached response.
$this->apachesolr_response = $response;

// Store the results.
$this->pager->total_items = $view->total_rows = $this->apachesolr_response->response->numFound;
$this->pager->update_page_info();

// We shouldn't use $results['performance']['complete'] here, since
// extracting the results probably takes considerable time as well.
$view->execute_time = microtime(TRUE) - $start;
}
catch (Exception $e) {
$this->errors[] = $e->getMessage();
}

if ($this->errors) {
foreach ($this->errors as $msg) {
drupal_set_message($msg, 'error');
}
$view->result = array();
$view->total_rows = 0;
$view->execute_time = 0;
return;
}
}

public function add_filter($type, $value, $exclude = FALSE) {
$exclude_string = ($exclude) ? '-' : '';
$this->params['filters'][] = $exclude_string . $type . ':(' . $value . ')';
}

public function add_filter_string($string) {
$this->params['q.alt'][] = $string;
}

public function add_sort($field, $order) {
$this->params['sort'] = array($field, $order);
}

public function add_parameter($key, $value) {
$this->params[$key] = $value;
}

public function add_field($table_alias, $field, $alias = '', $params = array()) {
if (isset($table_alias[$field])) {
return $table_alias[$field];
}
}

public function get_params() {
return $this->params;
}

/**
* Build filter string from where array.
*/
function build_where_string($where) {
if (!isset($where['conditions'])) {
return $where['field'] . ':(' . $where['value'] . ')';
}
else {
$condition_strings = array();
foreach ($where['conditions'] as $condition) {
$condition_strings[] = $this->build_where_string($condition);
}
$condition_strings = array_filter($condition_strings);
return implode(' ' . $where['type'] . ' ', $condition_strings);
}
}

/**
* Support for groupping.
*
* @see views_plugin_query_default::add_where().
*/
function add_where($group, $field, $value = NULL, $operator = NULL) {
// Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
// the default group.
if (empty($group)) {
$group = 0;
}

// Check for a group.
if (!isset($this->where[$group])) {
$this->set_where_group('AND', $group);
}

$this->where[$group]['conditions'][] = array(
'field' => $field,
'value' => $value,
'operator' => $operator,
);
}

/**
* Support for groupping.
*
* @see views_plugin_query_default::set_where_group().
*/
function set_where_group($type = 'AND', $group = NULL, $where = 'where') {
// Set an alias.
$groups = &$this->$where;

if (!isset($group)) {
$group = empty($groups) ? 1 : max(array_keys($groups)) + 1;
}

// Create an empty group
if (empty($groups[$group])) {
$groups[$group] = array('conditions' => array(), 'args' => array());
}

$groups[$group]['type'] = strtoupper($type);
return $group;
}
}
@@ -0,0 +1,15 @@
<?php

/**
* Custom SolrBaseQuery class for Apachesolr Views.
*
* Needed to set proper base path for facets.
*/
class ApachesolrViewsSolrBaseQuery extends SolrBaseQuery {
public function getPath($new_keywords = NULL) {
if (isset($new_keywords)) {
return $this->base_path . '/' . $new_keywords;
}
return $this->base_path;
}
}

0 comments on commit 248cd97

Please sign in to comment.