From 104bca1e0ea2ea0ff122e50da69cc79bd855d705 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Wed, 15 Jul 2020 15:59:38 +0100 Subject: [PATCH] Issue #2780869 by claudiu.cristea, Lendude, joachim, jmadden27: Cannot save a view where a filter value option contains a period --- .../optional/views.view.moderated_content.yml | 6 +- .../optional/views.view.contextual_recent.yml | 2 +- .../config/optional/views.view.archive.yml | 2 +- .../optional/views.view.content_recent.yml | 2 +- .../config/optional/views.view.frontpage.yml | 2 +- .../config/optional/views.view.glossary.yml | 2 +- .../test_views/views.view.test_language.yml | 8 +-- ...iew.test_options_list_argument_numeric.yml | 2 +- ...view.test_options_list_argument_string.yml | 2 +- .../views.view.test_options_list_filter.yml | 6 +- .../Kernel/Views/OptionsListFilterTest.php | 22 +++++++ .../src/Kernel/Views/OptionsTestBase.php | 3 + ...view.test_excluded_field_token_display.yml | 2 +- .../views.view.test_field_counter_display.yml | 2 +- .../optional/views.view.taxonomy_term.yml | 2 +- .../views.view.test_filter_permission.yml | 2 +- .../Kernel/Views/HandlerFilterRolesTest.php | 4 +- .../views/src/Plugin/views/filter/Bundle.php | 2 +- .../src/Plugin/views/filter/InOperator.php | 9 ++- core/modules/views/src/ViewsConfigUpdater.php | 66 ++++++++++++++++++- .../views.view.test_argument_default_node.yml | 2 +- .../test_views/views.view.test_display.yml | 2 +- ...ews.view.test_duplicate_field_handlers.yml | 2 +- .../views.view.test_entity_type_filter.yml | 6 +- .../test_views/views.view.test_glossary.yml | 2 +- .../test_views/views.view.test_tag_cache.yml | 2 +- .../views.view.test_view_sort_translation.yml | 4 +- .../Update/InOperatorValuesUpdateTest.php | 52 +++++++++++++++ .../Kernel/Entity/FilterEntityBundleTest.php | 4 +- .../Kernel/Handler/FilterInOperatorTest.php | 54 ++++++++++++++- core/modules/views/views.post_update.php | 12 ++++ .../install/views.view.articles_aside.yml | 4 +- .../install/views.view.featured_articles.yml | 2 +- .../config/install/views.view.frontpage.yml | 2 +- .../install/views.view.promoted_items.yml | 8 +-- .../install/views.view.recipe_collections.yml | 2 +- .../config/install/views.view.recipes.yml | 2 +- 37 files changed, 254 insertions(+), 56 deletions(-) create mode 100644 core/modules/views/tests/src/Functional/Update/InOperatorValuesUpdateTest.php diff --git a/core/modules/content_moderation/config/optional/views.view.moderated_content.yml b/core/modules/content_moderation/config/optional/views.view.moderated_content.yml index beedf9d08be1..241dcac94590 100644 --- a/core/modules/content_moderation/config/optional/views.view.moderated_content.yml +++ b/core/modules/content_moderation/config/optional/views.view.moderated_content.yml @@ -635,8 +635,8 @@ display: admin_label: '' operator: in value: - editorial-draft: editorial-draft - editorial-archived: editorial-archived + - editorial-draft + - editorial-archived group: 1 exposed: true expose: @@ -722,7 +722,7 @@ display: admin_label: '' operator: 'not in' value: - editorial-published: editorial-published + - editorial-published group: 1 exposed: false expose: diff --git a/core/modules/contextual/tests/modules/contextual_test/config/optional/views.view.contextual_recent.yml b/core/modules/contextual/tests/modules/contextual_test/config/optional/views.view.contextual_recent.yml index b3c1ea4c8465..c5d7f33624a6 100644 --- a/core/modules/contextual/tests/modules/contextual_test/config/optional/views.view.contextual_recent.yml +++ b/core/modules/contextual/tests/modules/contextual_test/config/optional/views.view.contextual_recent.yml @@ -209,7 +209,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/node/config/optional/views.view.archive.yml b/core/modules/node/config/optional/views.view.archive.yml index e76342b2b3fb..ec6d1fa797a5 100644 --- a/core/modules/node/config/optional/views.view.archive.yml +++ b/core/modules/node/config/optional/views.view.archive.yml @@ -123,7 +123,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/node/config/optional/views.view.content_recent.yml b/core/modules/node/config/optional/views.view.content_recent.yml index 54ef192695ea..b3bb4b262732 100644 --- a/core/modules/node/config/optional/views.view.content_recent.yml +++ b/core/modules/node/config/optional/views.view.content_recent.yml @@ -209,7 +209,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/node/config/optional/views.view.frontpage.yml b/core/modules/node/config/optional/views.view.frontpage.yml index d9ee305bd356..0b37cc099b0a 100644 --- a/core/modules/node/config/optional/views.view.frontpage.yml +++ b/core/modules/node/config/optional/views.view.frontpage.yml @@ -132,7 +132,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/optional/views.view.glossary.yml index 81cd423d886e..f44c743cde65 100644 --- a/core/modules/node/config/optional/views.view.glossary.yml +++ b/core/modules/node/config/optional/views.view.glossary.yml @@ -316,7 +316,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml index b2bbe805ae56..6939123b09f7 100644 --- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml @@ -180,7 +180,7 @@ display: table: node_field_data field: type value: - page: page + - page plugin_id: bundle entity_type: node entity_field: type @@ -193,9 +193,9 @@ display: admin_label: '' operator: in value: - fr: fr - es: es - und: und + - fr + - es + - und group: 1 exposed: false expose: diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml index 3ea7c67bb6bf..20ff503924ea 100644 --- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml +++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_numeric.yml @@ -105,7 +105,7 @@ display: admin_label: '' operator: in value: - article: article + - article group: 1 exposed: false expose: diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml index 8ed3633de2c4..5721bd7f764b 100644 --- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml +++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_argument_string.yml @@ -105,7 +105,7 @@ display: admin_label: '' operator: in value: - article: article + - article group: 1 exposed: false expose: diff --git a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml index 4bc225b8798c..ca7d17341c45 100644 --- a/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml +++ b/core/modules/options/tests/options_test_views/test_views/views.view.test_options_list_filter.yml @@ -105,8 +105,8 @@ display: admin_label: '' operator: or value: - man: man - woman: woman + - man + - woman group: 1 exposed: false expose: @@ -145,7 +145,7 @@ display: admin_label: '' operator: in value: - article: article + - article group: 1 exposed: false expose: diff --git a/core/modules/options/tests/src/Kernel/Views/OptionsListFilterTest.php b/core/modules/options/tests/src/Kernel/Views/OptionsListFilterTest.php index 06bedade85a3..8450090bc9bd 100644 --- a/core/modules/options/tests/src/Kernel/Views/OptionsListFilterTest.php +++ b/core/modules/options/tests/src/Kernel/Views/OptionsListFilterTest.php @@ -107,6 +107,28 @@ public function testViewsTestOptionsListGroupedFilter() { $column_map = ['nid' => 'nid']; $this->assertIdenticalResultset($view, $resultset, $column_map); + $view->destroy(); + + $view = Views::getView('test_options_list_filter'); + $view->setDisplay(); + // Add a filter with a period in the options. + $view->displayHandlers->get('default')->overrideOption('filters', [ + 'field_test_list_string_value' => [ + 'id' => 'field_test_list_string_value', + 'table' => 'field_data_field_test_list_string', + 'field' => 'field_test_list_string_value', + 'relationship' => 'none', + 'group_type' => 'group', + 'admin_label' => '', + 'operator' => 'or', + 'value' => [$this->fieldValues[2] => $this->fieldValues[2]], + 'exposed' => FALSE, + 'plugin_id' => 'list_field', + ], + ]); + $view->save(); + + $this->executeView($view); } } diff --git a/core/modules/options/tests/src/Kernel/Views/OptionsTestBase.php b/core/modules/options/tests/src/Kernel/Views/OptionsTestBase.php index 8be66d1c25db..ebebeb1c59e5 100644 --- a/core/modules/options/tests/src/Kernel/Views/OptionsTestBase.php +++ b/core/modules/options/tests/src/Kernel/Views/OptionsTestBase.php @@ -84,6 +84,7 @@ protected function mockStandardInstall() { $this->fieldValues = [ $this->randomMachineName(), $this->randomMachineName(), + 'option.with.periods', ]; $this->fieldNames = ['field_test_list_string', 'field_test_list_integer']; @@ -98,6 +99,7 @@ protected function mockStandardInstall() { 'allowed_values' => [ $this->fieldValues[0] => $this->fieldValues[0], $this->fieldValues[1] => $this->fieldValues[1], + $this->fieldValues[2] => $this->fieldValues[2], ], ], ])->save(); @@ -110,6 +112,7 @@ protected function mockStandardInstall() { 'allowed_values' => [ $this->fieldValues[0], $this->fieldValues[1], + $this->fieldValues[2], ], ], ])->save(); diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_excluded_field_token_display.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_excluded_field_token_display.yml index ba3d5457cee1..cfd726ce2017 100644 --- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_excluded_field_token_display.yml +++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_excluded_field_token_display.yml @@ -205,7 +205,7 @@ display: table: node_field_data field: type value: - article: article + - article entity_type: node entity_field: type plugin_id: bundle diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_field_counter_display.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_field_counter_display.yml index 092e00aa6465..8c4e22d42f48 100644 --- a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_field_counter_display.yml +++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_field_counter_display.yml @@ -147,7 +147,7 @@ display: table: node_field_data field: type value: - article: article + - article entity_type: node entity_field: type plugin_id: bundle diff --git a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml index 92da5368f019..3ece15f84d45 100644 --- a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml +++ b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml @@ -142,7 +142,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml index ca19af958634..b3f0d1cb223f 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml @@ -94,7 +94,7 @@ display: admin_label: '' operator: or value: - 'access user profiles': 'access user profiles' + - access user profiles group: 1 exposed: false expose: diff --git a/core/modules/user/tests/src/Kernel/Views/HandlerFilterRolesTest.php b/core/modules/user/tests/src/Kernel/Views/HandlerFilterRolesTest.php index 878300b79d51..043ad850469b 100644 --- a/core/modules/user/tests/src/Kernel/Views/HandlerFilterRolesTest.php +++ b/core/modules/user/tests/src/Kernel/Views/HandlerFilterRolesTest.php @@ -54,7 +54,7 @@ public function testDependencies() { 'table' => 'user__roles', 'field' => 'roles_target_id', 'value' => [ - 'test_user_role' => 'test_user_role', + 'test_user_role', ], 'operator' => 'empty', 'plugin_id' => 'user_roles', @@ -70,7 +70,7 @@ public function testDependencies() { 'table' => 'user__roles', 'field' => 'roles_target_id', 'value' => [ - 'test_user_role' => 'test_user_role', + 'test_user_role', ], 'operator' => 'not empty', 'plugin_id' => 'user_roles', diff --git a/core/modules/views/src/Plugin/views/filter/Bundle.php b/core/modules/views/src/Plugin/views/filter/Bundle.php index 703173d79fdb..aec1401b7267 100644 --- a/core/modules/views/src/Plugin/views/filter/Bundle.php +++ b/core/modules/views/src/Plugin/views/filter/Bundle.php @@ -128,7 +128,7 @@ public function calculateDependencies() { $bundle_entity_type = $this->entityType->getBundleEntityType(); $bundle_entity_storage = $this->entityTypeManager->getStorage($bundle_entity_type); - foreach (array_keys($this->value) as $bundle) { + foreach ($this->value as $bundle) { if ($bundle_entity = $bundle_entity_storage->load($bundle)) { $dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName(); } diff --git a/core/modules/views/src/Plugin/views/filter/InOperator.php b/core/modules/views/src/Plugin/views/filter/InOperator.php index 8a884898f596..5fcb23ab14e3 100644 --- a/core/modules/views/src/Plugin/views/filter/InOperator.php +++ b/core/modules/views/src/Plugin/views/filter/InOperator.php @@ -208,7 +208,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) { } if (empty($this->options['expose']['multiple'])) { - if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce'])) || isset($this->options['value']['all'])) { + if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce'])) || in_array('all', $this->options['value'], TRUE)) { $default_value = 'All'; } elseif (empty($default_value)) { @@ -275,11 +275,11 @@ public function reduceValueOptions($input = NULL) { elseif (is_object($option) && !$option instanceof MarkupInterface) { $keys = array_keys($option->option); $key = array_shift($keys); - if (isset($this->options['value'][$key])) { + if (in_array($key, $this->options['value'], TRUE)) { $options[$id] = $option; } } - elseif (isset($this->options['value'][$id])) { + elseif (in_array($id, $this->options['value'], TRUE)) { $options[$id] = $option; } } @@ -316,8 +316,7 @@ protected function valueSubmit($form, FormStateInterface $form_state) { // Luckily, the '#value' on the checkboxes form actually contains // *only* a list of checkboxes that were set, and we can use that // instead. - - $form_state->setValue(['options', 'value'], $form['value']['#value']); + $form_state->setValue(['options', 'value'], array_values($form['value']['#value'])); } public function adminSummary() { diff --git a/core/modules/views/src/ViewsConfigUpdater.php b/core/modules/views/src/ViewsConfigUpdater.php index 88442d46ddc1..f1dc4b124fc7 100644 --- a/core/modules/views/src/ViewsConfigUpdater.php +++ b/core/modules/views/src/ViewsConfigUpdater.php @@ -10,6 +10,8 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\Sql\DefaultTableMapping; +use Drupal\views\Plugin\views\filter\InOperator; +use Drupal\views\Plugin\ViewsHandlerManager; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -57,6 +59,13 @@ class ViewsConfigUpdater implements ContainerInjectionInterface { */ protected $multivalueBaseFieldsUpdateTableInfo; + /** + * The Views filter plugin manager service. + * + * @var \Drupal\views\Plugin\ViewsHandlerManager + */ + protected $filterPluginManager; + /** * Flag determining whether deprecations should be triggered. * @@ -82,17 +91,21 @@ class ViewsConfigUpdater implements ContainerInjectionInterface { * The typed config manager. * @param \Drupal\views\ViewsData $views_data * The views data service. + * @param \Drupal\views\Plugin\ViewsHandlerManager $filter_plugin_manager + * The Views filter plugin manager service. */ public function __construct( EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, TypedConfigManagerInterface $typed_config_manager, - ViewsData $views_data + ViewsData $views_data, + ViewsHandlerManager $filter_plugin_manager ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; $this->typedConfigManager = $typed_config_manager; $this->viewsData = $views_data; + $this->filterPluginManager = $filter_plugin_manager; } /** @@ -103,7 +116,8 @@ public static function create(ContainerInterface $container) { $container->get('entity_type.manager'), $container->get('entity_field.manager'), $container->get('config.typed'), - $container->get('views.views_data') + $container->get('views.views_data'), + $container->get('plugin.manager.views.filter') ); } @@ -138,6 +152,9 @@ public function updateAll(ViewEntityInterface $view) { if ($this->processMultivalueBaseFieldHandler($handler, $handler_type, $key, $display_id, $view)) { $changed = TRUE; } + if ($this->processInOperatorFilterValues($handler, $handler_type)) { + $changed = TRUE; + } return $changed; }); } @@ -477,4 +494,49 @@ protected function mapOperatorFromSingleToMultiple($single_operator) { } } + /** + * Update values for of in_operators filters. + * + * @param \Drupal\views\ViewEntityInterface $view + * The View to update. + * + * @return bool + * Whether the view was updated. + */ + public function needsInOperatorFilterValuesUpdate(ViewEntityInterface $view): bool { + return $this->processDisplayHandlers($view, TRUE, function (array &$handler, string $handler_type): bool { + return $this->processInOperatorFilterValues($handler, $handler_type); + }); + } + + /** + * Processes the in_operator filter values. + * + * @param array $handler + * A display handler. + * @param string $handler_type + * The handler type. + * + * @return bool + * Whether the handler was updated. + * + * @throws \Drupal\Component\Plugin\Exception\PluginException + * If the filter plugin instance cannot be created. + */ + protected function processInOperatorFilterValues(array &$handler, string $handler_type): bool { + if ($handler_type === 'filter' && !empty($handler['value']) && is_array($handler['value'])) { + $values = array_values($handler['value']); + // Only process if the keys are the same as the values. + if ($values === array_keys($handler['value'])) { + $class = $this->filterPluginManager->getDefinition($handler['plugin_id'])['class']; + // Process for 'in_operator' plugin but also for its descendants. + if ($class === InOperator::class || is_subclass_of($class, InOperator::class)) { + $handler['value'] = $values; + return TRUE; + } + } + } + return FALSE; + } + } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_node.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_node.yml index 02d3db1beec3..e000db0c3c28 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_node.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_argument_default_node.yml @@ -135,7 +135,7 @@ display: table: node_field_data field: type value: - page: page + - page entity_type: node entity_field: type plugin_id: bundle diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml index 3a426e426250..4f80881ee259 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml @@ -47,7 +47,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_duplicate_field_handlers.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_duplicate_field_handlers.yml index bca6747c2c1b..84fb91b920db 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_duplicate_field_handlers.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_duplicate_field_handlers.yml @@ -131,7 +131,7 @@ display: admin_label: '' operator: in value: - article: article + - article group: 1 exposed: false expose: diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml index 0c6d0be80b17..cae09605ae4c 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_type_filter.yml @@ -101,9 +101,9 @@ display: field: type relationship: none value: - 180575: '180575' - test_bundle: test_bundle - test_bundle_2: test_bundle_2 + - '180575' + - test_bundle + - test_bundle_2 plugin_id: bundle entity_type: node entity_field: type diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml index a6d3a3641afd..2f40c5901a50 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_glossary.yml @@ -314,7 +314,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml index 78e7ca30ba62..fe4dff1424c5 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_tag_cache.yml @@ -68,7 +68,7 @@ display: admin_label: '' operator: in value: - page: page + - page group: 1 exposed: false expose: diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_sort_translation.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_sort_translation.yml index d161b0b27325..701847bf8b37 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_sort_translation.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_view_sort_translation.yml @@ -42,7 +42,7 @@ display: admin_label: '' operator: in value: - 'en': 'en' + - en group: 1 exposed: false entity_type: node @@ -77,7 +77,7 @@ display: admin_label: '' operator: in value: - 'de': 'de' + - de group: 1 exposed: false entity_type: node diff --git a/core/modules/views/tests/src/Functional/Update/InOperatorValuesUpdateTest.php b/core/modules/views/tests/src/Functional/Update/InOperatorValuesUpdateTest.php new file mode 100644 index 000000000000..a64eb3371918 --- /dev/null +++ b/core/modules/views/tests/src/Functional/Update/InOperatorValuesUpdateTest.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types = 1); + +namespace Drupal\Tests\views\Functional\Update; + +use Drupal\FunctionalTests\Update\UpdatePathTestBase; + +/** + * Tests the upgrade path for in_operation filter values. + * + * @group views + * @group legacy + * + * @coversDefaultClass \Drupal\views\ViewsConfigUpdater + * + * @see views_post_update_in_operator_values() + */ +class InOperatorValuesUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles(): void { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.8.0.bare.standard.php.gz', + ]; + } + + /** + * Tests the upgrade path for in_operation filter values. + * + * @covers ::needsInOperatorFilterValuesUpdate + * @covers ::processInOperatorFilterValues + */ + public function testInOperatorValuesUpdate(): void { + $config_factory = \Drupal::configFactory(); + $view = $config_factory->get('views.view.frontpage'); + $path = 'display.default.display_options.filters.langcode.value'; + $value = $view->get($path); + $this->assertSame([ + '***LANGUAGE_language_content***' => '***LANGUAGE_language_content***', + ], $value); + + $this->runUpdates(); + + $view = $config_factory->get('views.view.frontpage'); + $value = $view->get($path); + $this->assertSame(['***LANGUAGE_language_content***'], $value); + } + +} diff --git a/core/modules/views/tests/src/Kernel/Entity/FilterEntityBundleTest.php b/core/modules/views/tests/src/Kernel/Entity/FilterEntityBundleTest.php index 19c9e5bde314..ee1e7e8d0bf7 100644 --- a/core/modules/views/tests/src/Kernel/Entity/FilterEntityBundleTest.php +++ b/core/modules/views/tests/src/Kernel/Entity/FilterEntityBundleTest.php @@ -84,7 +84,7 @@ public function testFilterEntity() { // Test each bundle type. $view->initDisplay(); $filters = $view->display_handler->getOption('filters'); - $filters['type']['value'] = [$key => $key]; + $filters['type']['value'] = [$key]; $view->display_handler->setOption('filters', $filters); $this->executeView($view); @@ -96,7 +96,7 @@ public function testFilterEntity() { // Test an invalid bundle type to make sure we have no results. $view->initDisplay(); $filters = $view->display_handler->getOption('filters'); - $filters['type']['value'] = ['type_3' => 'type_3']; + $filters['type']['value'] = ['type_3']; $view->display_handler->setOption('filters', $filters); $this->executeView($view); diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php index eaada3ef04f0..d20fdb9ce137 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php @@ -15,6 +15,7 @@ * @group views */ class FilterInOperatorTest extends ViewsKernelTestBase { + use StringTranslationTrait; protected static $modules = ['system']; @@ -39,6 +40,22 @@ class FilterInOperatorTest extends ViewsKernelTestBase { public function viewsData() { $data = parent::viewsData(); $data['views_test_data']['age']['filter']['id'] = 'in_operator'; + $data['views_test_data']['job']['filter']['id'] = 'in_operator'; + return $data; + } + + /** + * {@inheritdoc} + */ + protected function dataSet() { + $data = parent::dataSet(); + $data[] = [ + 'name' => 'Dries', + 'age' => 8, + 'job' => 'B.D.F.L.', + 'created' => gmmktime(6, 30, 30, 1, 1, 2000), + 'status' => 1, + ]; return $data; } @@ -82,7 +99,7 @@ public function testFilterInOperatorSimple() { 'id' => 'age', 'field' => 'age', 'table' => 'views_test_data', - 'value' => [26, 30], + 'value' => [26, 30, 8], 'operator' => 'not in', ], ]); @@ -224,7 +241,7 @@ protected function getGroupedExposedFilters() { 2 => [ 'title' => 'Age is not one of 26, 30', 'operator' => 'not in', - 'value' => [26, 30], + 'value' => [26, 30, 8], ], ], ], @@ -246,7 +263,7 @@ public function testFilterOptionAsMarkup() { $manager = $this->container->get('plugin.manager.views.filter'); /** @var \Drupal\views\Plugin\views\filter\InOperator $operator */ $operator = $manager->createInstance('in_operator'); - $options = ['value' => ['foo' => [], 'baz' => []]]; + $options = ['value' => ['foo', 'baz']]; $operator->init($view->reveal(), $display->reveal(), $options); $input_options = [ @@ -260,7 +277,38 @@ public function testFilterOptionAsMarkup() { $this->assertInstanceOf(TranslatableMarkup::class, $reduced_values['baz']); $this->assertSame('qux', (string) $reduced_values['baz']); $this->assertSame('bar', $reduced_values['foo']); + } + + /** + * Tests that the InOperator filter can handle options containing dots. + */ + public function testFilterInOperatorSimpleString(): void { + $view = Views::getView('test_view'); + $view->setDisplay(); + + // Add an in_operator on job. + $view->displayHandlers->get('default')->overrideOption('filters', [ + 'job' => [ + 'id' => 'job', + 'field' => 'job', + 'table' => 'views_test_data', + 'value' => ['B.D.F.L.' => 'B.D.F.L.'], + 'plugin_id' => 'in_operator', + ], + ]); + $view->save(); + + $this->executeView($view); + $expected_result = [ + [ + 'name' => 'Dries', + 'age' => 8, + ], + ]; + + $this->assertCount(1, $view->result); + $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); } } diff --git a/core/modules/views/views.post_update.php b/core/modules/views/views.post_update.php index 23aedc1c0323..d04db0ddf0c1 100644 --- a/core/modules/views/views.post_update.php +++ b/core/modules/views/views.post_update.php @@ -6,6 +6,7 @@ */ use Drupal\Core\Config\Entity\ConfigEntityUpdater; +use Drupal\views\ViewEntityInterface; use Drupal\views\ViewsConfigUpdater; /** @@ -51,3 +52,14 @@ function views_post_update_field_names_for_multivalue_fields(&$sandbox = NULL) { function views_post_update_configuration_entity_relationships() { // Empty update to clear Views data. } + +/** + * Update the in_operator filter plugins values. + */ +function views_post_update_in_operator_values(?array &$sandbox = NULL): void { + /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */ + $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class); + \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function (ViewEntityInterface $view) use ($view_config_updater): bool { + return $view_config_updater->needsInOperatorFilterValuesUpdate($view); + }); +} diff --git a/core/profiles/demo_umami/config/install/views.view.articles_aside.yml b/core/profiles/demo_umami/config/install/views.view.articles_aside.yml index 70989b335c19..1748ff6529ed 100644 --- a/core/profiles/demo_umami/config/install/views.view.articles_aside.yml +++ b/core/profiles/demo_umami/config/install/views.view.articles_aside.yml @@ -125,7 +125,7 @@ display: table: node_field_data field: type value: - article: article + - article entity_type: node entity_field: type plugin_id: bundle @@ -141,7 +141,7 @@ display: admin_label: '' operator: in value: - '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + - '***LANGUAGE_language_content***' group: 1 exposed: false expose: diff --git a/core/profiles/demo_umami/config/install/views.view.featured_articles.yml b/core/profiles/demo_umami/config/install/views.view.featured_articles.yml index 88d5550615d9..40ff01461454 100644 --- a/core/profiles/demo_umami/config/install/views.view.featured_articles.yml +++ b/core/profiles/demo_umami/config/install/views.view.featured_articles.yml @@ -139,7 +139,7 @@ display: table: node_field_data field: type value: - article: article + - article entity_type: node entity_field: type plugin_id: bundle diff --git a/core/profiles/demo_umami/config/install/views.view.frontpage.yml b/core/profiles/demo_umami/config/install/views.view.frontpage.yml index 86397d039a5b..a614aa2c8d9d 100644 --- a/core/profiles/demo_umami/config/install/views.view.frontpage.yml +++ b/core/profiles/demo_umami/config/install/views.view.frontpage.yml @@ -133,7 +133,7 @@ display: admin_label: '' operator: in value: - recipe: recipe + - recipe group: 1 exposed: false expose: diff --git a/core/profiles/demo_umami/config/install/views.view.promoted_items.yml b/core/profiles/demo_umami/config/install/views.view.promoted_items.yml index ee99489eb8a7..6427d0a15d0b 100644 --- a/core/profiles/demo_umami/config/install/views.view.promoted_items.yml +++ b/core/profiles/demo_umami/config/install/views.view.promoted_items.yml @@ -171,8 +171,8 @@ display: admin_label: '' operator: in value: - article: article - recipe: recipe + - article + - recipe group: 1 exposed: false expose: @@ -330,7 +330,7 @@ display: admin_label: '' operator: in value: - recipe: recipe + - recipe group: 1 exposed: false expose: @@ -491,7 +491,7 @@ display: admin_label: '' operator: in value: - article: article + - article group: 1 exposed: false expose: diff --git a/core/profiles/demo_umami/config/install/views.view.recipe_collections.yml b/core/profiles/demo_umami/config/install/views.view.recipe_collections.yml index 1257ba1b1d18..6c2509344401 100644 --- a/core/profiles/demo_umami/config/install/views.view.recipe_collections.yml +++ b/core/profiles/demo_umami/config/install/views.view.recipe_collections.yml @@ -118,7 +118,7 @@ display: table: taxonomy_term_field_data field: vid value: - tags: tags + - tags entity_type: taxonomy_term entity_field: vid plugin_id: bundle diff --git a/core/profiles/demo_umami/config/install/views.view.recipes.yml b/core/profiles/demo_umami/config/install/views.view.recipes.yml index 7a5bc31f38e9..8c1475355855 100644 --- a/core/profiles/demo_umami/config/install/views.view.recipes.yml +++ b/core/profiles/demo_umami/config/install/views.view.recipes.yml @@ -139,7 +139,7 @@ display: table: node_field_data field: type value: - recipe: recipe + - recipe entity_type: node entity_field: type plugin_id: bundle -- GitLab