diff --git a/core/modules/system/tests/fixtures/update/drupal-8.views-entity-views-data-2846614.php b/core/modules/system/tests/fixtures/update/drupal-8.views-entity-views-data-2846614.php index 2bb0b3c..2dcacb2 100644 --- a/core/modules/system/tests/fixtures/update/drupal-8.views-entity-views-data-2846614.php +++ b/core/modules/system/tests/fixtures/update/drupal-8.views-entity-views-data-2846614.php @@ -18,15 +18,15 @@ foreach ($views_configs as $views_config) { $connection->insert('config') - ->fields(array( + ->fields([ 'collection', 'name', 'data', - )) - ->values(array( + ]) + ->values([ 'collection' => '', 'name' => 'views.view.' . $views_config['id'], 'data' => serialize($views_config), - )) + ]) ->execute(); } diff --git a/core/modules/user/src/Plugin/views/filter/Roles.php b/core/modules/user/src/Plugin/views/filter/Roles.php index 64074c3..6a75fa9 100644 --- a/core/modules/user/src/Plugin/views/filter/Roles.php +++ b/core/modules/user/src/Plugin/views/filter/Roles.php @@ -74,7 +74,14 @@ function operators() { */ public function calculateDependencies() { $dependencies = array(); - foreach ($this->value as $role_id) { + + // Due to a bug $this->value might be a string. In the empty case stop + // early. Otherwise we cast it to an array later. + if (is_string($this->value) && $this->value === '') { + return []; + } + + foreach ((array) $this->value as $role_id) { $role = $this->roleStorage->load($role_id); $dependencies[$role->getConfigDependencyKey()][] = $role->getConfigDependencyName(); } diff --git a/core/modules/views/src/Tests/Update/EntityViewsMultiValueBaseFieldDataUpdateTest.php b/core/modules/views/src/Tests/Update/EntityViewsMultiValueBaseFieldDataUpdateTest.php index a4e17fc..642dc4d 100644 --- a/core/modules/views/src/Tests/Update/EntityViewsMultiValueBaseFieldDataUpdateTest.php +++ b/core/modules/views/src/Tests/Update/EntityViewsMultiValueBaseFieldDataUpdateTest.php @@ -46,6 +46,10 @@ public function testUpdateMultiValueBaseFields() { $this->assertEqual('roles_target_id', $handler_config['field']); // Check the table is still correct. $this->assertEqual('user__roles', $handler_config['table']); + + + // The plugin ID should be updated as well. + $this->assertEqual($type === 'arguments' ? 'user__roles_rid' : 'user_roles', $handler_config['plugin_id']); } } diff --git a/core/modules/views/views.install b/core/modules/views/views.install index 82cdee5..a469752 100644 --- a/core/modules/views/views.install +++ b/core/modules/views/views.install @@ -460,14 +460,22 @@ function views_update_8300() { } $config_factory = \Drupal::configFactory(); - $handler_types = ['fields', 'arguments', 'sorts', 'relationships', 'filters']; - + /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */ + $typed_config_manager = \Drupal::service('config.typed'); + $views_data = \Drupal\views\Views::viewsData(); + $handler_types_plural = ['fields', 'arguments', 'sorts', 'relationships', 'filters']; + $handler_types_singular = array_map(function ($handler_type) { + return substr($handler_type, 0, -1); + }, array_combine($handler_types_plural, $handler_types_plural)); + + $required_cleanup_handlers = []; foreach ($config_factory->listAll('views.view.') as $id) { $view = $config_factory->getEditable($id); + /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_view */ $changed = FALSE; foreach ($view->get('display') as $display_id => &$display) { - foreach ($handler_types as $handler_type) { + foreach ($handler_types_plural as $handler_type) { $handler_data = $view->get("display.$display_id.display_options.$handler_type"); if (empty($handler_data)) { @@ -479,14 +487,34 @@ function views_update_8300() { // name. $table = $data['table']; if (isset($table_update_info[$table])) { - $path = "display.$display_id.display_options.$handler_type.$key.field"; - $original_field_name = $view->get($path); + $path_to_handler = "display.$display_id.display_options.$handler_type.$key"; + $path_field = "{$path_to_handler}.field"; + $path_plugin_id = "{$path_to_handler}.plugin_id"; + $original_field_name = $view->get($path_field); // Only if the wrong field name is set do we change the field. It // could already be using the correct field. Like // user__roles/roles_target_id. if (isset($table_update_info[$table][$original_field_name])) { - $view->set($path, $table_update_info[$table][$original_field_name]); + $required_cleanup_handlers[] = [$id, $path_to_handler]; + + // Set both the new table field as well as new 'plugin_id' field. + $view->set($path_field, $table_update_info[$table][$original_field_name]); + $view->set($path_plugin_id, $views_data->get($table)[$table_update_info[$table][$original_field_name]][$handler_types_singular[$handler_type]]['id']); + + // Filter values we want to convert from a string to an array. + if ($handler_type === 'filters' && is_string($data['value'])) { + // An empty string casted to an array is an array with one + // element. + if ($data['value'] === '') { + $data['value'] = []; + } + else { + $data['value'] = (array) $data['value']; + } + $view->set("{$path_to_handler}.value", $data['value']); + } + $changed = TRUE; } } @@ -495,10 +523,37 @@ function views_update_8300() { } if ($changed) { + $view->save(TRUE); + } + } + + // Beside of updating the field and plugin ID we also need to truncate orphan + // keys so he configuration applies to the config schema. + foreach ($required_cleanup_handlers as list($id, $path_to_handler)) { + $changed = FALSE; + $typed_view = $typed_config_manager->get($id); + $view = $config_factory->getEditable($id); + + // For all the other fields we try to determine the fields using + // config schema and remove everything which is not needed. + /** @var \Drupal\Core\Config\Schema\ArrayElement $typed_config */ + $typed_config = $typed_view->get($path_to_handler); + $config = $typed_config->getValue(); + foreach (array_keys($config) as $config_key) { + if (!isset($typed_config->getDataDefinition()['mapping'][$config_key])) { + unset($config[$config_key]); + $changed = TRUE; + } + } + $typed_config->setValue($config); + + if ($changed) { + $view->set($path_to_handler, $typed_config->getValue()); $view->save(); } } + } /**