- πΊπΈUnited States GuyPaddock
I rewrote the description of this issue because I wasn't 100% sure what the original description was alluding to and I just ran into this issue when reverting a config as part of an existing module that uses install-time config overrides.
- πΊπΈUnited States GuyPaddock
I am not sure if a lot can be done inside the ICO module to handle this case better, since it doesn't impact how configuration files get discovered by Core. It appears that Core caches only a single path for each config, so solving this problem might require a custom
InstallStorage
implementation that changes the way thatgetAllFolders()
builds its cache under the hood.As a workaround, an update hook could write the desired configuration directly into configuration storage using a utility method like this:
/** * Import a config from an explicit file path into database storage. * * @param string $config_name * The name of the config item to import from the config folder. * @param string $config_path * The path to the config folder. * * @return bool * TRUE on success, or FALSE if the config could not be installed. */ function my_module_import_single_config(string $config_name, string $config_path): bool { $source = new FileStorage($config_path); $config_storage = \Drupal::service('config.storage'); assert($config_storage instanceof StorageInterface); return $config_storage->write($config_name, $source->read($config_name)); }
This is risky, since the config does NOT get validated. A safer version could look like this:
/** * Import a config from an explicit file path by its entity type and ID. * * @param string $config_path * The path to the config folder. * @param string $entity_type * The machine name of the configuration entity being imported. * @param string $id * The ID of the configuration being imported. */ function my_module_import_single_config_safer(string $config_path, string $entity_type, string $id): void { $source = new FileStorage($config_path); try { $config_full_name = _arkayo_am_get_full_config_name($entity_type, $id); $config_storage = \Drupal::entityTypeManager()->getStorage($entity_type); // _arkayo_am_get_full_config_name() should have thrown an exception on the // entity type by now if this assertion does not hold. assert($config_storage instanceof ConfigEntityStorageInterface); $config_data = $source->read($config_full_name); $entity = $config_storage->createFromStorageRecord($config_data); $entity->save(); } catch (PluginNotFoundException | InvalidPluginDefinitionException $ex) { throw new InvalidArgumentException( sprintf( 'Invalid configuration entity type ("%s"): %s', $entity_type, $ex->getMessage() ) ); } catch (EntityStorageException $ex) { throw new InvalidArgumentException( sprintf( 'Failed to import configuration to "%s": %s', $config_full_name ?? sprintf('%s.%s', $entity_type, $id), $ex->getMessage() )); } }