diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 538ab6d..6302478 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -128,11 +128,6 @@ public function isNew() { * would return array('bar' => 'baz'). * If no key is specified, then the entire data array is returned. * - * The configuration system does not retain data types. Every saved value is - * casted to a string. In most cases this is not an issue; however, it can - * cause issues with Booleans, which are casted to "1" (TRUE) or "0" (FALSE). - * In particular, code relying on === or !== will no longer function properly. - * * @see http://php.net/manual/language.operators.comparison.php. * * @return @@ -216,9 +211,6 @@ protected function resetOverriddenData() { * @todo */ public function set($key, $value) { - // Type-cast value into a string. - $value = $this->castValue($value); - // The dot/period is a reserved character; it may appear between keys, but // not within keys. $parts = explode('.', $key); @@ -233,45 +225,6 @@ public function set($key, $value) { } /** - * Casts a saved value to a string. - * - * The configuration system only saves strings or arrays. Any scalar - * non-string value is cast to a string. The one exception is boolean FALSE - * which would normally become '' when cast to a string, but is manually - * cast to '0' here for convenience and consistency. - * - * Any non-scalar value that is not an array (aka objects) gets cast - * to an array. - * - * @param $value - * A value being saved into the configuration system. - * @param $value - * The value cast to a string or array. - */ - public function castValue($value) { - if (is_scalar($value)) { - // Handle special case of FALSE, which should be '0' instead of ''. - if ($value === FALSE) { - $value = '0'; - } - else { - $value = (string) $value; - } - } - else { - // Any non-scalar value must be an array. - if (!is_array($value)) { - $value = (array) $value; - } - // Recurse into any nested keys. - foreach ($value as $key => $nested_value) { - $value[$key] = $this->castValue($nested_value); - } - } - return $value; - } - - /** * Unsets value in this config object. * * @param $key @@ -310,6 +263,7 @@ public function load() { * Saves the configuration object. */ public function save() { + $this->validateData($this->data); $this->sortByKey($this->data); $this->storage->write($this->name, $this->data); $this->isNew = FALSE; @@ -331,6 +285,38 @@ public function rename($new_name) { } /** + * Validates configuration data. + * + * @param array $data + * The configuration data to validate. + * + * @throws ConfigException + */ + public function validateData(array $data) { + array_walk_recursive($data, array($this, 'validateValue')); + } + + /** + * Validates a configuration value. + * + * Helper callback for array_walk_recursive(). + * + * @param mixed $value + * The configuration data value to validate. + * @param string $key + * The key of the value. + * + * @throws ConfigException + * + * @see Config::validateData() + */ + public function validateValue($value, $key) { + if (!is_scalar($value)) { + throw new ConfigException(sprintf('Unsupported non-scalar value of type %s in key %s in config object %s', gettype($value), $key, $this->name)); + } + } + + /** * Sorts all keys in configuration data. * * Ensures that re-inserted keys appear in the same location as before, in diff --git a/core/modules/aggregator/config/aggregator.settings.yml b/core/modules/aggregator/config/aggregator.settings.yml index 8db22de..35c6171 100644 --- a/core/modules/aggregator/config/aggregator.settings.yml +++ b/core/modules/aggregator/config/aggregator.settings.yml @@ -4,8 +4,8 @@ processors: - aggregator items: allowed_html: '
      • ' - teaser_length: '600' - expire: '9676800' + teaser_length: 600 + expire: 9676800 source: - list_max: '3' + list_max: 3 category_selector: checkboxes diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php index 9eea495..3127cde 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php @@ -7,12 +7,16 @@ namespace Drupal\config\Tests; +use Drupal\Core\Config\ConfigException; use Drupal\simpletest\WebTestBase; /** * Tests CRUD operations on configuration objects. */ class ConfigCRUDTest extends WebTestBase { + + public static $modules = array('config_test'); + public static function getInfo() { return array( 'name' => 'CRUD operations', @@ -118,4 +122,72 @@ function testDataKeySort() { // their order must be identical. $this->assertIdentical($new_config->get(), $config->get()); } + + /** + * Tests data type preservation. + */ + function testDataTypePreservation() { + $config = config('config_test.types'); + + // Test typed varaibles. + $data = array( + 'array' => array(), + 'boolean' => TRUE, + 'exp' => 1.2e+34, + 'float' => 3.14159, + 'hex' => 0xC, + 'int' => 99, + 'octal' => 0775, + 'string' => 'string', + ); + + // Test data provided by config_test.types.yml. + $this->assertIdentical($config->get(), $data); + + // Set each key using config::set(). + foreach($data as $key => $value) { + $config->set($key, $value); + } + $config->save(); + $this->assertIdentical($config->get(), $data); + + // Set data using config::setData(). + $config->setData($data)->save(); + $this->assertIdentical($config->get(), $data); + } + + /** + * Tests data type validation. + */ + function testDataTypeValidation() { + $config = config('config_test.invalid_data'); + + // Config can't save resources. + $data = array( + 'valid_data_type' => 1, + 'invalid_type' => fopen(__FILE__, 'r'), + ); + // Test using config::set() + foreach ($data as $key => $value) { + $config->set($key, $value); + } + try { + $config->save(); + } + catch (ConfigException $e) { + $message = $e->getMessage(); + } + $this->assertEqual($message, 'Unsupported non-scalar value of type resource in key invalid_type in config object config_test.invalid_data'); + + // Config can't save objects. + $data['invalid_type'] = new \stdClass(); + // Test using config::setData(). + try { + $config->setData($data)->save(); + } + catch (ConfigException $e) { + $message = $e->getMessage(); + } + $this->assertEqual($message, 'Unsupported non-scalar value of type object in key invalid_type in config object config_test.invalid_data'); + } } diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php index 6b7a74f..2a3b5bc 100644 --- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php +++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php @@ -145,6 +145,29 @@ function testCRUD() { } + /** + * Tests storage controller writing and reading data preserving data type. + */ + function testDataTypes() { + $name = 'config_test.types'; + $data = array( + 'array' => array(), + 'boolean' => TRUE, + 'exp' => 1.2e+34, + 'float' => 3.14159, + 'hex' => 0xC, + 'int' => 99, + 'octal' => 0775, + 'string' => 'string', + ); + + $result = $this->storage->write($name, $data); + $this->assertIdentical($result, TRUE); + + $read_data = $this->storage->read($name); + $this->assertIdentical($read_data, $data); + } + abstract protected function read($name); abstract protected function insert($name, $data); diff --git a/core/modules/config/tests/config_test/config/config_test.types.yml b/core/modules/config/tests/config_test/config/config_test.types.yml new file mode 100644 index 0000000..d4005b1 --- /dev/null +++ b/core/modules/config/tests/config_test/config/config_test.types.yml @@ -0,0 +1,8 @@ +array: [] +boolean: true +exp: 1.2e+34 +float: 3.14159 +hex: 0xC +int: 99 +octal: 0775 +string: string diff --git a/core/modules/contact/config/contact.settings.yml b/core/modules/contact/config/contact.settings.yml index b23538a..99d11c7 100644 --- a/core/modules/contact/config/contact.settings.yml +++ b/core/modules/contact/config/contact.settings.yml @@ -1,4 +1,4 @@ flood: - limit: '5' - interval: '3600' -user_default_enabled: '1' + limit: 5 + interval: 3600 +user_default_enabled: 1 diff --git a/core/modules/forum/config/forum.settings.yml b/core/modules/forum/config/forum.settings.yml index bd39d97..9f2980b 100644 --- a/core/modules/forum/config/forum.settings.yml +++ b/core/modules/forum/config/forum.settings.yml @@ -1,11 +1,11 @@ block: active: - limit: '5' + limit: 5 new: - limit: '5' + limit: 5 containers: [] topics: - hot_threshold: '15' - order: '1' - page_limit: '25' -vocabulary: '0' + hot_threshold: 15 + order: 1 + page_limit: 25 +vocabulary: 0 diff --git a/core/modules/search/config/search.settings.yml b/core/modules/search/config/search.settings.yml index 97732b5..ff29fd2 100644 --- a/core/modules/search/config/search.settings.yml +++ b/core/modules/search/config/search.settings.yml @@ -1,22 +1,22 @@ active_modules: - node - user -and_or_limit: '7' +and_or_limit: 7 default_module: node index: - cron_limit: '100' - overlap_cjk: '1' - minimum_word_size: '3' + cron_limit: 100 + overlap_cjk: 1 + minimum_word_size: 3 tag_weights: - h1: '25' - h2: '18' - h3: '15' - h4: '14' - h5: '9' - h6: '6' - u: '3' - b: '3' - i: '3' - strong: '3' - em: '3' - a: '10' + h1: 25 + h2: 18 + h3: 15 + h4: 14 + h5: 9 + h6: 6 + u: 3 + b: 3 + i: 3 + strong: 3 + em: 3 + a: 10 diff --git a/core/modules/search/tests/modules/search_embedded_form/config/search_embedded_form.settings.yml b/core/modules/search/tests/modules/search_embedded_form/config/search_embedded_form.settings.yml index 11386c2..cc2ebd4 100644 --- a/core/modules/search/tests/modules/search_embedded_form/config/search_embedded_form.settings.yml +++ b/core/modules/search/tests/modules/search_embedded_form/config/search_embedded_form.settings.yml @@ -1,2 +1 @@ -submitted: '12' - +submitted: 12 diff --git a/core/modules/system/config/system.cron.yml b/core/modules/system/config/system.cron.yml index 4d96e30..5c1debe 100644 --- a/core/modules/system/config/system.cron.yml +++ b/core/modules/system/config/system.cron.yml @@ -1,5 +1,5 @@ key: '' threshold: - autorun: '10800' - requirements_warning: '172800' - requirements_error: '1209600' + autorun: 10800 + requirements_warning: 172800 + requirements_error: 1209600 diff --git a/core/modules/system/config/system.maintenance.yml b/core/modules/system/config/system.maintenance.yml index 04d92a8..ac34970 100644 --- a/core/modules/system/config/system.maintenance.yml +++ b/core/modules/system/config/system.maintenance.yml @@ -1,2 +1,2 @@ -enabled: '0' +enabled: 0 message: @site is currently under maintenance. We should be back shortly. Thank you for your patience. diff --git a/core/modules/system/config/system.rss.yml b/core/modules/system/config/system.rss.yml index 74b3228..c1835f7 100644 --- a/core/modules/system/config/system.rss.yml +++ b/core/modules/system/config/system.rss.yml @@ -1,5 +1,5 @@ channel: description: '' items: - limit: '10' + limit: 10 view_mode: fulltext diff --git a/core/modules/system/tests/modules/update_script_test/config/update_script_test.settings.yml b/core/modules/system/tests/modules/update_script_test/config/update_script_test.settings.yml index e0be69e..0c4e667 100644 --- a/core/modules/system/tests/modules/update_script_test/config/update_script_test.settings.yml +++ b/core/modules/system/tests/modules/update_script_test/config/update_script_test.settings.yml @@ -1 +1 @@ -requirement_type: '0' +requirement_type: 0 diff --git a/core/modules/update/config/update.settings.yml b/core/modules/update/config/update.settings.yml index 1caf745..d938061 100644 --- a/core/modules/update/config/update.settings.yml +++ b/core/modules/update/config/update.settings.yml @@ -1,10 +1,10 @@ check: - disabled_extensions: '0' - interval_days: '1' + disabled_extensions: 0 + interval_days: 1 fetch: url: '' - max_attempts: '2' - timeout: '5' + max_attempts: 2 + timeout: 5 notification: emails: [] - threshold: '0' + threshold: 0 diff --git a/core/modules/update/tests/modules/update_test/config/update_test.settings.yml b/core/modules/update/tests/modules/update_test/config/update_test.settings.yml index a52338a..de154ea 100644 --- a/core/modules/update/tests/modules/update_test/config/update_test.settings.yml +++ b/core/modules/update/tests/modules/update_test/config/update_test.settings.yml @@ -1,3 +1,3 @@ system_info: [] update_status: [] -xml_map: '0' +xml_map: 0