Index: apachesolr.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/apachesolr.module,v
retrieving revision 1.1.2.12.2.112
diff -u -r1.1.2.12.2.112 apachesolr.module
--- apachesolr.module 20 Feb 2009 19:31:16 -0000 1.1.2.12.2.112
+++ apachesolr.module 28 Feb 2009 15:22:26 -0000
@@ -194,6 +194,13 @@
db_query("UPDATE {apachesolr_search_node} SET changed = %d WHERE nid IN (SELECT nid FROM {node} WHERE type = '%s' OR type = '%s')", time(), $info->old_type, $info->type);
}
}
+
+/**
+ * Implementation of hook_views_api().
+ */
+function apachesolr_views_api() {
+ return array('api' => '2.0');
+}
/**
* Helper function for modules implmenting hook_search's 'status' op.
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/README.txt,v
retrieving revision 1.1.2.1.2.11
diff -u -r1.1.2.1.2.11 README.txt
--- README.txt 20 Feb 2009 15:20:38 -0000 1.1.2.1.2.11
+++ README.txt 28 Feb 2009 15:22:25 -0000
@@ -70,7 +70,19 @@
is visible in search.
Enable blocks for facets first at Administer > Site configuration > Apache Solr > Enabled filters,
-then position them as you like at Administer > Site building > Blocks.
+then position them as you like at Administer > Site building > Blocks.
+
+Creating an Apache Solr view
+----------------------------
+
+Once this module is enabled, a new base table becomes available when creating a
+new view. In Views > Add just select "Apache Solr" as the view type to create a
+view which gets its data from the Solr search server.
+
+You can then go on to add fields, a style, etc., to the view, just like normal.
+To create a view for normally searching with Apache Solr (just like in
+search/apachesolr_search), add the "Apachesolr: Search" argument to the view.
+
Troubleshooting
--------------
Index: handlers/apachesolr_views_handler_field_taxonomy.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field_taxonomy.inc
diff -N handlers/apachesolr_views_handler_field_taxonomy.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field_taxonomy.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,76 @@
+ TRUE);
+ return $options;
+ }
+
+ /**
+ * Unset the link_to_node option and provide link_to_terms.
+ */
+ public function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ if (isset($form['link_to_node'])) {
+ unset($form['link_to_node']);
+ }
+ $form['link_to_terms'] = array(
+ '#title' => t("Link each term to the term's overview page."),
+ '#type' => 'checkbox',
+ '#default_value' => !empty($this->options['link_to_terms']),
+ );
+ }
+
+ /**
+ * Tell the query object to retrieve this field.
+ */
+ public function query() {
+ parent::query();
+ $this->query->add_field('vid');
+ }
+
+ /**
+ * Render the taxonomy terms as links.
+ */
+ public function render($values) {
+ $taxonomies = '';
+
+ if (is_array($values->tid)) {
+ $taxonomies = array();
+
+ if (!empty($this->options['link_to_terms'])) {
+ while (!empty($values->tid) && !empty($values->taxonomy_names)) {
+ $term = new stdClass();
+ $term->tid = array_shift($values->tid);
+ $term->vid = array_shift($values->vid);
+ $url = taxonomy_term_path($term);
+ $name = array_shift($values->taxonomy_names);
+
+ $taxonomies[] = l($name, $url, array('absolute' => TRUE));
+ }
+ }
+ else {
+ $taxonomies = $values->taxonomy_name;
+ }
+
+ $taxonomies = implode(', ', $taxonomies);
+ }
+
+ return $taxonomies;
+ }
+
+}
Index: handlers/apachesolr_views_handler_field.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field.inc
diff -N handlers/apachesolr_views_handler_field.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,59 @@
+field_alias = $this->real_field;
+ $this->query->add_field($this->real_field);
+ }
+
+ /**
+ * Render whatever the data is as a link to the node.
+ *
+ * This is copied from views_handler_field_node, but without the indirection
+ * via the aliases table, since in Apache Solr there are no field aliases.
+ */
+ public function render_link($data, $values) {
+ if (!empty($this->options['link_to_node'])
+ && $data !== NULL && $data !== '') {
+ $this->options['alter']['make_link'] = TRUE;
+ $this->options['alter']['path'] = $values->url;
+ }
+ return $data;
+ }
+
+ /**
+ * Called when click-sorting.
+ */
+ public function click_sort($order) {
+ /* These fields have a special "*_sort" field for sorting: */
+ $special_sort_fields = array(
+ 'name' => 'name_sort',
+ 'title' => 'title_sort',
+ );
+
+ if (empty($special_sort_fields[$this->real_field])) {
+ $this->query->add_sort($this->real_field, strtolower($order), TRUE);
+ }
+ else {
+ $this->query->add_sort(
+ $special_sort_fields[$this->real_field], strtolower($order), TRUE);
+ }
+ }
+
+}
Index: handlers/apachesolr_views_handler_field_generic.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field_generic.inc
diff -N handlers/apachesolr_views_handler_field_generic.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field_generic.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,170 @@
+_original->$name)) {
+ return $this->_original->$name;
+ }
+ return NULL;
+ }
+
+ /**
+ * Gets called when trying to set an undefined property.
+ */
+ public function __set($name, $value) {
+ $this->_original->$name = $value;
+ }
+
+ /**
+ * Gets called when calling isset() or empty() on an undefined property.
+ */
+ public function __isset($name) {
+ return isset($this->_original->$name);
+ }
+
+ /**
+ * Gets called when calling unser() on an undefined property.
+ */
+ public function __unset($name) {
+ unset($this->_original->$name);
+ }
+
+ /**
+ * Gets called when calling an undefined instance method.
+ */
+ public function __call($name, $args) {
+ if (!method_exists($this->_original, $name)) {
+ trigger_error("tried to call undefined instance method $name", E_USER_ERROR);
+ }
+ return call_user_func_array(array($this->_original, $name), $args);
+ }
+
+ /**
+ * Gets called when calling an undefined static method.
+ */
+ public static function __callStatic($name, $args) {
+ $method = array(get_class($this->_original), $name);
+ if (!method_exists($method)) {
+ trigger_error("tried to call undefined static method $name", E_USER_ERROR);
+ }
+ call_user_func_array($method, $args);
+ }
+
+ /*
+ * "Normal" methods
+ */
+
+ /**
+ * Loads the base handler and loads it with the specified definition.
+ * Throws an exception if unsuccessful.
+ */
+ public function set_definition($definition) {
+ if (empty($definition['apachesolr base handler'])) {
+ watchdog('views',
+ 'no base handler specified for apachesolr field handler', array(),
+ WATCHDOG_ERROR);
+ }
+ $o = $definition['apachesolr base handler'];
+ $this->_original = views_get_handler($o['table'], $o['field'], 'field');
+ if (empty($this->_original)) {
+ watchdog('views',
+ 'invalid base handler specified for apachesolr field handler: ' .
+ $o['table'] . '/' . $o['field'], array(), WATCHDOG_ERROR);
+ }
+ // Give the original handler the correct definition.
+ $this->_original->set_definition($definition);
+ }
+
+ /**
+ * Get option form definition.
+ *
+ * NOTE: This method must be defined explicitly since
+ * pass-by-reference doesn't work with call_user_func_array().
+ */
+ public function options_form(&$form, &$form_state) {
+ return $this->_original->options_form($form, $form_state);
+ }
+
+ /**
+ * Construct a new apachesolr field handler.
+ */
+ public function construct() {
+ $this->_original->construct();
+
+ $this->_original->aliases = drupal_map_assoc(
+ array('id', 'site', 'hash', 'url', 'title', 'body', 'type', 'type_name',
+ 'path', 'path_alias', 'uid', 'name', 'created', 'changed',
+ 'last_comment_or_change', 'nid', 'status', 'promote', 'moderate',
+ 'sticky', 'tnid', 'translate', 'language', 'comment_count', 'tid',
+ 'vid', 'timestamp'
+ ));
+ }
+
+ /**
+ * We don't need to ensure any tables.
+ * So overwrite this method because it might be called by inherited methods.
+ */
+ public function ensure_my_table() {}
+
+ /**
+ * Tell the query object to retrieve this field.
+ */
+ public function query() {
+ $this->_original->field_alias = $this->_original->real_field;
+ $this->_original->query->add_field($this->_original->real_field);
+ $this->add_additional_fields();
+ }
+
+ /**
+ * Add additionally required fields.
+ */
+ public function add_additional_fields($fields = NULL) {
+ if (!empty($fields)) {
+ return $this->_original->add_additional_fields($fields);
+ }
+ foreach ($this->_original->additional_fields as $f) {
+ $this->_original->query->add_field($f);
+ }
+ }
+
+ /**
+ * Called when click-sorting.
+ */
+ public function click_sort($order) {
+ /* These fields have a special "*_sort" field for sorting: */
+ $special_sort_fields = array(
+ 'name' => 'name_sort',
+ 'title' => 'title_sort',
+ );
+
+ if (empty($special_sort_fields[$this->real_field])) {
+ $this->_original->query->add_sort(
+ $this->_original->real_field, $order, TRUE);
+ }
+ else {
+ $this->_original->query->add_sort(
+ $special_sort_fields[$this->_original->real_field], $order, TRUE);
+ }
+ }
+
+}
Index: handlers/apachesolr_views_handler_field_type.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field_type.inc
diff -N handlers/apachesolr_views_handler_field_type.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field_type.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,19 @@
+render_link(
+ node_get_types('name', $values->{$this->real_field}), $values);
+ }
+
+}
Index: handlers/apachesolr_views_handler_argument.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_argument.inc
diff -N handlers/apachesolr_views_handler_argument.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_argument.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,18 @@
+query->add_term(apachesolr_views_query::escape_term($this->argument),
+ $this->real_field);
+ }
+
+}
Index: apachesolr.views.inc
===================================================================
RCS file: apachesolr.views.inc
diff -N apachesolr.views.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ apachesolr.views.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,288 @@
+ array(
+ 'path' => drupal_get_path('module', 'apachesolr') . '/handlers',
+ ),
+ 'handlers' => array(
+ 'apachesolr_views_handler_argument' => array(
+ 'parent' => 'views_handler_argument',
+ ),
+ 'apachesolr_views_handler_field' => array(
+ 'parent' => 'views_handler_field_node',
+ ),
+ 'apachesolr_views_handler_field_author' => array(
+ 'parent' => 'apachesolr_views_handler_field',
+ ),
+ 'apachesolr_views_handler_field_date' => array(
+ 'parent' => 'apachesolr_views_handler_field',
+ ),
+ 'apachesolr_views_handler_field_generic' => array(
+ 'parent' => 'views_object',
+ ),
+ 'apachesolr_views_handler_field_taxonomy' => array(
+ 'parent' => 'apachesolr_views_handler_field',
+ ),
+ 'apachesolr_views_handler_field_type' => array(
+ 'parent' => 'apachesolr_views_handler_field',
+ ),
+ 'apachesolr_views_handler_filter_author' => array(
+ 'parent' => 'views_handler_filter',
+ ),
+ 'apachesolr_views_handler_filter_search' => array(
+ 'parent' => 'views_handler_filter_string',
+ ),
+ 'apachesolr_views_handler_filter_type' => array(
+ 'parent' => 'views_handler_filter',
+ ),
+ 'apachesolr_views_handler_sort' => array(
+ 'parent' => 'views_handler_sort',
+ ),
+ ),
+ );
+}
+
+/**
+ * Implementation of hook_views_plugins().
+ */
+function apachesolr_views_plugins() {
+ return array(
+ 'module' => 'apachesolr',
+ '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_data() {
+ $data['apachesolr']['table']['group'] = t('Apache Solr');
+
+ $data['apachesolr']['table']['base'] = array(
+ 'query class' => 'apachesolr_views_query',
+ 'title' => t('Apache Solr'),
+ 'help' => t('Searches the site with the Apache Solr search engine.'),
+ );
+
+ $data['apachesolr']['nid'] = array(
+ 'title' => t('Nid'),
+ 'help' => t('The node ID of the node.'),
+ 'field' => array(
+ 'name field' => 'title',
+ 'numeric' => TRUE,
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'nid',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['title'] = array(
+ 'title' => t('Title'),
+ 'help' => t('The title of the node.'),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'title',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['created'] = array(
+ 'title' => t('Creation date'),
+ 'help' => t('The date the node was created.'),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'created',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['changed'] = array(
+ 'title' => t('Updated date'),
+ 'help' => t('The date the node was last updated.'),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'changed',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['type'] = array(
+ 'title' => t('Type'),
+ 'help' => t('The type of a node (for example, "blog entry", "forum post", "story", etc).'),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'type',
+ ),
+ ),
+ 'filter' => array(
+ 'handler' => 'views_handler_filter_apachesolr_type',
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['name'] = array(
+ 'title' => t('Author'),
+ 'help' => t("The node's author."),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'additional fields' => array('uid'),
+ 'apachesolr base handler' => array(
+ 'table' => 'users',
+ 'field' => 'name',
+ ),
+ ),
+ 'filter' => array(
+ 'handler' => 'apachesolr_views_handler_filter_author',
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ $data['apachesolr']['uid'] = array(
+ 'title' => t('Author Uid'),
+ 'help' => t("The node's author's user ID."),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'field' => array(
+ 'name field' => 'name',
+ 'numeric' => TRUE,
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'users',
+ 'field' => 'uid',
+ ),
+ ),
+ );
+ $data['apachesolr']['body'] = array(
+ 'title' => t('Body'),
+ 'help' => t("The node's content."),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => FALSE,
+ 'element type' => 'div',
+ 'apachesolr base handler' => array(
+ 'table' => 'node_revisions',
+ 'field' => 'body',
+ ),
+ ),
+ );
+ $data['apachesolr']['comment_count'] = array(
+ 'title' => t('Comment count'),
+ 'help' => t('The number of comments that were posted to the node.'),
+ 'field' => array(
+ 'numeric' => TRUE,
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node_comment_statistics',
+ 'field' => 'comment_count',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ // TODO Get taxonomy fields to work
+ /*if (module_exists('taxonomy')) {
+ $data['apachesolr']['tid'] = array(
+ 'title' => t('Taxonomy terms'),
+ 'help' => t('Taxonomy terms associated with the node.'),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_taxonomy',
+ 'click sortable' => FALSE,
+ 'additional fields' => array('vid'),
+ 'apachesolr base handler' => array(
+ 'table' => 'vocabulary',
+ 'field' => 'name',
+ ),
+ ),
+ );
+ }*/
+ if (module_exists('translation')) {
+ $data['apachesolr']['language'] = array(
+ 'title' => t('Language'),
+ 'help' => t('The language the node is in.'),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'field' => array(
+ 'handler' => 'apachesolr_views_handler_field_generic',
+ 'click sortable' => TRUE,
+ 'apachesolr base handler' => array(
+ 'table' => 'node',
+ 'field' => 'language',
+ ),
+ ),
+ 'sort' => array(
+ 'handler' => 'apachesolr_views_handler_sort',
+ ),
+ );
+ }
+
+ $data['apachesolr']['text'] = array(
+ 'title' => t('Search'),
+ 'help' => t('Searches the content with Solr'),
+ 'argument' => array(
+ 'handler' => 'apachesolr_views_handler_argument',
+ ),
+ 'filter' => array(
+ 'handler' => 'apachesolr_views_handler_filter_search',
+ ),
+ );
+
+ return $data;
+}
Index: handlers/apachesolr_views_handler_field_date.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field_date.inc
diff -N handlers/apachesolr_views_handler_field_date.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field_date.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,89 @@
+ 'small');
+ $options['custom_date_format'] = array('default' => '');
+
+ return $options;
+ }
+
+ public function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $time = time();
+
+ $form['date_format'] = array(
+ '#type' => 'select',
+ '#title' => t('Date format'),
+ '#options' => array(
+ 'small' => format_date($time, 'small'),
+ 'medium' => format_date($time, 'medium'),
+ 'large' => format_date($time, 'large'),
+ 'custom' => t('Custom'),
+ 'raw time ago' => t('Time ago'),
+ 'time ago' => t('Time ago (with "ago" appended)'),
+ ),
+ '#default_value' =>
+ isset($this->options['date_format'])
+ ? $this->options['date_format']
+ : 'small',
+ );
+ $form['custom_date_format'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Custom date format'),
+ '#description' => t('If "Custom", see ' .
+ 'the PHP docs for date formats. If "Time ago" this is the the ' .
+ 'number of different units to display, which defaults to two.',
+ array('!url' => 'http://us.php.net/manual/en/function.date.php')),
+ '#default_value' =>
+ isset($this->options['custom_date_format'])
+ ? $this->options['custom_date_format']
+ : '',
+ '#process' => array('views_process_dependency'),
+ '#dependency' =>
+ array('edit-options-date-format' => array('custom', 'time ago')),
+ );
+ }
+
+ public function render($values) {
+ // Apache Solr sends the time as a time string, so first convert it back
+ $value = strtotime($values->{$this->real_field});
+
+ $format = $this->options['date_format'];
+ if ($format == 'custom' || $format == 'time ago' || $format == 'raw time ago') {
+ $custom_format = $this->options['custom_date_format'];
+ }
+
+ switch ($format) {
+ case 'raw time ago':
+ return $value
+ ? format_interval(time() - $value,
+ is_numeric($custom_format) ? $custom_format : 2)
+ : theme('views_nodate');
+ case 'time ago':
+ return $value
+ ? t('%time ago', array('%time' => format_interval(time() - $value,
+ is_numeric($custom_format) ? $custom_format : 2)))
+ : theme('views_nodate');
+ case 'custom':
+ return $value
+ ? format_date($value, $format, $custom_format)
+ : theme('views_nodate');
+ default:
+ return $value
+ ? format_date($value, $format)
+ : theme('views_nodate');
+ }
+ }
+
+}
Index: handlers/apachesolr_views_handler_filter_search.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_filter_search.inc
diff -N handlers/apachesolr_views_handler_filter_search.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_filter_search.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,57 @@
+ array(
+ 'title' => t('Append to query'),
+ 'short' => '',
+ 'method' => 'query',
+ 'values' => 1,
+ ),
+ );
+
+ return $operators;
+ }
+
+ public function query() {
+ if (!empty($this->value)) {
+ $this->query->add_term($this->value);
+ }
+ }
+
+ public function admin_summary() {
+ if (!empty($this->options['exposed'])) {
+ return t('exposed');
+ }
+
+ return $this->value;
+ }
+
+}
Index: handlers/apachesolr_views_handler_sort.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_sort.inc
diff -N handlers/apachesolr_views_handler_sort.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_sort.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,30 @@
+ 'name_sort',
+ 'title' => 'title_sort',
+ );
+ $order = strtolower($this->options['order']);
+
+ if (empty($special_sort_fields[$this->real_field])) {
+ $this->query->add_sort($this->real_field, $order);
+ }
+ else {
+ $this->query->add_sort(
+ $special_sort_fields[$this->real_field], $order);
+ }
+ }
+
+}
Index: handlers/apachesolr_views_handler_filter_author.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_filter_author.inc
diff -N handlers/apachesolr_views_handler_filter_author.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_filter_author.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,87 @@
+ 'one of');
+ $options['value'] = array('default' => '');
+
+ return $options;
+ }
+
+ public function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $time = time();
+
+ $form['operator'] = array(
+ '#type' => 'select',
+ '#title' => t('Filter for'),
+ '#options' => array(
+ 'one of' => t('One of these'),
+ 'not one of' => t('Not one of these'),
+ 'current' => t('Current user'),
+ 'not current' => t('Not current user'),
+ ),
+ '#default_value' =>
+ isset($this->options['operator'])
+ ? $this->options['operator']
+ : 'one of',
+ );
+ $form['value'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Usernames'),
+ '#description' => t('Enter a comma seperated list of user names.'),
+ '#default_value' =>
+ isset($this->options['value'])
+ ? $this->options['value']
+ : '',
+ '#process' => array('views_process_dependency'),
+ '#dependency' =>
+ array('edit-options-operator' => array('one of', 'not one of')),
+ );
+ }
+
+ public function query() {
+ if ($this->options['operator'] == 'current') {
+ global $user;
+ $this->query->add_term($user->uid, 'uid');
+ }
+ else if ($this->options['operator'] == 'not current') {
+ global $user;
+ $this->query->add_term('NOT uid:' . $user->uid);
+ }
+ else {
+ $not = $this->options['operator'] == 'not one of';
+ $names = array_map('trim', explode(',', $this->options['value']));
+ foreach ($names as $i => $name) {
+ if (empty($name)) {
+ unset($names[$i]);
+ }
+ }
+ if (empty($names)) {
+ if (!$not) {
+ $this->query->add_term('nid:-1');//Add term that will yield no results
+ }
+ }
+ else if (count($names) == 1) {
+ $this->query->add_term(($not ? 'NOT ' : '') . 'name:' .
+ array_shift($names));
+ }
+ else {
+ $key = 'name:' . array_shift($names);
+ foreach ($names as $name) {
+ $key .= ' OR name:' . $name;
+ }
+ $this->query->add_term($not ? 'NOT (' . $key . ')' : $key);
+ }
+ }
+ }
+
+}
Index: handlers/apachesolr_views_handler_field_author.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_field_author.inc
diff -N handlers/apachesolr_views_handler_field_author.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_field_author.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,47 @@
+ TRUE);
+ return $options;
+ }
+
+ /**
+ * Provide link_to_profile option
+ */
+ public function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ if (isset($form['link_to_node'])) {
+ unset($form['link_to_node']);
+ }
+ $form['link_to_profile'] = array(
+ '#title' => t("Link the name to the user's profile."),
+ '#type' => 'checkbox',
+ '#default_value' => !empty($this->options['link_to_profile']),
+ );
+ }
+
+ /**
+ * If the link_to_profile option is set, render the field as a link to the
+ * user's profile.
+ */
+ function render_link($data, $values) {
+ if (!empty($this->options['link_to_profile']) && $data !== NULL && $data !== '') {
+ $this->options['alter']['make_link'] = TRUE;
+ $this->options['alter']['path'] = "user/" . $values->uid;
+ }
+ return $data;
+ }
+
+}
Index: handlers/apachesolr_views_handler_filter_type.inc
===================================================================
RCS file: handlers/apachesolr_views_handler_filter_type.inc
diff -N handlers/apachesolr_views_handler_filter_type.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ handlers/apachesolr_views_handler_filter_type.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,72 @@
+ 'one of');
+ $options['value'] = array('default' => '');
+
+ return $options;
+ }
+
+ public function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $time = time();
+
+ $form['operator'] = array(
+ '#type' => 'select',
+ '#title' => t('Filter for'),
+ '#options' => array(
+ 'one of' => t('One of these'),
+ 'not one of' => t('Not one of these'),
+ ),
+ '#default_value' =>
+ isset($this->options['operator'])
+ ? $this->options['operator']
+ : 'one of',
+ );
+ $form['value'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Usernames'),
+ '#description' => t('Enter a comma seperated list of types.'),
+ '#default_value' =>
+ isset($this->options['value'])
+ ? $this->options['value']
+ : '',
+ );
+ }
+
+ public function query() {
+ $not = $this->options['operator'] == 'not one of';
+ $types = array_map('trim', explode(',', $this->options['value']));
+ foreach ($types as $i => $type) {
+ if (empty($type)) {
+ unset($types[$i]);
+ }
+ }
+ if (empty($types)) {
+ if (!$not) {
+ $this->query->add_term('nid:-1');//Add term that will yield no results
+ }
+ }
+ else if (count($types) == 1) {
+ $this->query->add_term(($not ? 'NOT ' : '') . 'type:' .
+ array_shift($types));
+ }
+ else {
+ $key = 'type:' . array_shift($types);
+ foreach ($types as $type) {
+ $key .= ' OR type:' . $type;
+ }
+ $this->query->add_term($not ? 'NOT (' . $key . ')' : $key);
+ }
+ }
+
+}
Index: apachesolr_views_query.inc
===================================================================
RCS file: apachesolr_views_query.inc
diff -N apachesolr_views_query.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ apachesolr_views_query.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,379 @@
+_keys = array();
+ // Always retrieve these fields:
+ $this->_used_fields = array(
+ 'id' => TRUE,
+ 'nid' => TRUE,
+ 'url' => TRUE,
+ );
+ $this->_params = $this->_get_params();
+
+ // For use within the escape_term() method.
+ include_once(drupal_get_path('module', 'apachesolr') .
+ '/Drupal_Apache_Solr_Service.php');
+ }
+
+ /**
+ * Build the query object.
+ */
+ public function build() {
+ if (empty($this->_keys)) {
+ $this->_query = FALSE;
+ return;
+ }
+ else if (count($this->_keys)) {
+ $this->_query = $this->_keys[0];
+ }
+ else {
+ $this->_query = '(' . implode(') (', $this->_keys) . ')';
+ }
+
+ $this->_query_object = apachesolr_current_query($this->_query, '',
+ $this->get_param('sort'));
+ }
+
+ /**
+ * Let modules modify the query just prior to finalizing it.
+ */
+ public function alter(&$view) {
+ // TODO Do something here? (apachesolr_modify_query() is called later.)
+ }
+
+ /**
+ * 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) {
+ $view->result = array();
+ $start_time = views_microtime();
+ $query = $this->_query_object;
+ $params = $this->_params;
+ $solr = $this->_solr;
+
+ if (empty($query)) {
+ return;
+ }
+
+ try {
+ // Get only the necessary fields.
+ $params['fl'] = implode(',', array_keys($this->_used_fields));
+
+ // Get the number of results to retrieve.
+ $params['rows'] = $view->pager['items_per_page'];
+
+ // Since only now the query is known, we couldn't do this earlier
+ // (i.e., in _get_params())
+ if (variable_get('apachesolr_search_spellcheck', FALSE)) {
+ //Add new parameter to the search request
+ $params['spellcheck.q'] = $this->_query_object->get_query_basic();
+ $params['spellcheck'] = 'true';
+ }
+
+ // We default to getting snippets from the body.
+ $hl_fl = is_null($params['hl.fl']) ? 'body' : $params['hl.fl'];
+
+ // This hook allows modules to modify the query and params objects.
+ apachesolr_modify_query($query, $params, 'apachesolr_search');
+ if (!$query) {
+ return array();
+ }
+
+ $response = $solr->search($query->get_query_basic(), $params['start'],
+ $params['rows'], $params);
+
+ $view->total_rows = $total = $response->response->numFound;
+ $view->pager['current_page'] = $params['start'] / $params['rows'];
+
+ // The response is cached so that it is accessible to the blocks and
+ // anything else that needs it beyond the initial search.
+ apachesolr_static_response_cache($response);
+ apachesolr_has_searched(TRUE);
+ pager_query("SELECT %d", $params['rows'], 0, NULL, $total);
+
+ if ($total > 0) {
+ $results = $response->response->docs;
+
+ // Process dates
+ $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);
+ }
+ }
+ }
+
+ // Hook to allow modifications of the retrieved results
+ foreach (module_implements('apachesolr_process_results') as $module) {
+ $function = $module .'_apachesolr_process_results';
+ call_user_func_array($function, array(&$results));
+ }
+
+ $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());
+ }
+
+ $view->execute_time = views_microtime() - $start_time;
+ }
+
+
+ /*
+ * Functions offered for apachesolr-specific handlers, etc.
+ */
+
+ /** Adds the specified term to the query. */
+ public function add_term($term, $field = 'text') {
+ if ($field != 'text') {
+ $term = $field . ':' . $term;
+ }
+ $this->_keys[] = $term;
+ }
+
+ /**
+ * Add a group of search terms to the query, which will be connected by OR
+ * operators.
+ *
+ * @param $terms an array where each entry must be either of the form
+ * array('term' => $term, 'field' => $field);
+ * (the 'field' entry can be omitted, in which case 'text' is assumed), or
+ * $term
+ */
+ public function add_or_group($terms) {
+ if (count($terms) == 0 || !is_array($terms)) {
+ return;
+ }
+ $keys = array();
+ foreach ($terms as $term) {
+ if (is_array($term)) {
+ if (empty($term['field']) || $term['field'] == 'text') {
+ $keys[] = $term['term'];
+ }
+ else {
+ $keys[] = $term['field'] . ':' . $term['term'];
+ }
+ }
+ else {
+ $keys[] = $term;
+ }
+ }
+ $this->_keys[] = '(' . implode(' OR ', $keys) . ')';
+ }
+
+ /** Sets the specified Solr search parameter to the specified value. */
+ public function set_param($param, $value) {
+ $this->_params[$param] = $value;
+ }
+
+ /** Get the specified Solr search parameter. */
+ public function get_param($param) {
+ return isset($this->_params[$param]) ? $this->_params[$param] : '';
+ }
+
+ /**
+ * Adds the specified parameters to the Solr search parameters, overwriting
+ * old values where necessary. Parameters must be specified as
+ * $param => $value in the array.
+ */
+ public function set_params($params) {
+ $this->_params = $params + $this->_params;
+ }
+
+ /**
+ * Add a field to retrieve.
+ *
+ * $compat_field is used for compatibility with the views_plugin_query_default
+ * definition of this method - when $compat_field is set, $field is ignored
+ * and $compat_field used instead.
+ */
+ public function add_field($field, $compat_field = NULL) {
+ if (!empty($compat_field)) {
+ $field = $compat_field;
+ }
+ if (is_array($field) && isset($field['field'])) {
+ $field = $field['field'];
+ }
+ if (empty($field) || !is_string($field)) {
+ return FALSE;
+ }
+ $this->_used_fields[$field] = TRUE;
+ return $field;
+ }
+
+ /**
+ * Add a sorting directive.
+ *
+ * @param $single If TRUE, the results will only be sorted by this order.
+ */
+ public function add_sort($field, $order, $single = FALSE) {
+ $sort = $field . ' ' . strtolower($order);
+ if (empty($this->_params['sort']) || $single) {
+ $this->_params['sort'] = $sort;
+ }
+ else {
+ $this->_params['sort'] .= ',' . $sort;
+ }
+ }
+
+
+ /*
+ * (Public and private) helper functions
+ */
+
+ /** Escapes a term for passing it to the query. */
+ 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, ' ') !== FALSE) {
+ return Drupal_Apache_Solr_Service::phrase($term);
+ }
+ return Drupal_Apache_Solr_Service::escape($term);
+ }
+
+ /**
+ * Returns the parameters that will be handed to Solr along with the query.
+ */
+ private function _get_params() {
+ // Whole method copied from
+ // apachesolr_search.module:101-209: apachesolr_search_search()
+ // TODO Refactor, so both this class and apachesolr_search_search() call new
+ // function, apachesolr_get_params().
+ // (If apachesolr_search_get_params() is used, add apachesolr_search to
+ // dependencies in .info.)
+ $params = array(
+ 'fl' => 'id,nid,title,comment_count,type,created,changed,url,uid,name',
+ 'facet' => 'true',
+ 'facet.mincount' => 1,
+ 'facet.sort' => 'true',
+ 'hl' => 'false',
+ );
+
+ $facet_query_limits = variable_get('apachesolr_facet_query_limits', array());
+ // Request all enabled facets.
+ foreach (apachesolr_get_enabled_facets() as $module => $module_facets) {
+ foreach($module_facets as $delta => $facet_field) {
+ $params['facet.field'][] = $facet_field;
+ // Facet limits
+ if (isset($facet_query_limits[$module][$delta])) {
+ $params['f.' . $facet_field . '.facet.limit'] = $facet_query_limits[$module][$delta];
+ }
+ }
+ }
+ if (!empty($params['facet.field'])) {
+ // Add a default limit for fields where no limit was set.
+ $params['facet.limit'] = variable_get('apachesolr_facet_query_limit_default', 20);
+ }
+
+ $page = isset($_GET['page']) ? $_GET['page'] : 0;
+ $params['start'] = $page * $params['rows'];
+ // This is the object that does the communication with the solr server.
+ $solr = $this->_solr = apachesolr_get_solr();
+
+ // Note - we have query fields set in solrconfig.xml, which will operate when
+ // none are set.
+ $qf = variable_get('apachesolr_search_query_fields', array());
+ $fields = $solr->getFields();
+ if ($qf && $fields) {
+ foreach ($fields as $field_name => $field) {
+ if (!empty($qf[$field_name])) {
+ if ($field_name == 'body') {
+ // Body is the only normed field.
+ $qf[$field_name] *= 40.0;
+ }
+ $params['qf'][] = $field_name . '^'. $qf[$field_name];
+ }
+ }
+ }
+ // Note: we use 2 since 1 fails on Ubuntu Hardy.
+ $data = $solr->getLuke(2);
+ if (isset($data->index->numDocs)) {
+ $total = $data->index->numDocs;
+ }
+ else {
+ $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);
+ // Default date-biasing function, as suggested (but steeper) at
+ // http://wiki.apache.org/solr/DisMaxRequestHandler
+ // rord() returns 1 for the newset doc, and the number in the index for
+ // the oldest doc. The function is thus: $total/(rord()*$steepness + $total).
+ if ($date_boost) {
+ $params['bf'][] = "recip(rord(created),$date_steepness,$total,$total)^$date_boost";
+ }
+ $comment_settings = variable_get('apachesolr_search_comment_boost', '4:200.0');
+ list($comment_steepness, $comment_boost) = explode(':', $comment_settings);
+ // Default date-biasing function, as suggested (but steeper) at
+ // http://wiki.apache.org/solr/DisMaxRequestHandler
+ // rord() returns 1 for the newset doc, and the number in the index for
+ // the oldest doc. The function is thus: $total/(rord()*$steepness + $total).
+ if ($comment_boost) {
+ $params['bf'][] = "recip(rord(comment_count),$comment_steepness,$total,$total)^$comment_boost";
+ }
+
+ // Modify the weight of results according to the node types.
+ $type_boosts = variable_get('apachesolr_search_type_boosts', array());
+ if (!empty($type_boosts)) {
+ foreach ($type_boosts as $type => $boost) {
+ $params['bq'][] = "type:$type^$boost";
+ }
+ }
+
+ return $params;
+ }
+
+}