diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 0128c66..52d91fd 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -159,6 +159,7 @@ protected function setOverriddenData() { } if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) { $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->settingsOverrides), TRUE); + $this->overriddenData['isImmutable'] = TRUE; } return $this; } @@ -285,6 +286,7 @@ public function getOriginal($key = '', $apply_overrides = TRUE) { } if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) { $original_data = NestedArray::mergeDeepArray(array($original_data, $this->settingsOverrides), TRUE); + $original_data['isImmutable'] = TRUE; } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index 08e7e19..5d72ada 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; +use Drupal\Core\Config\ImmutableConfigException; use Drupal\Core\Config\Schema\SchemaIncompleteException; use Drupal\Core\Entity\Entity; use Drupal\Core\Config\ConfigDuplicateUUIDException; @@ -107,6 +108,13 @@ protected $trustedData = FALSE; /** + * The entity may contain overridden values and may therefore not be saved. + * + * @var bool + */ + protected $isImmutable = FALSE; + + /** * {@inheritdoc} */ public function __construct(array $values, $entity_type) { @@ -630,10 +638,18 @@ public function hasTrustedData() { return $this->trustedData; } + public function isImmutable() { + return $this->isImmutable; + } + /** * {@inheritdoc} */ public function save() { + if ($this->isImmutable()) { + throw new ImmutableConfigException("Can not save immutable configuration entity {$this->id()}. Load the entity via \\Drupal\\Core\\Config\\Entity\\ConfigEntityStorageInterface::loadOverrideFree() / ::loadMultipleOverrideFree() to retrieve a mutable configuration entity object"); + } + $return = parent::save(); $this->trustedData = FALSE; return $return; diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 248701e..6f68d7f 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -217,4 +217,13 @@ public function trustData(); */ public function hasTrustedData(); + /** + * Returns whether the entity might contain overridden values and may + * therefore not be saved. + * + * @return bool + * TRUE if the entity is immutable, FALSE otherwise. + */ + public function isImmutable(); + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 3834dae..35e8b30 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -5,6 +5,7 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigImporterException; +use Drupal\Core\Config\ImmutableConfigException; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityMalformedException; use Drupal\Core\Entity\EntityStorageBase; @@ -256,6 +257,11 @@ public function save(EntityInterface $entity) { throw new ConfigEntityIdLengthException("Configuration entity ID {$entity->get($this->idKey)} exceeds maximum allowed length of " . self::MAX_ID_LENGTH . " characters."); } + // Ensure an immutable configuration entity is not saved. + if ($entity->isImmutable()) { + throw new ImmutableConfigException("Can not save immutable configuration entity {$entity->id()}. Load the entity via \\Drupal\\Core\\Config\\Entity\\ConfigEntityStorageInterface::loadOverrideFree() / ::loadMultipleOverrideFree() to retrieve a mutable configuration entity object"); + } + return parent::save($entity); } diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 6195c8c..9db425e 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -1348,4 +1348,11 @@ public function addCacheTags(array $cache_tags) { return $this->storage->addCacheTags($cache_tags); } + /** + * {@inheritdoc} + */ + public function isImmutable() { + return $this->storage->isImmutable(); + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityOverrideTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityOverrideTest.php index 8d62875..4a5e2dd 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityOverrideTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigEntityOverrideTest.php @@ -86,8 +86,7 @@ function testConfEntityOverride() { try { /** @var \Drupal\config_test\Entity\ConfigTest $config_entity */ $config_entity = $config_test_storage->load('dotted.default'); - $expected_original_data['weight'] = 420; - $config_entity->weight = $expected_original_data['weight']; + $config_entity->weight = 240; $config_entity->save(); } catch (\Exception $e) {}