From 72ede2d7fc1b36bce20a34863ca8e30e48588f49 Mon Sep 17 00:00:00 2001
From: catch <6915-catch@users.noreply.drupalcode.org>
Date: Thu, 23 Jan 2025 20:24:00 +0000
Subject: [PATCH] Issue #3458099 by scott_euser, catch, smustgrave: Views
 handler loading should respect configuration

---
 .../rest_test_views/rest_test_views.install   |  21 +++
 ...ws.view.test_serializer_display_entity.yml |  46 ++++--
 ...ews.view.test_serializer_display_field.yml |  96 +++++++-----
 .../Views/StyleSerializerEntityTest.php       |   1 +
 .../views/src/Plugin/ViewsHandlerManager.php  |  24 ++-
 .../views.view.test_block_exposed_ajax.yml    |   2 +-
 ...view.test_block_exposed_ajax_with_page.yml |   2 +-
 .../test_views/views.view.test_click_sort.yml |  45 +++---
 .../views.view.test_click_sort_ajax.yml       | 144 +++++++++++++++---
 ...view.test_entity_test_protected_access.yml |   2 +-
 .../views.view.test_exposed_block.yml         |  85 +++++++----
 .../views.view.test_exposed_form_buttons.yml  |  74 +++++----
 ...iews.view.test_exposed_form_checkboxes.yml |  76 ++++-----
 .../views.view.test_exposed_form_pager.yml    |   2 +-
 .../views.view.test_filter_in_operator_ui.yml |   2 +-
 .../test_views/views.view.test_history.yml    |   5 +-
 .../views.view.test_remember_selected.yml     |   2 +-
 .../views_test_data_alter.info.yml            |   7 +
 .../views_test_data_alter.views.inc           |  19 +++
 .../Functional/Entity/BaseFieldAccessTest.php |   9 --
 .../src/Functional/Handler/HandlerTest.php    |   6 +
 .../Plugin/ExposedFormCheckboxesTest.php      |   2 +-
 .../src/Functional/Plugin/ExposedFormTest.php |   2 +-
 .../Kernel/Handler/FieldTimeIntervalTest.php  |  15 +-
 .../views/tests/src/Kernel/ModuleTest.php     |  13 +-
 .../Kernel/Plugin/ExposedFormRenderTest.php   | 107 ++++---------
 26 files changed, 517 insertions(+), 292 deletions(-)
 create mode 100644 core/modules/rest/tests/modules/rest_test_views/rest_test_views.install
 create mode 100644 core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.info.yml
 create mode 100644 core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.views.inc

diff --git a/core/modules/rest/tests/modules/rest_test_views/rest_test_views.install b/core/modules/rest/tests/modules/rest_test_views/rest_test_views.install
new file mode 100644
index 000000000000..edc5a585f84d
--- /dev/null
+++ b/core/modules/rest/tests/modules/rest_test_views/rest_test_views.install
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Install function for the Rest Test Views module.
+ */
+
+declare(strict_types=1);
+
+use Drupal\views\Tests\ViewTestData;
+
+/**
+ * Implements hook_install().
+ */
+function rest_test_views_install(): void {
+
+  // Install the state and schema by for views test data.
+  \Drupal::state()->set('views_test_data_schema', ViewTestData::schemaDefinition());
+  \Drupal::state()->set('views_test_data_views_data', ViewTestData::viewsData());
+  drupal_flush_all_caches();
+}
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
index 9444338650fa..8612f65df475 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_entity.yml
@@ -2,7 +2,9 @@ langcode: en
 status: true
 dependencies:
   module:
+    - entity_test
     - rest
+    - serialization
     - user
 id: test_serializer_display_entity
 label: 'Test serialize display entity rows'
@@ -13,42 +15,60 @@ base_table: entity_test
 base_field: id
 display:
   default:
-    display_plugin: default
     id: default
     display_title: Default
+    display_plugin: default
     position: null
     display_options:
+      title: 'Test serialize'
+      exposed_form:
+        type: basic
       access:
         type: perm
         options:
           perm: 'access content'
       cache:
         type: tag
-      query:
-        type: views_query
-      exposed_form:
-        type: basic
-      style:
-        type: serializer
-      row:
-        type: data_entity
       sorts:
         id:
           id: standard
           table: entity_test
           field: id
-          order: DESC
-          plugin_id: date
           entity_type: entity_test
           entity_field: id
-      title: 'Test serialize'
+          plugin_id: date
+          order: DESC
       arguments: {  }
+      style:
+        type: serializer
+      row:
+        type: data_entity
+      query:
+        type: views_query
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - entity_test_view_grants
+        - 'languages:language_interface'
+        - request_format
+        - url.query_args
+        - user.permissions
+      tags: {  }
   rest_export_1:
-    display_plugin: rest_export
     id: rest_export_1
     display_title: serializer
+    display_plugin: rest_export
     position: null
     display_options:
       defaults:
         access: false
+      display_extenders: {  }
       path: test/serialize/entity
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - entity_test_view_grants
+        - 'languages:language_interface'
+        - request_format
+      tags: {  }
diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
index 414de42d6b19..cac819a38727 100644
--- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
+++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_serializer_display_field.yml
@@ -3,7 +3,9 @@ status: true
 dependencies:
   module:
     - rest
+    - serialization
     - user
+    - views_test_data
 id: test_serializer_display_field
 label: 'Test serializer display field rows'
 module: rest
@@ -13,32 +15,19 @@ base_table: views_test_data
 base_field: id
 display:
   default:
-    display_plugin: default
     id: default
     display_title: Default
+    display_plugin: default
     position: null
     display_options:
-      access:
-        type: perm
-        options:
-          perm: 'access content'
-      cache:
-        type: tag
-      query:
-        type: views_query
-      exposed_form:
-        type: basic
-      style:
-        type: serializer
-      row:
-        type: data_field
+      title: 'Test serialize'
       fields:
         name:
           id: name
           table: views_test_data
           field: name
-          label: ''
           plugin_id: string
+          label: ''
         nothing:
           id: nothing
           table: views
@@ -56,49 +45,71 @@ display:
           id: created
           table: views_test_data
           field: created
-          type: timestamp
-          settings:
-            date_format: medium
-            custom_date_format: ''
-            timezone: ''
-          plugin_id: field
+          plugin_id: date
+          date_format: timestamp
+          custom_date_format: ''
+          timezone: ''
+      exposed_form:
+        type: basic
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
       sorts:
         created:
           id: created
           table: views_test_data
           field: created
-          order: DESC
           plugin_id: date
-      title: 'Test serialize'
+          order: DESC
       arguments: {  }
+      style:
+        type: serializer
+      row:
+        type: data_field
+      query:
+        type: views_query
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - request_format
+        - url.query_args
+        - user.permissions
+      tags: {  }
   rest_export_1:
-    display_plugin: rest_export
     id: rest_export_1
     display_title: serializer
+    display_plugin: rest_export
     position: null
     display_options:
-      defaults:
-        access: false
-        style: false
-        row: false
-      path: test/serialize/field
       access:
         type: none
       style:
         type: serializer
       row:
         type: data_field
+      defaults:
+        access: false
+        style: false
+        row: false
+      display_extenders: {  }
+      path: test/serialize/field
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - request_format
+      tags: {  }
   rest_export_2:
-    display_plugin: rest_export
     id: rest_export_2
     display_title: 'serialize - access denied'
+    display_plugin: rest_export
     position: null
     display_options:
-      defaults:
-        access: false
-        style: false
-        row: false
-      path: test/serialize/denied
       access:
         type: perm
         options:
@@ -107,3 +118,16 @@ display:
         type: serializer
       row:
         type: data_field
+      defaults:
+        access: false
+        style: false
+        row: false
+      display_extenders: {  }
+      path: test/serialize/denied
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - request_format
+        - user.permissions
+      tags: {  }
diff --git a/core/modules/rest/tests/src/Functional/Views/StyleSerializerEntityTest.php b/core/modules/rest/tests/src/Functional/Views/StyleSerializerEntityTest.php
index 01ffcc139059..019a03335d23 100644
--- a/core/modules/rest/tests/src/Functional/Views/StyleSerializerEntityTest.php
+++ b/core/modules/rest/tests/src/Functional/Views/StyleSerializerEntityTest.php
@@ -41,6 +41,7 @@ class StyleSerializerEntityTest extends ViewTestBase {
     'field',
     'language',
     'basic_auth',
+    'views_test_data',
   ];
 
   /**
diff --git a/core/modules/views/src/Plugin/ViewsHandlerManager.php b/core/modules/views/src/Plugin/ViewsHandlerManager.php
index a8a3fdae9046..8bd3d243c39b 100644
--- a/core/modules/views/src/Plugin/ViewsHandlerManager.php
+++ b/core/modules/views/src/Plugin/ViewsHandlerManager.php
@@ -105,6 +105,7 @@ public function getHandler(array $item, ?string $override_plugin_id = NULL): Vie
         }
       }
 
+      // First priority is to use the override.
       // When aggregation is enabled, particular plugins need to be
       // replaced in order to override the query with a query that
       // can run the aggregate counts, sums, or averages for example.
@@ -112,13 +113,24 @@ public function getHandler(array $item, ?string $override_plugin_id = NULL): Vie
       // for example which aggressively overrides any filter used
       // by a number of mathematical-type queries regardless of the
       // original filter.
-      $plugin_id = $override_plugin_id ?: $definition['id'];
-      // Try to use the overridden handler.
-      $handler = $this->createInstance($plugin_id, $definition);
-      if ($override_plugin_id && method_exists($handler, 'broken') && $handler->broken()) {
-        $handler = $this->createInstance($definition['id'], $definition);
+      if ($override_plugin_id) {
+        $handler = $this->createInstance($override_plugin_id, $definition);
+        if (!method_exists($handler, 'broken') || !$handler->broken()) {
+          return $handler;
+        }
       }
-      return $handler;
+
+      // Then try the configuration provided for the handler.
+      if (isset($item['plugin_id'])) {
+        $handler = $this->createInstance($item['plugin_id'], $definition);
+        if (!method_exists($handler, 'broken') || !$handler->broken()) {
+          return $handler;
+        }
+      }
+
+      // Finally, fall back to the default configuration suggested
+      // by the view data.
+      return $this->createInstance($definition['id'], $definition);
     }
 
     // Finally, use the 'broken' handler.
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax.yml
index 649b5fe8abde..69e49097ad17 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax.yml
@@ -35,7 +35,7 @@ display:
           field: type
           id: type
           table: node_field_data
-          plugin_id: in_operator
+          plugin_id: bundle
           entity_type: node
           entity_field: type
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax_with_page.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax_with_page.yml
index c484c6b1389e..ab6321d8b6f2 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax_with_page.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_block_exposed_ajax_with_page.yml
@@ -35,7 +35,7 @@ display:
           field: type
           id: type
           table: node_field_data
-          plugin_id: in_operator
+          plugin_id: bundle
           entity_type: node
           entity_field: type
       pager:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
index 3ab5ecb66894..5aaa351c1ae2 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort.yml
@@ -1,40 +1,44 @@
 langcode: en
 status: true
-dependencies: {  }
+dependencies:
+  module:
+    - user
+    - views_test_data
 id: test_click_sort
 label: test_click_sort
 module: views
 description: ''
 tag: ''
 base_table: views_test_data
-base_field: nid
+base_field: id
 display:
   default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: null
     display_options:
       fields:
         id:
           id: id
           table: views_test_data
           field: id
-          label: ID
           plugin_id: numeric
+          label: ID
         name:
           id: name
           table: views_test_data
           field: name
-          label: Name
           plugin_id: string
+          label: ''
         created:
           id: created
           table: views_test_data
           field: created
-          label: created
-          plugin_id: field
-          type: timestamp
-          settings:
-            date_format: medium
-            custom_date_format: ''
-            timezone: ''
+          plugin_id: date
+          date_format: timestamp
+          custom_date_format: ''
+          timezone: ''
       access:
         type: none
       cache:
@@ -51,14 +55,17 @@ display:
               default_sort_order: desc
             created:
               sortable: false
-    display_plugin: default
-    display_title: Default
-    id: default
-    position: 0
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url.query_args
+        - user.permissions
+      tags: {  }
   page_1:
-    display_options:
-      path: test_click_sort
-    display_plugin: page
-    display_title: Page
     id: page_1
+    display_title: Page
+    display_plugin: page
     position: 0
+    display_options:
+      path: test_click_sort
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml
index bf65e0eaf379..534e3eaecbac 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml
@@ -1,41 +1,105 @@
 langcode: en
 status: true
-dependencies: {  }
+dependencies:
+  module:
+    - views_test_data
 id: test_click_sort_ajax
 label: test_click_sort_ajax
 module: views
 description: ''
 tag: ''
 base_table: views_test_data
-base_field: nid
+base_field: id
 display:
   default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: null
     display_options:
-      use_ajax: true
       fields:
         id:
           id: id
           table: views_test_data
           field: id
-          label: ID
           plugin_id: numeric
+          label: ID
         name:
           id: name
           table: views_test_data
           field: name
-          label: Name
+          relationship: none
+          group_type: group
+          admin_label: ''
           plugin_id: string
+          label: Name
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
         created:
           id: created
           table: views_test_data
           field: created
-          label: created
-          plugin_id: field
-          type: timestamp
-          settings:
-            date_format: medium
-            custom_date_format: ''
-            timezone: ''
+          plugin_id: date
+          date_format: timestamp
+          custom_date_format: ''
+          timezone: ''
+      pager:
+        type: mini
+        options:
+          offset: 0
+          pagination_heading_level: h4
+          items_per_page: 1
+          total_pages: null
+          id: 0
+          tags:
+            next: 'Next ›'
+            previous: '‹ Previous'
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
       access:
         type: none
       cache:
@@ -43,23 +107,61 @@ display:
       style:
         type: table
         options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          columns:
+            id: id
+            name: name
+            created: created
+          default: id
           info:
             id:
-              sortable: true
+              sortable: false
               default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
             name:
               sortable: true
               default_sort_order: desc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
             created:
               sortable: false
-    display_plugin: default
-    display_title: Default
-    id: default
-    position: 0
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+          override: true
+          sticky: false
+          summary: ''
+          empty_table: false
+          caption: ''
+          description: ''
+      use_ajax: true
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url.query_args
+      tags: {  }
   page_1:
-    display_options:
-      path: test_click_sort
-    display_plugin: page
-    display_title: Page
     id: page_1
+    display_title: Page
+    display_plugin: page
     position: 0
+    display_options:
+      display_extenders: {  }
+      path: test_click_sort
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url.query_args
+      tags: {  }
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
index a41124d71e84..1a3bf61bc688 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_test_protected_access.yml
@@ -86,7 +86,7 @@ display:
           exclude: false
           entity_type: entity_test
           entity_field: test_text_access
-          plugin_id: standard
+          plugin_id: field
           empty: ''
           hide_empty: false
           empty_zero: false
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
index 2df02b0b6633..ebcf5c9f704d 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_block.yml
@@ -1,6 +1,8 @@
 langcode: en
 status: true
 dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
   module:
     - node
 id: test_exposed_block
@@ -12,66 +14,83 @@ base_table: node_field_data
 base_field: nid
 display:
   default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
     display_options:
       title: 'Test Exposed Block'
+      pager:
+        type: full
+      exposed_form:
+        type: basic
+        options:
+          reset_button: true
       access:
         type: none
       cache:
         type: tag
-      exposed_form:
-        options:
-          reset_button: true
-        type: basic
       filters:
         type:
-          expose:
-            identifier: type
-            label: 'Content: Type'
-            operator_id: type_op
-            reduce: false
-          exposed: true
-          field: type
           id: type
           table: node_field_data
-          plugin_id: in_operator
+          field: type
           entity_type: node
           entity_field: type
-      pager:
-        type: full
-      query:
-        options:
-          query_comment: ''
-        type: views_query
+          plugin_id: bundle
+          exposed: true
+          expose:
+            operator_id: type_op
+            label: 'Content: Type'
+            identifier: type
+            reduce: false
       style:
         type: default
       row:
         type: 'entity:node'
-    display_plugin: default
-    display_title: Default
-    id: default
-    position: 0
-  page_1:
-    display_options:
-      path: test_exposed_block
-      exposed_block: true
-    display_plugin: page
-    display_title: Page
-    id: page_1
-    position: 0
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - 'user.node_grants:view'
+      tags: {  }
   block_1:
-    display_plugin: block
     id: block_1
     display_title: Block
+    display_plugin: block
     position: 2
     display_options:
+      exposed_block: true
       display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - 'user.node_grants:view'
+      tags: {  }
+  page_1:
+    id: page_1
+    display_title: Page
+    display_plugin: page
+    position: 0
+    display_options:
       exposed_block: true
+      display_extenders: {  }
+      path: test_exposed_block
     cache_metadata:
       max-age: -1
       contexts:
-        - 'languages:language_content'
         - 'languages:language_interface'
+        - url
         - url.query_args
         - 'user.node_grants:view'
-        - user.permissions
       tags: {  }
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
index 9a3605845e80..89b658d11dc3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_buttons.yml
@@ -1,6 +1,8 @@
 langcode: en
 status: true
 dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
   module:
     - node
 id: test_exposed_form_buttons
@@ -12,48 +14,66 @@ base_table: node_field_data
 base_field: nid
 display:
   default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
     display_options:
+      pager:
+        type: full
+      exposed_form:
+        type: basic
+        options:
+          reset_button: true
       access:
         type: none
       cache:
         type: tag
-      exposed_form:
-        options:
-          reset_button: true
-        type: basic
       filters:
         type:
-          expose:
-            identifier: type
-            label: 'Content: Type'
-            operator_id: type_op
-            reduce: false
-            description: 'Exposed description'
-          exposed: true
-          field: type
           id: type
           table: node_field_data
-          plugin_id: in_operator
+          field: type
           entity_type: node
           entity_field: type
-      pager:
-        type: full
-      query:
-        options:
-          query_comment: ''
-        type: views_query
+          plugin_id: bundle
+          exposed: true
+          expose:
+            operator_id: type_op
+            label: 'Content: Type'
+            description: 'Exposed description'
+            identifier: type
+            reduce: false
       style:
         type: default
       row:
         type: 'entity:node'
-    display_plugin: default
-    display_title: Default
-    id: default
-    position: 0
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - 'user.node_grants:view'
+      tags: {  }
   page_1:
-    display_options:
-      path: test_exposed_form_buttons
-    display_plugin: page
-    display_title: Page
     id: page_1
+    display_title: Page
+    display_plugin: page
     position: 0
+    display_options:
+      display_extenders: {  }
+      path: test_exposed_form_buttons
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - 'user.node_grants:view'
+      tags: {  }
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_checkboxes.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_checkboxes.yml
index a61c0adb625c..bd45360bc7b9 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_checkboxes.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_checkboxes.yml
@@ -2,7 +2,8 @@ langcode: en
 status: true
 dependencies:
   config:
-    - taxonomy.vocabulary.test_exposed_checkboxes
+    - core.entity_view_mode.node.teaser
+    - taxonomy.vocabulary.tags
   module:
     - node
     - taxonomy
@@ -15,33 +16,44 @@ base_table: node_field_data
 base_field: nid
 display:
   default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
     display_options:
+      pager:
+        type: full
+      exposed_form:
+        type: basic
+        options:
+          reset_button: true
       access:
         type: none
       cache:
         type: tag
-      exposed_form:
-        options:
-          reset_button: true
-        type: basic
       filters:
-        type:
-          id: type
+        type_1:
+          id: type_1
           table: node_field_data
           field: type
           relationship: none
           group_type: group
           admin_label: ''
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
           operator: in
           value: {  }
           group: 1
           exposed: true
           expose:
-            operator_id: type_op
-            label: 'Content: Type'
-            description: 'Exposed description'
+            operator_id: type_1_op
+            label: 'Content type'
+            description: ''
             use_operator: false
-            operator: ''
+            operator: type_1_op
+            operator_limit_selection: false
+            operator_list: {  }
             identifier: type
             required: false
             remember: false
@@ -49,6 +61,7 @@ display:
             remember_roles:
               authenticated: authenticated
               anonymous: '0'
+              content_editor: '0'
               administrator: '0'
             reduce: false
           is_grouped: false
@@ -63,9 +76,6 @@ display:
             default_group: All
             default_group_multiple: {  }
             group_items: {  }
-          plugin_id: in_operator
-          entity_type: node
-          entity_field: type
         tid:
           id: tid
           table: taxonomy_index
@@ -73,6 +83,7 @@ display:
           relationship: none
           group_type: group
           admin_label: ''
+          plugin_id: taxonomy_index_tid
           operator: and
           value: {  }
           group: 1
@@ -83,6 +94,8 @@ display:
             description: ''
             use_operator: false
             operator: tid_op
+            operator_limit_selection: false
+            operator_list: {  }
             identifier: tid
             required: false
             remember: false
@@ -105,50 +118,45 @@ display:
             default_group_multiple: {  }
             group_items: {  }
           reduce_duplicates: false
+          vid: tags
           type: select
-          limit: true
-          vid: test_exposed_checkboxes
           hierarchy: false
+          limit: true
           error_message: true
-          plugin_id: taxonomy_index_tid
-      pager:
-        type: full
-      query:
-        options:
-          query_comment: ''
-        type: views_query
+      filter_groups:
+        operator: AND
+        groups:
+          1: AND
       style:
         type: default
       row:
         type: 'entity:node'
+      query:
+        type: views_query
+        options:
+          query_comment: ''
       display_extenders: {  }
-    display_plugin: default
-    display_title: Default
-    id: default
-    position: 0
     cache_metadata:
       max-age: -1
       contexts:
         - 'languages:language_interface'
         - url
         - url.query_args
-        - user
         - 'user.node_grants:view'
       tags: {  }
   page_1:
-    display_options:
-      path: test_exposed_form_checkboxes
-      display_extenders: {  }
-    display_plugin: page
-    display_title: Page
     id: page_1
+    display_title: Page
+    display_plugin: page
     position: 0
+    display_options:
+      display_extenders: {  }
+      path: test_exposed_form_checkboxes
     cache_metadata:
       max-age: -1
       contexts:
         - 'languages:language_interface'
         - url
         - url.query_args
-        - user
         - 'user.node_grants:view'
       tags: {  }
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_pager.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_pager.yml
index d091ef676222..c6565810be25 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_pager.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_exposed_form_pager.yml
@@ -62,7 +62,7 @@ display:
             default_group: All
             default_group_multiple: {  }
             group_items: {  }
-          plugin_id: in_operator
+          plugin_id: bundle
           entity_type: node
           entity_field: type
         created:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
index 44177e0e186a..3299d7ea86ad 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
@@ -63,7 +63,7 @@ display:
           field: type
           id: type
           table: node_field_data
-          plugin_id: in_operator
+          plugin_id: bundle
           entity_type: node
           entity_field: type
         nid:
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
index c2b25fff9697..d67f17051828 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_history.yml
@@ -188,8 +188,7 @@ display:
           group_type: group
           admin_label: ''
           operator: '='
-          value:
-            value: ''
+          value: ''
           group: 1
           exposed: false
           expose:
@@ -216,7 +215,7 @@ display:
             default_group: All
             default_group_multiple: {  }
             group_items: {  }
-          plugin_id: date
+          plugin_id: history_user_timestamp
       defaults:
         filters: false
         filter_groups: false
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_remember_selected.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_remember_selected.yml
index 11b3ceec29c2..6113f4337fad 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_remember_selected.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_remember_selected.yml
@@ -40,7 +40,7 @@ display:
           admin_label: ''
           entity_type: node
           entity_field: type
-          plugin_id: in_operator
+          plugin_id: bundle
           operator: in
           value: {  }
           group: 1
diff --git a/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.info.yml b/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.info.yml
new file mode 100644
index 000000000000..ac3d0bbb1217
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.info.yml
@@ -0,0 +1,7 @@
+name: 'Views Test Data Alter'
+type: module
+description: 'Test module for Views to alter data.'
+package: Testing
+version: VERSION
+dependencies:
+  - drupal:views
diff --git a/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.views.inc b/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.views.inc
new file mode 100644
index 000000000000..690a88b61d60
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_data_alter/views_test_data_alter.views.inc
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Provides views data alter isolated hook.
+ */
+
+declare(strict_types=1);
+
+/**
+ * Implements hook_views_data_alter().
+ */
+function views_test_data_alter_views_data_alter(array &$data): void {
+  // Modify a filter to use a different filter handler plugin
+  // by default so that we can test that the handler used
+  // respects the handler plugin ID specified in the
+  // configuration.
+  $data['node_field_data']['status']['filter']['id'] = 'numeric';
+}
diff --git a/core/modules/views/tests/src/Functional/Entity/BaseFieldAccessTest.php b/core/modules/views/tests/src/Functional/Entity/BaseFieldAccessTest.php
index 8ee795e5b60e..14b713d8cd58 100644
--- a/core/modules/views/tests/src/Functional/Entity/BaseFieldAccessTest.php
+++ b/core/modules/views/tests/src/Functional/Entity/BaseFieldAccessTest.php
@@ -39,15 +39,6 @@ class BaseFieldAccessTest extends ViewTestBase {
   protected function setUp($import_test_views = TRUE, $modules = ['views_test_config', 'comment_test_views']): void {
     parent::setUp($import_test_views, $modules);
 
-    \Drupal::state()->set('entity_test.views_data', [
-      'entity_test' => [
-        'test_text_access' => [
-          'field' => [
-            'id' => 'standard',
-          ],
-        ],
-      ],
-    ]);
     $entity_1 = EntityTest::create([
       'test_text_access' => 'no access value',
     ]);
diff --git a/core/modules/views/tests/src/Functional/Handler/HandlerTest.php b/core/modules/views/tests/src/Functional/Handler/HandlerTest.php
index fa9af239ca3e..c4b30958d54e 100644
--- a/core/modules/views/tests/src/Functional/Handler/HandlerTest.php
+++ b/core/modules/views/tests/src/Functional/Handler/HandlerTest.php
@@ -333,6 +333,12 @@ public function testSetRelationship(): void {
    * @see \Drupal\views\Plugin\views\HandlerBase::placeholder()
    */
   public function testPlaceholder(): void {
+    // Change the test view to use the test field plugin which has the
+    // additional get placeholder method.
+    $config = $this->config('views.view.test_view');
+    $config->set('display.default.display_options.fields.name.plugin_id', 'test_field');
+    $config->save();
+
     $view = Views::getView('test_view');
     $view->initHandlers();
     $view->initQuery();
diff --git a/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php b/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php
index a6e39524c245..a5b1b27db056 100644
--- a/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php
+++ b/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php
@@ -61,7 +61,7 @@ protected function setUp($import_test_views = TRUE, $modules = []): void {
     // vocabulary is in place to meet the view dependencies.
     $vocabulary = Vocabulary::create([
       'name' => 'test_exposed_checkboxes',
-      'vid' => 'test_exposed_checkboxes',
+      'vid' => 'tags',
       'nodes' => ['article' => 'article'],
     ]);
     $vocabulary->save();
diff --git a/core/modules/views/tests/src/Functional/Plugin/ExposedFormTest.php b/core/modules/views/tests/src/Functional/Plugin/ExposedFormTest.php
index fa9995eea82e..933554003ff0 100644
--- a/core/modules/views/tests/src/Functional/Plugin/ExposedFormTest.php
+++ b/core/modules/views/tests/src/Functional/Plugin/ExposedFormTest.php
@@ -116,7 +116,7 @@ public function testExposedIdentifier(): void {
         'field' => 'type',
         'id' => 'type',
         'table' => 'node_field_data',
-        'plugin_id' => 'in_operator',
+        'plugin_id' => 'bundle',
         'entity_type' => 'node',
         'entity_field' => 'type',
         'expose' => [
diff --git a/core/modules/views/tests/src/Kernel/Handler/FieldTimeIntervalTest.php b/core/modules/views/tests/src/Kernel/Handler/FieldTimeIntervalTest.php
index 9f4d930c6f78..25f1db02ecc1 100644
--- a/core/modules/views/tests/src/Kernel/Handler/FieldTimeIntervalTest.php
+++ b/core/modules/views/tests/src/Kernel/Handler/FieldTimeIntervalTest.php
@@ -44,13 +44,16 @@ class FieldTimeIntervalTest extends ViewsKernelTestBase {
    * Tests the TimeInterval handler.
    */
   public function testFieldTimeInterval(): void {
-    $view = Views::getView('test_view');
-    $view->setDisplay();
-    $this->executeView($view);
-    foreach ($view->result as $delta => $row) {
+    $view_config = $this->config('views.view.test_view');
+    $view_config->set('display.default.display_options.fields.age.plugin_id', 'time_interval');
+    foreach (array_keys($this->ages) as $delta) {
       [, $formatted_value, $granularity] = $this->ages[$delta];
-      $view->field['age']->options['granularity'] = $granularity;
-      $this->assertEquals($formatted_value, $view->field['age']->advancedRender($row));
+      $view_config->set('display.default.display_options.fields.age.granularity', $granularity);
+      $view_config->save();
+      $view = Views::getView('test_view');
+      $view->setDisplay();
+      $this->executeView($view);
+      $this->assertEquals($formatted_value, $view->field['age']->advancedRender($view->result[$delta]));
     }
   }
 
diff --git a/core/modules/views/tests/src/Kernel/ModuleTest.php b/core/modules/views/tests/src/Kernel/ModuleTest.php
index b3cdf6446d9d..ff2d42e327e8 100644
--- a/core/modules/views/tests/src/Kernel/ModuleTest.php
+++ b/core/modules/views/tests/src/Kernel/ModuleTest.php
@@ -8,6 +8,7 @@
 use Drupal\Core\Form\FormState;
 use Drupal\views\Plugin\views\area\Broken as BrokenArea;
 use Drupal\views\Plugin\views\field\Broken as BrokenField;
+use Drupal\views\Plugin\views\filter\BooleanOperator;
 use Drupal\views\Plugin\views\filter\Broken as BrokenFilter;
 use Drupal\views\Plugin\views\filter\Standard;
 use Drupal\views\Plugin\views\ViewsHandlerInterface;
@@ -25,12 +26,12 @@ class ModuleTest extends ViewsKernelTestBase {
    *
    * @var array
    */
-  public static $testViews = ['test_view_status', 'test_view', 'test_argument'];
+  public static $testViews = ['test_view_status', 'test_view', 'test_argument', 'test_redirect_view'];
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['field', 'user', 'block'];
+  protected static $modules = ['field', 'user', 'block', 'node', 'views_test_data_alter'];
 
   /**
    * Stores the last triggered error.
@@ -109,6 +110,14 @@ public function testViewsGetHandler(): void {
     ];
     $handler = $this->container->get('plugin.manager.views.filter')->getHandler($item, 'standard');
     $this->assertInstanceOf(Standard::class, $handler);
+
+    // Test that the configuration is respected rather than overridden
+    // by views data. Using assertSame() here to make the error more clearly
+    // show what the result is when an error is caused.
+    $test_view_config = $this->config('views.view.test_redirect_view');
+    $item = $test_view_config->get('display.default.display_options.filters.status');
+    $handler = $this->container->get('plugin.manager.views.filter')->getHandler($item);
+    $this->assertSame(BooleanOperator::class, get_class($handler));
   }
 
   /**
diff --git a/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php b/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php
index 97d670634b3f..fa4969d1e9b6 100644
--- a/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php
+++ b/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php
@@ -5,8 +5,12 @@
 namespace Drupal\Tests\views\Kernel\Plugin;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Form\FormState;
+use Drupal\Core\Path\CurrentPathStack;
 use Drupal\node\Entity\NodeType;
 use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
+use Drupal\views\ExposedFormCache;
+use Drupal\views\Form\ViewsExposedForm;
 use Drupal\views\Views;
 
 /**
@@ -20,7 +24,7 @@ class ExposedFormRenderTest extends ViewsKernelTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $testViews = ['test_exposed_form_buttons'];
+  public static $testViews = ['test_exposed_form_buttons', 'test_exposed_admin_ui'];
 
   /**
    * {@inheritdoc}
@@ -64,85 +68,38 @@ public function testExposedFormRawInput(): void {
       'name' => 'Article',
     ])->save();
 
-    $view = Views::getView('test_exposed_form_buttons');
+    // Build the form state.
+    $form = [];
+    $view = Views::getView('test_exposed_admin_ui');
     $view->setDisplay();
-    $view->displayHandlers->get('default')->overrideOption('filters', [
-      'type' => [
-        'exposed' => TRUE,
-        'field' => 'type',
-        'id' => 'type',
-        'table' => 'node_field_data',
-        'plugin_id' => 'in_operator',
-        'entity_type' => 'node',
-        'entity_field' => 'type',
-        'expose' => [
-          'identifier' => 'type',
-          'label' => 'Content: Type',
-          'operator_id' => 'type_op',
-          'reduce' => FALSE,
-          'multiple' => FALSE,
-        ],
-      ],
-      'type_with_default_value' => [
-        'exposed' => TRUE,
-        'field' => 'type',
-        'id' => 'type_with_default_value',
-        'table' => 'node_field_data',
-        'plugin_id' => 'in_operator',
-        'entity_type' => 'node',
-        'entity_field' => 'type',
-        'value' => ['article', 'article'],
-        'expose' => [
-          'identifier' => 'type_with_default_value',
-          'label' => 'Content: Type with value',
-          'operator_id' => 'type_op',
-          'reduce' => FALSE,
-          'multiple' => FALSE,
-        ],
-      ],
-      'multiple_types' => [
-        'exposed' => TRUE,
-        'field' => 'type',
-        'id' => 'multiple_types',
-        'table' => 'node_field_data',
-        'plugin_id' => 'in_operator',
-        'entity_type' => 'node',
-        'entity_field' => 'type',
-        'expose' => [
-          'identifier' => 'multiple_types',
-          'label' => 'Content: Type (multiple)',
-          'operator_id' => 'type_op',
-          'reduce' => FALSE,
-          'multiple' => TRUE,
-        ],
-      ],
-      'multiple_types_with_default_value' => [
-        'exposed' => TRUE,
-        'field' => 'type',
-        'id' => 'multiple_types_with_default_value',
-        'table' => 'node_field_data',
-        'plugin_id' => 'in_operator',
-        'entity_type' => 'node',
-        'entity_field' => 'type',
-        'value' => ['article', 'article'],
-        'expose' => [
-          'identifier' => 'multiple_types_with_default_value',
-          'label' => 'Content: Type with default value (multiple)',
-          'operator_id' => 'type_op',
-          'reduce' => FALSE,
-          'multiple' => TRUE,
-        ],
-      ],
-    ]);
-    $view->save();
     $this->executeView($view);
 
+    $form_state = new FormState();
+    $form_state->set('view', $view);
+    $form_state->setValue('type', 'article');
+
+    // Mock the exposed form.
+    $exposed_form_cache = $this->createMock(ExposedFormCache::class);
+    $current_path_stack = $this->createMock(CurrentPathStack::class);
+    $exposed_form = new ViewsExposedForm($exposed_form_cache, $current_path_stack);
+    $exposed_form->submitForm($form, $form_state);
+    $updated_view = $form_state->get('view');
+
     $expected = [
-      'type' => 'All',
-      'type_with_default_value' => 'article',
-      'multiple_types_with_default_value' => ['article' => 'article'],
+      'type' => 'article',
+    ];
+    $this->assertSame($updated_view->exposed_raw_input, $expected);
+
+    $form_state->setValue('type', ['article', 'page']);
+    $exposed_form->submitForm($form, $form_state);
+    $updated_view = $form_state->get('view');
+    $expected = [
+      'type' => [
+        'article',
+        'page',
+      ],
     ];
-    $this->assertSame($view->exposed_raw_input, $expected);
+    $this->assertSame($updated_view->exposed_raw_input, $expected);
   }
 
 }
-- 
GitLab