/** * Generates and adds files to a given package or profile. */ protected function addPackageFiles(array &$package) { $config_collection = $this->getConfigCollection(); // Ensure the directory reflects the current full machine name. $package['directory'] = $package['machine_name']; // Only add files if there is at least one piece of configuration // present. if (!empty($package['config'])) { // Add .info.yml files. $this->addInfoFile($package); // Add configuration files. foreach ($package['config'] as $name) { $config = $config_collection[$name]; // The UUID is site-specfic, so don't export it. if ($entity_type_id = $this->configManager->getEntityTypeIdByName($name)) { unset($config['data']['uuid']); } // User roles include all permissions currently assigned to them. To // avoid extraneous additions, reset permissions. if ($config['type'] == 'user_role') { $config['data']['permissions'] = []; } $package['files'][$name] = ['filename' => $config['name'] . '.yml', 'subdirectory' => $config['subdirectory'], 'string' => Yaml::encode($config['data'])]; } } }
/** * {@inheritdoc} */ public function updateExtension($type, $name, array $changelist = array(), $safe_only = TRUE) { // If no change list was passed, load one. if (empty($changelist)) { $changelist = $this->configSyncLister->getExtensionChangelist($type, $name, $safe_only); } // Process create changes. if (!empty($changelist['create'])) { foreach ($changelist['create'] as $item_name) { if (!($entity_type = $this->configManager->getEntityTypeIdByName($name))) { $entity_type = 'system.simple'; } $this->configRevert->import($entity_type, $item_name); } } // Process update changes. if (!empty($changelist['update'])) { foreach ($changelist['update'] as $item_name) { if (!($entity_type = $this->configManager->getEntityTypeIdByName($name))) { $entity_type = 'system.simple'; } $this->configRevert->revert($entity_type, $item_name); } } // Refresh the configuration snapshot. $this->configSyncSnapshotter->createExtensionSnapshot($type, $name); }
/** * Generates and adds files to a given package or profile. */ protected function addPackageFiles(Package $package) { $config_collection = $this->getConfigCollection(); // Ensure the directory reflects the current full machine name. $package->setDirectory($package->getMachineName()); // Only add files if there is at least one piece of configuration // present. if ($package->getConfig()) { // Add .info.yml files. $this->addInfoFile($package); // Add configuration files. foreach ($package->getConfig() as $name) { $config = $config_collection[$name]; // The UUID is site-specfic, so don't export it. if ($entity_type_id = $this->configManager->getEntityTypeIdByName($name)) { $data = $config->getData(); unset($data['uuid']); $config->setData($data); } // User roles include all permissions currently assigned to them. To // avoid extraneous additions, reset permissions. if ($config->getType() == 'user_role') { $data = $config->getData(); $data['permissions'] = []; $config->setData($data); } $package->appendFile(['filename' => $config->getName() . '.yml', 'subdirectory' => $config->getSubdirectory(), 'string' => Yaml::encode($config->getData())], $name); } } }
/** * Generates and adds files to a given package or profile. */ protected function addPackageFiles(Package $package) { $config_collection = $this->getConfigCollection(); // Always add .info.yml and .features.yml files. $this->addInfoFile($package); // Only add files if there is at least one piece of configuration present. if ($package->getConfig()) { // Add configuration files. foreach ($package->getConfig() as $name) { $config = $config_collection[$name]; $data = $config->getData(); // The _core is site-specific, so don't export it. unset($data['_core']); // The UUID is site-specfic, so don't export it. if ($entity_type_id = $this->configManager->getEntityTypeIdByName($name)) { unset($data['uuid']); } $config->setData($data); // User roles include all permissions currently assigned to them. To // avoid extraneous additions, reset permissions. if ($config->getType() == 'user_role') { $data = $config->getData(); // Unset and not empty permissions data to prevent loss of configured // role permissions in the event of a feature revert. unset($data['permissions']); $config->setData($data); } $package->appendFile(['filename' => $config->getName() . '.yml', 'subdirectory' => $config->getSubdirectory(), 'string' => Yaml::encode($config->getData())], $name); } } }
/** * Creates configuration in a collection based on the provided list. * * @param string $collection * The configuration collection. * @param array $config_to_create * An array of configuration data to create, keyed by name. */ protected function createConfiguration($collection, array $config_to_create) { // Order the configuration to install in the order of dependencies. if ($collection == StorageInterface::DEFAULT_COLLECTION) { $dependency_manager = new ConfigDependencyManager(); $config_names = $dependency_manager->setData($config_to_create)->sortAll(); } else { $config_names = array_keys($config_to_create); } foreach ($config_names as $name) { // Allow config factory overriders to use a custom configuration object if // they are responsible for the collection. $overrider = $this->configManager->getConfigCollectionInfo()->getOverrideService($collection); if ($overrider) { $new_config = $overrider->createConfigObject($name, $collection); } else { $new_config = new Config($name, $this->getActiveStorages($collection), $this->eventDispatcher, $this->typedConfig); } if ($config_to_create[$name] !== FALSE) { $new_config->setData($config_to_create[$name]); // Add a hash to configuration created through the installer so it is // possible to know if the configuration was created by installing an // extension and to track which version of the default config was used. if (!$this->isSyncing() && $collection == StorageInterface::DEFAULT_COLLECTION) { $new_config->set('_core.default_config_hash', Crypt::hashBase64(serialize($config_to_create[$name]))); } } if ($collection == StorageInterface::DEFAULT_COLLECTION && ($entity_type = $this->configManager->getEntityTypeIdByName($name))) { // If we are syncing do not create configuration entities. Pluggable // configuration entities can have dependencies on modules that are // not yet enabled. This approach means that any code that expects // default configuration entities to exist will be unstable after the // module has been enabled and before the config entity has been // imported. if ($this->isSyncing()) { continue; } /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $entity_storage */ $entity_storage = $this->configManager->getEntityManager()->getStorage($entity_type); // 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()); } else { $entity = $entity_storage->createFromStorageRecord($new_config->get()); } if ($entity->isInstallable()) { $entity->trustData()->save(); } } else { $new_config->save(TRUE); } } }
/** * Ensures bundles that will be deleted are not in use. * * @param \Drupal\Core\Config\ConfigImporterEvent $event * The config import event. */ public function onConfigImporterValidate(ConfigImporterEvent $event) { foreach ($event->getChangelist('delete') as $config_name) { // Get the config entity type ID. This also ensure we are dealing with a // configuration entity. if ($entity_type_id = $this->configManager->getEntityTypeIdByName($config_name)) { $entity_type = $this->entityManager->getDefinition($entity_type_id); // Does this entity type define a bundle of another entity type. if ($bundle_of = $entity_type->getBundleOf()) { // Work out if there are entities with this bundle. $bundle_of_entity_type = $this->entityManager->getDefinition($bundle_of); $bundle_id = ConfigEntityStorage::getIDFromConfigName($config_name, $entity_type->getConfigPrefix()); $entity_query = $this->entityManager->getStorage($bundle_of)->getQuery(); $entity_ids = $entity_query->condition($bundle_of_entity_type->getKey('bundle'), $bundle_id)->accessCheck(FALSE)->range(0, 1)->execute(); if (!empty($entity_ids)) { $entity = $this->entityManager->getStorage($entity_type_id)->load($bundle_id); $event->getConfigImporter()->logError($this->t('Entities exist of type %entity_type and %bundle_label %bundle. These entities need to be deleted before importing.', array('%entity_type' => $bundle_of_entity_type->getLabel(), '%bundle_label' => $bundle_of_entity_type->getBundleLabel(), '%bundle' => $entity->label()))); } } } } }
/** * Creates configuration in a collection based on the provided list. * * @param string $collection * The configuration collection. * @param array $config_to_install * A list of configuration object names to create. */ protected function createConfiguration($collection, array $config_to_install) { // Order the configuration to install in the order of dependencies. $data = $this->getSourceStorage($collection)->readMultiple($config_to_install); $config_entity_support = $this->configManager->supportsConfigurationEntities($collection); if ($config_entity_support) { $dependency_manager = new ConfigDependencyManager(); $config_to_install = $dependency_manager->setData($data)->sortAll(); } // Remove configuration that already exists in the active storage. $config_to_install = array_diff($config_to_install, $this->getActiveStorage($collection)->listAll()); foreach ($config_to_install as $name) { // Allow config factory overriders to use a custom configuration object if // they are responsible for the collection. $overrider = $this->configManager->getConfigCollectionInfo()->getOverrideService($collection); if ($overrider) { $new_config = $overrider->createConfigObject($name, $collection); } else { $new_config = new Config($name, $this->getActiveStorage($collection), $this->eventDispatcher, $this->typedConfig); } if ($data[$name] !== FALSE) { $new_config->setData($data[$name]); } if ($config_entity_support && ($entity_type = $this->configManager->getEntityTypeIdByName($name))) { // If we are syncing do not create configuration entities. Pluggable // configuration entities can have dependencies on modules that are // not yet enabled. This approach means that any code that expects // default configuration entities to exist will be unstable after the // module has been enabled and before the config entity has been // imported. if ($this->isSyncing) { continue; } $entity_storage = $this->configManager->getEntityManager()->getStorage($entity_type); // It is possible that secondary writes can occur during configuration // creation. Updates of such configuration are allowed. if ($this->getActiveStorage($collection)->exists($name)) { $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix()); $entity = $entity_storage->load($id); foreach ($new_config->get() as $property => $value) { $entity->set($property, $value); } $entity->save(); } else { $entity_storage->create($new_config->get())->save(); } } else { $new_config->save(); } } }
/** * Imports a configuration entity rename. * * @param string $collection * The configuration collection. * @param string $rename_name * The rename configuration name, as provided by * \Drupal\Core\Config\StorageComparer::createRenameName(). * * @throws \Drupal\Core\Entity\EntityStorageException * Thrown if the data is owned by an entity type, but the entity storage * does not support imports. * * @return bool * TRUE if the configuration was imported as a configuration entity. FALSE * otherwise. * * @see \Drupal\Core\Config\ConfigImporter::createRenameName() */ protected function importInvokeRename($collection, $rename_name) { $names = $this->storageComparer->extractRenameNames($rename_name); $entity_type_id = $this->configManager->getEntityTypeIdByName($names['old_name']); $old_config = new Config($names['old_name'], $this->storageComparer->getTargetStorage($collection), $this->eventDispatcher, $this->typedConfigManager); if ($old_data = $this->storageComparer->getTargetStorage($collection)->read($names['old_name'])) { $old_config->initWithData($old_data); } $data = $this->storageComparer->getSourceStorage($collection)->read($names['new_name']); $new_config = new Config($names['new_name'], $this->storageComparer->getTargetStorage($collection), $this->eventDispatcher, $this->typedConfigManager); if ($data !== FALSE) { $new_config->setData($data); } $entity_storage = $this->configManager->getEntityManager()->getStorage($entity_type_id); // Call to the configuration entity's storage to handle the configuration // change. if (!$entity_storage instanceof ImportableEntityStorageInterface) { throw new EntityStorageException(SafeMarkup::format('The entity storage "@storage" for the "@entity_type" entity type does not support imports', array('@storage' => get_class($entity_storage), '@entity_type' => $entity_type_id))); } $entity_storage->importRename($names['old_name'], $new_config, $old_config); $this->setProcessedConfiguration($collection, 'rename', $rename_name); return TRUE; }
/** * Returns the original language code for this shipped configuration. * * @param string $name * The configuration name. * * @return null|string * Language code of the default configuration for $name. If the default * configuration data for $name did not contain a language code, it is * assumed to be English. The return value is NULL if no such default * configuration exists. */ public function getDefaultConfigLangcode($name) { // Config entities that do not have the 'default_config_hash' cannot be // shipped configuration regardless of whether there is a name match. // configurable_language entities are a special case since they can be // translated regardless of whether they are shipped if they in the standard // language list. $config_entity_type = $this->configManager->getEntityTypeIdByName($name); if (!$config_entity_type || $config_entity_type === 'configurable_language' || !empty($this->configFactory->get($name)->get('_core.default_config_hash'))) { $shipped = $this->defaultConfigStorage->read($name); if (!empty($shipped)) { return !empty($shipped['langcode']) ? $shipped['langcode'] : 'en'; } } return NULL; }