commit 4003efde387d38d60fdfbc7d6fa9fefc587b05ce
Author: Assos Assos <assos+forge@centrale-marseille.fr>
Date:   Wed Mar 11 23:12:15 2020 +0100

    Weekly update of contrib modules

diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_area_result.inc b/drupal7/sites/all/modules/views/handlers/views_handler_area_result.inc
index 6c98c0e7..dd51bf17 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_area_result.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_area_result.inc
@@ -102,7 +102,10 @@ class views_handler_area_result extends views_handler_area {
     }
     // Send the output.
     if (!empty($total) || !empty($this->options['empty'])) {
-      $output .= filter_xss_admin(str_replace(array_keys($replacements), array_values($replacements), $format));
+      // We don't want to sanitize with filter_xss_admin() here because Views
+      // administrators are trusted users and should be allowed to insert
+      // arbitrary markup.
+      $output .= str_replace(array_keys($replacements), array_values($replacements), $format);
     }
     return $output;
   }
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_argument_string.inc b/drupal7/sites/all/modules/views/handlers/views_handler_argument_string.inc
index 86000c6c..c4c02a41 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_argument_string.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_argument_string.inc
@@ -225,9 +225,11 @@ class views_handler_argument_string extends views_handler_argument {
     if ($formula) {
       $placeholder = $this->placeholder();
       if (count($this->value) > 1) {
-        $placeholder = "($placeholder)";
+        $field .= " $operator ($placeholder)";
+      }
+      else {
+        $field .= " $operator $placeholder";
       }
-      $field .= " $operator $placeholder";
       $placeholders = array(
         $placeholder => $argument,
       );
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_field.inc b/drupal7/sites/all/modules/views/handlers/views_handler_field.inc
index 4b690dca..d592ef2a 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_field.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_field.inc
@@ -159,7 +159,7 @@ class views_handler_field extends views_handler {
               '@identifier' => $identifier,
               '@table' => $info['table'],
             );
-            debug(t('Handler @handler tried to add additional_field @identifier but @table could not be added!', $t_args));
+            debug(t('Handler @handler tried to add additional field @identifier but @table could not be added.', $t_args));
             $this->aliases[$identifier] = 'broken';
             continue;
           }
@@ -1249,6 +1249,12 @@ If you would like to have the characters \'[\' and \']\' please use the html ent
     // displays such as XML where we should not mess with tags.
     $value = $alter['text'];
     $value = strtr($value, $tokens);
+    // User might already used '%5B' and '%5D' instead of literal [ and ].
+    // After token replacements, we need to convert those codes to literal
+    // square bracket characters. Otherwise problems like comment #5 and #6 of
+    // https://www.drupal.org/node/578772 will happen.
+    // We could have used rawurldecode() also, but not sure about the consequences.
+    $value = strtr($value, array('%5B' => '[', '%5D' => ']'));
 
     return $value;
   }
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_filter.inc b/drupal7/sites/all/modules/views/handlers/views_handler_filter.inc
index 6ffb10d1..b6e06df6 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_filter.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_filter.inc
@@ -1387,7 +1387,9 @@ class views_handler_filter extends views_handler {
       // Various ways to check for the absence of non-required input.
       if (empty($this->options['expose']['required'])) {
         if ($this->operator == 'empty' || $this->operator == 'not empty') {
-          $value = is_array($value) ? $value['value'] : $value;
+          if (is_array($value) && array_key_exists('value', $value)) {
+            $value = $value['value'];
+          }
           $this->operator = ($this->operator == 'empty' && empty($value)) || ($this->operator == 'not empty' && !empty($value)) ? 'not empty' : 'empty';
         }
 
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_filter_combine.inc b/drupal7/sites/all/modules/views/handlers/views_handler_filter_combine.inc
index 35bfb20f..e7abb4e5 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_filter_combine.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_filter_combine.inc
@@ -129,7 +129,7 @@ class views_handler_filter_combine extends views_handler_filter_string {
     foreach ($matches as $match) {
       $phrase = FALSE;
       // Strip off phrase quotes.
-      if ($match[2]{0} == '"') {
+      if ($match[2][0] == '"') {
         $match[2] = substr($match[2], 1, -1);
         $phrase = TRUE;
       }
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_filter_numeric.inc b/drupal7/sites/all/modules/views/handlers/views_handler_filter_numeric.inc
index a3383741..95d23d65 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_filter_numeric.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_filter_numeric.inc
@@ -379,6 +379,13 @@ class views_handler_filter_numeric extends views_handler_filter {
           'value' => $value,
         );
       }
+      if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
+        if ($input[$this->options['expose']['operator_id']] === 'empty' || $input[$this->options['expose']['operator_id']] === 'not empty') {
+          // Parent method will expect a boolean value. We don't ask for a value
+          // so we'll force "Yes".
+          $value['value'] = 1;
+        }
+      }
     }
 
     $rc = parent::accept_exposed_input($input);
diff --git a/drupal7/sites/all/modules/views/handlers/views_handler_filter_string.inc b/drupal7/sites/all/modules/views/handlers/views_handler_filter_string.inc
index 85e3814f..8d2f7345 100644
--- a/drupal7/sites/all/modules/views/handlers/views_handler_filter_string.inc
+++ b/drupal7/sites/all/modules/views/handlers/views_handler_filter_string.inc
@@ -300,7 +300,7 @@ class views_handler_filter_string extends views_handler_filter {
     foreach ($matches as $match) {
       $phrase = FALSE;
       // Strip off phrase quotes
-      if ($match[2]{0} == '"') {
+      if ($match[2][0] == '"') {
         $match[2] = substr($match[2], 1, -1);
         $phrase = TRUE;
       }
diff --git a/drupal7/sites/all/modules/views/includes/ajax.inc b/drupal7/sites/all/modules/views/includes/ajax.inc
index 37eee9c7..8f560977 100644
--- a/drupal7/sites/all/modules/views/includes/ajax.inc
+++ b/drupal7/sites/all/modules/views/includes/ajax.inc
@@ -26,7 +26,9 @@ function views_ajax() {
     $commands = array();
 
     // Remove all of this stuff from $_GET so it doesn't end up in pagers and
-    // tablesort URLs.
+    // tablesort URLs; do not modify $_POST itself but make a new "clean"
+    // copy to merge it with $_GET later.
+    $cleaned_post = $_POST;
     foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state') as $key) {
       if (isset($_GET[$key])) {
         unset($_GET[$key]);
@@ -34,8 +36,8 @@ function views_ajax() {
       if (isset($_REQUEST[$key])) {
         unset($_REQUEST[$key]);
       }
-      if (isset($_POST[$key])) {
-        unset($_POST[$key]);
+      if (isset($cleaned_post[$key])) {
+        unset($cleaned_post[$key]);
       }
     }
 
@@ -52,7 +54,7 @@ function views_ajax() {
       $exclude = isset($_POST['page']) ? array('page') : array();
       // Add all $_POST data to $_GET as many things, such as tablesorts,
       // exposed filters and paging assume $_GET.
-      $_GET = $_POST + drupal_get_query_parameters($_GET, $exclude);
+      $_GET = $cleaned_post + drupal_get_query_parameters($_GET, $exclude);
 
       // Overwrite the destination.
       // @see drupal_get_destination()
diff --git a/drupal7/sites/all/modules/views/includes/analyze.inc b/drupal7/sites/all/modules/views/includes/analyze.inc
index 5dd58de2..47042028 100644
--- a/drupal7/sites/all/modules/views/includes/analyze.inc
+++ b/drupal7/sites/all/modules/views/includes/analyze.inc
@@ -113,7 +113,7 @@ function views_ui_views_analyze($view) {
     if ($display->handler->has_path() && $path = $display->handler->get_option('path')) {
       $normal_path = drupal_get_normal_path($path);
       if ($path != $normal_path) {
-        $ret[] = views_ui_analysis(t('You have configured display %display with a path which is an path alias as well. This might lead to unwanted effects so better use an internal path.', array('%display' => $display->display_title)), 'warning');
+        $ret[] = views_ui_analysis(t('You have configured display %display with a path which is a path alias as well. This might lead to unwanted effects so you should use an internal path.', array('%display' => $display->display_title)), 'warning');
       }
     }
   }
diff --git a/drupal7/sites/all/modules/views/includes/view.inc b/drupal7/sites/all/modules/views/includes/view.inc
index 4f26650b..4541f80b 100644
--- a/drupal7/sites/all/modules/views/includes/view.inc
+++ b/drupal7/sites/all/modules/views/includes/view.inc
@@ -1000,6 +1000,7 @@ class view extends views_db_object {
     // Let the handlers interact with each other if they really want.
     $this->_pre_query();
 
+    $exposed_form = FALSE;
     if ($this->display_handler->uses_exposed()) {
       $exposed_form = $this->display_handler->get_plugin('exposed_form');
       // (1) Record the errors before rendering the exposed form widgets.
@@ -1080,7 +1081,7 @@ class view extends views_db_object {
     $this->style_plugin->query($this->display_handler->use_group_by());
 
     // Allow exposed form to affect the query.
-    if (isset($exposed_form)) {
+    if ($exposed_form) {
       $exposed_form->query();
     }
 
diff --git a/drupal7/sites/all/modules/views/js/ajax_view.js b/drupal7/sites/all/modules/views/js/ajax_view.js
index 5012c33e..1d235d3b 100644
--- a/drupal7/sites/all/modules/views/js/ajax_view.js
+++ b/drupal7/sites/all/modules/views/js/ajax_view.js
@@ -80,7 +80,10 @@
     // Add a trigger to update this view specifically.
     var self_settings = this.element_settings;
     self_settings.event = 'RefreshView';
-    this.refreshViewAjax = new Drupal.ajax(this.selector, this.$view, self_settings);
+    var self = this;
+    this.$view.once('refresh', function () {
+      self.refreshViewAjax = new Drupal.ajax(self.selector, self.$view, self_settings);
+    });
   };
 
   Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() {
@@ -101,21 +104,22 @@
    * Attach the ajax behavior to each link.
    */
   Drupal.views.ajaxView.prototype.attachPagerAjax = function() {
-    this.$view.find('ul.pager > li > a, th.views-field a, .attachment .views-summary a')
+    this.$view.find('ul.pager > li > a, ol.pager > li > a, th.views-field a, .attachment .views-summary a')
       .each(jQuery.proxy(this.attachPagerLinkAjax, this));
   };
 
   /**
-   * Attach the ajax behavior to a singe link.
+   * Attach the ajax behavior to a single link.
    */
   Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) {
     var $link = $(link);
+    var viewData = {};
+    var href = $link.attr('href');
     // Don't attach to pagers inside nested views.
-    if ($link.closest('.view')[0] !== this.$view[0]) {
+    if ($link.closest('.view')[0] !== this.$view[0] &&
+      $link.closest('.view').parent().hasClass('attachment') === false) {
       return;
     }
-    var viewData = {};
-    var href = $link.attr('href');
 
     // Provide a default page if none has been set. This must be done
     // prior to merging with settings to avoid accidentally using the
@@ -127,11 +131,11 @@
     // Construct an object using the settings defaults and then overriding
     // with data specific to the link.
     $.extend(
-    viewData,
-    this.settings,
-    Drupal.Views.parseQueryString(href),
-    // Extract argument data from the URL.
-    Drupal.Views.parseViewArgs(href, this.settings.view_base_path)
+      viewData,
+      this.settings,
+      Drupal.Views.parseQueryString(href),
+      // Extract argument data from the URL.
+      Drupal.Views.parseViewArgs(href, this.settings.view_base_path)
     );
 
     // For anchor tags, these will go to the target of the anchor rather
diff --git a/drupal7/sites/all/modules/views/js/exposed-form-ajax.js b/drupal7/sites/all/modules/views/js/exposed-form-ajax.js
new file mode 100644
index 00000000..6322ba41
--- /dev/null
+++ b/drupal7/sites/all/modules/views/js/exposed-form-ajax.js
@@ -0,0 +1,26 @@
+/**
+ * @file
+ * Handles Views' exposed form AJAX data submission.
+ */
+
+(function ($) {
+  'use strict';
+
+  /**
+   * Gets Form build info from settings and adds it to ajax data.
+   *
+   * @see views_exposed_form_ajax_enable().
+   */
+  Drupal.behaviors.ViewsExposedFormAjax = {
+    attach: function (context, settings) {
+      for (var ajaxObject in Drupal.ajax) {
+        for (var name in Drupal.settings.ViewsExposedFormInfo) {
+          if (Drupal.ajax[ajaxObject].options && Drupal.ajax[ajaxObject].options.data._triggering_element_name === name) {
+            jQuery.extend(Drupal.ajax[ajaxObject].options.data, Drupal.settings.ViewsExposedFormInfo[name]);
+          }
+        }
+      }
+    }
+  };
+
+})(jQuery);
diff --git a/drupal7/sites/all/modules/views/js/views-admin.js b/drupal7/sites/all/modules/views/js/views-admin.js
index 807d7f7b..f3aaf63b 100644
--- a/drupal7/sites/all/modules/views/js/views-admin.js
+++ b/drupal7/sites/all/modules/views/js/views-admin.js
@@ -231,7 +231,7 @@ Drupal.behaviors.viewsUiRenderAddViewButton.attach = function (context, settings
     return;
   }
   var $addDisplayDropdown = $('<li class="add"><a href="#"><span class="icon add"></span>' + Drupal.t('Add') + '</a><ul class="action-list" style="display:none;"></ul></li>');
-  var $displayButtons = $menu.nextAll('input.add-display').detach();
+  var $displayButtons = $menu.nextAll('.add-display').detach();
   $displayButtons.appendTo($addDisplayDropdown.find('.action-list')).wrap('<li>')
     .parent().first().addClass('first').end().last().addClass('last');
   // Remove the 'Add ' prefix from the button labels since they're being palced
diff --git a/drupal7/sites/all/modules/views/modules/comment.views.inc b/drupal7/sites/all/modules/views/modules/comment.views.inc
index 3cecfcc2..5cde8bc7 100644
--- a/drupal7/sites/all/modules/views/modules/comment.views.inc
+++ b/drupal7/sites/all/modules/views/modules/comment.views.inc
@@ -419,20 +419,6 @@ function comment_views_data() {
     ),
   );
 
-  $data['comment']['cid'] = array(
-    'title' => t('Comment id'),
-    'help' => t('Unique identifier for the comment.'),
-    'filter' => array(
-      'handler' => 'views_handler_filter_numeric',
-    ),
-    'argument' => array(
-      'handler' => 'views_handler_argument_numeric',
-    ),
-    'field' => array(
-      'handler' => 'views_handler_field_numeric',
-    ),
-  );
-
   $data['comment']['uid'] = array(
     'title' => t('Author uid'),
     'help' => t('If you need more fields than the uid add the comment: author relationship'),
diff --git a/drupal7/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc b/drupal7/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc
index 552ccf2e..c8dd9e36 100644
--- a/drupal7/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc
+++ b/drupal7/sites/all/modules/views/modules/locale/views_handler_field_locale_language.inc
@@ -39,7 +39,7 @@ class views_handler_field_locale_language extends views_handler_field {
    * {@inheritdoc}
    */
   public function render($values) {
-    $languages = locale_language_list(empty($this->options['native_language']) ? 'name' : 'native');
+    $languages = views_language_list(empty($this->options['native_language']) ? 'name' : 'native');
     $value = $this->get_value($values);
     return isset($languages[$value]) ? $languages[$value] : '';
   }
diff --git a/drupal7/sites/all/modules/views/modules/system.views.inc b/drupal7/sites/all/modules/views/modules/system.views.inc
index b4c93c58..058463bb 100644
--- a/drupal7/sites/all/modules/views/modules/system.views.inc
+++ b/drupal7/sites/all/modules/views/modules/system.views.inc
@@ -112,7 +112,7 @@ function system_views_data() {
   $data['file_managed']['extension'] = array(
     'title' => t('Extension'),
     'help' => t('The extension of the file.'),
-    'real field' => 'filename',
+    'real field' => 'uri',
     'field' => array(
       'handler' => 'views_handler_field_file_extension',
       'click sortable' => FALSE,
diff --git a/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc b/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc
index 3bd32123..a026d3e6 100644
--- a/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc
+++ b/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_field_term_link_edit.inc
@@ -76,6 +76,7 @@ class views_handler_field_term_link_edit extends views_handler_field {
     $term->vocabulary_machine_name = $values->{$this->aliases['vocabulary_machine_name']};
     if ($data && taxonomy_term_edit_access($term)) {
       $text = !empty($this->options['text']) ? $this->options['text'] : t('edit');
+      $this->options['alter']['make_link'] = TRUE;
       $this->options['alter']['path'] = "taxonomy/term/$data/edit";
       $this->options['alter']['query'] = drupal_get_destination();
       return $text;
diff --git a/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc b/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc
index 03b8d11e..3909e211 100644
--- a/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc
+++ b/drupal7/sites/all/modules/views/modules/taxonomy/views_handler_filter_term_node_tid.inc
@@ -152,8 +152,10 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on
       }
     }
     else {
+      $options = array();
       if (!empty($this->options['hierarchy']) && $this->options['limit']) {
         $tree = taxonomy_get_tree($vocabulary->vid, 0, NULL, TRUE);
+        $options = array();
         if (!empty($tree)) {
           if (!empty($this->options['optgroups'])) {
             foreach ($tree as $term) {
@@ -174,7 +176,6 @@ class views_handler_filter_term_node_tid extends views_handler_filter_many_to_on
         }
       }
       else {
-        $options = array();
         $query = db_select('taxonomy_term_data', 'td');
         $query->innerJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
         $query->fields('td');
diff --git a/drupal7/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc b/drupal7/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc
index 7601c25f..88f373cc 100644
--- a/drupal7/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc
+++ b/drupal7/sites/all/modules/views/modules/translation/views_handler_relationship_translation.inc
@@ -34,7 +34,7 @@ class views_handler_relationship_translation extends views_handler_relationship
       'current' => t('Current language'),
       'default' => t('Default language'),
     );
-    $options = array_merge($options, locale_language_list());
+    $options = array_merge($options, views_language_list());
     $form['language'] = array(
       '#type' => 'select',
       '#options' => $options,
diff --git a/drupal7/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc b/drupal7/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc
index 86a0b7a0..8d9eb325 100644
--- a/drupal7/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc
+++ b/drupal7/sites/all/modules/views/modules/user/views_handler_field_user_roles.inc
@@ -20,6 +20,28 @@ class views_handler_field_user_roles extends views_handler_field_prerender_list
     $this->additional_fields['uid'] = array('table' => 'users', 'field' => 'uid');
   }
 
+  function option_definition() {
+    $options = parent::option_definition();
+    $options['display_roles'] = array('default' => array());
+
+    return $options;
+  }
+
+  function options_form(&$form, &$form_state) {
+    $roles = user_roles(TRUE);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);
+    if (!empty($roles)) {
+      $form['display_roles'] = array(
+        '#type' => 'checkboxes',
+        '#title' => t('Only display the selected roles'),
+        '#description' => t("If no roles are selected, all of the user's roles will be shown."),
+        '#options' => $roles,
+        '#default_value' => $this->options['display_roles'],
+      );
+    }
+    parent::options_form($form, $form_state);
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -40,8 +62,15 @@ class views_handler_field_user_roles extends views_handler_field_prerender_list
     }
 
     if ($uids) {
-      $result = db_query("SELECT u.uid, u.rid, r.name FROM {role} r INNER JOIN {users_roles} u ON u.rid = r.rid WHERE u.uid IN (:uids) ORDER BY r.name",
-        array(':uids' => $uids));
+      $rids = array_filter($this->options['display_roles']);
+      if (!empty($rids)) {
+        $result = db_query("SELECT u.uid, u.rid, r.name FROM {role} r INNER JOIN {users_roles} u ON u.rid = r.rid WHERE u.uid IN (:uids) AND r.rid IN (:rids) ORDER BY r.name",
+          array(':uids' => $uids, ':rids' => $rids));
+      }
+      else {
+        $result = db_query("SELECT u.uid, u.rid, r.name FROM {role} r INNER JOIN {users_roles} u ON u.rid = r.rid WHERE u.uid IN (:uids) ORDER BY r.name",
+          array(':uids' => $uids));
+      }
       foreach ($result as $role) {
         $this->items[$role->uid][$role->rid]['role'] = check_plain($role->name);
         $this->items[$role->uid][$role->rid]['rid'] = $role->rid;
@@ -53,7 +82,7 @@ class views_handler_field_user_roles extends views_handler_field_prerender_list
    * {@inheritdoc}
    */
   public function render_item($count, $item) {
-    return $item['role'];
+    return t($item['role']);
   }
 
   /**
diff --git a/drupal7/sites/all/modules/views/plugins/views_plugin_display.inc b/drupal7/sites/all/modules/views/plugins/views_plugin_display.inc
index 7383ac98..3d47a14a 100644
--- a/drupal7/sites/all/modules/views/plugins/views_plugin_display.inc
+++ b/drupal7/sites/all/modules/views/plugins/views_plugin_display.inc
@@ -314,7 +314,7 @@ class views_plugin_display extends views_plugin {
         }
       }
       $pager = $this->get_plugin('pager');
-      if (isset($pager) && $pager->uses_exposed()) {
+      if ($pager && $pager->uses_exposed()) {
         $this->has_exposed = TRUE;
         return TRUE;
       }
@@ -1400,9 +1400,8 @@ class views_plugin_display extends views_plugin {
       '***DEFAULT_LANGUAGE***' => t("Default site language"),
       LANGUAGE_NONE => t('Language neutral'),
     );
-    if (module_exists('locale')) {
-      $languages = array_merge($languages, locale_language_list());
-    }
+    $languages = array_merge($languages, views_language_list());
+
     $field_language = array();
     $options['field_language'] = array(
       'category' => 'other',
diff --git a/drupal7/sites/all/modules/views/plugins/views_plugin_display_page.inc b/drupal7/sites/all/modules/views/plugins/views_plugin_display_page.inc
index 9b9e900b..d743836d 100644
--- a/drupal7/sites/all/modules/views/plugins/views_plugin_display_page.inc
+++ b/drupal7/sites/all/modules/views/plugins/views_plugin_display_page.inc
@@ -87,7 +87,7 @@ class views_plugin_display_page extends views_plugin_display {
     $path = implode('/', $bits);
 
     $access_plugin = $this->get_plugin('access');
-    if (!isset($access_plugin)) {
+    if (!$access_plugin) {
       $access_plugin = views_get_plugin('access', 'none');
     }
 
diff --git a/drupal7/sites/all/modules/views/plugins/views_plugin_style.inc b/drupal7/sites/all/modules/views/plugins/views_plugin_style.inc
index 1433f319..ed5d3c02 100644
--- a/drupal7/sites/all/modules/views/plugins/views_plugin_style.inc
+++ b/drupal7/sites/all/modules/views/plugins/views_plugin_style.inc
@@ -71,7 +71,7 @@ class views_plugin_style extends views_plugin {
   public function destroy() {
     parent::destroy();
 
-    if (isset($this->row_plugin)) {
+    if ($this->row_plugin) {
       $this->row_plugin->destroy();
     }
   }
@@ -625,7 +625,7 @@ class views_plugin_style extends views_plugin {
    */
   public function query() {
     parent::query();
-    if (isset($this->row_plugin)) {
+    if ($this->row_plugin) {
       $this->row_plugin->query();
     }
   }
diff --git a/drupal7/sites/all/modules/views/tests/comment/views_handler_argument_comment_user_uid.test b/drupal7/sites/all/modules/views/tests/comment/views_handler_argument_comment_user_uid.test
index 95994990..9564450d 100644
--- a/drupal7/sites/all/modules/views/tests/comment/views_handler_argument_comment_user_uid.test
+++ b/drupal7/sites/all/modules/views/tests/comment/views_handler_argument_comment_user_uid.test
@@ -35,8 +35,11 @@ class viewsHandlerArgumentCommentUserUidTest extends ViewsSqlTest {
     return comment_save((object) $comment);
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Add two users, create a node with the user1 as author and another node
     // with user2 as author. For the second node add a comment from user1.
diff --git a/drupal7/sites/all/modules/views/tests/field/views_fieldapi.test b/drupal7/sites/all/modules/views/tests/field/views_fieldapi.test
index 0d049e10..4ac71bc8 100644
--- a/drupal7/sites/all/modules/views/tests/field/views_fieldapi.test
+++ b/drupal7/sites/all/modules/views/tests/field/views_fieldapi.test
@@ -119,8 +119,11 @@ class viewsFieldApiDataTest extends ViewsFieldApiTestHelper {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     $langcode = LANGUAGE_NONE;
 
@@ -285,8 +288,11 @@ class viewsHandlerFieldFieldTest extends ViewsFieldApiTestHelper {
     );
   }
 
-  protected function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Setup basic fields.
     $this->setUpFields(3);
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_argument_string.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_argument_string.test
deleted file mode 100644
index 4c76ff6a..00000000
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_argument_string.test
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * @file
- * Definition of ViewsHandlerArgumentNullTest.
- */
-
-/**
- * Tests the core views_handler_argument_string handler.
- */
-class ViewsHandlerArgumentStringTest extends ViewsSqlTest {
-  public static function getInfo() {
-    return array(
-      'name' => 'Argument: String',
-      'description' => 'Test the core views_handler_argument_string handler.',
-      'group' => 'Views Handlers',
-    );
-  }
-
-  /**
-   * Tests the glossary feature.
-   */
-  function testGlossary() {
-    // Setup some nodes, one with a, two with b and three with c.
-    $counter = 1;
-    foreach (array('a', 'b', 'c') as $char) {
-      for ($i = 0; $i < $counter; $i++) {
-        $edit = array(
-          'title' => $char . $this->randomName(),
-        );
-        $this->drupalCreateNode($edit);
-      }
-    }
-
-    $view = $this->viewGlossary();
-    $view->init_display();
-    $this->executeView($view);
-
-    $count_field = 'nid';
-    foreach ($view->result as &$row) {
-      if (strpos($row->node_title, 'a') === 0) {
-        $this->assertEqual(1, $row->{$count_field});
-      }
-      if (strpos($row->node_title, 'b') === 0) {
-        $this->assertEqual(2, $row->{$count_field});
-      }
-      if (strpos($row->node_title, 'c') === 0) {
-        $this->assertEqual(3, $row->{$count_field});
-      }
-    }
-  }
-
-  /**
-   * Provide a test view for testGlossary.
-   *
-   * @see testGlossary
-   *
-   * @return view
-   */
-  function viewGlossary() {
-    $view = new view();
-    $view->name = 'test_glossary';
-    $view->description = '';
-    $view->tag = 'default';
-    $view->base_table = 'node';
-    $view->human_name = 'test_glossary';
-    $view->core = 7;
-    $view->api_version = '3.0';
-    $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
-
-    /* Display: Master */
-    $handler = $view->new_display('default', 'Master', 'default');
-    $handler->display->display_options['access']['type'] = 'perm';
-    $handler->display->display_options['cache']['type'] = 'none';
-    $handler->display->display_options['query']['type'] = 'views_query';
-    $handler->display->display_options['exposed_form']['type'] = 'basic';
-    $handler->display->display_options['pager']['type'] = 'full';
-    $handler->display->display_options['style_plugin'] = 'default';
-    $handler->display->display_options['row_plugin'] = 'fields';
-    /* Field: Content: Title */
-    $handler->display->display_options['fields']['title']['id'] = 'title';
-    $handler->display->display_options['fields']['title']['table'] = 'node';
-    $handler->display->display_options['fields']['title']['field'] = 'title';
-    $handler->display->display_options['fields']['title']['label'] = '';
-    /* Contextual filter: Content: Title */
-    $handler->display->display_options['arguments']['title']['id'] = 'title';
-    $handler->display->display_options['arguments']['title']['table'] = 'node';
-    $handler->display->display_options['arguments']['title']['field'] = 'title';
-    $handler->display->display_options['arguments']['title']['default_argument_type'] = 'fixed';
-    $handler->display->display_options['arguments']['title']['summary']['number_of_records'] = '0';
-    $handler->display->display_options['arguments']['title']['summary']['format'] = 'default_summary';
-    $handler->display->display_options['arguments']['title']['summary_options']['items_per_page'] = '25';
-    $handler->display->display_options['arguments']['title']['glossary'] = TRUE;
-    $handler->display->display_options['arguments']['title']['limit'] = '1';
-
-    return $view;
-  }
-
-}
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_field.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_field.test
index df9574f8..aa44666f 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_field.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_field.test
@@ -24,10 +24,11 @@ class ViewsHandlerFieldTest extends ViewsSqlTest {
   }
 
   /**
-   *
+   * {@inheritdoc}
    */
-  protected function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->column_map = array(
       'views_test_name' => 'name',
     );
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_field_xss.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_field_xss.test
index c12a4088..37bb2f21 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_field_xss.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_field_xss.test
@@ -29,7 +29,6 @@ class ViewsHandlerTestXss extends ViewsSqlTest {
     return $map;
   }
 
-
   function viewsData() {
     $data = parent::viewsData();
     $data['views_test']['name']['field']['handler'] = 'views_handler_field_xss';
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_combine.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_combine.test
index 57d5e6f8..d81b4564 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_combine.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_combine.test
@@ -19,8 +19,12 @@ class ViewsHandlerFilterCombineTest extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->column_map = array(
       'views_test_name' => 'name',
       'views_test_job' => 'job',
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_date.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_date.test
index ad6a98bc..5e8f34be 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_date.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_date.test
@@ -17,8 +17,12 @@ class ViewsHandlerFilterDateTest extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     // Add some basic test nodes.
     $this->nodes = array();
     $this->nodes[] = $this->drupalCreateNode(array('created' => 100000));
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test
index a1dbc4e4..1c3abd6f 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_equality.test
@@ -17,8 +17,12 @@ class ViewsHandlerFilterEqualityTest extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->column_map = array(
       'views_test_name' => 'name',
     );
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test
index a18e20ac..6faf9d15 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_numeric.test
@@ -19,8 +19,36 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  protected function dataSet() {
+    $data_set = parent::dataSet();
+    $data_set[] = array(
+      'name' => 'Charles',
+      'age' => NULL,
+      'job' => 'Bassist',
+        'created' => gmmktime(6, 30, 10, 1, 1, 2001),
+    );
+    return $data_set;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function schemaDefinition() {
+    $schema = parent::schemaDefinition();
+    $schema['views_test']['fields']['age']['not null'] = FALSE;
+    $schema['views_test']['indexes'] = array();
+    return $schema;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->column_map = array(
       'views_test_name' => 'name',
       'views_test_age' => 'age',
@@ -114,7 +142,7 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     );
     $this->assertIdenticalResultset($view, $resultset, $this->column_map);
 
-    // test not between.
+    // Test not between.
     $view->delete();
     $view = $this->getBasicView();
 
@@ -182,7 +210,7 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     $filters = $this->getGroupedExposedFilters();
     $view = $this->getBasicPageView();
 
-    // Filter: Age, Operator: between, Value: 26 and 29
+    // Filter: Age, Operator: not between, Value: 26 and 29
     $filters['age']['group_info']['default_group'] = 3;
     $view->set_display('page_1');
     $view->display['page_1']->handler->override_option('filters', $filters);
@@ -221,7 +249,12 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     ));
 
     $this->executeView($view);
-    $resultset = array();
+    $resultset = array(
+      array(
+        'name' => 'Charles',
+        'age' => NULL,
+      ),
+    );
     $this->assertIdenticalResultset($view, $resultset, $this->column_map);
 
     $view->delete();
@@ -275,7 +308,12 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     $view->display['page_1']->handler->override_option('filters', $filters);
 
     $this->executeView($view);
-    $resultset = array();
+    $resultset = array(
+      array(
+        'name' => 'Charles',
+        'age' => NULL,
+      ),
+    );
     $this->assertIdenticalResultset($view, $resultset, $this->column_map);
   }
 
@@ -346,6 +384,238 @@ class ViewsHandlerFilterNumericTest extends ViewsSqlTest {
     }
   }
 
+  /**
+   * Tests exposed numeric filter with exposed operator.
+   */
+  public function testFilterNumericExposedOperator() {
+    $this->applyFilterNumericExposedOperator('=', array('value' => '27'), array(
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('<', array('value' => '27'), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('<=', array(
+      'value' => '27',
+    ), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('!=', array(
+      'value' => '27',
+    ), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('>=', array(
+      'value' => '27',
+    ), array(
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('>', array('value' => '27'), array(
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('between', array(
+      'min' => '28',
+      'max' => '31',
+    ), array(
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('not between', array(
+      'min' => '28',
+      'max' => '31',
+    ), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('empty', array(), array(
+      array(
+        'name' => 'Charles',
+        'age' => NULL,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('not empty', array(), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('regular_expression', array(
+      'value' => '^(0|[1-9][0-9]*)$',
+    ), array(
+      array(
+        'name' => 'John',
+        'age' => 25,
+      ),
+      array(
+        'name' => 'George',
+        'age' => 27,
+      ),
+      array(
+        'name' => 'Ringo',
+        'age' => 28,
+      ),
+      array(
+        'name' => 'Paul',
+        'age' => 26,
+      ),
+      array(
+        'name' => 'Meredith',
+        'age' => 30,
+      ),
+    ));
+    $this->applyFilterNumericExposedOperator('not_regular_expression', array(
+      'value' => '^(0|[1-9][0-9]*)$',
+    ), array());
+  }
+
+  /**
+   * Tests exposed numeric filter with an individual exposed operator.
+   *
+   * @param string $operator
+   *   Operator to test.
+   * @param array $value
+   *   Filter value to use in exposed input. Keys might be 'value', 'min' or
+   *   'max'. If one of those keys doesn't exist, an empty string is used as the
+   *   key's value.
+   * @param array $resultset
+   *   The expected result set.
+   */
+  protected function applyFilterNumericExposedOperator($operator, array $value, array $resultset) {
+    $exposed_input = array(
+      'age' => ($value += array(
+        'value' => '',
+        'min' => '',
+        'max' => '',
+      )),
+      'age_op' => $operator,
+    );
+    $filters = array(
+      'age' => array(
+        'id' => 'age',
+        'table' => 'views_test',
+        'field' => 'age',
+        'relationship' => 'none',
+        'exposed' => TRUE,
+        'expose' => array(
+          'operator' => 'age_op',
+          'label' => 'age',
+          'identifier' => 'age',
+          'use_operator' => TRUE,
+        ),
+      ),
+    );
+    $view = $this->getBasicPageView();
+    $view->set_display('page_1');
+    $view->display['page_1']->handler->override_option('filters', $filters);
+    $view->set_exposed_input($exposed_input);
+    $this->executeView($view);
+    $this->assertIdenticalResultset($view, $resultset, $this->column_map, 'Identical result set for ' . $operator . ' with untouched values.');
+    $view->destroy();
+
+    // Min, max and value fields are shown/hidden only via JS, so they might
+    // still be set from a previous operation. Assert that this doesn't change
+    // the expected result set.
+    $exposed_input['age'] += array(
+      'value' => '25',
+      'min' => '28',
+      'max' => '30',
+    );
+    $view = $this->getBasicPageView();
+    $view->set_display('page_1');
+    $view->display['page_1']->handler->override_option('filters', $filters);
+    $view->set_exposed_input($exposed_input);
+    $this->executeView($view);
+    $this->assertIdenticalResultset($view, $resultset, $this->column_map, 'Identical result set for ' . $operator . ' with leftover values from previous operation.');
+  }
 
   public function testAllowEmpty() {
     $view = $this->getBasicView();
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_string.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_string.test
index ab6af92a..e2551562 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_string.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_filter_string.test
@@ -19,8 +19,12 @@ class ViewsHandlerFilterStringTest extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->column_map = array(
       'views_test_name' => 'name',
     );
diff --git a/drupal7/sites/all/modules/views/tests/handlers/views_handler_manytoone.test b/drupal7/sites/all/modules/views/tests/handlers/views_handler_manytoone.test
index fb06645e..5b086694 100644
--- a/drupal7/sites/all/modules/views/tests/handlers/views_handler_manytoone.test
+++ b/drupal7/sites/all/modules/views/tests/handlers/views_handler_manytoone.test
@@ -83,8 +83,8 @@ class ViewsHandlerManyToOneTest extends ViewsSqlTest {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Create boolean field.
     $this->fields[0] = array(
diff --git a/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_jump_menu.test b/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_jump_menu.test
index aadaa56b..3be7858c 100644
--- a/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_jump_menu.test
+++ b/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_jump_menu.test
@@ -29,10 +29,11 @@ class viewsPluginStyleJumpMenuTest extends ViewsSqlTest {
   }
 
   /**
-   *
+   * {@inheritdoc}
    */
-  public function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     $this->nodes = array();
     $this->nodes['page'][] = $this->drupalCreateNode(array('type' => 'page'));
     $this->nodes['page'][] = $this->drupalCreateNode(array('type' => 'page'));
diff --git a/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_mapping.test b/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_mapping.test
index c73cb575..57ffefd9 100644
--- a/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_mapping.test
+++ b/drupal7/sites/all/modules/views/tests/styles/views_plugin_style_mapping.test
@@ -18,8 +18,11 @@ class ViewsPluginStyleMappingTest extends ViewsPluginStyleTestBase {
     );
   }
 
-  public function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Reset the plugin data.
     views_fetch_plugin_data(NULL, NULL, TRUE);
diff --git a/drupal7/sites/all/modules/views/tests/taxonomy/views_handler_relationship_node_term_data.test b/drupal7/sites/all/modules/views/tests/taxonomy/views_handler_relationship_node_term_data.test
index 7bce9804..954a3cb7 100644
--- a/drupal7/sites/all/modules/views/tests/taxonomy/views_handler_relationship_node_term_data.test
+++ b/drupal7/sites/all/modules/views/tests/taxonomy/views_handler_relationship_node_term_data.test
@@ -31,8 +31,11 @@ class ViewsHandlerRelationshipNodeTermDataTest extends ViewsSqlTest {
     return $term;
   }
 
-  function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // $web_user = $this->drupalCreateUser(array('create article content'));
     // $this->drupalLogin($web_user);
diff --git a/drupal7/sites/all/modules/views/tests/user/views_user.test b/drupal7/sites/all/modules/views/tests/user/views_user.test
index 2f0e2cd5..8f917aa2 100644
--- a/drupal7/sites/all/modules/views/tests/user/views_user.test
+++ b/drupal7/sites/all/modules/views/tests/user/views_user.test
@@ -34,8 +34,8 @@ class ViewsUserTestCase extends ViewsSqlTest {
   /**
    *
    */
-  protected function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     $this->users[] = $this->drupalCreateUser();
     $this->users[] = user_load(1);
diff --git a/drupal7/sites/all/modules/views/tests/user/views_user_argument_validate.test b/drupal7/sites/all/modules/views/tests/user/views_user_argument_validate.test
index 91aebba9..78c24fa0 100644
--- a/drupal7/sites/all/modules/views/tests/user/views_user_argument_validate.test
+++ b/drupal7/sites/all/modules/views/tests/user/views_user_argument_validate.test
@@ -17,8 +17,13 @@ class ViewsUserArgumentValidate extends ViewsSqlTest {
     );
   }
 
-  function setUp() {
-    parent::setUp('views');
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    $modules[] = 'views';
+    parent::setUp($modules);
+
     $this->account = $this->drupalCreateUser();
   }
 
diff --git a/drupal7/sites/all/modules/views/tests/views_access.test b/drupal7/sites/all/modules/views/tests/views_access.test
index 73b23efa..d05436be 100644
--- a/drupal7/sites/all/modules/views/tests/views_access.test
+++ b/drupal7/sites/all/modules/views/tests/views_access.test
@@ -20,8 +20,8 @@ class ViewsAccessTest extends ViewsSqlTest {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     $this->admin_user = $this->drupalCreateUser(array('access all views'));
     $this->web_user = $this->drupalCreateUser();
@@ -161,6 +161,26 @@ class ViewsAccessTest extends ViewsSqlTest {
     $this->assertTrue(views_access($expected_hook_menu, $argument1, $argument2));
   }
 
+  /**
+   * Tests access for a view with a missing access plugin.
+   */
+  public function testMissingAccessPlugin() {
+    $view = $this->getMissingAccessPluginTestView();
+
+    $view->set_display('default');
+    $access_plugin = $view->display_handler->get_plugin('access');
+    $this->assertFalse($access_plugin);
+
+    $this->assertTrue($view->display_handler->access($this->admin_user), t('Admin-Account should be able to access the view everytime'));
+    $this->assertTrue($view->display_handler->access($this->web_user));
+    $this->assertTrue($view->display_handler->access($this->normal_user));
+
+    $hook_menu = $view->execute_hook_menu('page_1');
+    $this->assertTrue($hook_menu['test_access_missing']['access arguments'][0]);
+
+    $this->assertTrue(views_access(TRUE));
+  }
+
   function view_access_none() {
     $view = new view;
     $view->name = 'test_access_none';
@@ -285,4 +305,34 @@ class ViewsAccessTest extends ViewsSqlTest {
 
     return $view;
   }
+
+  /**
+   * Generates a view with an access plugin that doesn't exist.
+   */
+  protected function getMissingAccessPluginTestView() {
+    $view = new view();
+    $view->name = 'test_access_missing';
+    $view->description = '';
+    $view->tag = '';
+    $view->view_php = '';
+    $view->base_table = 'node';
+    $view->is_cacheable = FALSE;
+    $view->api_version = 2;
+    $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+
+    /* Display: Master */
+    $handler = $view->new_display('default', 'Master', 'default');
+    $handler->display->display_options['access']['type'] = 'does_not_exist';
+    $handler->display->display_options['cache']['type'] = 'none';
+    $handler->display->display_options['exposed_form']['type'] = 'basic';
+    $handler->display->display_options['pager']['type'] = 'full';
+    $handler->display->display_options['style_plugin'] = 'default';
+    $handler->display->display_options['row_plugin'] = 'fields';
+
+    $handler = $view->new_display('page', 'Page', 'page_1');
+    $handler->display->display_options['path'] = 'test_access_missing';
+
+    return $view;
+  }
+
 }
diff --git a/drupal7/sites/all/modules/views/tests/views_ajax.test b/drupal7/sites/all/modules/views/tests/views_ajax.test
index 685d09ef..6395044d 100644
--- a/drupal7/sites/all/modules/views/tests/views_ajax.test
+++ b/drupal7/sites/all/modules/views/tests/views_ajax.test
@@ -17,8 +17,12 @@ class ViewsAjaxTest extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp('views', 'views_test');
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     // Create a second node.
     $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
   }
diff --git a/drupal7/sites/all/modules/views/tests/views_analyze.test b/drupal7/sites/all/modules/views/tests/views_analyze.test
index d16103ef..02ea2d59 100644
--- a/drupal7/sites/all/modules/views/tests/views_analyze.test
+++ b/drupal7/sites/all/modules/views/tests/views_analyze.test
@@ -17,9 +17,12 @@ class ViewsAnalyzeTest extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp('views_ui');
-    module_enable(array('views_ui'));
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     // @todo Figure out why it's required to clear the cache here.
     views_module_include('views_default', TRUE);
     views_get_all_views(TRUE);
diff --git a/drupal7/sites/all/modules/views/tests/views_argument_default.test b/drupal7/sites/all/modules/views/tests/views_argument_default.test
index f6e1282e..7dea3805 100644
--- a/drupal7/sites/all/modules/views/tests/views_argument_default.test
+++ b/drupal7/sites/all/modules/views/tests/views_argument_default.test
@@ -9,6 +9,7 @@
  * Basic test for pluggable argument default.
  */
 class ViewsArgumentDefaultTest extends ViewsSqlTest {
+
   public static function getInfo() {
     return array(
       'name' => 'Argument_default',
@@ -17,8 +18,11 @@ class ViewsArgumentDefaultTest extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp('views');
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     $this->random = $this->randomString();
   }
diff --git a/drupal7/sites/all/modules/views/tests/views_clone.test b/drupal7/sites/all/modules/views/tests/views_clone.test
index 7ac10aba..44ba3cf3 100644
--- a/drupal7/sites/all/modules/views/tests/views_clone.test
+++ b/drupal7/sites/all/modules/views/tests/views_clone.test
@@ -33,8 +33,8 @@ class ViewsCloneTest extends ViewsSqlTest {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     $vocabulary = taxonomy_vocabulary_machine_name_load('tags');
     $this->term = $this->createTerm($vocabulary);
diff --git a/drupal7/sites/all/modules/views/tests/views_exposed_form.test b/drupal7/sites/all/modules/views/tests/views_exposed_form.test
index b202564b..d0a87fa6 100644
--- a/drupal7/sites/all/modules/views/tests/views_exposed_form.test
+++ b/drupal7/sites/all/modules/views/tests/views_exposed_form.test
@@ -22,11 +22,11 @@ class ViewsExposedFormTest extends ViewsSqlTest {
   }
 
   /**
-   *
+   * {@inheritdoc}
    */
-  public function setUp() {
-    parent::setUp('views_ui');
-    module_enable(array('views_ui'));
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     // @todo Figure out why it's required to clear the cache here.
     views_module_include('views_default', TRUE);
     views_get_all_views(TRUE);
diff --git a/drupal7/sites/all/modules/views/tests/views_glossary.test b/drupal7/sites/all/modules/views/tests/views_glossary.test
index d7d7c64b..56d4a979 100644
--- a/drupal7/sites/all/modules/views/tests/views_glossary.test
+++ b/drupal7/sites/all/modules/views/tests/views_glossary.test
@@ -6,9 +6,13 @@
  */
 
 /**
- * Tests glossary view ( summary of arguments ).
+ * Tests the glossary feature.
  */
 class ViewsGlossaryTestCase extends ViewsSqlTest {
+
+  /**
+   * {@inheritdoc}
+   */
   public static function getInfo() {
     return array(
       'name' => 'Glossary Test',
@@ -17,17 +21,13 @@ class ViewsGlossaryTestCase extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp('views');
-  }
-
   /**
-   * Tests the default glossary view.
+   * Tests the glossary feature.
    */
   public function testGlossaryView() {
-    // create a contentype and add some nodes, with a non random title.
+    // Create a content type and add some nodes, with a non random title.
     $type = $this->drupalCreateContentType();
-    $nodes_per_char = array(
+    $nodes_per_character = array(
       'd' => 1,
       'r' => 4,
       'u' => 10,
@@ -35,27 +35,146 @@ class ViewsGlossaryTestCase extends ViewsSqlTest {
       'a' => 3,
       'l' => 6,
     );
-    foreach ($nodes_per_char as $char => $count) {
+    $nodes = array();
+    foreach ($nodes_per_character as $character => $count) {
       $setting = array(
         'type' => $type->type,
       );
       for ($i = 0; $i < $count; $i++) {
         $node = $setting;
-        $node['title'] = $char . $this->randomString(3);
-        $this->drupalCreateNode($node);
+        $node['title'] = $character . strtolower($this->randomName());
+        $nodes[$character][] = $this->drupalCreateNode($node);
       }
     }
 
+    // Sort created nodes the same way the view does, so that we can assert
+    // correct node ids for each row in the result set later.
+    foreach ($nodes_per_character as $character => $count) {
+      usort($nodes[$character], function ($a, $b) {
+        return strcmp($a->title, $b->title);
+      });
+    }
+
     // Execute glossary view.
     $view = views_get_view('glossary');
     $view->set_display('attachment');
     $view->execute_display('attachment');
 
-    // Check that the amount of nodes per char.
-    $result_nodes_per_char = array();
+    // Check the amount of nodes per character.
     foreach ($view->result as $item) {
-      $this->assertEqual($nodes_per_char[$item->title_truncated], $item->num_records);
+      $this->assertEqual($nodes_per_character[$item->title_truncated], $item->num_records);
+    }
+    $view->destroy();
+
+    // Checks that a glossary view with an argument containing one letter
+    // returns only and all the nodes that start with that letter.
+    $view = views_get_view('glossary');
+    $view->init_display();
+    $this->executeView($view, array('a'));
+    $result_count = isset($view->result) && is_array($view->result) ? count($view->result) : 0;
+    $this->assertIdentical($result_count, 3, 'View has 3 results.');
+    foreach ($view->result as $delta => $item) {
+      $nid = isset($view->result[$delta]->nid) ? $view->result[$delta]->nid : '0';
+      $this->assertIdentical($nid, $nodes['a'][$delta]->nid, 'View result ' . (string) (int) $delta . ' has correct node id.');
+    }
+    $view->destroy();
+
+    // Checks that a glossary view with an argument containing multiple values
+    // returns only and all nodes that start with these values.
+    $view = views_get_view('glossary');
+    $view->init_display();
+    $arguments = $view->display_handler->get_option('arguments');
+    $arguments['title']['break_phrase'] = TRUE;
+    $view->display_handler->set_option('arguments', $arguments);
+    $this->executeView($view, array('d+p'));
+    $expected_result_count = $nodes_per_character['d'] + $nodes_per_character['p'];
+    $result_count = isset($view->result) && is_array($view->result) ? count($view->result) : 0;
+    $this->assertIdentical($result_count, 3, 'View has 3 results.');
+    $nid = isset($view->result[0]->nid) ? $view->result[0]->nid : '0';
+    $this->assertIdentical($nid, $nodes['d'][0]->nid, 'View result 0 has correct node id.');
+    $nid = isset($view->result[1]->nid) ? $view->result[1]->nid : '0';
+    $this->assertIdentical($nid, $nodes['p'][0]->nid, 'View result 1 has correct node id.');
+    $nid = isset($view->result[2]->nid) ? $view->result[2]->nid : '0';
+    $this->assertIdentical($nid, $nodes['p'][1]->nid, 'View result 2 has correct node id.');
+    $view->destroy();
+
+    // Checks that a glossary view with a phrase as an argument does not
+    // interpret that phrase as multiple values.
+    $view = views_get_view('glossary');
+    $view->init_display();
+    $arguments = $view->display_handler->get_option('arguments');
+    $view->display_handler->set_option('arguments', $arguments);
+    $this->executeView($view, array('d+p'));
+    $result_count = isset($view->result) && is_array($view->result) ? count($view->result) : 1;
+    $this->assertIdentical($result_count, 0, 'View has zero results.');
+    $view->destroy();
+
+    // Checks that a glossary view with an argument containing one letter
+    // excludes all nodes that start with that letter.
+    $view = views_get_view('glossary');
+    $view->init_display();
+    $arguments = $view->display_handler->get_option('arguments');
+    $arguments['title']['not'] = TRUE;
+    $view->display_handler->set_option('arguments', $arguments);
+    $this->executeView($view, array('a'));
+    $result_count = isset($view->result) && is_array($view->result) ? count($view->result) : 0;
+    $this->assertIdentical($result_count, 23, 'View has 23 results.');
+    $character = 'd';
+    $character_delta = 0;
+    foreach ($view->result as $delta => $item) {
+      if ($delta === 1) {
+        $character = 'l';
+        $character_delta = 0;
+      }
+      elseif ($delta === 7) {
+        $character = 'p';
+        $character_delta = 0;
+      }
+      elseif ($delta === 9) {
+        $character = 'r';
+        $character_delta = 0;
+      }
+      elseif ($delta === 13) {
+        $character = 'u';
+        $character_delta = 0;
+      }
+      $nid = isset($view->result[$delta]->nid) ? $view->result[$delta]->nid : '0';
+      $this->assertIdentical($nid, $nodes[$character][$character_delta]->nid, 'View result ' . (string) (int) $delta . ' has correct node id.');
+      $character_delta++;
+    }
+    $view->destroy();
+
+    // Checks that a glossary view with an argument containing multiple values
+    // excludes all nodes that start with these values.
+    $view = views_get_view('glossary');
+    $view->init_display();
+    $arguments = $view->display_handler->get_option('arguments');
+    $arguments['title']['break_phrase'] = TRUE;
+    $arguments['title']['not'] = TRUE;
+    $view->display_handler->set_option('arguments', $arguments);
+    $this->executeView($view, array('a+p'));
+    $result_count = isset($view->result) && is_array($view->result) ? count($view->result) : 0;
+    $this->assertIdentical($result_count, 21, 'View has 21 results.');
+    $character = 'd';
+    $character_delta = 0;
+    foreach ($view->result as $delta => $item) {
+      if ($delta === 1) {
+        $character = 'l';
+        $character_delta = 0;
+      }
+      elseif ($delta === 7) {
+        $character = 'r';
+        $character_delta = 0;
+      }
+      elseif ($delta === 11) {
+        $character = 'u';
+        $character_delta = 0;
+      }
+      $nid = isset($view->result[$delta]->nid) ? $view->result[$delta]->nid : '0';
+      $this->assertIdentical($nid, $nodes[$character][$character_delta]->nid, 'View result ' . (string) (int) $delta . ' has correct node id.');
+      $character_delta++;
     }
+    $view->destroy();
   }
 
 }
diff --git a/drupal7/sites/all/modules/views/tests/views_groupby.test b/drupal7/sites/all/modules/views/tests/views_groupby.test
index 364e61b3..2c873ad8 100644
--- a/drupal7/sites/all/modules/views/tests/views_groupby.test
+++ b/drupal7/sites/all/modules/views/tests/views_groupby.test
@@ -435,9 +435,11 @@ class ViewsUiGroupbyTestCase extends DrupalWebTestCase {
   /**
    * {@inheritdoc}
    */
-  function setUp() {
-    // Enable views_ui.
-    parent::setUp('views_ui', 'views_test');
+  public function setUp(array $modules = array()) {
+    $modules[] = 'views';
+    $modules[] = 'views_ui';
+    $modules[] = 'views_test';
+    parent::setUp($modules);
 
     // Create and log in a user with administer views permission.
     $views_admin = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view revisions'));
diff --git a/drupal7/sites/all/modules/views/tests/views_handler_filter.test b/drupal7/sites/all/modules/views/tests/views_handler_filter.test
index e41b35a3..69fdb822 100644
--- a/drupal7/sites/all/modules/views/tests/views_handler_filter.test
+++ b/drupal7/sites/all/modules/views/tests/views_handler_filter.test
@@ -24,9 +24,8 @@ class ViewsHandlerFilterTest extends ViewsSqlTest {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
-    // The Views and Views UI modules will be enabled with this.
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Assign vocabulary 'tag' to user entity.
     $field_definition = field_read_field('field_tags');
diff --git a/drupal7/sites/all/modules/views/tests/views_handlers.test b/drupal7/sites/all/modules/views/tests/views_handlers.test
index e0ace985..ee19d197 100644
--- a/drupal7/sites/all/modules/views/tests/views_handlers.test
+++ b/drupal7/sites/all/modules/views/tests/views_handlers.test
@@ -17,11 +17,6 @@ class ViewsHandlersTest extends ViewsSqlTest {
     );
   }
 
-  protected function setUp() {
-    parent::setUp('views', 'views_ui');
-    module_enable(array('views_ui'));
-  }
-
   function testFilterInOperatorUi() {
     $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration'));
     $this->drupalLogin($admin_user);
diff --git a/drupal7/sites/all/modules/views/tests/views_module.test b/drupal7/sites/all/modules/views/tests/views_module.test
index c3dd9947..cfa93ab7 100644
--- a/drupal7/sites/all/modules/views/tests/views_module.test
+++ b/drupal7/sites/all/modules/views/tests/views_module.test
@@ -17,8 +17,12 @@ class ViewsModuleTest extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     drupal_theme_rebuild();
   }
 
diff --git a/drupal7/sites/all/modules/views/tests/views_pager.test b/drupal7/sites/all/modules/views/tests/views_pager.test
index 7a99fb67..ac7658ed 100644
--- a/drupal7/sites/all/modules/views/tests/views_pager.test
+++ b/drupal7/sites/all/modules/views/tests/views_pager.test
@@ -21,13 +21,6 @@ class ViewsPagerTest extends ViewsSqlTest {
     );
   }
 
-  /**
-   *
-   */
-  public function setUp() {
-    parent::setUp('views', 'views_ui', 'views_test');
-  }
-
   /**
    * Pagers was sometimes not stored.
    *
diff --git a/drupal7/sites/all/modules/views/tests/views_query.test b/drupal7/sites/all/modules/views/tests/views_query.test
index ed10f3be..b2f00291 100644
--- a/drupal7/sites/all/modules/views/tests/views_query.test
+++ b/drupal7/sites/all/modules/views/tests/views_query.test
@@ -179,8 +179,10 @@ abstract class ViewsSqlTest extends ViewsTestCase {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
-    parent::setUp('views', 'views_ui');
+  public function setUp(array $modules = array()) {
+    $modules[] = 'views';
+    $modules[] = 'views_ui';
+    parent::setUp($modules);
 
     // Define the schema and views data variable before enabling the test
     // module.
diff --git a/drupal7/sites/all/modules/views/tests/views_test.info b/drupal7/sites/all/modules/views/tests/views_test.info
index d7e79211..d3ce59dd 100644
--- a/drupal7/sites/all/modules/views/tests/views_test.info
+++ b/drupal7/sites/all/modules/views/tests/views_test.info
@@ -5,8 +5,8 @@ core = 7.x
 dependencies[] = views
 hidden = TRUE
 
-; Information added by Drupal.org packaging script on 2019-05-10
-version = "7.x-3.23"
+; Information added by Drupal.org packaging script on 2020-03-07
+version = "7.x-3.24"
 core = "7.x"
 project = "views"
-datestamp = "1557505389"
+datestamp = "1583615732"
diff --git a/drupal7/sites/all/modules/views/tests/views_translatable.test b/drupal7/sites/all/modules/views/tests/views_translatable.test
index 9c3422c7..7e68acc5 100644
--- a/drupal7/sites/all/modules/views/tests/views_translatable.test
+++ b/drupal7/sites/all/modules/views/tests/views_translatable.test
@@ -37,8 +37,11 @@ class ViewsTranslatableTest extends ViewsSqlTest {
     );
   }
 
-  public function setUp() {
-    parent::setUp();
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     variable_set('views_localization_plugin', 'test');
     // Reset the plugin data.
diff --git a/drupal7/sites/all/modules/views/tests/views_ui.test b/drupal7/sites/all/modules/views/tests/views_ui.test
index 8a7e0e16..81a662c5 100644
--- a/drupal7/sites/all/modules/views/tests/views_ui.test
+++ b/drupal7/sites/all/modules/views/tests/views_ui.test
@@ -11,11 +11,11 @@
 class ViewsUIWizardHelper extends DrupalWebTestCase {
 
   /**
-   *
+   * {@inheritdoc}
    */
-  function setUp() {
-    // Enable views_ui.
-    parent::setUp('views_ui');
+  public function setUp(array $modules = array()) {
+    $modules[] = 'views_ui';
+    parent::setUp($modules);
 
     // Create and log in a user with administer views permission.
     $views_admin = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view revisions'));
@@ -317,8 +317,8 @@ class ViewsUIWizardTaggedWithTestCase extends ViewsUIWizardHelper {
   /**
    * {@inheritdoc}
    */
-  function setUp() {
-    parent::setUp();
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
 
     // Create two content types. One will have an autocomplete tagging field,
     // and one won't.
diff --git a/drupal7/sites/all/modules/views/tests/views_upgrade.test b/drupal7/sites/all/modules/views/tests/views_upgrade.test
index 0c4da8fb..0b3c17f2 100644
--- a/drupal7/sites/all/modules/views/tests/views_upgrade.test
+++ b/drupal7/sites/all/modules/views/tests/views_upgrade.test
@@ -26,11 +26,11 @@ class ViewsUpgradeTestCase extends ViewsSqlTest {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  public function setUp(array $modules = array()) {
+    parent::setUp($modules);
+
     // To import a view the user needs use PHP for settings rights, so enable
     // PHP module.
-    parent::setUp();
-
     module_enable(array('php'));
     $this->resetAll();
   }
diff --git a/drupal7/sites/all/modules/views/views.info b/drupal7/sites/all/modules/views/views.info
index a857b233..df73eacc 100644
--- a/drupal7/sites/all/modules/views/views.info
+++ b/drupal7/sites/all/modules/views/views.info
@@ -268,7 +268,6 @@ files[] = plugins/views_plugin_style_table.inc
 files[] = tests/handlers/views_handlers.test
 files[] = tests/handlers/views_handler_area_text.test
 files[] = tests/handlers/views_handler_argument_null.test
-files[] = tests/handlers/views_handler_argument_string.test
 files[] = tests/handlers/views_handler_field.test
 files[] = tests/handlers/views_handler_field_boolean.test
 files[] = tests/handlers/views_handler_field_custom.test
@@ -331,8 +330,8 @@ files[] = tests/views_clone.test
 files[] = tests/views_view.test
 files[] = tests/views_ui.test
 
-; Information added by Drupal.org packaging script on 2019-05-10
-version = "7.x-3.23"
+; Information added by Drupal.org packaging script on 2020-03-07
+version = "7.x-3.24"
 core = "7.x"
 project = "views"
-datestamp = "1557505389"
+datestamp = "1583615732"
diff --git a/drupal7/sites/all/modules/views/views.module b/drupal7/sites/all/modules/views/views.module
index aa407f02..d37bfda9 100644
--- a/drupal7/sites/all/modules/views/views.module
+++ b/drupal7/sites/all/modules/views/views.module
@@ -2197,6 +2197,97 @@ function views_form_views_exposed_form_alter(&$form, &$form_state) {
   $form['form_build_id']['#access'] = FALSE;
   $form['form_token']['#access'] = FALSE;
   $form['form_id']['#access'] = FALSE;
+
+  // AJAX behaviors need these data, so we add it back in #after_build.
+  $form['#after_build'][] = 'views_exposed_form_ajax_enable';
+}
+
+/**
+ * Checks whether the exposed form will use AJAX.
+ *
+ * Passes required form information removed in
+ * views_form_views_exposed_form_alter().
+ *
+ * @param array $form
+ *   The form being processed.
+ * @param array $form_state
+ *   The form state.
+ *
+ * @return array
+ *   The form being processed.
+ */
+function views_exposed_form_ajax_enable(array &$form, array &$form_state) {
+  // In order for AJAX to work the form build info is needed. Here check if
+  // #ajax has been added to any form elements, and if so, pass this info as
+  // settings via JavaScript, which get attached to the submitted form on AJAX
+  // form submissions. #ajax property can be set not only for the first level of
+  // the form, so look for it in the whole form.
+  $ajax_info = array();
+  $ajax_elements = views_exposed_form_ajax_lookup_recursive($form);
+  // Determine if form is being processed.
+  $triggering_element_name = '';
+  if (!empty($form_state['input']['_triggering_element_name'])) {
+    $triggering_element_name = $form_state['input']['_triggering_element_name'];
+  }
+
+  // When there are multiple elements with #ajax set on exposed form, pass only
+  // triggering element name to JavaScript, otherwise #ajax will work only for
+  // the first element.
+  if (!empty($triggering_element_name) && !empty($ajax_elements)) {
+    // Check if element has #ajax property set.
+    if (in_array($triggering_element_name, $ajax_elements)) {
+      $ajax_elements = array(
+        $triggering_element_name => $triggering_element_name,
+      );
+    }
+    else {
+      $ajax_elements = array();
+    }
+  }
+
+  if (!empty($ajax_elements)) {
+    $form_info = array(
+      'form_id' => $form['#form_id'],
+      'form_build_id' => $form['#build_id'],
+    );
+    // Anonymous users don't get a token.
+    if (!empty($form['#token'])) {
+      $form_info['form_token'] = drupal_get_token($form['#token']);
+    }
+    foreach ($ajax_elements as $element_name) {
+      $ajax_info[$element_name] = $form_info;
+    }
+    drupal_add_js(array('ViewsExposedFormInfo' => $ajax_info), 'setting');
+
+    // Add the javascript behavior that will handle this data.
+    $form['#attached']['js'][] = array(
+      'weight' => 100,
+      'data' => drupal_get_path('module', 'views') . '/js/exposed-form-ajax.js',
+    );
+  }
+
+  return $form;
+}
+
+/**
+ * Recursively looks for the #ajax property for every form elemet.
+ *
+ * @param array $elements
+ *   The element array to look for #ajax property.
+ *
+ * @return array
+ *   Array of the elements names where #ajax was found.
+ */
+function views_exposed_form_ajax_lookup_recursive(array $elements) {
+  $ajax_elements = array();
+  foreach (element_children($elements) as $key) {
+    if (!empty($elements[$key]['#name']) && !empty($elements[$key]['#ajax'])) {
+      $ajax_elements[$elements[$key]['#name']] = $elements[$key]['#name'];
+    }
+    // Recursive call to look for #ajax in element's childrens.
+    $ajax_elements += views_exposed_form_ajax_lookup_recursive($elements[$key]);
+  }
+  return $ajax_elements;
 }
 
 /**
diff --git a/drupal7/sites/all/modules/views/views_ui.info b/drupal7/sites/all/modules/views/views_ui.info
index 7a8e5383..88549716 100644
--- a/drupal7/sites/all/modules/views/views_ui.info
+++ b/drupal7/sites/all/modules/views/views_ui.info
@@ -8,8 +8,8 @@ dependencies[] = views
 files[] = views_ui.module
 files[] = plugins/views_wizard/views_ui_base_views_wizard.class.php
 
-; Information added by Drupal.org packaging script on 2019-05-10
-version = "7.x-3.23"
+; Information added by Drupal.org packaging script on 2020-03-07
+version = "7.x-3.24"
 core = "7.x"
 project = "views"
-datestamp = "1557505389"
+datestamp = "1583615732"
