diff --git a/sites/all/modules/contrib/files/imce/imce/imce.info b/sites/all/modules/contrib/files/imce/imce/imce.info
index ac23626d..c812d4fc 100644
--- a/sites/all/modules/contrib/files/imce/imce/imce.info
+++ b/sites/all/modules/contrib/files/imce/imce/imce.info
@@ -4,9 +4,9 @@ core = "7.x"
package = "Media"
configure = "admin/config/media/imce"
-; Information added by Drupal.org packaging script on 2016-03-30
-version = "7.x-1.10"
+; Information added by Drupal.org packaging script on 2017-05-27
+version = "7.x-1.11"
core = "7.x"
project = "imce"
-datestamp = "1459346870"
+datestamp = "1495890787"
diff --git a/sites/all/modules/contrib/files/imce/imce/imce.install b/sites/all/modules/contrib/files/imce/imce/imce.install
index 40ddcd3f..9062e88c 100644
--- a/sites/all/modules/contrib/files/imce/imce/imce.install
+++ b/sites/all/modules/contrib/files/imce/imce/imce.install
@@ -25,6 +25,7 @@ function imce_uninstall() {
variable_del('imce_settings_replace');
variable_del('imce_settings_thumb_method');
variable_del('imce_settings_disable_private');
+ variable_del('imce_settings_admin_theme');
variable_del('imce_custom_content');
variable_del('imce_custom_process');
variable_del('imce_custom_init');
diff --git a/sites/all/modules/contrib/files/imce/imce/imce.module b/sites/all/modules/contrib/files/imce/imce/imce.module
index f3dc4bf7..e2b6baea 100644
--- a/sites/all/modules/contrib/files/imce/imce/imce.module
+++ b/sites/all/modules/contrib/files/imce/imce/imce.module
@@ -46,6 +46,20 @@ function imce_menu() {
return $items;
}
+/**
+ * Implements hook_admin_paths().
+ */
+function imce_admin_paths() {
+ if (variable_get('imce_settings_admin_theme', FALSE)) {
+ return array(
+ 'imce' => TRUE,
+ 'imce/*' => TRUE,
+ 'file/imce/*' => TRUE,
+ 'imce-filefield/*' => TRUE,
+ );
+ }
+}
+
/**
* Implements hook_permission().
*/
diff --git a/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc b/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc
index 587aa474..23529c22 100644
--- a/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc
+++ b/sites/all/modules/contrib/files/imce/imce/inc/imce.admin.inc
@@ -109,6 +109,12 @@ function imce_admin_form($form, &$form_state) {
'#default_value' => variable_get('imce_settings_disable_private', 1),
'#description' => t('IMCE serves all files under private files directory without applying any access restrictions. This allows anonymous access to any file(/system/files/filename) unless there is a module restricting access to the files. Here you can disable this feature.'),
);
+ $form['common']['admin_theme'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Use admin theme for IMCE paths'),
+ '#default_value' => variable_get('imce_settings_admin_theme', FALSE),
+ '#description' => t('If you have user interface issues with the active theme you may consider switching to admin theme.'),
+ );
$form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
$form['#theme'] = 'imce_admin';
@@ -183,6 +189,7 @@ function imce_admin_submit($form, &$form_state) {
variable_set('imce_settings_replace', $form_state['values']['replace']);
variable_set('imce_settings_thumb_method', $form_state['values']['thumb_method']);
variable_set('imce_settings_disable_private', $form_state['values']['disable_private']);
+ variable_set('imce_settings_admin_theme', $form_state['values']['admin_theme']);
drupal_set_message(t('Changes have been saved.'));
}
diff --git a/sites/all/modules/contrib/files/imce/imce/js/imce.js b/sites/all/modules/contrib/files/imce/imce/js/imce.js
index 49cc1569..17c8f7c6 100644
--- a/sites/all/modules/contrib/files/imce/imce/js/imce.js
+++ b/sites/all/modules/contrib/files/imce/imce/js/imce.js
@@ -801,12 +801,17 @@ updateUI: function() {
if (furl.charAt(furl.length - 1) != '/') {
furl = imce.conf.furl = furl + '/';
}
- imce.conf.modfix = imce.conf.clean && furl.indexOf(host + '/system/') > -1;
+ imce.conf.modfix = imce.conf.clean && furl.split('/')[3] === 'system';
if (absurls && !isabs) {
imce.conf.furl = baseurl + furl;
}
else if (!absurls && isabs && furl.indexOf(baseurl) == 0) {
- imce.conf.furl = furl.substr(baseurl.length);
+ furl = furl.substr(baseurl.length);
+ // Server base url is defined with a port which is missing in current page url.
+ if (furl.charAt(0) === ':') {
+ furl = furl.replace(/^:\d*/, '');
+ }
+ imce.conf.furl = furl;
}
//convert button elements to input elements.
imce.convertButtons(imce.FW);
diff --git a/sites/all/modules/contrib/search/search_api/CHANGELOG.txt b/sites/all/modules/contrib/search/search_api/CHANGELOG.txt
index 0084fe0d..c1e66d96 100644
--- a/sites/all/modules/contrib/search/search_api/CHANGELOG.txt
+++ b/sites/all/modules/contrib/search/search_api/CHANGELOG.txt
@@ -1,3 +1,83 @@
+Search API 1.26 (2019-03-11):
+-----------------------------
+- #2324023 by drumm, drunken monkey: Changed Views field definition for to
+ float.
+- #3008849 by pamatt, drunken monkey: Fixed non-exposed numeric and date
+ filters in Views.
+- #3009744 by evgeny.chernyavskiy, drunken monkey: Fixed wrong "continue" in
+ search_api_server_tasks_check().
+- #3003742 by Jelle_S, drunken monkey: Fixed problems with Views date filters.
+- #3002043 by alonaoneill, drunken monkey: Fixed module name capitalization and
+ dependency namespacing in .info files.
+- #2990940 by drunken monkey: Fixed multi-byte handling of Highlight processor.
+- #3001424 by drunken monkey: Fixed notice when configuring the More Like This
+ contextual filter.
+
+Search API 1.25 (2018-09-17):
+-----------------------------
+- #2408727 by swim, drunken monkey: Added a batch operation for executing
+ pending tasks.
+- #2325917 by guillaumev, drunken monkey: Added a Views cache plugin based on
+ Views Content Cache.
+- #2989578 by KarlShea, drunken monkey: Fixed Views exposed form fields for
+ "not between" operator.
+- #2982167 by osopolar, drunken monkey: Added a Drush command for re-indexing
+ specific entities.
+- #1783746 by das-peter, sammys, SpadXIII, drunken monkey, ruloweb, KarlShea,
+ heshanlk, Anas_maw, pinkonomy, Damien Tournoud, rudiedirkx: Added support
+ for the "(not) between" operator.
+- #2408727 by drunken monkey, OliverColeman: Fixed out-of-memory errors when
+ executing pending tasks.
+- Issue #2948820 by capysara, drunken monkey: Added a link to the "need to
+ reindex" message on the Filters tab.
+- #2828883 by JorgenSandstrom, drunken monkey: Fixed property type for
+ string-typed aggregated fields.
+- #2949899 by drunken monkey, DamienMcKenna: Added a warning against using
+ particular processors with Solr servers to the "Workflow" tab.
+
+Search API 1.24 (2018-04-05):
+-----------------------------
+- #2958201 by jcnventura, drunken monkey: Reverted issue #2566529: Added
+ support for the "Content access" processor for "Multiple types" indexes.
+
+Search API 1.23 (2018-03-31):
+-----------------------------
+- #2949562 by DamienMcKenna, drunken monkey: Fixed stemming of multi-word
+ tokens.
+- #1903004 by AndyF, joseph.olstad, drunken monkey: Fixed errors at feature
+ module installation in certain edge cases.
+- #2889989 by kevineinarsson, drunken monkey, kristofferwiklund: Fixed
+ highlighting for text with multi-byte characters.
+- #1393064 by xlyz, drunken monkey, jannis: Fixed handling of empty facet
+ filters.
+- #2927692 by drunken monkey, Kristi Wachter: Fixed exposed grouped Views
+ options filters.
+- #2928769 by jannis, drunken monkey: Fixed Views cache not being cleared when
+ enabling indexes.
+- #2566529 by Dylan Donkersgoed, drunken monkey, joachim, swirt: Added support
+ for the "Content access" processor for "Multiple types" indexes.
+- #2905445 by ciss, drunken monkey: Fixed error handling in Views term filter
+ handler.
+- #2904268 by pobster, drunken monkey: Added support for language hierarchy in
+ Views.
+
+Search API 1.22 (2017-07-18):
+-----------------------------
+- #1710212 by drunken monkey: Added a data alteration for indexing a user's
+ content.
+- #2879892 by blacklabel_tom, drunken monkey: Fixed link in description of
+ "Stemmer" processor.
+- #2788593 by drunken monkey: Fixed error in Views query settings for specific
+ setups.
+- #2749963 by drunken monkey: Fixed "Index hierarchy" not having values
+ numerically indexed.
+- #2875793 by drunken monkey: Fixed buggy error handling in Views.
+- #2860624 by drunken monkey: Fixed problem with empty words in Views fulltext
+ filter.
+- #2855447 by mparker17, drunken monkey: Added "Separator" option for
+ aggregated fields of type "Fulltext".
+- #2863445 by dbjpanda, drunken monkey: Fixed phrasing in README.txt.
+
Search API 1.21 (2017-02-23):
-----------------------------
- #2780341 by Berdir: Fixed passing of custom ranges to date facets.
diff --git a/sites/all/modules/contrib/search/search_api/README.txt b/sites/all/modules/contrib/search/search_api/README.txt
index 3943ceec..a6264e97 100644
--- a/sites/all/modules/contrib/search/search_api/README.txt
+++ b/sites/all/modules/contrib/search/search_api/README.txt
@@ -31,9 +31,9 @@ Terms as used in this module.
Sphinx or any other professional or simple indexing mechanism. Takes care of
the details of all operations, especially indexing or searching content.
- Server:
- One specific place for indexing data, using a set service class. Can
- e.g. be some tables in a database, a connection to a Solr server or other
- external services, etc.
+ One specific place for indexing data, using a specific service class. For
+ example this could be some tables in a database, a connection to a Solr server
+ or other external services, etc.
- Index:
A configuration object for indexing data of a specific type. What and how data
is indexed is determined by its settings. Also keeps track of which items
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
index 64d797a7..4c674a8a 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
@@ -115,7 +115,7 @@ class SearchApiFacetapiTerm extends FacetapiQueryType implements FacetapiQueryTy
if ($filter == '!') {
$query_filter->condition($field, NULL, $exclude ? '<>' : '=');
}
- elseif ($filter[0] == '[' && $filter[strlen($filter) - 1] == ']' && ($pos = strpos($filter, ' TO '))) {
+ elseif ($filter && $filter[0] == '[' && $filter[strlen($filter) - 1] == ']' && ($pos = strpos($filter, ' TO '))) {
$lower = trim(substr($filter, 1, $pos));
$upper = trim(substr($filter, $pos + 4, -1));
if ($lower == '*' && $upper == '*') {
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/search_api_facetapi.info b/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/search_api_facetapi.info
index 022eefc0..904a64dc 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/search_api_facetapi.info
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_facetapi/search_api_facetapi.info
@@ -1,7 +1,7 @@
-name = Search facets
+name = Search Facets
description = "Integrate the Search API with the Facet API to provide facetted searches."
-dependencies[] = search_api
-dependencies[] = facetapi
+dependencies[] = search_api:search_api
+dependencies[] = facetapi:facetapi
core = 7.x
package = Search
@@ -9,9 +9,8 @@ files[] = plugins/facetapi/adapter.inc
files[] = plugins/facetapi/query_type_term.inc
files[] = plugins/facetapi/query_type_date.inc
-; Information added by Drupal.org packaging script on 2017-02-23
-version = "7.x-1.21"
+; Information added by Drupal.org packaging script on 2019-03-11
+version = "7.x-1.26"
core = "7.x"
project = "search_api"
-datestamp = "1487844493"
-
+datestamp = "1552334832"
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/README.txt b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/README.txt
index b36a7b55..50cfce1c 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/README.txt
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/README.txt
@@ -40,6 +40,21 @@ in that position. If the query is sorted in this way, then the
random sort, as an associative array with any of the following keys:
- seed: A numeric seed value to use for the random sort.
+"BETWEEN operator" feature
+--------------------------
+This module defines the "BETWEEN operator" feature (feature key:
+"search_api_between") that adds the "BETWEEN" and "NOT BETWEEN" filter
+operators to search queries. If your search server supports this feature, you
+can use the "Is between" and "Is not between" operators when adding Views
+filters for numeric, string or date types.
+
+For developers:
+A service class that wants to support this feature has to accept "BETWEEN" and
+"NOT BETWEEN" as additional $operator values in query conditions. The value in
+both cases is an array with the keys 0 and 1, with the value under key 0 being
+the lower and the value under key 1 being the upper bound for the range in which
+the field's value should ("BETWEEN") or should not ("NOT BETWEEN") be.
+
"Facets block" display
----------------------
Most features should be clear to users of Views. However, the module also
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument.inc
index a11a662b..a31738ee 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument.inc
@@ -79,8 +79,8 @@ class SearchApiViewsHandlerArgument extends views_handler_argument {
public function option_definition() {
$options = parent::option_definition();
- $options['break_phrase'] = array('default' => FALSE);
- $options['not'] = array('default' => FALSE);
+ $options['break_phrase'] = array('default' => FALSE, 'bool' => TRUE);
+ $options['not'] = array('default' => FALSE, 'bool' => TRUE);
return $options;
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument_more_like_this.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument_more_like_this.inc
index df526e4b..bfb20393 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument_more_like_this.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_argument_more_like_this.inc
@@ -16,8 +16,6 @@ class SearchApiViewsHandlerArgumentMoreLikeThis extends SearchApiViewsHandlerArg
*/
public function option_definition() {
$options = parent::option_definition();
- unset($options['break_phrase']);
- unset($options['not']);
$options['entity_type'] = array('default' => FALSE);
$options['fields'] = array('default' => array());
return $options;
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_date.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_date.inc
index c7897245..c921e9f5 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_date.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_date.inc
@@ -6,9 +6,9 @@
*/
/**
- * Views filter handler base class for handling all "normal" cases.
+ * Views filter handler base class for handling date fields.
*/
-class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter {
+class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilterNumeric {
/**
* Add a "widget type" option.
@@ -88,9 +88,22 @@ class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter {
public function value_form(&$form, &$form_state) {
parent::value_form($form, $form_state);
+ $is_date_popup = ($this->options['widget_type'] == 'date_popup' && module_exists('date_popup'));
+
+ // If the operator is between
+ if ($this->operator == 'between') {
+ if ($is_date_popup) {
+ $form['value']['min']['#type'] = 'date_popup';
+ $form['value']['min']['#date_format'] = $this->options['date_popup_format'];
+ $form['value']['min']['#date_year_range'] = $this->options['year_range'];
+ $form['value']['max']['#type'] = 'date_popup';
+ $form['value']['max']['#date_format'] = $this->options['date_popup_format'];
+ $form['value']['max']['#date_year_range'] = $this->options['year_range'];
+ }
+ }
// If we are using the date popup widget, overwrite the settings of the form
// according to what date_popup expects.
- if ($this->options['widget_type'] == 'date_popup' && module_exists('date_popup')) {
+ elseif ($is_date_popup) {
$form['value']['#type'] = 'date_popup';
$form['value']['#date_format'] = $this->options['date_popup_format'];
$form['value']['#date_year_range'] = $this->options['year_range'];
@@ -109,17 +122,38 @@ class SearchApiViewsHandlerFilterDate extends SearchApiViewsHandlerFilter {
* Add this filter to the query.
*/
public function query() {
+ $this->normalizeValue();
+
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']);
}
- else {
- while (is_array($this->value)) {
- $this->value = $this->value ? reset($this->value) : NULL;
+ elseif (in_array($this->operator, array('between', 'not between'), TRUE)) {
+ $min = $this->value['min'];
+ if ($min !== '') {
+ $min = is_numeric($min) ? $min : strtotime($min, REQUEST_TIME);
}
- $v = is_numeric($this->value) ? $this->value : strtotime($this->value, REQUEST_TIME);
+ $max = $this->value['max'];
+ if ($max !== '') {
+ $max = is_numeric($max) ? $max : strtotime($max, REQUEST_TIME);
+ }
+
+ if (is_numeric($min) && is_numeric($max)) {
+ $this->query->condition($this->real_field, array($min, $max), strtoupper($this->operator), $this->options['group']);
+ }
+ elseif (is_numeric($min)) {
+ $operator = $this->operator === 'between' ? '>=' : '<';
+ $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
+ }
+ elseif (is_numeric($max)) {
+ $operator = $this->operator === 'between' ? '<=' : '>';
+ $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
+ }
+ }
+ else {
+ $v = is_numeric($this->value['value']) ? $this->value['value'] : strtotime($this->value['value'], REQUEST_TIME);
if ($v !== FALSE) {
$this->query->condition($this->real_field, $v, $this->operator, $this->options['group']);
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_fulltext.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_fulltext.inc
index 320adc36..dcb3e263 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_fulltext.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_fulltext.inc
@@ -121,6 +121,11 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
$words = preg_split('/\s+/', $input);
$quoted = FALSE;
foreach ($words as $i => $word) {
+ $word_length = drupal_strlen($word);
+ if (!$word_length) {
+ unset($words[$i]);
+ continue;
+ }
// Protect quoted strings.
if ($quoted && $word[strlen($word) - 1] === '"') {
$quoted = FALSE;
@@ -130,7 +135,7 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
$quoted = TRUE;
continue;
}
- if (drupal_strlen($word) < $this->options['min_length']) {
+ if ($word_length < $this->options['min_length']) {
unset($words[$i]);
}
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_language.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_language.inc
index a7de5f94..3202cdbc 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_language.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_language.inc
@@ -18,10 +18,13 @@ class SearchApiViewsHandlerFilterLanguage extends SearchApiViewsHandlerFilterOpt
*/
protected function get_value_options() {
parent::get_value_options();
- $this->value_options = array(
- 'current' => t("Current user's language"),
- 'default' => t('Default site language'),
- ) + $this->value_options;
+ $options = array();
+ if (module_exists('language_hierarchy')) {
+ $options['fallback'] = t("Current user's language with fallback");
+ }
+ $options['current'] = t("Current user's language");
+ $options['default'] = t('Default site language');
+ $this->value_options = $options + $this->value_options;
}
/**
@@ -40,6 +43,11 @@ class SearchApiViewsHandlerFilterLanguage extends SearchApiViewsHandlerFilterOpt
elseif ($v == 'default') {
$this->value[$i] = language_default('language');
}
+ elseif ($v == 'fallback' && module_exists('language_hierarchy')) {
+ $fallbacks = array($language_content->language => $language_content->language);
+ $fallbacks += array_keys(language_hierarchy_get_ancestors($language_content->language));
+ $this->value[$i] = drupal_map_assoc($fallbacks);
+ }
}
parent::query();
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc
new file mode 100644
index 00000000..b4c8ec19
--- /dev/null
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_numeric.inc
@@ -0,0 +1,248 @@
+normalizeValue();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function option_definition() {
+ $options = parent::option_definition();
+ $options['value'] = array(
+ 'contains' => array(
+ 'value' => array('default' => ''),
+ 'min' => array('default' => ''),
+ 'max' => array('default' => ''),
+ ),
+ );
+
+ return $options;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function operator_options() {
+ $operators = parent::operator_options();
+
+ $index = search_api_index_load(substr($this->table, 17));
+ $server = NULL;
+ try {
+ if ($index) {
+ $server = $index->server();
+ }
+ }
+ catch (SearchApiException $e) {
+ // Ignore.
+ }
+ if ($server && $server->supportsFeature('search_api_between')) {
+ $operators += array(
+ 'between' => t('Is between'),
+ 'not between' => t('Is not between'),
+ );
+ }
+
+ return $operators;
+ }
+
+ /**
+ * Provides a form for setting the filter value.
+ *
+ * Heavily borrowed from views_handler_filter_numeric.
+ *
+ * @see views_handler_filter_numeric::value_form()
+ */
+ public function value_form(&$form, &$form_state) {
+ $form['value']['#tree'] = TRUE;
+
+ $single_field_operators = $this->operator_options();
+ unset(
+ $single_field_operators['empty'],
+ $single_field_operators['not empty'],
+ $single_field_operators['between'],
+ $single_field_operators['not between']
+ );
+ $between_operators = array('between', 'not between');
+
+ // We have to make some choices when creating this as an exposed
+ // filter form. For example, if the operator is locked and thus
+ // not rendered, we can't render dependencies; instead we only
+ // render the form items we need.
+ $which = 'all';
+ $source = NULL;
+ if (!empty($form['operator'])) {
+ $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator';
+ }
+
+ $identifier = NULL;
+ if (!empty($form_state['exposed'])) {
+ $identifier = $this->options['expose']['identifier'];
+ if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
+ // Exposed and locked.
+ $which = in_array($this->operator, $between_operators) ? 'minmax' : 'value';
+ }
+ else {
+ $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']);
+ }
+ }
+
+ // 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.
+ if ($which == 'all') {
+ $form['value']['value'] = array(
+ '#type' => 'textfield',
+ '#title' => empty($form_state['exposed']) ? t('Value') : '',
+ '#size' => 30,
+ '#default_value' => $this->value['value'],
+ '#dependency' => array($source => array_keys($single_field_operators)),
+ );
+ if ($identifier && !isset($form_state['input'][$identifier]['value'])) {
+ $form_state['input'][$identifier]['value'] = $this->value['value'];
+ }
+ }
+ elseif ($which == 'value') {
+ // When exposed we drop the value-value and just do value if
+ // the operator is locked.
+ $form['value'] = array(
+ '#type' => 'textfield',
+ '#title' => empty($form_state['exposed']) ? t('Value') : '',
+ '#size' => 30,
+ '#default_value' => isset($this->value['value']) ? $this->value['value'] : '',
+ );
+ if ($identifier && !isset($form_state['input'][$identifier])) {
+ $form_state['input'][$identifier] = isset($this->value['value']) ? $this->value['value'] : '';
+ }
+ }
+
+ if ($which == 'all' || $which == 'minmax') {
+ $form['value']['min'] = array(
+ '#type' => 'textfield',
+ '#title' => empty($form_state['exposed']) ? t('Min') : '',
+ '#size' => 30,
+ '#default_value' => $this->value['min'],
+ );
+ $form['value']['max'] = array(
+ '#type' => 'textfield',
+ '#title' => empty($form_state['exposed']) ? t('And max') : t('And'),
+ '#size' => 30,
+ '#default_value' => $this->value['max'],
+ );
+
+ if ($which == 'all') {
+ $form['value']['min']['#dependency'] = array($source => $between_operators);
+ $form['value']['max']['#dependency'] = array($source => $between_operators);
+ }
+
+ if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min'])) {
+ $form_state['input'][$identifier]['min'] = $this->value['min'];
+ }
+ if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max'])) {
+ $form_state['input'][$identifier]['max'] = $this->value['max'];
+ }
+
+ if (!isset($form['value']['value'])) {
+ // Ensure there is something in the 'value'.
+ $form['value']['value'] = array(
+ '#type' => 'value',
+ '#value' => NULL,
+ );
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function admin_summary() {
+ if (!empty($this->options['exposed'])) {
+ return t('exposed');
+ }
+
+ if ($this->operator === 'empty') {
+ return t('is empty');
+ }
+ if ($this->operator === 'not empty') {
+ return t('is not empty');
+ }
+
+ if (in_array($this->operator, array('between', 'not between'), TRUE)) {
+ // This is of course wrong for translation purposes, but copied from
+ // views_handler_filter_numeric::admin_summary() so probably still better
+ // to re-use this than to do it correctly.
+ $operator = $this->operator === 'between' ? t('between') : t('not between');
+ $vars = array(
+ '@min' => (string) $this->value['min'],
+ '@max' => (string) $this->value['max'],
+ );
+ return $operator . ' ' . t('@min and @max', $vars);
+ }
+
+ return check_plain((string) $this->operator) . ' ' . check_plain((string) $this->value['value']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function query() {
+ $this->normalizeValue();
+
+ if (in_array($this->operator, array('between', 'not between'), TRUE)) {
+ $min = $this->value['min'];
+ $max = $this->value['max'];
+ if ($min !== '' && $max !== '') {
+ $this->query->condition($this->real_field, array($min, $max), strtoupper($this->operator), $this->options['group']);
+ }
+ elseif ($min !== '') {
+ $operator = $this->operator === 'between' ? '>=' : '<';
+ $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
+ }
+ elseif ($max !== '') {
+ $operator = $this->operator === 'between' ? '<=' : '>';
+ $this->query->condition($this->real_field, $min, $operator, $this->options['group']);
+ }
+ }
+ else {
+ // The parent handler doesn't expect our value structure, just pass the
+ // scalar value instead.
+ $this->value = $this->value['value'];
+ parent::query();
+ }
+ }
+
+ /**
+ * Sets $this->value to an array of options as defined by the filter.
+ *
+ * @see SearchApiViewsHandlerFilterNumeric::option_definition()
+ */
+ protected function normalizeValue() {
+ $value = $this->value;
+ if (is_array($value) && isset($value[0])) {
+ $value = $value[0];
+ }
+ if (!is_array($value)) {
+ $value = array('value' => $value);
+ }
+ $this->value = array(
+ 'value' => isset($value['value']) ? $value['value'] : '',
+ 'min' => isset($value['min']) ? $value['min'] : '',
+ 'max' => isset($value['max']) ? $value['max'] : '',
+ );
+ }
+
+}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_options.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_options.inc
index c63c07e7..2184fc85 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_options.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_options.inc
@@ -121,6 +121,7 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
*/
public function option_definition() {
$options = parent::option_definition();
+ $options['value'] = array('default' => '');
$options['expose']['contains']['reduce'] = array('default' => FALSE);
return $options;
}
@@ -256,6 +257,32 @@ class SearchApiViewsHandlerFilterOptions extends SearchApiViewsHandlerFilter {
return $operator . (($values !== '') ? ' ' . $values : '');
}
+ /**
+ * {@inheritdoc}
+ */
+ function accept_exposed_input($input) {
+ $accepted = parent::accept_exposed_input($input);
+
+ // Grouped filters will have the raw form values structure from the
+ // checkboxes as the value here. Convert that into the correct array of
+ // values instead.
+ if ($accepted && is_array($this->value) && $this->is_a_group()) {
+ // For some reason, Views thinks it's a good idea to nest the form values
+ // into a second array in some cases. That one will be numerically indexed
+ // with just a single entry, though, so it should be relatively easy to
+ // spot.
+ if (count($this->value) && isset($this->value[0])) {
+ $this->value = reset($this->value);
+ }
+ $this->value = array_keys(array_filter($this->value));
+ if (!$this->value) {
+ return FALSE;
+ }
+ }
+
+ return $accepted;
+ }
+
/**
* Add this filter to the query.
*/
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_taxonomy_term.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_taxonomy_term.inc
index f3317cfa..51982b0e 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_taxonomy_term.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/handler_filter_taxonomy_term.inc
@@ -321,9 +321,13 @@ class SearchApiViewsHandlerFilterTaxonomyTerm extends SearchApiViewsHandlerFilte
* {@inheritdoc}
*/
protected function ids_to_strings(array $ids) {
+ $ids = array_filter($ids);
+ if (!$ids) {
+ return '';
+ }
return implode(', ', db_select('taxonomy_term_data', 'td')
->fields('td', array('name'))
- ->condition('td.tid', array_filter($ids))
+ ->condition('td.tid', $ids)
->execute()
->fetchCol());
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_cache.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_cache.inc
index c6bd41d4..c63aed5e 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_cache.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_cache.inc
@@ -35,11 +35,16 @@ class SearchApiViewsCache extends views_plugin_cache_time {
}
$cid = $this->get_results_key();
+ $results = NULL;
+ $query_plugin = $this->view->query;
+ if ($query_plugin instanceof SearchApiViewsQuery) {
+ $results = $query_plugin->getSearchApiResults();
+ }
$data = array(
'result' => $this->view->result,
'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0,
'current_page' => $this->view->get_current_page(),
- 'search_api results' => $this->view->query->getSearchApiResults(),
+ 'search_api results' => $results,
);
cache_set($cid, $data, $this->table, $this->cache_set_expire($type));
}
@@ -80,7 +85,7 @@ class SearchApiViewsCache extends views_plugin_cache_time {
* Overrides views_plugin_cache::get_cache_key().
*
* Use the Search API query as the main source for the key. Note that in
- * Views < 3.8, this function does not exist.
+ * Views < 3.8, this method does not exist.
*/
public function get_cache_key($key_data = array()) {
global $user;
@@ -121,7 +126,7 @@ class SearchApiViewsCache extends views_plugin_cache_time {
}
/**
- * Get the Search API query object associated with the current view.
+ * Retrieves the Search API query object associated with the current view.
*
* @return SearchApiQueryInterface|null
* The Search API query object associated with the current view; or NULL if
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_content_cache.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_content_cache.inc
new file mode 100644
index 00000000..555fe89a
--- /dev/null
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/plugin_content_cache.inc
@@ -0,0 +1,146 @@
+get_results_key();
+ $results = NULL;
+ $query_plugin = $this->view->query;
+ if ($query_plugin instanceof SearchApiViewsQuery) {
+ $results = $query_plugin->getSearchApiResults();
+ }
+ $data = array(
+ 'result' => $this->view->result,
+ 'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0,
+ 'current_page' => $this->view->get_current_page(),
+ 'search_api results' => $results,
+ );
+ cache_set($cid, $data, $this->table, $this->cache_set_expire($type));
+ }
+
+ /**
+ * Overrides views_plugin_cache::cache_get().
+ *
+ * Additionally stores successfully retrieved results with
+ * search_api_current_search().
+ */
+ public function cache_get($type) {
+ if ($type != 'results') {
+ return parent::cache_get($type);
+ }
+
+ // Values to set: $view->result, $view->total_rows, $view->execute_time,
+ // $view->current_page.
+ if ($cache = cache_get($this->get_results_key(), $this->table)) {
+ $cutoff = $this->cache_expire($type);
+ if (!$cutoff || $cache->created > $cutoff) {
+ $this->view->result = $cache->data['result'];
+ $this->view->total_rows = $cache->data['total_rows'];
+ $this->view->set_current_page($cache->data['current_page']);
+ $this->view->execute_time = 0;
+
+ // Trick Search API into believing a search happened, to make facetting
+ // et al. work.
+ $query = $this->getSearchApiQuery();
+ search_api_current_search($query->getOption('search id'), $query, $cache->data['search_api results']);
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
+ /**
+ * Overrides views_plugin_cache::get_cache_key().
+ *
+ * Use the Search API query as the main source for the key. Note that in
+ * Views < 3.8, this method does not exist.
+ */
+ public function get_cache_key($key_data = array()) {
+ global $user;
+
+ if (!isset($this->_results_key)) {
+ $query = $this->getSearchApiQuery();
+ $query->preExecute();
+ $key_data += array(
+ 'query' => $query,
+ 'roles' => array_keys($user->roles),
+ 'super-user' => $user->uid == 1, // special caching for super user.
+ 'language' => $GLOBALS['language']->language,
+ 'base_url' => $GLOBALS['base_url'],
+ 'offset' => $this->view->get_current_page() . '*' . $this->view->get_items_per_page() . '+' . $this->view->get_offset(),
+ );
+ // Not sure what gets passed in exposed_info, so better include it. All
+ // 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['exposed_info'] = $_GET['exposed_info'];
+ }
+ }
+ $key = drupal_hash_base64(serialize($key_data));
+ return $key;
+ }
+
+ /**
+ * Overrides views_plugin_cache::get_results_key().
+ *
+ * This is unnecessary for Views >= 3.8.
+ */
+ public function get_results_key() {
+ if (!isset($this->_results_key)) {
+ $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . $this->get_cache_key();
+ }
+
+ return $this->_results_key;
+ }
+
+ /**
+ * Retrieves the Search API query object associated with the current view.
+ *
+ * @return SearchApiQueryInterface|null
+ * The Search API query object associated with the current view; or NULL if
+ * there is none.
+ */
+ protected function getSearchApiQuery() {
+ if (!isset($this->search_api_query)) {
+ $this->search_api_query = FALSE;
+ if (isset($this->view->query) && $this->view->query instanceof SearchApiViewsQuery) {
+ $this->search_api_query = $this->view->query->getSearchApiQuery();
+ }
+ }
+
+ return $this->search_api_query ? $this->search_api_query : NULL;
+ }
+
+}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/query.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/query.inc
index 4394c5f3..ae58b9a7 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/query.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/includes/query.inc
@@ -135,7 +135,9 @@ class SearchApiViewsQuery extends views_plugin_query {
* The order to sort items in - either 'ASC' or 'DESC'. Defaults to 'ASC'.
*/
public function add_selector_orderby($selector, $order = 'ASC') {
- $this->query->sort($selector, $order);
+ if (!$this->errors) {
+ $this->query->sort($selector, $order);
+ }
}
/**
@@ -213,7 +215,7 @@ class SearchApiViewsQuery extends views_plugin_query {
'#default_value' => $this->options['search_api_bypass_access'],
);
- if ($this->index->getEntityType()) {
+ if ($this->index && $this->index->getEntityType()) {
$form['entity_access'] = array(
'#type' => 'checkbox',
'#title' => t('Additional access checks on result entities'),
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.info b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.info
index 2ba7ccaa..2f0bfd72 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.info
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.info
@@ -1,7 +1,7 @@
-name = Search views
+name = Search Views
description = Integrates the Search API with Views, enabling users to create views with searches as filters or arguments.
-dependencies[] = search_api
-dependencies[] = views
+dependencies[] = search_api:search_api
+dependencies[] = views:views
core = 7.x
package = Search
@@ -19,17 +19,18 @@ files[] = includes/handler_filter_date.inc
files[] = includes/handler_filter_entity.inc
files[] = includes/handler_filter_fulltext.inc
files[] = includes/handler_filter_language.inc
+files[] = includes/handler_filter_numeric.inc
files[] = includes/handler_filter_options.inc
files[] = includes/handler_filter_taxonomy_term.inc
files[] = includes/handler_filter_text.inc
files[] = includes/handler_filter_user.inc
files[] = includes/handler_sort.inc
files[] = includes/plugin_cache.inc
+files[] = includes/plugin_content_cache.inc
files[] = includes/query.inc
-; Information added by Drupal.org packaging script on 2017-02-23
-version = "7.x-1.21"
+; Information added by Drupal.org packaging script on 2019-03-11
+version = "7.x-1.26"
core = "7.x"
project = "search_api"
-datestamp = "1487844493"
-
+datestamp = "1552334832"
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.module b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.module
index 62fcb944..a927f082 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.module
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.module
@@ -27,8 +27,11 @@ function search_api_views_search_api_index_insert() {
*/
function search_api_views_search_api_index_update(SearchApiIndex $index) {
// Check whether index was disabled.
- if (!$index->enabled && $index->original->enabled) {
+ $is_enabled = $index->enabled;
+ $was_enabled = $index->original->enabled;
+ if (!$is_enabled && $was_enabled) {
_search_api_views_index_unavailable($index);
+ return;
}
// Check whether the indexed fields changed.
@@ -36,7 +39,9 @@ function search_api_views_search_api_index_update(SearchApiIndex $index) {
$old_fields = $old_fields['fields'];
$new_fields = $index->options + array('fields' => array());
$new_fields = $new_fields['fields'];
- if ($old_fields != $new_fields) {
+
+ // If the index was enabled or its fields changed, invalidate the Views cache.
+ if ($is_enabled != $was_enabled || $old_fields != $new_fields) {
views_invalidate_cache();
}
}
diff --git a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.views.inc b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.views.inc
index ff52d692..afec2d86 100644
--- a/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.views.inc
+++ b/sites/all/modules/contrib/search/search_api/contrib/search_api_views/search_api_views.views.inc
@@ -99,6 +99,7 @@ function search_api_views_views_data() {
$table['search_api_relevance']['title'] = t('Relevance');
$table['search_api_relevance']['help'] = t('The relevance of this search result with respect to the query.');
$table['search_api_relevance']['field']['type'] = 'decimal';
+ $table['search_api_relevance']['field']['float'] = TRUE;
$table['search_api_relevance']['field']['handler'] = 'entity_views_handler_field_numeric';
$table['search_api_relevance']['field']['click sortable'] = TRUE;
$table['search_api_relevance']['sort']['handler'] = 'SearchApiViewsHandlerSort';
@@ -219,6 +220,9 @@ function _search_api_views_add_handlers($id, array $field, EntityMetadataWrapper
$table[$id]['filter']['vocabulary'] = $vocabulary;
}
}
+ elseif (in_array($inner_type, array('integer', 'decimal', 'duration', 'string'))) {
+ $table[$id]['filter']['handler'] = 'SearchApiViewsHandlerFilterNumeric';
+ }
else {
$table[$id]['filter']['handler'] = 'SearchApiViewsHandlerFilter';
}
@@ -285,6 +289,16 @@ function search_api_views_views_plugins() {
);
}
+ if (module_exists('views_content_cache')) {
+ $ret['cache']['search_api_views_content_cache'] = array(
+ 'title' => t('Search-specific content-based'),
+ 'help' => t("Cache Search API views based on content updates. (Requires Views Content Cache)"),
+ 'base' => $bases,
+ 'handler' => 'SearchApiViewsContentCache',
+ 'uses options' => TRUE,
+ );
+ }
+
return $ret;
}
diff --git a/sites/all/modules/contrib/search/search_api/includes/callback_add_aggregation.inc b/sites/all/modules/contrib/search/search_api/includes/callback_add_aggregation.inc
index 069c4107..55ed611c 100644
--- a/sites/all/modules/contrib/search/search_api/includes/callback_add_aggregation.inc
+++ b/sites/all/modules/contrib/search/search_api/includes/callback_add_aggregation.inc
@@ -20,11 +20,23 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
*/
protected $reductionType;
+ /**
+ * A separator to use when the aggregation type is 'fulltext'.
+ *
+ * Used to temporarily store a string separator when the aggregation type is
+ * "fulltext", for use in SearchApiAlterAddAggregation::reduce() with
+ * array_reduce().
+ *
+ * @var string
+ */
+ protected $fulltextReductionSeparator;
+
public function configurationForm() {
$form['#attached']['css'][] = drupal_get_path('module', 'search_api') . '/search_api.admin.css';
$fields = $this->index->getFields(FALSE);
$field_options = array();
+ $field_properties = array();
foreach ($fields as $name => $field) {
$field_options[$name] = check_plain($field['name']);
$field_properties[$name] = array(
@@ -79,9 +91,23 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
'#required' => TRUE,
);
$form['fields'][$name]['type_descriptions'] = $type_descriptions;
+ $type_selector = ':input[name="callbacks[search_api_alter_add_aggregation][settings][fields][' . $name . '][type]"]';
foreach (array_keys($types) as $type) {
- $form['fields'][$name]['type_descriptions'][$type]['#states']['visible'][':input[name="callbacks[search_api_alter_add_aggregation][settings][fields][' . $name . '][type]"]']['value'] = $type;
+ $form['fields'][$name]['type_descriptions'][$type]['#states']['visible'][$type_selector]['value'] = $type;
}
+ $form['fields'][$name]['separator'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Fulltext separator'),
+ '#description' => t('For aggregation type "Fulltext", set the text that should be used to separate the aggregated field values. Use "\t" for tabs and "\n" for newline characters.'),
+ '#default_value' => addcslashes(isset($field['separator']) ? $field['separator'] : "\n\n", "\0..\37\\"),
+ '#states' => array(
+ 'visible' => array(
+ $type_selector => array(
+ 'value' => 'fulltext',
+ ),
+ ),
+ ),
+ );
$form['fields'][$name]['fields'] = array_merge($field_properties, array(
'#type' => 'checkboxes',
'#title' => t('Contained fields'),
@@ -125,11 +151,12 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
return;
}
foreach ($values['fields'] as $name => $field) {
- $fields = $values['fields'][$name]['fields'] = array_values(array_filter($field['fields']));
unset($values['fields'][$name]['actions']);
+ $fields = $values['fields'][$name]['fields'] = array_values(array_filter($field['fields']));
if ($field['name'] && !$fields) {
form_error($form['fields'][$name]['fields'], t('You have to select at least one field to aggregate. If you want to remove an aggregated field, please delete its name.'));
}
+ $values['fields'][$name]['separator'] = stripcslashes($field['separator']);
}
}
@@ -176,6 +203,7 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
$values = $this->flattenArray($values);
$this->reductionType = $field['type'];
+ $this->fulltextReductionSeparator = isset($field['separator']) ? $field['separator'] : "\n\n";
$item->$name = array_reduce($values, array($this, 'reduce'), NULL);
if ($field['type'] == 'count' && !$item->$name) {
$item->$name = 0;
@@ -192,7 +220,7 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
public function reduce($a, $b) {
switch ($this->reductionType) {
case 'fulltext':
- return isset($a) ? $a . "\n\n" . $b : $b;
+ return isset($a) ? $a . $this->fulltextReductionSeparator . $b : $b;
case 'sum':
return $a + $b;
case 'count':
@@ -300,10 +328,10 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
'count' => 'integer',
'max' => 'integer',
'min' => 'integer',
- 'first' => 'string',
- 'first_char' => 'string',
- 'last' => 'string',
- 'list' => 'list ' . t('Optionally, provide an exclusion list to override the stemmer algorithm. Read about the algorithm and exclusions.', $args) . ' ' . t('Optionally, provide an exclusion list to override the stemmer algorithm. (Read about the algorithm.)', $args) . ' ' . t("Select processors which will pre- and post-process data at index and search time, and their order. Most processors will only influence fulltext fields, but refer to their individual descriptions for details regarding their effect. ' . t("Check the server's service class description for details.",
+ array('@server-url' => url('admin/config/search/search_api/server/' . $index->server . '/edit'))) . '
Also, some processors shouldn't be used with more advanced search engines (like Solr or Elasticsearch), since the search engine already provides this functionality.") . '
' . t('Check the ' . "server's service class description for details.", - array('@server-url' => url('admin/config/search/search_api/server/' . $index->server))) . '
'; + $form['description']['#description'] .= '' . t("Check the server's service class description for details.", + array('@server-url' => url('admin/config/search/search_api/server/' . $index->server . '/edit'))) . '
'; } foreach ($fields as $key => $info) { $form['fields'][$key]['title']['#markup'] = check_plain($info['name']); diff --git a/sites/all/modules/contrib/search/search_api/search_api.drush.inc b/sites/all/modules/contrib/search/search_api/search_api.drush.inc index 61957b9a..8c995b17 100644 --- a/sites/all/modules/contrib/search/search_api/search_api.drush.inc +++ b/sites/all/modules/contrib/search/search_api/search_api.drush.inc @@ -95,6 +95,18 @@ function search_api_drush_command() { 'aliases' => array('sapi-r'), ); + $items['search-api-reindex-items'] = array( + 'description' => 'Force re-indexing of one or more specific items.', + 'examples' => array( + 'drush search-api-reindex-items node 12,34,56' => dt('Schedule the nodes with ID 12, 34 and 56 for re-indexing.'), + ), + 'arguments' => array( + 'entity_type' => dt('The entity type whose items should be re-indexed.'), + 'entities' => dt('The entities of the given entity type to be re-indexed.'), + ), + 'aliases' => array('sapi-ri'), + ); + $items['search-api-clear'] = array( 'description' => 'Clear one or all search indexes and mark them for re-indexing.', 'examples' => array( @@ -109,6 +121,19 @@ function search_api_drush_command() { 'aliases' => array('sapi-c'), ); + $items['search-api-execute-tasks'] = array( + 'description' => 'Execute all pending tasks or all for a given server.', + 'examples' => array( + 'drush search-api-execute-tasks my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')), + 'drush sapi-et my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')), + 'drush sapi-et' => dt('Execute all pending tasks on all servers.') + ), + 'arguments' => array( + 'server_id' => dt('The numeric ID or machine name of a server to execute tasks on.'), + ), + 'aliases' => array('sapi-et') + ); + $items['search-api-set-index-server'] = array( 'description' => 'Set the search server used by a given index.', 'examples' => array( @@ -448,6 +473,33 @@ function drush_search_api_reindex($index_id = NULL) { } } +/** + * Marks the given entities as needing to be re-indexed. + */ +function drush_search_api_reindex_items($entity_type, $entities) { + if (search_api_drush_static(__FUNCTION__)) { + return; + } + + // Validate list of entity ids. + if (!empty($entities) && !preg_match('#^[0-9]*(,[0-9]*)*$#', $entities)) { + drush_log(dt('Entities should be a single numeric entity ID or a list with the numeric entity IDs separated by comma.'), 'error'); + return; + } + + $ids = explode(',', $entities); + + if (!empty($ids)) { + search_api_track_item_change($entity_type, $ids); + + $combined_ids = array(); + foreach ($ids as $id) { + $combined_ids[] = $entity_type . '/' . $id; + } + search_api_track_item_change('multiple', $combined_ids); + } +} + /** * Clear an index. */ @@ -466,6 +518,34 @@ function drush_search_api_clear($index_id = NULL) { } } +/** + * Execute all pending tasks or all for a given server. + */ +function drush_search_api_execute_tasks($server_id = NULL) { + if (search_api_drush_static(__FUNCTION__)) { + return; + } + + // Attempt to load the associated server. + $server = NULL; + if ($server_id) { + $servers = search_api_drush_get_server($server_id); + if (!$servers) { + return; + } + $server = reset($servers); + } + + // Process batch op with drush. + try { + search_api_execute_pending_tasks($server); + drush_log(dt('!server tasks have been successfully executed.', array('!server' => $server->machine_name ? $server->machine_name : 'All')), 'ok'); + } + catch (SearchApiException $e) { + drush_log($e->getMessage(), 'error'); + } +} + /** * Set the server for a given index. */ diff --git a/sites/all/modules/contrib/search/search_api/search_api.info b/sites/all/modules/contrib/search/search_api/search_api.info index e7317531..b59bc929 100644 --- a/sites/all/modules/contrib/search/search_api/search_api.info +++ b/sites/all/modules/contrib/search/search_api/search_api.info @@ -1,6 +1,6 @@ name = Search API description = "Provides a generic API for modules offering search capabilities." -dependencies[] = entity +dependencies[] = entity:entity core = 7.x package = Search @@ -16,6 +16,7 @@ files[] = includes/callback_language_control.inc files[] = includes/callback_node_access.inc files[] = includes/callback_node_status.inc files[] = includes/callback_role_filter.inc +files[] = includes/callback_user_content.inc files[] = includes/callback_user_status.inc files[] = includes/datasource.inc files[] = includes/datasource_entity.inc @@ -37,9 +38,8 @@ files[] = includes/service.inc configure = admin/config/search/search_api -; Information added by Drupal.org packaging script on 2017-02-23 -version = "7.x-1.21" +; Information added by Drupal.org packaging script on 2019-03-11 +version = "7.x-1.26" core = "7.x" project = "search_api" -datestamp = "1487844493" - +datestamp = "1552334832" diff --git a/sites/all/modules/contrib/search/search_api/search_api.install b/sites/all/modules/contrib/search/search_api/search_api.install index 5dc26895..61f686d7 100644 --- a/sites/all/modules/contrib/search/search_api/search_api.install +++ b/sites/all/modules/contrib/search/search_api/search_api.install @@ -264,6 +264,51 @@ function search_api_schema() { return $schema; } +/** + * Implements hook_requirements(). + */ +function search_api_requirements($phase) { + $requirements = array(); + + if ($phase == 'runtime') { + // Check whether at least one server has pending tasks. + if (search_api_server_tasks_count()) { + $items = array(); + + $conditions = array('enabled' => TRUE); + foreach (search_api_server_load_multiple(FALSE, $conditions) as $server) { + $count = search_api_server_tasks_count($server); + if ($count) { + $args = array( + '@name' => $server->name, + ); + $text = format_plural($count, '@name has @count pending task.', '@name has @count pending tasks.', $args); + $items[] = l($text, "admin/config/search/search_api/server/{$server->machine_name}/execute-tasks"); + } + } + + if ($items) { + $text = t('There are pending tasks for the following servers:'); + $text .= theme('item_list', array( + 'type' => 'ul', + 'items' => $items, + )); + if (count($items) > 1) { + $label = t('Execute pending tasks on all servers'); + $text .= l($label, 'admin/config/search/search_api/execute-tasks'); + } + $requirements['search_api_pending_tasks'] = array( + 'title' => t('Search API'), + 'value' => $text, + 'severity' => REQUIREMENT_WARNING, + ); + } + } + } + + return $requirements; +} + /** * Implements hook_install(). * diff --git a/sites/all/modules/contrib/search/search_api/search_api.module b/sites/all/modules/contrib/search/search_api/search_api.module index 61385c5d..c1cf4e4b 100644 --- a/sites/all/modules/contrib/search/search_api/search_api.module +++ b/sites/all/modules/contrib/search/search_api/search_api.module @@ -72,6 +72,15 @@ function search_api_menu() { 'type' => MENU_LOCAL_TASK, 'context' => MENU_CONTEXT_INLINE | MENU_CONTEXT_PAGE, ); + $items[$pre . '/server/%search_api_server/execute-tasks'] = array( + 'title' => 'Execute pending tasks', + 'description' => 'Attempt to process pending tasks for a given server.', + 'page callback' => 'search_api_execute_pending_tasks', + 'page arguments' => array(5), + 'access callback' => 'search_api_access_execute_tasks_batch', + 'access arguments' => array(5), + 'type' => MENU_CALLBACK, + ); $items[$pre . '/server/%search_api_server/disable'] = array( 'title' => 'Disable', 'description' => 'Disable index.', @@ -98,6 +107,13 @@ function search_api_menu() { 'context' => MENU_CONTEXT_INLINE, 'weight' => 10, ); + $items[$pre . '/execute-tasks'] = array( + 'title' => 'Execute pending tasks', + 'description' => 'Attempt to process pending server tasks.', + 'page callback' => 'search_api_execute_pending_tasks', + 'access callback' => 'search_api_access_execute_tasks_batch', + 'type' => MENU_LOCAL_ACTION, + ); $items[$pre . '/index/%search_api_index'] = array( 'title' => 'View index', 'title callback' => 'search_api_admin_item_title', @@ -1025,6 +1041,28 @@ function search_api_search_api_item_type_info() { return $types; } +/** + * Implements hook_module_implements_alter(). + * + * Ensures the item type and service class static caches are invalidated at the + * right time. + */ +function search_api_module_implements_alter(array &$implementations, $hook) { + switch ($hook) { + case 'modules_enabled': + $group = $implementations['search_api']; + unset($implementations['search_api']); + $implementations = array('search_api' => $group) + $implementations; + break; + + case 'modules_disabled': + $group = $implementations['search_api']; + unset($implementations['search_api']); + $implementations['search_api'] = $group; + break; + } +} + /** * Implements hook_modules_enabled(). */ @@ -1103,6 +1141,11 @@ function search_api_search_api_alter_callback_info() { 'description' => t('Exclude unpublished nodes from the index. Caution: This only affects the indexed nodes themselves. If an enabled node has references to disabled nodes, those will still be indexed (or displayed) normally.'), 'class' => 'SearchApiAlterNodeStatus', ); + $callbacks['search_api_alter_user_content'] = array( + 'name' => t('Add user content'), + 'description' => t('Allows indexing of nodes (and their fields) created by the indexed user. (Caution: This might lead to performance problems, or even errors during indexing, on larger sites.)'), + 'class' => 'SearchApiAlterAddUserContent', + ); $callbacks['search_api_alter_user_status'] = array( 'name' => t('Exclude blocked users'), 'description' => t('Exclude blocked users from the index. Caution: This only affects the indexed users themselves. If an active user account includes a reference to a disabled user, that reference will still be indexed (or displayed) normally.'), @@ -1382,6 +1425,10 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) { // Sometimes the order of tasks might be important, so make sure to order by // the task ID (which should be in order of insertion). $select->orderBy('t.id'); + // Only retrieve and execute 100 tasks at once, to avoid running out of memory + // or time. We just can't do anything else until all tasks have been resolved, + // but at least we shouldn't crash sites, or keep piling up tasks, that way. + $select->range(0, 100); $tasks = $select->execute(); $executed_tasks = array(); @@ -1429,7 +1476,7 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) { default: // This should never happen. - continue; + continue 2; } $executed_tasks[] = $task->id; } @@ -1438,11 +1485,116 @@ function search_api_server_tasks_check(SearchApiServer $server = NULL) { if (!$executed_tasks) { return TRUE; } - // Otherwise, delete the executed tasks and check if new tasks were created. + // Otherwise, delete the executed tasks and check if new tasks were created + // (or if we didn't even fetch all due to the 100 tasks limit). search_api_server_tasks_delete($executed_tasks); return $count_query->execute()->fetchField() === 0; } +/** + * Provides a batch wrapper for search_api_server_tasks_check(). + * + * @param SearchApiServer|null $server + * (optional) The server whose tasks should be executed, or NULL to execute + * tasks for all servers. + */ +function search_api_execute_pending_tasks(SearchApiServer $server = NULL) { + batch_set(array( + 'title' => t('Processing pending tasks'), + 'operations' => array( + array( + 'search_api_execute_pending_tasks_batch', + array( + $server, + ), + ), + ), + 'finished' => 'search_api_execute_pending_tasks_finished' + )); + if ($server) { + $path = 'admin/config/search/search_api/server/' . $server->machine_name; + } + else { + $path = 'admin/config/search/search_api'; + } + + if (function_exists('drush_backend_batch_process')) { + drush_backend_batch_process(); + } + else { + batch_process($path); + } +} + +/** + * Executes pending server tasks as part of a batch operation. + */ +function search_api_execute_pending_tasks_batch(SearchApiServer $server = NULL, &$context) { + if (!isset($context['results']['total'])) { + $context['results']['total'] = search_api_server_tasks_count($server); + } + $total = $context['results']['total']; + + search_api_server_tasks_check($server); + + $remaining = search_api_server_tasks_count($server); + $executed = max($total - $remaining, 0); + + $args['@remaining'] = $remaining; + $context['message'] = format_plural($executed, 'Successfully executed @count task, @remaining remaining.', 'Successfully executed @count tasks, @remaining remaining.', $args); + $context['finished'] = $executed / $total; +} + +/** + * Batch finish callback for pending server tasks. + */ +function search_api_execute_pending_tasks_finished($success, $results, $operations) { + if ($success) { + // Clear the previous warning. + drupal_get_messages('warning'); + + // Alert user to the number of tasks executed. + drupal_set_message(format_plural($results['total'], 'Successfully executed @count task.', 'Successfully executed @count tasks.')); + } +} + +/** + * Return the number of pending tasks. + * + * @param SearchApiServer|null $server + * (optional) The server for which tasks should be counted, or NULL to count + * for all enabled servers. + * + * @return int + * The number of pending tasks for the server, or in total. + */ +function search_api_server_tasks_count(SearchApiServer $server = NULL) { + $query = db_select('search_api_task', 't') + ->fields('t'); + + if ($server) { + $query->condition('server_id', $server->machine_name); + } + else { + $query->join('search_api_server', 's', 's.machine_name = t.server_id'); + $query->condition('s.enabled', 1); + } + + return $query->countQuery()->execute()->fetchField(); +} + +/** + * Access callback: Checks whether a user can execute pending tasks. + * + * @param SearchApiServer|null $server + * (optional) The server for which tasks would be executed. + */ +function search_api_access_execute_tasks_batch(SearchApiServer $server = NULL) { + return user_access('administer search_api') + && search_api_server_tasks_count($server) + && (!$server || $server->enabled); +} + /** * Adds an entry into a server's list of pending tasks. * diff --git a/sites/all/modules/contrib/search/search_api/search_api.test b/sites/all/modules/contrib/search/search_api/search_api.test index 23f36bcf..76a89705 100644 --- a/sites/all/modules/contrib/search/search_api/search_api.test +++ b/sites/all/modules/contrib/search/search_api/search_api.test @@ -86,6 +86,7 @@ class SearchApiWebTest extends DrupalWebTestCase { * and then run tests on it. */ public function testFramework() { + module_enable(array('search_api_test_2')); $this->drupalLogin($this->drupalCreateUser(array('administer search_api'))); $this->insertItems(); $this->createIndex(); @@ -730,13 +731,17 @@ class SearchApiWebTest extends DrupalWebTestCase { * deleteServer()) and that all associated tables and variables are removed. */ protected function disableModules() { + module_disable(array('search_api_test_2'), FALSE); + $this->assertFalse(module_exists('search_api_test_2'), 'Second test module was successfully disabled.'); module_disable(array('search_api_test'), FALSE); - $this->assertFalse(module_exists('search_api_test'), 'Test module was successfully disabled.'); + $this->assertFalse(module_exists('search_api_test'), 'First test module was successfully disabled.'); module_disable(array('search_api'), FALSE); $this->assertFalse(module_exists('search_api'), 'Search API module was successfully disabled.'); + drupal_uninstall_modules(array('search_api_test_2'), FALSE); + $this->assertEqual(drupal_get_installed_schema_version('search_api_test_2', TRUE), SCHEMA_UNINSTALLED, 'Second test module was successfully uninstalled.'); drupal_uninstall_modules(array('search_api_test'), FALSE); - $this->assertEqual(drupal_get_installed_schema_version('search_api_test', TRUE), SCHEMA_UNINSTALLED, 'Test module was successfully uninstalled.'); + $this->assertEqual(drupal_get_installed_schema_version('search_api_test', TRUE), SCHEMA_UNINSTALLED, 'First test module was successfully uninstalled.'); $this->assertFalse(db_table_exists('search_api_test'), 'Test module table was successfully removed.'); drupal_uninstall_modules(array('search_api'), FALSE); $this->assertEqual(drupal_get_installed_schema_version('search_api', TRUE), SCHEMA_UNINSTALLED, 'Search API module was successfully uninstalled.'); diff --git a/sites/all/modules/contrib/search/search_api/tests/search_api_test.info b/sites/all/modules/contrib/search/search_api/tests/search_api_test.info index 95c999ab..2c5f46e0 100644 --- a/sites/all/modules/contrib/search/search_api/tests/search_api_test.info +++ b/sites/all/modules/contrib/search/search_api/tests/search_api_test.info @@ -1,18 +1,16 @@ - -name = Search API test +name = Search API Test description = "Some dummy implementations for testing the Search API." core = 7.x package = Search -dependencies[] = search_api +dependencies[] = search_api:search_api files[] = search_api_test.module hidden = TRUE -; Information added by Drupal.org packaging script on 2017-02-23 -version = "7.x-1.21" +; Information added by Drupal.org packaging script on 2019-03-11 +version = "7.x-1.26" core = "7.x" project = "search_api" -datestamp = "1487844493" - +datestamp = "1552334832" diff --git a/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.info b/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.info new file mode 100644 index 00000000..5d36c8fb --- /dev/null +++ b/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.info @@ -0,0 +1,16 @@ +name = Search API Test Service 2 +description = "A module providing a second test search service." +core = 7.x +package = Search + +dependencies[] = search_api:search_api + +files[] = search_api_test_service_2.module + +hidden = TRUE + +; Information added by Drupal.org packaging script on 2019-03-11 +version = "7.x-1.26" +core = "7.x" +project = "search_api" +datestamp = "1552334832" diff --git a/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.module b/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.module new file mode 100644 index 00000000..d78a80eb --- /dev/null +++ b/sites/all/modules/contrib/search/search_api/tests/search_api_test_2.module @@ -0,0 +1,136 @@ + $name, + 'description' => 'search_api_test_service_2 description', + 'class' => 'SearchApiDummyService', + ); + return $services; +} + +/** + * Implements hook_default_search_api_server(). + */ +function search_api_test_2_default_search_api_server() { + $id = 'test_server_2'; + $items[$id] = entity_create('search_api_server', array( + 'name' => 'Search API test server 2', + 'machine_name' => $id, + 'enabled' => 1, + 'description' => 'A server used for testing.', + 'class' => 'search_api_test_service_2', + )); + return $items; +} + +/** + * Dummy service for testing. + */ +class SearchApiDummyService implements SearchApiServiceInterface { + + /** + * {@inheritdoc} + */ + public function __construct(\SearchApiServer $server) {} + + /** + * {@inheritdoc} + */ + public function configurationForm(array $form, array &$form_state) { + return array(); + } + + /** + * {@inheritdoc} + */ + public function configurationFormValidate(array $form, array &$values, array &$form_state) {} + + /** + * {@inheritdoc} + */ + public function configurationFormSubmit(array $form, array &$values, array &$form_state) {} + + /** + * {@inheritdoc} + */ + public function supportsFeature($feature) { + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function viewSettings() { + return array(); + } + + /** + * {@inheritdoc} + */ + public function postCreate() {} + + /** + * {@inheritdoc} + */ + public function postUpdate() { + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function preDelete() {} + + /** + * {@inheritdoc} + */ + public function addIndex(SearchApiIndex $index) {} + + /** + * {@inheritdoc} + */ + public function fieldsUpdated(SearchApiIndex $index) { + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function removeIndex($index) {} + + /** + * {@inheritdoc} + */ + public function indexItems(SearchApiIndex $index, array $items) { + return array(); + } + + /** + * {@inheritdoc} + */ + public function deleteItems($ids = 'all', SearchApiIndex $index = NULL) {} + + /** + * {@inheritdoc} + */ + public function query(SearchApiIndex $index, $options = array()) { + throw new SearchApiException("The dummy service doesn't support queries"); + } + + /** + * {@inheritdoc} + */ + public function search(SearchApiQueryInterface $query) { + return array(); + } +} diff --git a/sites/all/modules/contrib/search/search_api_solr_overrides/README.txt b/sites/all/modules/contrib/search/search_api_solr_overrides/README.txt index 9ddedd2d..f13e5e80 100644 --- a/sites/all/modules/contrib/search/search_api_solr_overrides/README.txt +++ b/sites/all/modules/contrib/search/search_api_solr_overrides/README.txt @@ -1 +1,39 @@ -See major version branches. +INTRODUCTION +------------ +Allows you to override solr connection settings on an environment (site) basis, +via your settings.php without editing servers managed in features. + +REQUIREMENTS +------------ +* search_api_solr module + +CONFIGURATION +------------- +The module has no menu or modifiable settings. There is no configuration. When +enabled, you can set your override values in your settings.php file. +Search api will automatically pick up your values, but make sure to clear your +cache first. + +EXAMPLE +------- +You can add following example to your settings.php file. + +$conf['search_api_solr_overrides'] = array( + 'solr-server-id' => array( + 'name' => 'Solr Server (Overridden)', + 'options' => array( + 'host' => '127.0.0.1', + 'port' => 8983, + 'path' => '/solr', + ), + ), +); + +MAINTAINERS +----------- +Current maintainers: +* nick_schuch - https://www.drupal.org/u/nick_schuch +* cafuego - https://www.drupal.org/u/cafuego + +This project has been sponsored by: +* PreviousNext - http://www.previousnext.com.au diff --git a/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.info b/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.info index 58a03527..1da542fb 100644 --- a/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.info +++ b/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.info @@ -3,9 +3,9 @@ description = Provides site specific overrides for search_api_solr configuration core = 7.x dependencies[] = search_api_solr -; Information added by drupal.org packaging script on 2013-10-01 -version = "7.x-1.0-rc1+1-dev" +; Information added by Drupal.org packaging script on 2017-06-13 +version = "7.x-1.0" core = "7.x" project = "search_api_solr_overrides" -datestamp = "1380626863" +datestamp = "1497319149" diff --git a/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.module b/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.module old mode 100644 new mode 100755 index e83dfcc1..515faf87 --- a/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.module +++ b/sites/all/modules/contrib/search/search_api_solr_overrides/search_api_solr_overrides.module @@ -15,7 +15,7 @@ * Example: * $conf['search_api_solr_overrides'] = array( * 'solr-server-id' => array( - * 'name' => t('Solr Server (Overridden)'), + * 'name' => 'Solr Server (Overridden)', * 'options' => array( * 'host' => '127.0.0.1', * 'port' => 8983, @@ -32,7 +32,7 @@ function search_api_solr_overrides_search_api_server_load($servers) { $overrides = variable_get('search_api_solr_overrides', FALSE); // Ensure the is information provided. - if (empty($overrides)) { + if (empty($overrides) || !is_array($overrides)) { return; } @@ -41,12 +41,12 @@ function search_api_solr_overrides_search_api_server_load($servers) { // Check to see if the server config exists. if (!empty($servers[$id])) { foreach ($servers[$id] as $key => $field) { - // Ensure we need to override. - if (empty($override[$key])) { + // Ensure we need to override. User isset, so we can set FALSE values. + if (!isset($override[$key])) { continue; } - // Check for if the field is an array. + // Check if the field contains an array. if (is_array($field)) { $servers[$id]->$key = array_merge($servers[$id]->$key, $override[$key]); }