/** * Returns a map of all config object names and their folders. * * The list is based on enabled modules and themes. The active configuration * storage is used rather than \Drupal\Core\Extension\ModuleHandler and * \Drupal\Core\Extension\ThemeHandler in order to resolve circular * dependencies between these services and \Drupal\Core\Config\ConfigInstaller * and \Drupal\Core\Config\TypedConfigManager. * * @return array * An array mapping config object names with directories. */ protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); $this->folders += $this->getComponentNames('core', array('core')); $extensions = $this->configStorage->read('core.extension'); if (!empty($extensions['module'])) { $modules = $extensions['module']; if (!$this->includeProfile) { if ($install_profile = Settings::get('install_profile')) { unset($modules[$install_profile]); } } $this->folders += $this->getComponentNames('module', array_keys($modules)); } if (!empty($extensions['theme'])) { $this->folders += $this->getComponentNames('theme', array_keys($extensions['theme'])); } // The install profile can override module default configuration. We do // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. $profile_folders = $this->getComponentNames('profile', array(drupal_get_profile())); $folders_to_replace = array_intersect_key($profile_folders, $this->folders); if (!empty($folders_to_replace)) { $this->folders = array_merge($this->folders, $folders_to_replace); } } return $this->folders; }
/** * {@inheritdoc} */ public function get($name) { $data = $this->configStorage->read($name); $type_definition = $this->getDefinition($name); $data_definition = $this->buildDataDefinition($type_definition, $data); return $this->create($data_definition, $data); }
/** * {@inheritdoc} */ public function read($name) { if (isset($this->replacementData[$this->collection][$name])) { return $this->replacementData[$this->collection][$name]; } return $this->storage->read($name); }
/** * {@inheritdoc} */ public function loadOverrides($names) { $overrides = array(); // loadOverrides() runs on config entities, which means that if we try // to run this routine on our own data, then we end up in an infinite loop. // So ensure that we are _not_ looking up a domain.record.*. $check = current($names); $list = explode('.', $check); if (isset($list[0]) && isset($list[1]) && $list[0] == 'domain' && $list[1] == 'record') { return $overrides; } $this->initiateContext(); if (!empty($this->domain)) { foreach ($names as $name) { $config_name = $this->getDomainConfigName($name, $this->domain); // Check to see if the config storage has an appropriately named file // containing override data. if ($override = $this->storage->read($config_name['langcode'])) { $overrides[$name] = $override; } elseif ($override = $this->storage->read($config_name['domain'])) { $overrides[$name] = $override; } } } return $overrides; }
/** * {@inheritdoc} */ public function read($name) { $data = $this->storage->read($name); foreach ($this->filters as $filter) { $data = $filter->filterRead($name, $data); } return $data; }
public function filterWrite($name, array $data, StorageInterface $storage) { if ($name != 'core.extension') { return $data; } $originalData = $storage->read($name); return $this->filterOutIgnored($data, $storage->read($name)); }
/** * Returns a map of all config object names and their folders. * * The list is based on enabled modules and themes. The active configuration * storage is used rather than \Drupal\Core\Extension\ModuleHandler and * \Drupal\Core\Extension\ThemeHandler in order to resolve circular * dependencies between these services and \Drupal\Core\Config\ConfigInstaller * and \Drupal\Core\Config\TypedConfigManager. * * @return array * An array mapping config object names with directories. */ protected function getAllFolders() { if (!isset($this->folders)) { $this->folders = array(); $this->folders += $this->getCoreNames(); $install_profile = Settings::get('install_profile'); $profile = drupal_get_profile(); $extensions = $this->configStorage->read('core.extension'); // @todo Remove this scan as part of https://www.drupal.org/node/2186491 $listing = new ExtensionDiscovery(\Drupal::root()); if (!empty($extensions['module'])) { $modules = $extensions['module']; // Remove the install profile as this is handled later. unset($modules[$install_profile]); $profile_list = $listing->scan('profile'); if ($profile && isset($profile_list[$profile])) { // Prime the drupal_get_filename() static cache with the profile info // file location so we can use drupal_get_path() on the active profile // during the module scan. // @todo Remove as part of https://www.drupal.org/node/2186491 drupal_get_filename('profile', $profile, $profile_list[$profile]->getPathname()); } $module_list_scan = $listing->scan('module'); $module_list = array(); foreach (array_keys($modules) as $module) { if (isset($module_list_scan[$module])) { $module_list[$module] = $module_list_scan[$module]; } } $this->folders += $this->getComponentNames($module_list); } if (!empty($extensions['theme'])) { $theme_list_scan = $listing->scan('theme'); foreach (array_keys($extensions['theme']) as $theme) { if (isset($theme_list_scan[$theme])) { $theme_list[$theme] = $theme_list_scan[$theme]; } } $this->folders += $this->getComponentNames($theme_list); } if ($this->includeProfile) { // The install profile can override module default configuration. We do // this by replacing the config file path from the module/theme with the // install profile version if there are any duplicates. if (isset($profile)) { if (!isset($profile_list)) { $profile_list = $listing->scan('profile'); } if (isset($profile_list[$profile])) { $profile_folders = $this->getComponentNames(array($profile_list[$profile])); $this->folders = $profile_folders + $this->folders; } } } } return $this->folders; }
/** * {@inheritdoc} */ public function read($name) { $data = $this->baseStorage->read($name); if ($name == 'core.extension' && isset($data['module'])) { // Remove any profiles from the list. These will be installed later. // @see config_installer_config_import_profile() $data['module'] = array_diff_key($data['module'], $this->profiles); } return $data; }
/** * Implements Drupal\Core\Config\StorageInterface::read(). */ public function read($name) { if ($cache = $this->cache->get($name)) { // The cache contains either the cached configuration data or FALSE // if the configuration file does not exist. return $cache->data; } // Read from the storage on a cache miss and cache the data. Also cache // information about missing configuration objects. $data = $this->storage->read($name); $this->cache->set($name, $data); return $data; }
/** * Copies configuration objects from source storage to target storage. * * @param \Drupal\Core\Config\StorageInterface $source_storage * The source config storage service. * @param \Drupal\Core\Config\StorageInterface $target_storage * The target config storage service. */ protected function copyConfig(StorageInterface $source_storage, StorageInterface $target_storage) { $target_storage->deleteAll(); foreach ($source_storage->listAll() as $name) { $target_storage->write($name, $source_storage->read($name)); } }
/** * Creates a snapshot of a given configuration item as provided by an * extension. * * @param FileStorage $extension_storage * An extension's configuration file storage. * @param string $item_name * The name of the configuration item. */ function createItemSnapshot(FileStorage $extension_storage, $item_name) { // Snapshot the configuration item as provided by the extension. $extension_value = $extension_storage->read($item_name); $this->snapshotExtensionStorage->write($item_name, $extension_value); // Snapshot the configuration item as installed in the active storage. $active_value = $this->activeStorage->read($item_name); $this->snapshotActiveStorage->write($item_name, $active_value); }
/** * {@inheritdoc} */ public function getFromExtension($type, $name) { $full_name = $this->getFullName($type, $name); $value = $this->extensionConfigStorage->read($full_name); if (!$value) { $value = $this->extensionOptionalConfigStorage->read($full_name); } return $value; }
/** * Read a configuration from install storage or default languages. * * @param string $name * Configuration object name. * * @return array * Configuration data from install storage or default language. */ public function read($name) { if ($this->requiredInstallStorage->exists($name)) { return $this->requiredInstallStorage->read($name); } elseif ($this->optionalInstallStorage->exists($name)) { return $this->optionalInstallStorage->read($name); } elseif (strpos($name, 'language.entity.') === 0) { // Simulate default languages as if they were shipped as default // configuration. $langcode = str_replace('language.entity.', '', $name); $predefined_languages = $this->languageManager->getStandardLanguageList(); if (isset($predefined_languages[$langcode])) { $data = $this->configStorage->read($name); $data['label'] = $predefined_languages[$langcode][0]; return $data; } } }
protected function addConfigList($full_name, &$list) { if (!in_array($full_name, $list)) { array_unshift($list, $full_name); $value = $this->extensionStorage->read($full_name); if (isset($value['dependencies']['config'])) { foreach ($value['dependencies']['config'] as $config_name) { $this->addConfigList($config_name, $list); } } } }
public function filterWrite($name, array $data, StorageInterface $storage) { if ($name == 'core.extension') { return $this->filterOutIgnored($data, $storage->read($name)); } $dependent_configs = $this->getAllDependentConfigs($storage); if (in_array($name, $dependent_configs)) { $data = ($existing = $storage->read($name)) ? $existing : NULL; } return $data; }
/** * Updates all configuration translations for the names / languages provided. * * To be used when interface translation changes result in the need to update * configuration translations to keep them in sync. * * @param array $names * Array of names of configuration objects to update. * @param array $langcodes * (optional) Array of language codes to update. Defaults to all * configurable languages. * * @return int * Total number of configuration override and active configuration objects * updated (saved or removed). */ public function updateConfigTranslations(array $names, array $langcodes = array()) { $langcodes = $langcodes ? $langcodes : array_keys($this->languageManager->getLanguages()); $count = 0; foreach ($names as $name) { $translatable = $this->getTranslatableDefaultConfig($name); if (empty($translatable)) { // If there is nothing translatable in this configuration or not // supported, skip it. continue; } $active_langcode = $this->getActiveConfigLangcode($name); $active = $this->configStorage->read($name); foreach ($langcodes as $langcode) { $processed = $this->processTranslatableData($name, $active, $translatable, $langcode); if ($langcode != $active_langcode) { // If the language code is not the same as the active storage // language, we should update a configuration override. if (!empty($processed)) { // Update translation data in configuration override. $this->saveTranslationOverride($name, $langcode, $processed); $count++; } else { $override = $this->languageManager->getLanguageConfigOverride($langcode, $name); if (!$override->isNew()) { $data = $this->filterOverride($override->get(), $translatable); if (empty($data)) { // Delete language override if there is no data left at all. // This means all prior translations in the override were locale // managed. $this->deleteTranslationOverride($name, $langcode); $count++; } else { // If there were translatable elements besides locale managed // items, save with only those, and remove the ones managed // by locale only. $this->saveTranslationOverride($name, $langcode, $data); $count++; } } } } elseif (locale_is_translatable($langcode)) { // If the language code is the active storage language, we should // update. If it is English, we should only update if English is also // translatable. $active = NestedArray::mergeDeepArray(array($active, $processed), TRUE); $this->saveTranslationActive($name, $active); $count++; } } } return $count; }
/** * Handles switching the export textarea. */ public function updateExport($form, FormStateInterface $form_state) { // Determine the full config name for the selected config entity. if ($form_state['values']['config_type'] !== 'system.simple') { $definition = $this->entityManager->getDefinition($form_state['values']['config_type']); $name = $definition->getConfigPrefix() . '.' . $form_state['values']['config_name']; } else { $name = $form_state['values']['config_name']; } // Read the raw data for this config name, encode it, and display it. $form['export']['#value'] = Yaml::encode($this->configStorage->read($name)); $form['export']['#description'] = $this->t('The filename is %name.', array('%name' => $name . '.yml')); return $form['export']; }
/** * Gets locale wrapper with typed configuration data. * * @param string $name * Configuration object name. * * @return \Drupal\locale\LocaleTypedConfig * Locale-wrapped configuration element. */ public function get($name) { // Read default and current configuration data. $default = $this->installStorage->read($name); $updated = $this->configStorage->read($name); // We get only the data that didn't change from default. $data = $this->compareConfigData($default, $updated); $definition = $this->typedConfigManager->getDefinition($name); $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $data); // Unless the configuration has a explicit language code we assume English. $langcode = isset($default['langcode']) ? $default['langcode'] : 'en'; $wrapper = new LocaleTypedConfig($data_definition, $name, $langcode, $this, $this->typedConfigManager); $wrapper->setValue($data); return $wrapper; }
/** * Updates all configuration translations for the names / languages provided. * * To be used when interface translation changes result in the need to update * configuration translations to keep them in sync. * * @param array $names * Array of names of configuration objects to update. * @param array $langcodes * (optional) Array of language codes to update. Defaults to all * configurable languages. * * @return int * Total number of configuration override and active configuration objects * updated (saved or removed). */ public function updateConfigTranslations(array $names, array $langcodes = array()) { $langcodes = $langcodes ? $langcodes : array_keys($this->languageManager->getLanguages()); $count = 0; foreach ($names as $name) { $translatable = $this->getTranslatableDefaultConfig($name); if (empty($translatable)) { // If there is nothing translatable in this configuration or not // supported, skip it. continue; } $active_langcode = $this->getActiveConfigLangcode($name); $active = $this->configStorage->read($name); foreach ($langcodes as $langcode) { $processed = $this->processTranslatableData($name, $active, $translatable, $langcode); // If the language code is not the same as the active storage // language, we should update the configuration override. if ($langcode != $active_langcode) { $override = $this->languageManager->getLanguageConfigOverride($langcode, $name); // Filter out locale managed configuration keys so that translations // removed from Locale will be reflected in the config override. $data = $this->filterOverride($override->get(), $translatable); if (!empty($processed)) { // Merge in the Locale managed translations with existing data. $data = NestedArray::mergeDeepArray(array($data, $processed), TRUE); } if (empty($data) && !$override->isNew()) { // The configuration override contains Locale overrides that no // longer exist. $this->deleteTranslationOverride($name, $langcode); $count++; } elseif (!empty($data)) { // Update translation data in configuration override. $this->saveTranslationOverride($name, $langcode, $data); $count++; } } elseif (locale_is_translatable($langcode)) { // If the language code is the active storage language, we should // update. If it is English, we should only update if English is also // translatable. $active = NestedArray::mergeDeepArray(array($active, $processed), TRUE); $this->saveTranslationActive($name, $active); $count++; } } } return $count; }
/** * {@inheritdoc} */ public function detectOverrides(array $feature, $include_new = FALSE) { $config_diff = \Drupal::service('config_update.config_diff'); $different = array(); foreach ($feature['config'] as $name) { $active = $this->configStorage->read($name); $extension = $this->extensionStorages->read($name); $extension = !empty($extension) ? $extension : array(); if (($include_new || !empty($extension)) && !$config_diff->same($extension, $active)) { $different[] = $name; } } if (!empty($different)) { $feature['state'] = FeaturesManagerInterface::STATE_OVERRIDDEN; } return $different; }
/** * {@inheritdoc} */ public function detectOverrides(Package $feature, $include_new = FALSE) { /** @var \Drupal\config_update\ConfigDiffInterface $config_diff */ $config_diff = \Drupal::service('config_update.config_diff'); $different = array(); foreach ($feature->getConfig() as $name) { $active = $this->configStorage->read($name); $extension = $this->extensionStorages->read($name); $extension = !empty($extension) ? $extension : array(); if (($include_new || !empty($extension)) && !$config_diff->same($extension, $active)) { $different[] = $name; } } if (!empty($different)) { $feature->setState(FeaturesManagerInterface::STATE_OVERRIDDEN); } return $different; }
/** * {@inheritdoc} */ public function validateSiteUuid() { $source = $this->sourceStorage->read('system.site'); $target = $this->targetStorage->read('system.site'); return $source['uuid'] === $target['uuid']; }
/** * {@inheritdoc} */ public function createSnapshot(StorageInterface $source_storage, StorageInterface $snapshot_storage) { // Empty the snapshot of all configuration. $snapshot_storage->deleteAll(); foreach ($snapshot_storage->getAllCollectionNames() as $collection) { $snapshot_collection = $snapshot_storage->createCollection($collection); $snapshot_collection->deleteAll(); } foreach ($source_storage->listAll() as $name) { $snapshot_storage->write($name, $source_storage->read($name)); } // Copy collections as well. foreach ($source_storage->getAllCollectionNames() as $collection) { $source_collection = $source_storage->createCollection($collection); $snapshot_collection = $snapshot_storage->createCollection($collection); foreach ($source_collection->listAll() as $name) { $snapshot_collection->write($name, $source_collection->read($name)); } } }
/** * Tests that the storage supports collections. */ public function testCollection() { $name = 'config_test.storage'; $data = array('foo' => 'bar'); $result = $this->storage->write($name, $data); $this->assertIdentical($result, TRUE); $this->assertIdentical($data, $this->storage->read($name)); // Create configuration in a new collection. $new_storage = $this->storage->createCollection('collection.sub.new'); $this->assertFalse($new_storage->exists($name)); $this->assertEqual(array(), $new_storage->listAll()); $new_storage->write($name, $data); $this->assertIdentical($result, TRUE); $this->assertIdentical($data, $new_storage->read($name)); $this->assertEqual(array($name), $new_storage->listAll()); $this->assertTrue($new_storage->exists($name)); $new_data = array('foo' => 'baz'); $new_storage->write($name, $new_data); $this->assertIdentical($result, TRUE); $this->assertIdentical($new_data, $new_storage->read($name)); // Create configuration in another collection. $another_storage = $this->storage->createCollection('collection.sub.another'); $this->assertFalse($another_storage->exists($name)); $this->assertEqual(array(), $another_storage->listAll()); $another_storage->write($name, $new_data); $this->assertIdentical($result, TRUE); $this->assertIdentical($new_data, $another_storage->read($name)); $this->assertEqual(array($name), $another_storage->listAll()); $this->assertTrue($another_storage->exists($name)); // Create configuration in yet another collection. $alt_storage = $this->storage->createCollection('alternate'); $alt_storage->write($name, $new_data); $this->assertIdentical($result, TRUE); $this->assertIdentical($new_data, $alt_storage->read($name)); // Switch back to the collection-less mode and check the data still exists // add has not been touched. $this->assertIdentical($data, $this->storage->read($name)); // Check that the getAllCollectionNames() method works. $this->assertIdentical(array('alternate', 'collection.sub.another', 'collection.sub.new'), $this->storage->getAllCollectionNames()); // Check that the collections are removed when they are empty. $alt_storage->delete($name); $this->assertIdentical(array('collection.sub.another', 'collection.sub.new'), $this->storage->getAllCollectionNames()); // Create configuration in collection called 'collection'. This ensures that // FileStorage's collection storage works regardless of its use of // subdirectories. $parent_storage = $this->storage->createCollection('collection'); $this->assertFalse($parent_storage->exists($name)); $this->assertEqual(array(), $parent_storage->listAll()); $parent_storage->write($name, $new_data); $this->assertIdentical($result, TRUE); $this->assertIdentical($new_data, $parent_storage->read($name)); $this->assertEqual(array($name), $parent_storage->listAll()); $this->assertTrue($parent_storage->exists($name)); $this->assertIdentical(array('collection', 'collection.sub.another', 'collection.sub.new'), $this->storage->getAllCollectionNames()); $parent_storage->deleteAll(); $this->assertIdentical(array('collection.sub.another', 'collection.sub.new'), $this->storage->getAllCollectionNames()); // Check that the having an empty collection-less storage does not break // anything. Before deleting check that the previous delete did not affect // data in another collection. $this->assertIdentical($data, $this->storage->read($name)); $this->storage->delete($name); $this->assertIdentical(array('collection.sub.another', 'collection.sub.new'), $this->storage->getAllCollectionNames()); }