diff --git a/config/install/config_ignore.settings.yml b/config/install/config_ignore.settings.yml index 629b342..c89e103 100644 --- a/config/install/config_ignore.settings.yml +++ b/config/install/config_ignore.settings.yml @@ -1 +1,2 @@ ignored_config_entities: { } +ignored_config_collections: { } diff --git a/config/schema/config_ignore.schema.yml b/config/schema/config_ignore.schema.yml index 9930f0d..889c34c 100644 --- a/config/schema/config_ignore.schema.yml +++ b/config/schema/config_ignore.schema.yml @@ -7,3 +7,8 @@ config_ignore.settings: label: 'List of ignored configurations' sequence: type: string + ignored_config_collections: + type: sequence + label: 'List of ignored configuration storage collections' + sequence: + type: string diff --git a/config_ignore.api.php b/config_ignore.api.php index 89e9f91..1054e84 100644 --- a/config_ignore.api.php +++ b/config_ignore.api.php @@ -18,6 +18,13 @@ function hook_config_ignore_settings_alter(array &$settings) { $settings[] = 'field.*'; } +/** + * Alter the list of config entities that should be ignored. + */ +function hook_config_ignore_collections_alter(array &$collections) { + $collections[] = 'language.*'; +} + /** * @} End of "addtogroup hooks". */ diff --git a/config_ignore.install b/config_ignore.install index cf8f3a4..b602315 100644 --- a/config_ignore.install +++ b/config_ignore.install @@ -29,3 +29,11 @@ function config_ignore_update_8301() { \Drupal::cache('discovery')->delete('config_filter_plugins'); } +/** + * Update schema with storage collection ignore value. + */ +function config_ignore_update_8302() { + $config = \Drupal::configFactory()->getEditable('config_ignore.settings'); + $config->set('ignored_config_collections', [])->save(); +} + diff --git a/src/EventSubscriber/ConfigIgnoreEventSubscriber.php b/src/EventSubscriber/ConfigIgnoreEventSubscriber.php index 70c9162..3a14812 100644 --- a/src/EventSubscriber/ConfigIgnoreEventSubscriber.php +++ b/src/EventSubscriber/ConfigIgnoreEventSubscriber.php @@ -131,10 +131,26 @@ class ConfigIgnoreEventSubscriber implements EventSubscriberInterface, CacheTags $collection_names = array_unique(array_merge($transformation_storage->getAllCollectionNames(), $destination_storage->getAllCollectionNames())); array_unshift($collection_names, StorageInterface::DEFAULT_COLLECTION); + $ignored_collections = array_keys($this->getIgnoredCollections($collection_names)); + foreach ($collection_names as $collection_name) { $destination_storage = $destination_storage->createCollection($collection_name); $transformation_storage = $transformation_storage->createCollection($collection_name); + if (in_array($collection_name, $ignored_collections)) { + foreach ($this->configFactory->listAll() as $config_name) { + $collection_source_data = $destination_storage->read($config_name); + + if (is_array($collection_source_data) && count(array_filter($collection_source_data)) != 0) { + $transformation_storage->write($config_name, $destination_storage->read($config_name)); + } + else { + $transformation_storage->delete($config_name); + } + } + continue; + } + // Loop over the ignored config in the destination. // We need to do this inside of the collection loop because some config // to be ignored may only be present in some collections. @@ -247,6 +263,77 @@ class ConfigIgnoreEventSubscriber implements EventSubscriberInterface, CacheTags return array_diff_key($ignored_configs, array_flip($exceptions)); } + /** + * Returns the list of all ignored collections by expanding the wildcards. + * + * @param array $collection_names + * An array of existing collection names. + * + * @return array + * An associative array keyed by collection name and having the values either + * NULL, if the whole config is ignored, or an array of keys to be ignored. + * Each key is an array of parents: + * @code + * [ + * 'system.site' => NULL, + * 'user.settings' => [ + * ['notify', 'cancel_confirm'], + * ['password_reset_timeout'], + * ], + * ] + * @endcode + */ + protected function getIgnoredCollections(array $collection_names) { + /** @var string[] $ignored_collections_patterns */ + $ignored_collections_patterns = $this->configFactory->get('config_ignore.settings')->get('ignored_config_collections'); + $this->moduleHandler->invokeAll('config_ignore_collections_alter', [&$ignored_collections_patterns]); + + // Builds ignored collections exceptions and remove them from the pattern list. + $exceptions = []; + foreach ($ignored_collections_patterns as $delta => $ignored_collection_pattern) { + if (strpos($ignored_collection_pattern, '~') === 0) { + if (strpos($ignored_collection_pattern, '*') !== FALSE) { + throw new \LogicException("A collection ignore pattern entry cannot contain both, '~' and '*'."); + } + $exceptions[] = substr($ignored_collection_pattern, 1); + unset($ignored_collections_patterns[$delta]); + } + } + + $ignored_collections = []; + foreach ($collection_names as $collection_name) { + foreach ($ignored_collections_patterns as $ignored_collection_pattern) { + if (strpos($ignored_collection_pattern, ':') !== FALSE) { + // Some patterns are defining also a key. + [$collection_name_pattern, $key] = explode(':', $ignored_collection_pattern, 2); + $key = trim($key); + if (strpos($key, '*') !== FALSE) { + throw new \LogicException("The key part of the config ignore pattern cannot contain the wildcard character '*'."); + } + } + else { + $collection_name_pattern = $ignored_collection_pattern; + $key = NULL; + } + if ($this->wildcardMatch($collection_name_pattern, $collection_name)) { + if ($key) { + $ignored_collections[$collection_name][] = explode('.', $key); + } + else { + $ignored_collections[$collection_name] = NULL; + // As this pattern has no key we continue with the next config. Any + // subsequent pattern with the same config but with key is covered + // by this ignore pattern. + break; + } + } + } + } + + // Extract the exceptions from the ignored configs. + return array_diff_key($ignored_collections, array_flip($exceptions)); + } + /** * Checks if a string matches a given wildcard pattern. * diff --git a/src/Form/Settings.php b/src/Form/Settings.php index d5b6baa..d1bf521 100644 --- a/src/Form/Settings.php +++ b/src/Form/Settings.php @@ -54,6 +54,16 @@ Examples: