diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 51ade6c..8861481 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -203,22 +203,24 @@ public function clear($key) { /** * {@inheritdoc} */ - public function save() { + public function save($has_trusted_data = FALSE) { // Validate the configuration object name before saving. static::validateName($this->name); // 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 (!$has_trusted_data) { + 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); + } } } @@ -302,4 +304,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 c109ea7..082fa63 100644 --- a/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -304,11 +304,11 @@ protected function createConfiguration($collection, array $config_to_create) { $entity = $entity_storage->createFromStorageRecord($new_config->get()); } if ($entity->isInstallable()) { - $entity->save(); + $entity->trustData()->save(); } } else { - $new_config->save(); + $new_config->save(TRUE); } } } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index 6740541..0926912 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -105,6 +105,8 @@ */ protected $third_party_settings = array(); + protected $trustedData = FALSE; + /** * Overrides Entity::__construct(). */ @@ -324,7 +326,7 @@ public function preSave(EntityStorageInterface $storage) { throw new ConfigDuplicateUUIDException(SafeMarkup::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. @@ -568,4 +570,28 @@ public function isInstallable() { return TRUE; } + /** + * {@inheritdoc} + */ + public function trustData() { + $this->trustedData = TRUE; + return $this; + } + + /** + * {@inheritdoc} + */ + public function hasTrustedData() { + 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 3d688a5..76809ed 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -203,4 +203,27 @@ public function getDependencies(); */ public function isInstallable(); + /** + * Sets that the data should be trusted. + * + * If the data is trusted then dependencies will not be calculated on save and + * schema will not be used to cast the values. Generally this is only used + * during module and theme installation. Once the config entity has been saved + * the data will no longer be marked as trusted. This is an optimization for + * creation of configuration during installation. + * + * @return $this + * + * @see \Drupal\Core\Config\ConfigInstaller::createConfiguration() + */ + public function trustData(); + + /** + * Gets whether on not the data is trusted. + * + * @return bool + * TRUE if the configuration data is trusted, FALSE if not. + */ + public function hasTrustedData(); + } diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 2c3e798..540fa15 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -256,7 +256,7 @@ protected function doSave($id, EntityInterface $entity) { // Retrieve the desired properties and set them in config. $config->setData($this->mapToStorageRecord($entity)); - $config->save(); + $config->save($entity->hasTrustedData()); return $is_new ? SAVED_NEW : SAVED_UPDATED; } diff --git a/core/lib/Drupal/Core/Config/ImmutableConfig.php b/core/lib/Drupal/Core/Config/ImmutableConfig.php index e6938fb..8435f71 100644 --- a/core/lib/Drupal/Core/Config/ImmutableConfig.php +++ b/core/lib/Drupal/Core/Config/ImmutableConfig.php @@ -44,7 +44,7 @@ public function clear($key) { /** * {@inheritdoc} */ - public function save() { + public function save($has_trusted_data = FALSE) { throw new ImmutableConfigException(SafeMarkup::format('Can not save immutable configuration !name. Use \Drupal\Core\Config\ConfigFactoryInterface::getEditable() to retrieve a mutable configuration object', ['!name' => $this->getName()])); } diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php index 625900c..d5ea532 100644 --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -66,11 +66,18 @@ /** * Saves the configuration object. * + * @param bool $has_trusted_data + * Set to TRUE is the configuration data has already been checked to ensure + * it conforms to schema. Generally this is only used during module and + * theme installation. + * * Must invalidate the cache tags associated with the configuration object. * * @return $this + * + * @see \Drupal\Core\Config\ConfigInstaller::createConfiguration() */ - abstract public function save(); + abstract public function save($has_trusted_data = FALSE); /** * Deletes the configuration object. 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 fe9a6b6..26c6916 100644 --- a/core/modules/config/src/Tests/ConfigInstallTest.php +++ b/core/modules/config/src/Tests/ConfigInstallTest.php @@ -52,7 +52,7 @@ 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->installModules(array('config_test')); @@ -81,14 +81,10 @@ function testModuleInstallation() { // 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.'); - // 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_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/config/tests/config_test/config/optional/config_test.dynamic.override.yml b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml index 9721190..af26b07 100644 --- a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml +++ b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override.yml @@ -3,4 +3,4 @@ id: override label: Default weight: 0 protected_property: Default -status: 1 +status: true diff --git a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml index 7fa7ae4..82a9c3c 100644 --- a/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml +++ b/core/modules/config/tests/config_test/config/optional/config_test.dynamic.override_unmet.yml @@ -4,7 +4,7 @@ id: override_unmet label: Default weight: 0 protected_property: Default -status: 1 +status: true dependencies: module: - tour diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module index 110a6e4..85c5f74 100644 --- a/core/modules/contact/contact.module +++ b/core/modules/contact/contact.module @@ -24,8 +24,10 @@ function contact_help($route_name, RouteMatchInterface $route_match) { $output .= '
' . t('Add one or more forms on this page to set up your site-wide contact form.', array('@form' => \Drupal::url('contact.site_page'))) . '
'; - $output .= '' . t('A Contact menu item is added to the Footer menu, which you can modify on the Menus administration page.', array('@menu-settings' => \Drupal::url('entity.menu.collection'))) . '
'; + if (\Drupal::moduleHandler()->moduleExists('menu_ui')) { + $output .= '' . t('A Contact menu item is added to the Footer menu, which you can modify on the Menus administration page.', array('@menu-settings' => \Drupal::url('entity.menu.collection'))) . '
'; + } $output .= '' . t('If you would like additional text to appear on the site-wide contact page, use a block. You can create and edit blocks on the Blocks administration page.', array('@blocks' => \Drupal::url('block.admin_display'))) . '
'; return $output; } diff --git a/core/modules/file/config/optional/views.view.files.yml b/core/modules/file/config/optional/views.view.files.yml index 23bfd82..fc1b540 100644 --- a/core/modules/file/config/optional/views.view.files.yml +++ b/core/modules/file/config/optional/views.view.files.yml @@ -236,7 +236,7 @@ display: delta_first_last: false multi_type: separator separator: ', ' - field_api_classes: 0 + field_api_classes: false plugin_id: field entity_type: file entity_field: filename diff --git a/core/modules/forum/config/install/node.type.forum.yml b/core/modules/forum/config/install/node.type.forum.yml index 8ed965d..b03afe0 100644 --- a/core/modules/forum/config/install/node.type.forum.yml +++ b/core/modules/forum/config/install/node.type.forum.yml @@ -1,6 +1,8 @@ langcode: en status: true dependencies: + module: + - forum enforced: module: - forum diff --git a/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml b/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml index 951e4a3..cfbcca5 100644 --- a/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml +++ b/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml @@ -1,6 +1,8 @@ langcode: en status: true dependencies: + module: + - forum enforced: module: - forum diff --git a/core/modules/language/src/Config/LanguageConfigOverride.php b/core/modules/language/src/Config/LanguageConfigOverride.php index 5be48ad..b673f34 100644 --- a/core/modules/language/src/Config/LanguageConfigOverride.php +++ b/core/modules/language/src/Config/LanguageConfigOverride.php @@ -50,13 +50,16 @@ 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); + public function save($has_trusted_data = FALSE) { + if (!$has_trusted_data) { + // @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 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 8fd6e29..9ce7cb0 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListFloatItem.php @@ -110,4 +110,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 5992386..2ded4ca 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListIntegerItem.php @@ -73,4 +73,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 f3bf401..da30810 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListStringItem.php @@ -75,4 +75,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/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml index 05d5e27..fc76e73 100644 --- a/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml +++ b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml @@ -8,6 +8,8 @@ langcode: en locked: false pattern: 'U' dependencies: + theme: + - test_basetheme enforced: theme: - test_basetheme diff --git a/core/modules/user/config/optional/views.view.user_admin_people.yml b/core/modules/user/config/optional/views.view.user_admin_people.yml index 57dd4e4..b787d6b 100644 --- a/core/modules/user/config/optional/views.view.user_admin_people.yml +++ b/core/modules/user/config/optional/views.view.user_admin_people.yml @@ -570,7 +570,7 @@ display: delta_first_last: false multi_type: separator separator: ', ' - field_api_classes: 0 + field_api_classes: false plugin_id: field entity_type: user entity_field: mail diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 290d1a7..eab6e63 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -2294,7 +2294,7 @@ public function calculateCacheMetadata () { $cache_plugin->alterCacheMetadata($is_cacheable, $cache_contexts); } - return [$is_cacheable, $cache_contexts]; + return [(bool) $is_cacheable, $cache_contexts]; } /** diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 4c82de7..c053fcd 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -1285,4 +1285,18 @@ public function getThirdPartyProviders() { return $this->storage->getThirdPartyProviders(); } + /** + * {@inheritdoc} + */ + public function trustData() { + return $this->storage->trustData(); + } + + /** + * {@inheritdoc} + */ + public function hasTrustedData() { + return $this->storage->hasTrustedData(); + } + } diff --git a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml index 4a54a33..e0d67e0 100644 --- a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml +++ b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override.yml @@ -2,7 +2,7 @@ id: override label: Override weight: 0 protected_property: Default -status: 1 +status: true dependencies: module: - tour diff --git a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml index f20365f..d4e755d 100644 --- a/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml +++ b/core/profiles/testing_config_overrides/config/optional/config_test.dynamic.override_unmet.yml @@ -2,7 +2,7 @@ id: override_unmet label: Override weight: 0 protected_property: Default -status: 1 +status: true dependencies: module: - dblog