Commit 179c0920 authored by catch's avatar catch

Issue #2268939 by Gábor Hojtsy, vijaycs85: Fixed Config overrides not updated when config changes.

parent 074bc73e
<?php
/**
* @file
* Contains \Drupal\Core\Config\ConfigFactoryOverrideBase.
*/
namespace Drupal\Core\Config;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Defines a base event listener implementation configuration overrides.
*/
abstract class ConfigFactoryOverrideBase implements EventSubscriberInterface {
/**
* Reacts to the ConfigEvents::COLLECTION_INFO event.
*
* @param \Drupal\Core\Config\ConfigCollectionInfo $collection_info
* The configuration collection names event.
*/
abstract public function addCollections(ConfigCollectionInfo $collection_info);
/**
* Actions to be performed to configuration override on configuration save.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The config CRUD event.
*/
abstract public function onConfigSave(ConfigCrudEvent $event);
/**
* Actions to be performed to configuration override on configuration delete.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The config CRUD event.
*/
abstract public function onConfigDelete(ConfigCrudEvent $event);
/**
* Actions to be performed to configuration override on configuration rename.
*
* @param \Drupal\Core\Config\ConfigRenameEvent $event
* The config rename event.
*/
abstract public function onConfigRename(ConfigRenameEvent $event);
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
$events[ConfigEvents::COLLECTION_INFO][] = array('addCollections');
$events[ConfigEvents::SAVE][] = array('onConfigSave', 20);
$events[ConfigEvents::DELETE][] = array('onConfigDelete', 20);
$events[ConfigEvents::RENAME][] = array('onConfigRename', 20);
return $events;
}
/**
* Filters data in the override based on what is currently in configuration.
*
* @param \Drupal\Core\Config\Config $config
* Current configuration object.
* @param \Drupal\Core\Config\StorableConfigBase $override
* Override object corresponding to the configuration to filter data in.
*/
protected function filterOverride(Config $config, StorableConfigBase $override) {
$override_data = $override->get();
$this->filterNestedArray($config->get(), $override_data);
if (empty($override_data)) {
// If no override values are left that would apply, remove the override.
$override->delete();
}
else {
// Otherwise set the filtered override values back.
$override->setData($override_data)->save();
}
}
/**
* Filters data in nested arrays.
*
* @param array $original_data
* Original data array to filter against.
* @param array $override_data
* Override data to filter.
*/
protected function filterNestedArray(array $original_data, array &$override_data) {
foreach ($override_data as $key => $value) {
if (!isset($original_data[$key])) {
// The original data is not there anymore, remove the override.
unset($override_data[$key]);
}
elseif (is_array($override_data[$key])) {
if (is_array($original_data[$key])) {
// Do the filtering one level deeper.
$this->filterNestedArray($original_data[$key], $override_data[$key]);
// If no overrides are left under this level, remove the level.
if (empty($override_data[$key])) {
unset($override_data[$key]);
}
}
else {
// The override is an array but the value is not, this will not go
// well, remove the override.
unset($override_data[$key]);
}
}
}
}
}
......@@ -76,6 +76,56 @@ function testConfigLanguageOverride() {
$config = \Drupal::config('config_test.new');
$this->assertIdentical($config->get('language'), NULL);
\Drupal::configFactory()->setOverrideState($old_state);
// Test how overrides react to base configuration changes. Set up some base
// values.
\Drupal::config('config_test.foo')
->set('value', array('key' => 'original'))
->set('label', 'Original')
->save();
\Drupal::languageManager()
->getLanguageConfigOverride('de', 'config_test.foo')
->set('value', array('key' => 'override'))
->set('label', 'Override')
->save();
\Drupal::languageManager()
->getLanguageConfigOverride('fr', 'config_test.foo')
->set('value', array('key' => 'override'))
->save();
\Drupal::configFactory()->clearStaticCache();
$config = \Drupal::config('config_test.foo');
$this->assertIdentical($config->get('value'), array('key' => 'override'));
// Ensure renaming the config will rename the override.
\Drupal::configFactory()->rename('config_test.foo', 'config_test.bar');
$config = \Drupal::config('config_test.bar');
$this->assertEqual($config->get('value'), array('key' => 'original'));
$override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.foo');
$this->assertTrue($override->isNew());
$this->assertEqual($override->get('value'), NULL);
$override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.bar');
$this->assertFalse($override->isNew());
$this->assertEqual($override->get('value'), array('key' => 'override'));
$override = \Drupal::languageManager()->getLanguageConfigOverride('fr', 'config_test.bar');
$this->assertFalse($override->isNew());
$this->assertEqual($override->get('value'), array('key' => 'override'));
// Ensure changing data in the config will update the overrides.
$config = \Drupal::config('config_test.bar')->clear('value.key')->save();
$this->assertEqual($config->get('value'), array());
$override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.bar');
$this->assertFalse($override->isNew());
$this->assertEqual($override->get('value'), NULL);
// The French override will become empty and therefore removed.
$override = \Drupal::languageManager()->getLanguageConfigOverride('fr', 'config_test.bar');
$this->assertTrue($override->isNew());
$this->assertEqual($override->get('value'), NULL);
// Ensure deleting the config will delete the override.
\Drupal::configFactory()->get('config_test.bar')->delete();
$override = \Drupal::languageManager()->getLanguageConfigOverride('de', 'config_test.bar');
$this->assertTrue($override->isNew());
$this->assertEqual($override->get('value'), NULL);
}
}
......@@ -9,7 +9,9 @@
use Drupal\Component\Utility\String;
use Drupal\Core\Config\ConfigCollectionInfo;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigFactoryOverrideBase;
use Drupal\Core\Config\ConfigRenameEvent;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Language\LanguageDefault;
......@@ -20,7 +22,7 @@
/**
* Provides language overrides for the configuration factory.
*/
class LanguageConfigFactoryOverride implements LanguageConfigFactoryOverrideInterface, EventSubscriberInterface {
class LanguageConfigFactoryOverride extends ConfigFactoryOverrideBase implements LanguageConfigFactoryOverrideInterface, EventSubscriberInterface {
/**
* The configuration storage.
......@@ -194,10 +196,7 @@ protected function getLangcodeFromCollectionName($collection) {
}
/**
* Reacts to the ConfigEvents::COLLECTION_INFO event.
*
* @param \Drupal\Core\Config\ConfigCollectionInfo $collection_info
* The configuration collection names event.
* {@inheritdoc}
*/
public function addCollections(ConfigCollectionInfo $collection_info) {
foreach (\Drupal::languageManager()->getLanguages() as $language) {
......@@ -208,9 +207,47 @@ public function addCollections(ConfigCollectionInfo $collection_info) {
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
$events[ConfigEvents::COLLECTION_INFO][] = array('addCollections');
return $events;
public function onConfigSave(ConfigCrudEvent $event) {
$config = $event->getConfig();
$name = $config->getName();
foreach (\Drupal::languageManager()->getLanguages() as $language) {
$config_translation = $this->getOverride($language->getId(), $name);
if (!$config_translation->isNew()) {
$this->filterOverride($config, $config_translation);
}
}
}
/**
* {@inheritdoc}
*/
public function onConfigRename(ConfigRenameEvent $event) {
$config = $event->getConfig();
$name = $config->getName();
$old_name = $event->getOldName();
foreach (\Drupal::languageManager()->getLanguages() as $language) {
$config_translation = $this->getOverride($language->getId(), $old_name);
if (!$config_translation->isNew()) {
$saved_config = $config_translation->get();
$storage = $this->getStorage($language->getId());
$storage->write($name, $saved_config);
$config_translation->delete();
}
}
}
/**
* {@inheritdoc}
*/
public function onConfigDelete(ConfigCrudEvent $event) {
$config = $event->getConfig();
$name = $config->getName();
foreach (\Drupal::languageManager()->getLanguages() as $language) {
$config_translation = $this->getOverride($language->getId(), $name);
if (!$config_translation->isNew()) {
$config_translation->delete();
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment