Permalink
Browse files

Add apachesolr_views

  • Loading branch information...
sdboyer committed Oct 31, 2012
1 parent ded7dbd commit 248cd97fe2104bf3f8f1737c8766ec5f8d7bc5fe

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -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"
+
@@ -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');
+}
@@ -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;
+}
@@ -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;
+ }
+}
Oops, something went wrong.

0 comments on commit 248cd97

Please sign in to comment.