updated to 7.x-1.11
This commit is contained in:
@@ -151,11 +151,9 @@ class SearchApiViewsFacetsBlockDisplay extends views_plugin_display_block {
|
||||
}
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
if (substr($this->view->base_table, 0, 17) != 'search_api_index_') {
|
||||
form_set_error('', t('The "Facets block" display can only be used with base tables based on Search API indexes.'));
|
||||
return NULL;
|
||||
}
|
||||
public function query(){
|
||||
parent::query();
|
||||
|
||||
$facet_field = $this->get_option('facet_field');
|
||||
if (!$facet_field) {
|
||||
return NULL;
|
||||
@@ -165,7 +163,7 @@ class SearchApiViewsFacetsBlockDisplay extends views_plugin_display_block {
|
||||
if (!$base_path) {
|
||||
$base_path = $_GET['q'];
|
||||
}
|
||||
$this->view->build();
|
||||
|
||||
$limit = empty($this->view->query->pager->options['items_per_page']) ? 10 : $this->view->query->pager->options['items_per_page'];
|
||||
$query_options = &$this->view->query->getOptions();
|
||||
if (!$this->get_option('hide_block')) {
|
||||
@@ -179,6 +177,17 @@ class SearchApiViewsFacetsBlockDisplay extends views_plugin_display_block {
|
||||
}
|
||||
$query_options['search_api_base_path'] = $base_path;
|
||||
$this->view->query->range(0, 0);
|
||||
}
|
||||
|
||||
public function render() {
|
||||
if (substr($this->view->base_table, 0, 17) != 'search_api_index_') {
|
||||
form_set_error('', t('The "Facets block" display can only be used with base tables based on Search API indexes.'));
|
||||
return NULL;
|
||||
}
|
||||
$facet_field = $this->get_option('facet_field');
|
||||
if (!$facet_field) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$this->view->execute();
|
||||
|
||||
@@ -229,7 +238,7 @@ class SearchApiViewsFacetsBlockDisplay extends views_plugin_display_block {
|
||||
// Initializes variables passed to theme hook.
|
||||
$variables = array(
|
||||
'text' => $name,
|
||||
'path' => $base_path,
|
||||
'path' => $this->view->query->getOption('search_api_base_path'),
|
||||
'count' => $term['count'],
|
||||
'options' => array(
|
||||
'attributes' => array('class' => 'facetapi-inactive'),
|
||||
@@ -249,10 +258,16 @@ class SearchApiViewsFacetsBlockDisplay extends views_plugin_display_block {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$info['content']['facets'] = array(
|
||||
return array(
|
||||
'facets' => array(
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $facets,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function execute(){
|
||||
$info['content'] = $this->render();
|
||||
$info['content']['more'] = $this->render_more_link();
|
||||
$info['subject'] = filter_xss_admin($this->view->get_title());
|
||||
return $info;
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerArgument.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views argument handler class for handling all non-fulltext types.
|
||||
*/
|
||||
|
161
contrib/search_api_views/includes/handler_argument_date.inc
Normal file
161
contrib/search_api_views/includes/handler_argument_date.inc
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the SearchApiViewsHandlerArgumentDate class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines a contextual filter searching for a date or date range.
|
||||
*/
|
||||
class SearchApiViewsHandlerArgumentDate extends SearchApiViewsHandlerArgument {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query($group_by = FALSE) {
|
||||
if (empty($this->value)) {
|
||||
$this->fillValue();
|
||||
if ($this->value === FALSE) {
|
||||
$this->abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$outer_conjunction = strtoupper($this->operator);
|
||||
|
||||
if (empty($this->options['not'])) {
|
||||
$operator = '=';
|
||||
$inner_conjunction = 'OR';
|
||||
}
|
||||
else {
|
||||
$operator = '<>';
|
||||
$inner_conjunction = 'AND';
|
||||
}
|
||||
|
||||
if (!empty($this->value)) {
|
||||
if (!empty($this->value)) {
|
||||
$outer_filter = $this->query->createFilter($outer_conjunction);
|
||||
foreach ($this->value as $value) {
|
||||
$value_filter = $this->query->createFilter($inner_conjunction);
|
||||
$values = explode(';', $value);
|
||||
$values = array_map(array($this, 'getTimestamp'), $values);
|
||||
if (in_array(FALSE, $values, TRUE)) {
|
||||
$this->abort();
|
||||
return;
|
||||
}
|
||||
$is_range = (count($values) > 1);
|
||||
|
||||
$inner_filter = ($is_range ? $this->query->createFilter('AND') : $value_filter);
|
||||
$range_op = (empty($this->options['not']) ? '>=' : '<');
|
||||
$inner_filter->condition($this->real_field, $values[0], $is_range ? $range_op : $operator);
|
||||
if ($is_range) {
|
||||
$range_op = (empty($this->options['not']) ? '<=' : '>');
|
||||
$inner_filter->condition($this->real_field, $values[1], $range_op);
|
||||
$value_filter->filter($inner_filter);
|
||||
}
|
||||
$outer_filter->filter($value_filter);
|
||||
}
|
||||
|
||||
$this->query->filter($outer_filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to a timestamp, if it isn't one already.
|
||||
*
|
||||
* @param string|int $value
|
||||
* The value to convert. Either a timestamp, or a date/time string as
|
||||
* recognized by strtotime().
|
||||
*
|
||||
* @return int|false
|
||||
* The parsed timestamp, or FALSE if an illegal string was passed.
|
||||
*/
|
||||
public function getTimestamp($value) {
|
||||
if (is_numeric($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return strtotime($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills $this->value with data from the argument.
|
||||
*/
|
||||
protected function fillValue() {
|
||||
if (!empty($this->options['break_phrase'])) {
|
||||
// Set up defaults:
|
||||
if (!isset($this->value)) {
|
||||
$this->value = array();
|
||||
}
|
||||
|
||||
if (!isset($this->operator)) {
|
||||
$this->operator = 'OR';
|
||||
}
|
||||
|
||||
if (empty($this->argument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match('/^([-\d;:\s]+\+)*[-\d;:\s]+$/', $this->argument)) {
|
||||
// The '+' character in a query string may be parsed as ' '.
|
||||
$this->value = explode('+', $this->argument);
|
||||
}
|
||||
elseif (preg_match('/^([-\d;:\s]+,)*[-\d;:\s]+$/', $this->argument)) {
|
||||
$this->operator = 'AND';
|
||||
$this->value = explode(',', $this->argument);
|
||||
}
|
||||
|
||||
// Keep an 'error' value if invalid strings were given.
|
||||
if (!empty($this->argument) && (empty($this->value) || !is_array($this->value))) {
|
||||
$this->value = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->value = array($this->argument);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aborts the associated query due to an illegal argument.
|
||||
*/
|
||||
protected function abort() {
|
||||
$variables['!field'] = $this->definition['group'] . ': ' . $this->definition['title'];
|
||||
$this->query->abort(t('Illegal argument passed to !field contextual filter.', $variables));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the title this argument will assign the view, given the argument.
|
||||
*
|
||||
* @return string
|
||||
* A title fitting for the passed argument.
|
||||
*/
|
||||
public function title() {
|
||||
if (!empty($this->argument)) {
|
||||
if (empty($this->value)) {
|
||||
$this->fillValue();
|
||||
}
|
||||
$dates = array();
|
||||
foreach ($this->value as $date) {
|
||||
$date_parts = explode(';', $date);
|
||||
|
||||
$ts = $this->getTimestamp($date_parts[0]);
|
||||
$datestr = format_date($ts, 'short');
|
||||
if (count($date_parts) > 1) {
|
||||
$ts = $this->getTimestamp($date_parts[1]);
|
||||
$datestr .= ' - ' . format_date($ts, 'short');
|
||||
}
|
||||
|
||||
if ($datestr) {
|
||||
$dates[] = $datestr;
|
||||
}
|
||||
}
|
||||
|
||||
return $dates ? implode(', ', $dates) : check_plain($this->argument);
|
||||
}
|
||||
|
||||
return check_plain($this->argument);
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerArgumentFulltext.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views argument handler class for handling fulltext fields.
|
||||
*/
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerArgumentMoreLikeThis.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views argument handler providing a list of related items for search servers
|
||||
* supporting the "search_api_mlt" feature.
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerArgumentString.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views argument handler class for handling string fields.
|
||||
*/
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilter.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler base class for handling all "normal" cases.
|
||||
*/
|
||||
@@ -31,8 +36,8 @@ class SearchApiViewsHandlerFilter extends views_handler_filter {
|
||||
*/
|
||||
public function operator_options() {
|
||||
return array(
|
||||
'<' => t('Is smaller than'),
|
||||
'<=' => t('Is smaller than or equal to'),
|
||||
'<' => t('Is less than'),
|
||||
'<=' => t('Is less than or equal to'),
|
||||
'=' => t('Is equal to'),
|
||||
'<>' => t('Is not equal to'),
|
||||
'>=' => t('Is greater than or equal to'),
|
||||
@@ -46,8 +51,8 @@ class SearchApiViewsHandlerFilter extends views_handler_filter {
|
||||
* Provide a form for setting the filter value.
|
||||
*/
|
||||
public function value_form(&$form, &$form_state) {
|
||||
while (is_array($this->value)) {
|
||||
$this->value = $this->value ? array_shift($this->value) : NULL;
|
||||
while (is_array($this->value) && count($this->value) < 2) {
|
||||
$this->value = $this->value ? reset($this->value) : NULL;
|
||||
}
|
||||
$form['value'] = array(
|
||||
'#type' => 'textfield',
|
||||
@@ -58,10 +63,19 @@ class SearchApiViewsHandlerFilter extends views_handler_filter {
|
||||
|
||||
// Hide the value box if the operator is 'empty' or 'not empty'.
|
||||
// Radios share the same selector so we have to add some dummy selector.
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="options[operator]"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="options[operator]"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
if (empty($form_state['exposed'])) {
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="options[operator]"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="options[operator]"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
}
|
||||
elseif (!empty($this->options['expose']['use_operator'])) {
|
||||
$name = $this->options['expose']['operator_id'];
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="' . $name . '"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="' . $name . '"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterBoolean.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for handling fulltext fields.
|
||||
*/
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterDate.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler base class for handling all "normal" cases.
|
||||
*/
|
||||
|
211
contrib/search_api_views/includes/handler_filter_entity.inc
Normal file
211
contrib/search_api_views/includes/handler_filter_entity.inc
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterEntity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for entities.
|
||||
*
|
||||
* Should be extended for specific entity types, such as
|
||||
* SearchApiViewsHandlerFilterUser and SearchApiViewsHandlerFilterTaxonomyTerm.
|
||||
*
|
||||
* Based on views_handler_filter_term_node_tid.
|
||||
*/
|
||||
abstract class SearchApiViewsHandlerFilterEntity extends SearchApiViewsHandlerFilter {
|
||||
|
||||
/**
|
||||
* If exposed form input was successfully validated, the entered entity IDs.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $validated_exposed_input;
|
||||
|
||||
/**
|
||||
* Validates entered entity labels and converts them to entity IDs.
|
||||
*
|
||||
* Since this can come from either the form or the exposed filter, this is
|
||||
* abstracted out a bit so it can handle the multiple input sources.
|
||||
*
|
||||
* @param array $form
|
||||
* The form or form element for which any errors should be set.
|
||||
* @param array $values
|
||||
* The entered user names to validate.
|
||||
*
|
||||
* @return array
|
||||
* The entity IDs corresponding to all entities that could be found.
|
||||
*/
|
||||
abstract protected function validate_entity_strings(array &$form, array $values);
|
||||
|
||||
/**
|
||||
* Transforms an array of entity IDs into a comma-separated list of labels.
|
||||
*
|
||||
* @param array $ids
|
||||
* The entity IDs to transform.
|
||||
*
|
||||
* @return string
|
||||
* A string containing the labels corresponding to the IDs, separated by
|
||||
* commas.
|
||||
*/
|
||||
abstract protected function ids_to_strings(array $ids);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function operator_options() {
|
||||
$operators = array(
|
||||
'=' => $this->isMultiValued() ? t('Is one of') : t('Is'),
|
||||
'all of' => t('Is all of'),
|
||||
'<>' => $this->isMultiValued() ? t('Is not one of') : t('Is not'),
|
||||
'empty' => t('Is empty'),
|
||||
'not empty' => t('Is not empty'),
|
||||
);
|
||||
if (!$this->isMultiValued()) {
|
||||
unset($operators['all of']);
|
||||
}
|
||||
return $operators;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
|
||||
$options['expose']['multiple']['default'] = TRUE;
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value_form(&$form, &$form_state) {
|
||||
parent::value_form($form, $form_state);
|
||||
|
||||
if (!is_array($this->value)) {
|
||||
$this->value = $this->value ? array($this->value) : array();
|
||||
}
|
||||
|
||||
// Set the correct default value in case the admin-set value is used (and a
|
||||
// value is present). The value is used if the form is either not exposed,
|
||||
// or the exposed form wasn't submitted yet (there is
|
||||
if ($this->value && (empty($form_state['input']) || !empty($form_state['input']['live_preview']))) {
|
||||
$form['value']['#default_value'] = $this->ids_to_strings($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value_validate($form, &$form_state) {
|
||||
if (!empty($form['value'])) {
|
||||
$value = &$form_state['values']['options']['value'];
|
||||
$values = $this->isMultiValued($form_state['values']['options']) ? drupal_explode_tags($value) : array($value);
|
||||
$ids = $this->validate_entity_strings($form['value'], $values);
|
||||
|
||||
if ($ids) {
|
||||
$value = $ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function accept_exposed_input($input) {
|
||||
$rc = parent::accept_exposed_input($input);
|
||||
|
||||
if ($rc) {
|
||||
// If we have previously validated input, override.
|
||||
if ($this->validated_exposed_input) {
|
||||
$this->value = $this->validated_exposed_input;
|
||||
}
|
||||
}
|
||||
|
||||
return $rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exposed_validate(&$form, &$form_state) {
|
||||
if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$identifier = $this->options['expose']['identifier'];
|
||||
$input = $form_state['values'][$identifier];
|
||||
|
||||
if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) {
|
||||
$this->operator = $this->options['group_info']['group_items'][$input]['operator'];
|
||||
$input = $this->options['group_info']['group_items'][$input]['value'];
|
||||
}
|
||||
|
||||
$values = $this->isMultiValued() ? drupal_explode_tags($input) : array($input);
|
||||
|
||||
if (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All'))) {
|
||||
$this->validated_exposed_input = $this->validate_entity_strings($form[$identifier], $values);
|
||||
}
|
||||
else {
|
||||
$this->validated_exposed_input = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether multiple user names can be entered into this filter.
|
||||
*
|
||||
* This is either the case if the form isn't exposed, or if the " Allow
|
||||
* multiple selections" option is enabled.
|
||||
*
|
||||
* @param array $options
|
||||
* (optional) The options array to use. If not supplied, the options set on
|
||||
* this filter will be used.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if multiple values can be entered for this filter, FALSE otherwise.
|
||||
*/
|
||||
protected function isMultiValued(array $options = array()) {
|
||||
$options = $options ? $options : $this->options;
|
||||
return empty($options['exposed']) || !empty($options['expose']['multiple']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function admin_summary() {
|
||||
$value = $this->value;
|
||||
$this->value = empty($value) ? '' : $this->ids_to_strings($value);
|
||||
$ret = parent::admin_summary();
|
||||
$this->value = $value;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
if ($this->operator === 'empty') {
|
||||
$this->query->condition($this->real_field, NULL, '=', $this->options['group']);
|
||||
}
|
||||
elseif ($this->operator === 'not empty') {
|
||||
$this->query->condition($this->real_field, NULL, '<>', $this->options['group']);
|
||||
}
|
||||
elseif (is_array($this->value)) {
|
||||
$all_of = $this->operator === 'all of';
|
||||
$operator = $all_of ? '=' : $this->operator;
|
||||
if (count($this->value) == 1) {
|
||||
$this->query->condition($this->real_field, reset($this->value), $operator, $this->options['group']);
|
||||
}
|
||||
else {
|
||||
$filter = $this->query->createFilter($operator === '<>' || $all_of ? 'AND' : 'OR');
|
||||
foreach ($this->value as $value) {
|
||||
$filter->condition($this->real_field, $value, $operator);
|
||||
}
|
||||
$this->query->filter($filter, $this->options['group']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterFulltext.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for handling fulltext fields.
|
||||
*/
|
||||
@@ -33,6 +38,7 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
|
||||
$options['operator']['default'] = 'AND';
|
||||
|
||||
$options['mode'] = array('default' => 'keys');
|
||||
$options['min_length'] = array('default' => '');
|
||||
$options['fields'] = array('default' => array());
|
||||
|
||||
return $options;
|
||||
@@ -75,6 +81,55 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
|
||||
if (isset($form['expose'])) {
|
||||
$form['expose']['#weight'] = -5;
|
||||
}
|
||||
|
||||
$form['min_length'] = array(
|
||||
'#title' => t('Minimum keyword length'),
|
||||
'#description' => t('Minimum length of each word in the search keys. Leave empty to allow all words.'),
|
||||
'#type' => 'textfield',
|
||||
'#element_validate' => array('element_validate_integer_positive'),
|
||||
'#default_value' => $this->options['min_length'],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exposed_validate(&$form, &$form_state) {
|
||||
// Only validate exposed input.
|
||||
if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only need to validate if there is a minimum word length set.
|
||||
if ($this->options['min_length'] < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$identifier = $this->options['expose']['identifier'];
|
||||
$input = &$form_state['values'][$identifier];
|
||||
|
||||
if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) {
|
||||
$this->operator = $this->options['group_info']['group_items'][$input]['operator'];
|
||||
$input = &$this->options['group_info']['group_items'][$input]['value'];
|
||||
}
|
||||
|
||||
// If there is no input, we're fine.
|
||||
if (!trim($input)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$words = preg_split('/\s+/', $input);
|
||||
foreach ($words as $i => $word) {
|
||||
if (drupal_strlen($word) < $this->options['min_length']) {
|
||||
unset($words[$i]);
|
||||
}
|
||||
}
|
||||
if (!$words) {
|
||||
$vars['@count'] = $this->options['min_length'];
|
||||
$msg = t('You must include at least one positive keyword with @count characters or more.', $vars);
|
||||
form_error($form[$identifier], $msg);
|
||||
}
|
||||
$input = implode(' ', $words);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +163,9 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
|
||||
return;
|
||||
}
|
||||
|
||||
// If the operator was set to OR, set it as the conjunction. (AND is set by
|
||||
// default.)
|
||||
if ($this->operator === 'OR') {
|
||||
// If the operator was set to OR or NOT, set OR as the conjunction. (It is
|
||||
// also set for NOT since otherwise it would be "not all of these words".)
|
||||
if ($this->operator != 'AND') {
|
||||
$this->query->setOption('conjunction', $this->operator);
|
||||
}
|
||||
|
||||
|
@@ -41,6 +41,10 @@ class SearchApiViewsHandlerFilterLanguage extends SearchApiViewsHandlerFilterOpt
|
||||
*/
|
||||
public function query() {
|
||||
global $language_content;
|
||||
|
||||
if (!is_array($this->value)) {
|
||||
$this->value = $this->value ? array($this->value) : array();
|
||||
}
|
||||
foreach ($this->value as $i => $v) {
|
||||
if ($v == 'current') {
|
||||
$this->value[$i] = $language_content->language;
|
||||
|
@@ -1,16 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Views filter handler class for handling fields with a limited set of possible
|
||||
* values.
|
||||
*
|
||||
* Definition items:
|
||||
* - options: An array of possible values for this field.
|
||||
* @file
|
||||
* Contains the SearchApiViewsHandlerFilterOptions class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler for fields with a limited set of possible values.
|
||||
*/
|
||||
class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
|
||||
/**
|
||||
* Stores the values which are available on the form.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $value_options = NULL;
|
||||
|
||||
/**
|
||||
* The type of form element used to display the options.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value_form_type = 'checkboxes';
|
||||
|
||||
/**
|
||||
* Retrieves a wrapper for this filter's field.
|
||||
*
|
||||
* @return EntityMetadataWrapper|null
|
||||
* A wrapper for the field which this filter uses.
|
||||
*/
|
||||
protected function get_wrapper() {
|
||||
if ($this->query) {
|
||||
$index = $this->query->getIndex();
|
||||
}
|
||||
elseif (substr($this->view->base_table, 0, 17) == 'search_api_index_') {
|
||||
$index = search_api_index_load(substr($this->view->base_table, 17));
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
$wrapper = $index->entityWrapper(NULL, TRUE);
|
||||
$parts = explode(':', $this->real_field);
|
||||
foreach ($parts as $i => $part) {
|
||||
if (!isset($wrapper->$part)) {
|
||||
return NULL;
|
||||
}
|
||||
$wrapper = $wrapper->$part;
|
||||
$info = $wrapper->info();
|
||||
if ($i < count($parts) - 1) {
|
||||
// Unwrap lists.
|
||||
$level = search_api_list_nesting_level($info['type']);
|
||||
for ($j = 0; $j < $level; ++$j) {
|
||||
$wrapper = $wrapper[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the value_options property with all possible options.
|
||||
*/
|
||||
protected function get_value_options() {
|
||||
if (isset($this->value_options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wrapper = $this->get_wrapper();
|
||||
if ($wrapper) {
|
||||
$this->value_options = $wrapper->optionsList('view');
|
||||
}
|
||||
else {
|
||||
$this->value_options = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a list of options for the operator form.
|
||||
*/
|
||||
@@ -63,13 +129,12 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
* Reduce the options according to the selection.
|
||||
*/
|
||||
protected function reduce_value_options() {
|
||||
$options = array();
|
||||
foreach ($this->definition['options'] as $id => $option) {
|
||||
if (isset($this->options['value'][$id])) {
|
||||
$options[$id] = $option;
|
||||
foreach ($this->value_options as $id => $option) {
|
||||
if (!isset($this->options['value'][$id])) {
|
||||
unset($this->value_options[$id]);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
return $this->value_options;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,27 +157,38 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
* Provide a form for setting options.
|
||||
*/
|
||||
public function value_form(&$form, &$form_state) {
|
||||
$options = array();
|
||||
$this->get_value_options();
|
||||
if (!empty($this->options['expose']['reduce']) && !empty($form_state['exposed'])) {
|
||||
$options += $this->reduce_value_options($form_state);
|
||||
$options = $this->reduce_value_options();
|
||||
}
|
||||
else {
|
||||
$options += $this->definition['options'];
|
||||
$options = $this->value_options;
|
||||
}
|
||||
|
||||
$form['value'] = array(
|
||||
'#type' => $this->value_form_type,
|
||||
'#title' => empty($form_state['exposed']) ? t('Value') : '',
|
||||
'#options' => $options,
|
||||
'#multiple' => TRUE,
|
||||
'#size' => min(4, count($this->definition['options'])),
|
||||
'#size' => min(4, count($options)),
|
||||
'#default_value' => is_array($this->value) ? $this->value : array(),
|
||||
);
|
||||
// Hide the value box if operator is 'empty' or 'not empty'.
|
||||
|
||||
// Hide the value box if the operator is 'empty' or 'not empty'.
|
||||
// Radios share the same selector so we have to add some dummy selector.
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="options[operator]"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="options[operator]"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
if (empty($form_state['exposed'])) {
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="options[operator]"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="options[operator]"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
}
|
||||
elseif (!empty($this->options['expose']['use_operator'])) {
|
||||
$name = $this->options['expose']['operator_id'];
|
||||
$form['value']['#states']['visible'] = array(
|
||||
':input[name="' . $name . '"],dummy-empty' => array('!value' => 'empty'),
|
||||
':input[name="' . $name . '"],dummy-not-empty' => array('!value' => 'not empty'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,8 +215,9 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
$values = '';
|
||||
|
||||
// Remove every element which is not known.
|
||||
$this->get_value_options();
|
||||
foreach ($this->value as $i => $value) {
|
||||
if (!isset($this->definition['options'][$value])) {
|
||||
if (!isset($this->value_options[$value])) {
|
||||
unset($this->value[$i]);
|
||||
}
|
||||
}
|
||||
@@ -161,7 +238,7 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
}
|
||||
// If there is only a single value, use just the plain operator, = or <>.
|
||||
$operator = check_plain($operator);
|
||||
$values = check_plain($this->definition['options'][reset($this->value)]);
|
||||
$values = check_plain($this->value_options[reset($this->value)]);
|
||||
}
|
||||
else {
|
||||
foreach ($this->value as $value) {
|
||||
@@ -172,7 +249,7 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
$values .= '…';
|
||||
break;
|
||||
}
|
||||
$values .= check_plain($this->definition['options'][$value]);
|
||||
$values .= check_plain($this->value_options[$value]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,28 +274,24 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
|
||||
$this->value = reset($this->value);
|
||||
}
|
||||
|
||||
// Determine operator and conjunction.
|
||||
// Determine operator and conjunction. The defaults are already right for
|
||||
// "all of".
|
||||
$operator = '=';
|
||||
$conjunction = 'AND';
|
||||
switch ($this->operator) {
|
||||
case '=':
|
||||
$operator = '=';
|
||||
$conjunction = 'OR';
|
||||
break;
|
||||
|
||||
case 'all of':
|
||||
$operator = '=';
|
||||
$conjunction = 'AND';
|
||||
break;
|
||||
|
||||
case '<>':
|
||||
$operator = '<>';
|
||||
$conjunction = 'AND';
|
||||
break;
|
||||
}
|
||||
|
||||
// If the value is an empty array, we either want no filter at all (for
|
||||
// "is none of", or want to find only items with no value for the field.
|
||||
// "is none of"), or want to find only items with no value for the field.
|
||||
if ($this->value === array()) {
|
||||
if ($this->operator != '<>') {
|
||||
if ($operator != '<>') {
|
||||
$this->query->condition($this->real_field, NULL, '=', $this->options['group']);
|
||||
}
|
||||
return;
|
||||
|
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterTaxonomyTerm.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for taxonomy term entities.
|
||||
*
|
||||
* Based on views_handler_filter_term_node_tid.
|
||||
*/
|
||||
class SearchApiViewsHandlerFilterTaxonomyTerm extends SearchApiViewsHandlerFilterEntity {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has_extra_options() {
|
||||
return !empty($this->definition['vocabulary']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
|
||||
$options['type'] = array('default' => !empty($this->definition['vocabulary']) ? 'textfield' : 'select');
|
||||
$options['hierarchy'] = array('default' => 0);
|
||||
$options['error_message'] = array('default' => TRUE, 'bool' => TRUE);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function extra_options_form(&$form, &$form_state) {
|
||||
$form['type'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Selection type'),
|
||||
'#options' => array('select' => t('Dropdown'), 'textfield' => t('Autocomplete')),
|
||||
'#default_value' => $this->options['type'],
|
||||
);
|
||||
|
||||
$form['hierarchy'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Show hierarchy in dropdown'),
|
||||
'#default_value' => !empty($this->options['hierarchy']),
|
||||
);
|
||||
$form['hierarchy']['#states']['visible'][':input[name="options[type]"]']['value'] = 'select';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value_form(&$form, &$form_state) {
|
||||
parent::value_form($form, $form_state);
|
||||
|
||||
if (!empty($this->definition['vocabulary'])) {
|
||||
$vocabulary = taxonomy_vocabulary_machine_name_load($this->definition['vocabulary']);
|
||||
$title = t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name));
|
||||
}
|
||||
else {
|
||||
$vocabulary = FALSE;
|
||||
$title = t('Select terms');
|
||||
}
|
||||
$form['value']['#title'] = $title;
|
||||
|
||||
if ($vocabulary && $this->options['type'] == 'textfield') {
|
||||
$form['value']['#autocomplete_path'] = 'admin/views/ajax/autocomplete/taxonomy/' . $vocabulary->vid;
|
||||
}
|
||||
else {
|
||||
if ($vocabulary && !empty($this->options['hierarchy'])) {
|
||||
$tree = taxonomy_get_tree($vocabulary->vid);
|
||||
$options = array();
|
||||
|
||||
if ($tree) {
|
||||
foreach ($tree as $term) {
|
||||
$choice = new stdClass();
|
||||
$choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name);
|
||||
$options[] = $choice;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$options = array();
|
||||
$query = db_select('taxonomy_term_data', 'td');
|
||||
$query->innerJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
|
||||
$query->fields('td');
|
||||
$query->orderby('tv.weight');
|
||||
$query->orderby('tv.name');
|
||||
$query->orderby('td.weight');
|
||||
$query->orderby('td.name');
|
||||
$query->addTag('term_access');
|
||||
if ($vocabulary) {
|
||||
$query->condition('tv.machine_name', $vocabulary->machine_name);
|
||||
}
|
||||
$result = $query->execute();
|
||||
foreach ($result as $term) {
|
||||
$options[$term->tid] = $term->name;
|
||||
}
|
||||
}
|
||||
|
||||
$default_value = (array) $this->value;
|
||||
|
||||
if (!empty($form_state['exposed'])) {
|
||||
$identifier = $this->options['expose']['identifier'];
|
||||
|
||||
if (!empty($this->options['expose']['reduce'])) {
|
||||
$options = $this->reduce_value_options($options);
|
||||
|
||||
if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) {
|
||||
$default_value = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->options['expose']['multiple'])) {
|
||||
if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
|
||||
$default_value = 'All';
|
||||
}
|
||||
elseif (empty($default_value)) {
|
||||
$keys = array_keys($options);
|
||||
$default_value = array_shift($keys);
|
||||
}
|
||||
// Due to #1464174 there is a chance that array('') was saved in the
|
||||
// admin ui. Let's choose a safe default value.
|
||||
elseif ($default_value == array('')) {
|
||||
$default_value = 'All';
|
||||
}
|
||||
else {
|
||||
$copy = $default_value;
|
||||
$default_value = array_shift($copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
$form['value']['#type'] = 'select';
|
||||
$form['value']['#multiple'] = TRUE;
|
||||
$form['value']['#options'] = $options;
|
||||
$form['value']['#size'] = min(9, count($options));
|
||||
$form['value']['#default_value'] = $default_value;
|
||||
|
||||
if (!empty($form_state['exposed']) && isset($identifier) && !isset($form_state['input'][$identifier])) {
|
||||
$form_state['input'][$identifier] = $default_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the available exposed options according to the selection.
|
||||
*/
|
||||
protected function reduce_value_options(array $options) {
|
||||
foreach ($options as $id => $option) {
|
||||
if (empty($this->options['value'][$id])) {
|
||||
unset($options[$id]);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value_validate($form, &$form_state) {
|
||||
// We only validate if they've chosen the text field style.
|
||||
if ($this->options['type'] != 'textfield') {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::value_validate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function accept_exposed_input($input) {
|
||||
if (empty($this->options['exposed'])) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// If view is an attachment and is inheriting exposed filters, then assume
|
||||
// exposed input has already been validated.
|
||||
if (!empty($this->view->is_attachment) && $this->view->display_handler->uses_exposed()) {
|
||||
$this->validated_exposed_input = (array) $this->view->exposed_raw_input[$this->options['expose']['identifier']];
|
||||
}
|
||||
|
||||
// If it's non-required and there's no value don't bother filtering.
|
||||
if (!$this->options['expose']['required'] && empty($this->validated_exposed_input)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return parent::accept_exposed_input($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exposed_validate(&$form, &$form_state) {
|
||||
if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only validate if they've chosen the text field style.
|
||||
if ($this->options['type'] != 'textfield') {
|
||||
$input = $form_state['values'][$this->options['expose']['identifier']];
|
||||
if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) {
|
||||
$input = $this->options['group_info']['group_items'][$input]['value'];
|
||||
}
|
||||
|
||||
if ($input != 'All') {
|
||||
$this->validated_exposed_input = (array) $input;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
parent::exposed_validate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validate_entity_strings(array &$form, array $values) {
|
||||
if (empty($values)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$tids = array();
|
||||
$names = array();
|
||||
$missing = array();
|
||||
foreach ($values as $value) {
|
||||
$missing[strtolower($value)] = TRUE;
|
||||
$names[] = $value;
|
||||
}
|
||||
|
||||
if (!$names) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$query = db_select('taxonomy_term_data', 'td');
|
||||
$query->innerJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
|
||||
$query->fields('td');
|
||||
$query->condition('td.name', $names);
|
||||
if (!empty($this->definition['vocabulary'])) {
|
||||
$query->condition('tv.machine_name', $this->definition['vocabulary']);
|
||||
}
|
||||
$query->addTag('term_access');
|
||||
$result = $query->execute();
|
||||
foreach ($result as $term) {
|
||||
unset($missing[strtolower($term->name)]);
|
||||
$tids[] = $term->tid;
|
||||
}
|
||||
|
||||
if ($missing) {
|
||||
if (!empty($this->options['error_message'])) {
|
||||
form_error($form, format_plural(count($missing), 'Unable to find term: @terms', 'Unable to find terms: @terms', array('@terms' => implode(', ', array_keys($missing)))));
|
||||
}
|
||||
else {
|
||||
// Add a bogus TID which will show an empty result for a positive filter
|
||||
// and be ignored for an excluding one.
|
||||
$tids[] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $tids;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function expose_form(&$form, &$form_state) {
|
||||
parent::expose_form($form, $form_state);
|
||||
if ($this->options['type'] != 'select') {
|
||||
unset($form['expose']['reduce']);
|
||||
}
|
||||
$form['error_message'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Display error message'),
|
||||
'#description' => t('Display an error message if one of the entered terms could not be found.'),
|
||||
'#default_value' => !empty($this->options['error_message']),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function ids_to_strings(array $ids) {
|
||||
return implode(', ', db_select('taxonomy_term_data', 'td')
|
||||
->fields('td', array('name'))
|
||||
->condition('td.tid', array_filter($ids))
|
||||
->execute()
|
||||
->fetchCol());
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterText.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for handling fulltext fields.
|
||||
*/
|
||||
|
77
contrib/search_api_views/includes/handler_filter_user.inc
Normal file
77
contrib/search_api_views/includes/handler_filter_user.inc
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerFilterUser.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views filter handler class for handling user entities.
|
||||
*
|
||||
* Based on views_handler_filter_user_name.
|
||||
*/
|
||||
class SearchApiViewsHandlerFilterUser extends SearchApiViewsHandlerFilterEntity {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function value_form(&$form, &$form_state) {
|
||||
parent::value_form($form, $form_state);
|
||||
|
||||
// Set autocompletion.
|
||||
$path = $this->isMultiValued() ? 'admin/views/ajax/autocomplete/user' : 'user/autocomplete';
|
||||
$form['value']['#autocomplete_path'] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function ids_to_strings(array $ids) {
|
||||
$names = array();
|
||||
$args[':uids'] = array_filter($ids);
|
||||
$result = db_query("SELECT uid, name FROM {users} u WHERE uid IN (:uids)", $args);
|
||||
$result = $result->fetchAllKeyed();
|
||||
foreach ($ids as $uid) {
|
||||
if (!$uid) {
|
||||
$names[] = variable_get('anonymous', t('Anonymous'));
|
||||
}
|
||||
elseif (isset($result[$uid])) {
|
||||
$names[] = $result[$uid];
|
||||
}
|
||||
}
|
||||
return implode(', ', $names);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validate_entity_strings(array &$form, array $values) {
|
||||
$uids = array();
|
||||
$missing = array();
|
||||
foreach ($values as $value) {
|
||||
if (drupal_strtolower($value) === drupal_strtolower(variable_get('anonymous', t('Anonymous')))) {
|
||||
$uids[] = 0;
|
||||
}
|
||||
else {
|
||||
$missing[strtolower($value)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$missing) {
|
||||
return $uids;
|
||||
}
|
||||
|
||||
$result = db_query("SELECT * FROM {users} WHERE name IN (:names)", array(':names' => array_values($missing)));
|
||||
foreach ($result as $account) {
|
||||
unset($missing[strtolower($account->name)]);
|
||||
$uids[] = $account->uid;
|
||||
}
|
||||
|
||||
if ($missing) {
|
||||
form_error($form, format_plural(count($missing), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $missing))));
|
||||
}
|
||||
|
||||
return $uids;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsHandlerSort.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class for sorting results according to a specified field.
|
||||
*/
|
||||
|
@@ -98,7 +98,7 @@ class SearchApiViewsCache extends views_plugin_cache_time {
|
||||
// other parameters used in the parent method are already reflected in the
|
||||
// Search API query object we use.
|
||||
if (isset($_GET['exposed_info'])) {
|
||||
$key_data[$key] = $_GET[$key];
|
||||
$key_data['exposed_info'] = $_GET['exposed_info'];
|
||||
}
|
||||
|
||||
$this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data));
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains SearchApiViewsQuery.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Views query class using a Search API index as the data source.
|
||||
*/
|
||||
@@ -180,7 +185,6 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
'#options' => array(),
|
||||
'#default_value' => $this->options['parse_mode'],
|
||||
);
|
||||
$modes = array();
|
||||
foreach ($this->query->parseModes() as $key => $mode) {
|
||||
$form['parse_mode']['#options'][$key] = $mode['name'];
|
||||
if (!empty($mode['description'])) {
|
||||
@@ -243,16 +247,6 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
$view->init_pager();
|
||||
$this->pager->query();
|
||||
|
||||
// Views passes sometimes NULL and sometimes the integer 0 for "All" in a
|
||||
// pager. If set to 0 items, a string "0" is passed. Therefore, we unset
|
||||
// the limit if an empty value OTHER than a string "0" was passed.
|
||||
if (!$this->limit && $this->limit !== '0') {
|
||||
$this->limit = NULL;
|
||||
}
|
||||
// Set the range. (We always set this, as there might even be an offset if
|
||||
// all items are shown.)
|
||||
$this->query->range($this->offset, $this->limit);
|
||||
|
||||
// Set the search ID, if it was not already set.
|
||||
if ($this->query->getOption('search id') == get_class($this->query)) {
|
||||
$this->query->setOption('search id', 'search_api_views:' . $view->name . ':' . $view->current_display);
|
||||
@@ -262,6 +256,20 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
if (!empty($this->options['search_api_bypass_access'])) {
|
||||
$this->query->setOption('search_api_bypass_access', TRUE);
|
||||
}
|
||||
|
||||
// If the View and the Panel conspire to provide an overridden path then
|
||||
// pass that through as the base path.
|
||||
if (!empty($this->view->override_path) && strpos(current_path(), $this->view->override_path) !== 0) {
|
||||
$this->query->setOption('search_api_base_path', $this->view->override_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(&$view) {
|
||||
parent::alter($view);
|
||||
drupal_alter('search_api_views_query', $view, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,7 +292,28 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the "skip result count" option, if it wasn't already set to
|
||||
// FALSE.
|
||||
$skip_result_count = $this->query->getOption('skip result count', TRUE);
|
||||
if ($skip_result_count) {
|
||||
$skip_result_count = !$this->pager->use_count_query() && empty($view->get_total_rows);
|
||||
$this->query->setOption('skip result count', $skip_result_count);
|
||||
}
|
||||
|
||||
try {
|
||||
// Trigger pager pre_execute().
|
||||
$this->pager->pre_execute($this->query);
|
||||
|
||||
// Views passes sometimes NULL and sometimes the integer 0 for "All" in a
|
||||
// pager. If set to 0 items, a string "0" is passed. Therefore, we unset
|
||||
// the limit if an empty value OTHER than a string "0" was passed.
|
||||
if (!$this->limit && $this->limit !== '0') {
|
||||
$this->limit = NULL;
|
||||
}
|
||||
// Set the range. (We always set this, as there might even be an offset if
|
||||
// all items are shown.)
|
||||
$this->query->range($this->offset, $this->limit);
|
||||
|
||||
$start = microtime(TRUE);
|
||||
|
||||
// Execute the search.
|
||||
@@ -292,11 +321,13 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
$this->search_api_results = $results;
|
||||
|
||||
// Store the results.
|
||||
$this->pager->total_items = $view->total_rows = $results['result count'];
|
||||
if (!empty($this->pager->options['offset'])) {
|
||||
$this->pager->total_items -= $this->pager->options['offset'];
|
||||
if (!$skip_result_count) {
|
||||
$this->pager->total_items = $view->total_rows = $results['result count'];
|
||||
if (!empty($this->pager->options['offset'])) {
|
||||
$this->pager->total_items -= $this->pager->options['offset'];
|
||||
}
|
||||
$this->pager->update_page_info();
|
||||
}
|
||||
$this->pager->update_page_info();
|
||||
$view->result = array();
|
||||
if (!empty($results['results'])) {
|
||||
$this->addResults($results['results'], $view);
|
||||
@@ -304,6 +335,9 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
// We shouldn't use $results['performance']['complete'] here, since
|
||||
// extracting the results probably takes considerable time as well.
|
||||
$view->execute_time = microtime(TRUE) - $start;
|
||||
|
||||
// Trigger pager post_execute().
|
||||
$this->pager->post_execute($view->result);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->errors[] = $e->getMessage();
|
||||
@@ -317,8 +351,14 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
*
|
||||
* Used by handlers to flag a fatal error which shouldn't be displayed but
|
||||
* still lead to the view returning empty and the search not being executed.
|
||||
*
|
||||
* @param string|null $msg
|
||||
* Optionally, a translated, unescaped error message to display.
|
||||
*/
|
||||
public function abort() {
|
||||
public function abort($msg = NULL) {
|
||||
if ($msg) {
|
||||
$this->errors[] = $msg;
|
||||
}
|
||||
$this->abort = TRUE;
|
||||
}
|
||||
|
||||
@@ -520,9 +560,9 @@ class SearchApiViewsQuery extends views_plugin_query {
|
||||
// Query interface methods (proxy to $this->query)
|
||||
//
|
||||
|
||||
public function createFilter($conjunction = 'AND') {
|
||||
public function createFilter($conjunction = 'AND', $tags = array()) {
|
||||
if (!$this->errors) {
|
||||
return $this->query->createFilter($conjunction);
|
||||
return $this->query->createFilter($conjunction, $tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user