diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 51ade6c..439850e 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -209,16 +209,18 @@ public function save() { // If there is a schema for this configuration object, cast all values to // conform to the schema. - if ($this->typedConfigManager->hasConfigSchema($this->name)) { - // Ensure that the schema wrapper has the latest data. - $this->schemaWrapper = NULL; - foreach ($this->data as $key => $value) { - $this->data[$key] = $this->castValue($key, $value); + if (!$this->trustedData) { + if ($this->typedConfigManager->hasConfigSchema($this->name)) { + // Ensure that the schema wrapper has the latest data. + $this->schemaWrapper = NULL; + foreach ($this->data as $key => $value) { + $this->data[$key] = $this->castValue($key, $value); + } } - } - else { - foreach ($this->data as $key => $value) { - $this->validateValue($key, $value); + else { + foreach ($this->data as $key => $value) { + $this->validateValue($key, $value); + } } } @@ -229,6 +231,7 @@ public function save() { $this->isNew = FALSE; $this->eventDispatcher->dispatch(ConfigEvents::SAVE, new ConfigCrudEvent($this)); $this->originalData = $this->data; + $this->trustedData = FALSE; return $this; } @@ -302,4 +305,5 @@ public function getOriginal($key = '', $apply_overrides = TRUE) { } } } + } diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php index 8065613..042bf82 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -233,11 +233,11 @@ protected function createConfiguration($collection, array $config_to_install) { $entity = $entity_storage->createFromStorageRecord($new_config->get()); } if ($entity->isInstallable()) { - $entity->save(); + $entity->setTrustedData()->save(); } } else { - $new_config->save(); + $new_config->setTrustedData()->save(); } } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index e1242c6..6f692dd 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -96,6 +96,8 @@ */ protected $third_party_settings = array(); + protected $trustedData = FALSE; + /** * Overrides Entity::__construct(). */ @@ -315,7 +317,7 @@ public function preSave(EntityStorageInterface $storage) { throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid()))); } } - if (!$this->isSyncing()) { + if (!$this->isSyncing() && !$this->trustedData) { // Ensure the correct dependencies are present. If the configuration is // being written during a configuration synchronization then there is no // need to recalculate the dependencies. @@ -559,4 +561,28 @@ public function isInstallable() { return TRUE; } + /** + * {@inheritdoc} + */ + public function setTrustedData() { + $this->trustedData = TRUE; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getTrustedData() { + return $this->trustedData; + } + + /** + * {@inheritdoc} + */ + public function save() { + $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 235581d..6f46135 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -203,4 +203,21 @@ public function getDependencies(); */ public function isInstallable(); + /** + * Sets that the data should be trusted. + * @param bool $trust + * TRUE if the configuration data is trusted, FALSE if not. + * + * @return $this + */ + public function setTrustedData(); + + /** + * Gets whether on not the data is trusted. + * + * @return bool + * TRUE if the configuration data is trusted, FALSE if not. + */ + public function getTrustedData(); + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 1527ac6..aceab2f 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -256,6 +256,9 @@ protected function doSave($id, EntityInterface $entity) { // Retrieve the desired properties and set them in config. $config->setData($this->mapToStorageRecord($entity)); + if ($entity->getTrustedData()) { + $config->setTrustedData(); + } $config->save(); return $is_new ? SAVED_NEW : SAVED_UPDATED; diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php index 4af470e..a25cec4 100644 --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -64,6 +64,11 @@ protected $originalData = array(); /** + * @var bool + */ + protected $trustedData = FALSE; + + /** * Saves the configuration object. * * Must invalidate the cache tags associated with the configuration object. @@ -219,4 +224,17 @@ protected function castValue($key, $value) { return $value; } + /** + * Indicates that the configuration data is trusted. + * + * If the configuration data is trusted then we don't need to check schema on + * save. + * + * @return $this + */ + public function setTrustedData() { + $this->trustedData = TRUE; + return $this; + } + } diff --git a/core/modules/book/config/install/node.type.book.yml b/core/modules/book/config/install/node.type.book.yml index 1a5cc16..a5076b2 100644 --- a/core/modules/book/config/install/node.type.book.yml +++ b/core/modules/book/config/install/node.type.book.yml @@ -1,6 +1,8 @@ langcode: en status: true dependencies: + module: + - book enforced: module: - book diff --git a/core/modules/config/src/Tests/ConfigInstallTest.php b/core/modules/config/src/Tests/ConfigInstallTest.php index 2da9e53..2ea3b90 100644 --- a/core/modules/config/src/Tests/ConfigInstallTest.php +++ b/core/modules/config/src/Tests/ConfigInstallTest.php @@ -45,14 +45,14 @@ function testModuleInstallation() { // Ensure that schema provided by modules that are not installed is not // available. - $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.'); + $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema does not exist.'); // Install the test module. $this->enableModules(array('config_test', 'config_schema_test')); $this->installConfig(array('config_test', 'config_schema_test')); // After module installation the new schema should exist. - $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.'); + $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema exists.'); // Verify that default module config exists. \Drupal::configFactory()->reset($default_config); @@ -71,14 +71,10 @@ function testModuleInstallation() { $this->assertFalse(isset($GLOBALS['hook_config_test']['predelete'])); $this->assertFalse(isset($GLOBALS['hook_config_test']['delete'])); - // Ensure that data type casting is applied during config installation. - $config = $this->config('config_schema_test.schema_in_install'); - $this->assertIdentical($config->get('integer'), 1); - // Test that uninstalling configuration removes configuration schema. $this->config('core.extension')->set('module', array())->save(); \Drupal::service('config.manager')->uninstall('module', 'config_test'); - $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.'); + $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'), 'Configuration schema for config_schema_test.someschema does not exist.'); } /** diff --git a/core/modules/config/tests/config_schema_test/config/install/config_schema_test.schema_in_install.yml b/core/modules/config/tests/config_schema_test/config/install/config_schema_test.schema_in_install.yml deleted file mode 100644 index 2ae0ace..0000000 --- a/core/modules/config/tests/config_schema_test/config/install/config_schema_test.schema_in_install.yml +++ /dev/null @@ -1 +0,0 @@ -integer: '1' diff --git a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml index 8c8660c..a2da749 100644 --- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml +++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml @@ -121,14 +121,6 @@ config_schema_test.schema_data_types: sequence: - type: boolean -config_schema_test.schema_in_install: - label: 'Schema test data with parenting' - type: mapping - mapping: - integer: - type: integer - label: 'Integer' - config_schema_test_integer: type: integer label: 'Config test integer' diff --git a/core/modules/config/tests/config_test/config/install/config_test.types.yml b/core/modules/config/tests/config_test/config/install/config_test.types.yml index 060a2b0..6c27522 100644 --- a/core/modules/config/tests/config_test/config/install/config_test.types.yml +++ b/core/modules/config/tests/config_test/config/install/config_test.types.yml @@ -2,7 +2,7 @@ array: [] boolean: true exp: 1.2e+34 float: 3.14159 -float_as_integer: 1 +float_as_integer: !!float 1 hex: 0xC int: 99 octal: 0775 diff --git a/core/modules/language/src/Config/LanguageConfigOverride.php b/core/modules/language/src/Config/LanguageConfigOverride.php index 5be48ad..dabdab0 100644 --- a/core/modules/language/src/Config/LanguageConfigOverride.php +++ b/core/modules/language/src/Config/LanguageConfigOverride.php @@ -51,12 +51,15 @@ public function __construct($name, StorageInterface $storage, TypedConfigManager * {@inheritdoc} */ public function save() { - // @todo Use configuration schema to validate. - // https://drupal.org/node/2270399 - // Perform basic data validation. - foreach ($this->data as $key => $value) { - $this->validateValue($key, $value); + if (!$this->trustedData) { + // @todo Use configuration schema to validate. + // https://drupal.org/node/2270399 + // Perform basic data validation. + foreach ($this->data as $key => $value) { + $this->validateValue($key, $value); + } } + $this->storage->write($this->name, $this->data); // Invalidate the cache tags not only when updating, but also when creating, // because a language config override object uses the same cache tag as the @@ -66,6 +69,7 @@ public function save() { $this->isNew = FALSE; $this->eventDispatcher->dispatch(LanguageConfigOverrideEvents::SAVE_OVERRIDE, new LanguageConfigOverrideCrudEvent($this)); $this->originalData = $this->data; + $this->trustedData = FALSE; return $this; } diff --git a/core/modules/node/config/install/system.action.node_promote_action.yml b/core/modules/node/config/install/system.action.node_promote_action.yml index b1b4f05..4b3a9ae 100644 --- a/core/modules/node/config/install/system.action.node_promote_action.yml +++ b/core/modules/node/config/install/system.action.node_promote_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_promote_action +dependencies: + module: + - node diff --git a/core/modules/node/config/install/system.action.node_publish_action.yml b/core/modules/node/config/install/system.action.node_publish_action.yml index e882bf3..af0b82c 100644 --- a/core/modules/node/config/install/system.action.node_publish_action.yml +++ b/core/modules/node/config/install/system.action.node_publish_action.yml @@ -4,3 +4,6 @@ status: true langcode: en type: node plugin: node_publish_action +dependencies: + module: + - node diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php b/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php index 160dce0..5577ddf 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php @@ -109,4 +109,11 @@ public static function simplifyAllowedValues(array $structured_values) { return $values; } + /** + * {@inheritdoc} + */ + protected static function castAllowedValue($value) { + return (float) $value; + } + } diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php b/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php index afda838..d61c86e 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php @@ -72,4 +72,11 @@ protected static function validateAllowedValue($option) { } } + /** + * {@inheritdoc} + */ + protected static function castAllowedValue($value) { + return (int) $value; + } + } diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php index bdf063a..9b785d8 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php @@ -314,11 +314,24 @@ protected static function structureAllowedValues(array $values) { $label = static::structureAllowedValues($label); } $structured_values[] = array( - 'value' => $value, + 'value' => static::castAllowedValue($value), 'label' => $label, ); } return $structured_values; } + /** + * Converts a value to the correct type. + * + * @param mixed $value + * The value to cast. + * + * @return mixed + * The casted value. + */ + protected static function castAllowedValue($value) { + return $value; + } + } diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php index a95c8e8..37c219b 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php @@ -74,4 +74,11 @@ protected static function validateAllowedValue($option) { } } + /** + * {@inheritdoc} + */ + protected static function castAllowedValue($value) { + return (string) $value; + } + } diff --git a/core/modules/options/tests/options_config_install_test/config/install/field.storage.node.field_options_float.yml b/core/modules/options/tests/options_config_install_test/config/install/field.storage.node.field_options_float.yml index f355b2e..1d02c61 100644 --- a/core/modules/options/tests/options_config_install_test/config/install/field.storage.node.field_options_float.yml +++ b/core/modules/options/tests/options_config_install_test/config/install/field.storage.node.field_options_float.yml @@ -11,7 +11,7 @@ type: list_float settings: allowed_values: - - value: 0 + value: !!float 0 label: Zero - value: 0.5 diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 1d3c8be..cb1d321 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -11,6 +11,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Timer; use Drupal\Component\Utility\Xss; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\views\Views; @@ -1252,4 +1253,18 @@ public function isInstallable() { return $this->storage->isInstallable(); } + /** + * {@inheritdoc} + */ + public function setTrustedData() { + return $this->storage->setTrustedData(); + } + + /** + * {@inheritdoc} + */ + public function getTrustedData() { + return $this->storage->getTrustedData(); + } + }