namespace Drupal\Core\Config;
use Drupal\Component\Utility\Crypt;
-use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\Entity\ConfigDependencyManager;
-use Drupal\Core\Config\Entity\ConfigEntityDependency;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ConfigInstaller implements ConfigInstallerInterface {
*/
public function installOptionalConfig(StorageInterface $storage = NULL, $dependency = []) {
$profile = $this->drupalGetProfile();
- $optional_profile_config = [];
+ $enabled_extensions = $this->getEnabledExtensions();
+ $existing_config = $this->getActiveStorages()->listAll();
+
+ // Create the storages to read configuration from.
if (!$storage) {
// Search the install profile's optional configuration too.
$storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE, $this->installProfile);
// Creates a profile storage to search for overrides.
$profile_install_path = $this->drupalGetPath('module', $profile) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
$profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION);
- $optional_profile_config = $profile_storage->listAll();
}
else {
// Profile has not been set yet. For example during the first steps of the
$profile_storage = NULL;
}
- $enabled_extensions = $this->getEnabledExtensions();
- $existing_config = $this->getActiveStorages()->listAll();
+ // Build the list of possible configuration to create.
+ $list = $storage->listAll();
+ if ($profile_storage && !empty($dependency)) {
+ // Only add the optional profile configuration into the list if we are
+ // have a dependency to check. This ensures that optional profile
+ // configuration is not unexpectedly re-created after being deleted.
+ $list = array_unique(array_merge($list, $profile_storage->listAll()));
+ }
- $list = array_unique(array_merge($storage->listAll(), $optional_profile_config));
+ // Filter the list of configuration to only include configuration that
+ // should be created.
$list = array_filter($list, function ($config_name) use ($existing_config) {
// Only list configuration that:
// - does not already exist
$dependency_manager = new ConfigDependencyManager();
$dependency_manager->setData($config_to_create);
$config_to_create = array_merge(array_flip($dependency_manager->sortAll()), $config_to_create);
+ if (!empty($dependency)) {
+ // In order to work out dependencies we need the full config graph.
+ $dependency_manager->setData($this->getActiveStorages()->readMultiple($existing_config) + $config_to_create);
+ $dependencies = $dependency_manager->getDependentEntities(key($dependency), reset($dependency));
+ }
foreach ($config_to_create as $config_name => $data) {
// Remove configuration where its dependencies cannot be met.
$remove = !$this->validateDependencies($config_name, $data, $enabled_extensions, $all_config);
- // If $dependency is defined, remove configuration that does not have a
- // matching dependency.
+ // Remove configuration that is not dependent on $dependency, if it is
+ // defined.
if (!$remove && !empty($dependency)) {
- // Create a light weight dependency object to check dependencies.
- $config_entity = new ConfigEntityDependency($config_name, $data);
- $remove = !$config_entity->hasDependency(key($dependency), reset($dependency));
+ $remove = !isset($dependencies[$config_name]);
}
if ($remove) {
unset($all_config[$config_name]);
}
}
+
+ // Create the optional configuration if there is any left after filtering.
if (!empty($config_to_create)) {
$this->createConfiguration(StorageInterface::DEFAULT_COLLECTION, $config_to_create, TRUE);
}
$entity_storage = $this->configManager
->getEntityManager()
->getStorage($entity_type);
+
+ $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix());
// It is possible that secondary writes can occur during configuration
// creation. Updates of such configuration are allowed.
if ($this->getActiveStorages($collection)->exists($name)) {
- $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix());
$entity = $entity_storage->load($id);
$entity = $entity_storage->updateFromStorageRecord($entity, $new_config->get());
}
}
if ($entity->isInstallable()) {
$entity->trustData()->save();
+ if ($id !== $entity->id()) {
+ trigger_error(sprintf('The configuration name "%s" does not match the ID "%s"', $name, $entity->id()), E_USER_WARNING);
+ }
}
}
else {
// Only install configuration for enabled extensions.
$enabled_extensions = $this->getEnabledExtensions();
$config_to_install = array_filter($storage->listAll(), function ($config_name) use ($enabled_extensions) {
- $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
+ $provider = mb_substr($config_name, 0, strpos($config_name, '.'));
return in_array($provider, $enabled_extensions);
});
if (!empty($config_to_install)) {