diff --git a/core/includes/config.inc b/core/includes/config.inc index 39094f8..4abc363 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -1,6 +1,7 @@ $value) { + if (is_array($value)) { + $list += self::toList($value, $prefix . $key . '.'); + } + else { + $list[$prefix . $key] = $value; + } + } + return $list; + } + + /** + * Gets data from array using key with dot notation. + * + * @param array $array + * The array from which to get the value. + * + * @param $key + * A string that maps to a key within the array data. + * For instance in the following array: + * @code + * array( + * 'foo' => array( + * 'bar' => 'baz', + * ), + * ); + * @endcode + * A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo' + * would return array('bar' => 'baz'). + * If no key is specified, then the entire data array is returned. + */ + public static function &getData(array &$array, $key) { + if (empty($key)) { + return $array; + } + else { + $null = NULL; + $parts = explode('.', $key); + if (count($parts) == 1) { + if (isset($array[$key])) { + return $array[$key]; + } + else { + return $null; + } + } + else { + $value = NestedArray::getValue($array, $parts, $key_exists); + if ($key_exists) { + return $value; + } + else { + return $null; + } + } + } + } + + /** + * Sets value in array using key with dot notation. + * + * @param array $array + * The array from which to set the value. + * @param $key + * @todo + * @param $value + * @todo + */ + public static function setData(array &$array, $key, $value) { + // The dot/period is a reserved character; it may appear between keys, but + // not within keys. + $parts = explode('.', $key); + if (count($parts) == 1) { + $array[$key] = $value; + } + else { + NestedArray::setValue($array, $parts, $value); + } + } + + /** + * Unsets value in this config object. + * + * @param array $array + * The array from which to set the value. + * @param $key + * Name of the key whose value should be unset. + */ + public static function unsetData(array &$array, $key) { + $parts = explode('.', $key); + if (count($parts) == 1) { + unset($array[$key]); + } + else { + NestedArray::unsetValue($array, $parts); + } + } + + /** + * Sorts all keys in array. + * + * @param array $data + * An associative array to sort recursively by key name. + */ + public static function sortByKey(array &$data) { + ksort($data); + foreach ($data as &$value) { + if (is_array($value)) { + self::sortByKey($value); + } + } + } + + /** + * Casts a value or an array of values to a string. + * + * Any non-scalar value that is not an array (aka objects) gets cast + * to an array, unless the object implements the WrapperInterface. + * In that case the getString() method is used instead. + * + * @see Drupal\Core\TypedData\WrapperInterface + * + * @param $value + * A value being saved into the configuration system. + * @return + * The value cast to a string or array of strings. + */ + public static function castToStrings($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; + } + } + elseif (is_object($value) && $value instanceof WrapperInterface) { + $value = $value->getString(); + } + 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] = self::castToStrings($nested_value); + } + } + return $value; + } } diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 538ab6d..308b19e 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -34,7 +34,7 @@ class Config { * * @var array */ - protected $data; + protected $data = array(); /** * The overridden data of the configuration object. @@ -142,19 +142,7 @@ class Config { if (!isset($this->overriddenData)) { $this->setOverriddenData(); } - if (empty($key)) { - return $this->overriddenData; - } - else { - $parts = explode('.', $key); - if (count($parts) == 1) { - return isset($this->overriddenData[$key]) ? $this->overriddenData[$key] : NULL; - } - else { - $value = NestedArray::getValue($this->overriddenData, $parts, $key_exists); - return $key_exists ? $value : NULL; - } - } + return NestedArray::getData($this->overriddenData, $key); } /** @@ -218,16 +206,7 @@ class Config { 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); - if (count($parts) == 1) { - $this->data[$key] = $value; - } - else { - NestedArray::setValue($this->data, $parts, $value); - } + NestedArray::setData($this->data, $key, $value); $this->resetOverriddenData(); return $this; } @@ -249,26 +228,7 @@ class Config { * 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; + return NestedArray::castToStrings($value); } /** @@ -278,13 +238,7 @@ class Config { * Name of the key whose value should be unset. */ public function clear($key) { - $parts = explode('.', $key); - if (count($parts) == 1) { - unset($this->data[$key]); - } - else { - NestedArray::unsetValue($this->data, $parts); - } + NestedArray::unsetData($this->data, $key); $this->resetOverriddenData(); return $this; } @@ -310,7 +264,7 @@ class Config { * Saves the configuration object. */ public function save() { - $this->sortByKey($this->data); + NestedArray::sortByKey($this->data); $this->storage->write($this->name, $this->data); $this->isNew = FALSE; $this->notify('save'); @@ -331,26 +285,6 @@ class Config { } /** - * Sorts all keys in configuration data. - * - * Ensures that re-inserted keys appear in the same location as before, in - * order to ensure an identical order regardless of storage controller. - * A consistent order is important for any storage that allows any kind of - * diff operation. - * - * @param array $data - * An associative array to sort recursively by key name. - */ - public function sortByKey(array &$data) { - ksort($data); - foreach ($data as &$value) { - if (is_array($value)) { - $this->sortByKey($value); - } - } - } - - /** * Deletes the configuration object. */ public function delete() { diff --git a/core/lib/Drupal/Core/Config/ConfigMetadata.php b/core/lib/Drupal/Core/Config/ConfigMetadata.php new file mode 100644 index 0000000..68d9510 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigMetadata.php @@ -0,0 +1,105 @@ +getBaseName($offset)) { + $metadata = $this->offsetGet($basename); + } + // Merge current metadata on top of it. + if ($meta = $this->readMetadata($offset)) { + $metadata = NestedArray::mergeDeep($metadata, $meta); + } + $this->storage[$offset] = $metadata; + return $metadata; + } + + /** + * Get parent metadata name. + */ + protected static function getBaseName($name) { + $parts = explode('.', $name); + $last = array_pop($parts); + // If this is not the generic metadata (where the last component of the + // name is a '+'), try to load that first. + if ($last != self::BASE_MARK) { + return implode('.', array_merge($parts, array(self::BASE_MARK))); + } + } + + /** + * Read metadata from file system. + * + * @return array + * Metadata array if found or empty array if not. + */ + protected function readMetadata($name) { + $module = strtok($name, '.'); + // We are looking for a file in $module/meta/$name.yml + $directory = drupal_get_path('module', $module) . '/meta'; + $filepath = $directory . '/' . $name . '.yml'; + if (file_exists($filepath)) { + // We use FileStorage as a convenience though we could add our + // own reader and parser here. + try { + $storage = new FileStorage($directory); + return $storage->read($name); + } + catch (Drupal\Core\Config\FileStorageReadException $e) { + // Either the file does not exist or we cannot decode it. + // Do nothing. In the worst case, the value will be an empty array. + // @todo In that worst case, we should probably at least watchdog() or + // something. + } + } + return array(); + } +} diff --git a/core/lib/Drupal/Core/Config/ConfigWrapper.php b/core/lib/Drupal/Core/Config/ConfigWrapper.php new file mode 100644 index 0000000..1d2526e --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigWrapper.php @@ -0,0 +1,356 @@ +name = $name; + $this->metadata = $metadata; + $this->configData = $configData; + } + + + /** + * Gets medata array from this config metadata. + * + * An array of metadata contains the 'label' and 'type' keys as explained above. + * If $key is omitted, the full array is returned, where the array keys are the + * metadata keys and the values are the metadata arrays (see above). + * + * @param $key + * Optional string that maps to a key within the configuration metadata. + * @return + * The metadata property that was requested or the full metadata array. + */ + public function getMetadata($key = '') { + if (!isset($this->metadata)) { + $this->metadata = config_metadata($this->name); + } + if ($key) { + return isset($this->metadata[$key]) ? $this->metadata[$key] : array(); + } + else { + return $this->metadata; + } + } + + /** + * Gets raw configuration data. + * + * @return array + * Reference to array of configuration data. + */ + public function &getConfigData() { + if (!isset($this->configData)) { + $this->configData = config($this->name)->get(); + } + return $this->configData; + } + + /** + * Get typed data as nested array. + * + * @return + * Reference to nested array with Drupal\Core\TypedData\WrapperInterface elements. + */ + public function &getTypedData() { + if (!isset($this->typedData)) { + $this->typedData = $this->buildTypedData($this->getConfigData()); + } + return $this->typedData; + } + + /** + * Builds properties using configuration data and metadata. + * + * The result will be a nested array merging the full configuration data and + * the metadata. The array keys will be the property names + * and the array values will be data properties. + * + * Example: + * + * - Data: module/system/config/system.site.yml + * + * name: Drupal + * mail: '' + * slogan: '' + * page: + * 403: '' + * 404: '' + * front: user + * + * - Metadata: module/system/meta/system.site.yml + * + * name: + * label: 'Site name' + * type: 'string' + * mail: + * label: 'Site mail' + * type: 'email' + * slogan: + * label: 'Site slogan' + * type: 'string' + * page: + * label: 'Error pages' + * type: config_subkeys + * page.403: + * label: 'Default 403 (access denied) page' + * type: 'path' + * page.404: + * label: 'Default 404 (not found) page' + * type: 'path' + * page.front: + * label: 'Default front page' + * type: 'path' + * + * @param $data + * Array of configuration data. + * @param $name + * Base name to use for all elements. + */ + protected function buildTypedData($data, $name = '') { + $build = array(); + foreach ($data as $key => $value) { + $key_name = $name ? $name . '.' . $key : $key; + $meta = $this->getMetadata($key_name); + $build[$key] = $this->buildElement($key_name, $value, $meta); + } + return $build; + } + + /** + * Build configuration element with data and metadata. + * + * @param $name + * Element key + * @param $data + * Base name for this element. + * @param $meta + * Metadata for this element. + * + * @result array + * Built metadata array with one or more elements. + */ + protected function buildElement($name, $data, $meta) { + if (!isset($meta['type'])) { + $meta['type'] = 'variant'; + } + // $build[$key] = $meta; + // Build element depending on type. + switch ($meta['type']) { + case 'config_nested': + // This is an array of nested configuration elements. + return $this->buildNested($name, $data, $meta); + + case 'config_subkeys': + // Array with multiple nested properties. + return $this->buildSubkeys($name, $data, $meta); + + default: + // This is an end property. The metadata will be the property definition. + return $this->buildProperty($name, $data, $meta); + } + } + + /** + * Build nested configuration array. + * + * Example metadata from image.style.+.yml + * + * effects: + * label: 'Style effects' + * type: 'nested_config' + * config_name: 'image.style.effects.*' + * + * Example data from image.style.large.yml + * + * effects: + * ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d: + * name: image.style.effects.scale + * data: + * width: '480' + * height: '480' + * upscale: '1' + * weight: '0' + * ieid: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d + */ + protected function buildNested($name, $data, $meta) { + $build = array(); + $base_meta = isset($meta['config_name']) ? config_metadata($meta['config_name']) : array(); + foreach ($data as $key => $value) { + $key_name = $name . '.' . $key; + // For nested elements, the parent metadata file declares the child element + // using the 'config_name' key. Actual configuration files directly specify + // the nested configuration in one file and denote the child element with + // the 'name' key. + $nested_meta = $this->getMetadata($key_name); + if (!$nested_meta) { + $nested_meta = $base_meta; + if (isset($value['name'])) { + $nested_meta = NestedArray::mergeDeep($nested_meta, config_metadata($value['name'])); + } + // Store nested element metadata in case we need to rebuild. + $this->metadata[$key_name] = $nested_meta; + } + // Build this element with metadata taken from a different object. + $nested_config = new ConfigWrapper($key_name, $nested_meta, $value); + $build[$key] = $nested_config->getTypedData(); + } + return $build; + } + + /** + * Build array of configuration data with subkeys. + * + * Example metadata from image.style.effects.+.yml + image.style.effects.scale.yml + * + * data: + * label: 'Data' + * type: 'config_subkeys' + * data.width: + * label: 'Width' + * type: 'integer' + * data.height: + * label: 'Height' + * type: 'integer' + * data.upscale: + * label: 'Upscale' + * type: 'boolean' + * + * Example data from image.style.large.yml (effects/../data) + * + * width: '480' + * height: '480' + * upscale: '1' + * + * @param $data + * Array of configuration data. + * @param $meta + * + * @param $key + * Key to prepend to the data to match it with the metadata. + */ + protected function buildSubkeys($name, $data, $meta) { + // Prefix all data with given key and build as usual. + $build = array(); + foreach ($data as $key => $value) { + $key_name = $name . '.' . $key; + $key_meta = $this->getMetadata($key_name); + $build[$key] = $this->buildElement($key_name, $value, $key_meta); + } + return $build; + } + + /** + * Builds property as typed data. + * + * @see drupal_wrap_data(); + * + * @return Drupal\Core\TypedData\WrapperInterface + * Property as typed data. + */ + protected function buildProperty($name, $value = NULL, array $definition = array()) { + $type_info = drupal_get_data_type_info(); + $context = array( + 'name' => $name, + 'parent' => $this, + ); + // Allow per-data definition overrides of the used classes. + if (isset($definition['type']) && isset($type_info[$definition['type']])) { + $full_definition = $definition + $type_info[$definition['type']]; + } + else { + // We use a variant data type for properties that don't have a known type. + $full_definition = $definition + array('type' => 'variant', 'class' => 'Drupal\Core\TypedData\Type\Variant'); + } + $class = empty($full_definition['list']) ? $full_definition['class'] : $full_definition['list class']; + return new $class($full_definition, $value, $context); + } + + /** + * Gets typed data from this configuration object. + * + * @param string $key + * + * @return + * Object or array of WrapperInterface objects. + */ + public function get($key) { + return NestedArray::getData($this->getTypedData(), $key); + } + + /** + * Sets typed data in this config object. + * + * @param string $key + * The name of the property to set; e.g., 'title' or 'name'. + * @param $value + * Object or array of WrapperInterface objects to set. + */ + public function set($key, $value) { + NestedArray::setData($this->getTypedData(), $key, $value); + // Update the underlying configuration data. + $value = NestedArray::castToStrings($value); + NestedArray::setData($this->getConfigData(), $key, $value); + return $this; + } + + /** + * Gets all typed data properties as plain array. + * + * @return array + * Plain array of WrapperInterface objects indexed by full name (keys with dot notation). + */ + public function toList() { + return NestedArray::toList($this->getTypedData()); + } +} diff --git a/core/lib/Drupal/Core/TypedData/Type/String.php b/core/lib/Drupal/Core/TypedData/Type/String.php index 2adce82..f87e111 100644 --- a/core/lib/Drupal/Core/TypedData/Type/String.php +++ b/core/lib/Drupal/Core/TypedData/Type/String.php @@ -24,13 +24,6 @@ class String extends WrapperBase implements WrapperInterface { protected $value; /** - * Implements WrapperInterface::setValue(). - */ - public function setValue($value) { - $this->value = isset($value) ? (string) $value : $value; - } - - /** * Implements WrapperInterface::validate(). */ public function validate() { diff --git a/core/lib/Drupal/Core/TypedData/Type/Variant.php b/core/lib/Drupal/Core/TypedData/Type/Variant.php new file mode 100644 index 0000000..ceee7f4 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/Type/Variant.php @@ -0,0 +1,39 @@ +value = isset($value) ? (string) $value : $value; + } + + /** + * Implements WrapperInterface::validate(). + */ + public function validate() { + // TODO: Implement validate() method. + } +} diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigMetadataTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigMetadataTest.php new file mode 100644 index 0000000..8a4366e --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigMetadataTest.php @@ -0,0 +1,147 @@ + 'Metadata', + 'description' => 'Tests Metadata for configuration objects.', + 'group' => 'Configuration', + ); + } + + /** + * Tests the basic metadata retrieval layer. + */ + function testBasicMetadata() { + // Simple case, straight metadata. + $metadata = config_metadata('system.maintenance'); + $expected = array( + 'enabled' => array( + 'label' => 'Put site into maintenance mode', + 'type' => 'boolean' + ), + 'message' => array( + 'label' => 'Message to display when in maintenance mode', + 'type' => 'string' + ), + ); + $this->assertEqual($metadata, $expected, 'Retrieved the right metadata for system.maintenance'); + // More complex case, fallback to parent name. + $metadata = config_metadata('image.style.large'); + $expected = array( + 'name' => array( + 'label' => 'Machine name', + 'type' => 'machine_name' + ), + 'effects' => array( + 'label' => 'Style effects', + 'type' => 'config_nested', + 'config_name' => 'image.style.effects.*' + ) + ); + $this->assertEqual($metadata, $expected, 'Retrieved the right metadata for image.style.large'); + + // Most complex case, fallback to parent name with merging + $metadata = config_metadata('image.style.effects.scale'); + $expected = array( + 'name' => array( + 'label' => 'Style name' + ), + 'data' => array( + 'label' => 'Data', + 'type' => 'config_subkeys', + ), + 'weight' => array( + 'label' => 'Weight', + 'type' => 'integer' + ), + 'ieid' => array( + 'label' => 'IEID', + 'type' => 'ieid', + ), + 'data.width' => array( + 'label' => 'Width', + 'type' => 'integer' + ), + 'data.height' => array( + 'label' => 'Height', + 'type' => 'integer', + ), + 'data.upscale' => array( + 'label' => 'Upscale', + 'type' => 'boolean', + ) + ); + $this->assertEqual($metadata, $expected, 'Retrieved the right metadata for image.style.effects.scale'); + + } + + /** + * Tests metadata applied to configuration objects. + */ + function testConfigMetadata() { + // Try some simple properties. + $meta = new ConfigWrapper('system.site'); + $property = $meta->get('name'); + $this->assertTrue(is_a($property, 'Drupal\Core\TypedData\Type\String'), 'Got the right wrapper fo the site name property.'); + $this->assertEqual($property->getType(), 'string', 'Got the right string type for site name data.'); + $this->assertEqual($property->getValue(), 'Drupal', 'Got the right string value for site name data.'); + + $property = $meta->get('page.front'); + $this->assertTrue(is_a($property, 'Drupal\Core\TypedData\Type\Variant'), 'Got the right wrapper fo the page.front property.'); + $this->assertEqual($property->getType(), 'path', 'Got the right string type for page.front data.'); + $this->assertEqual($property->getValue(), 'user', 'Got the right value for page.front data.'); + + // Check nested array of properties. + $list = $meta->get('page'); + $this->assertEqual(count($list), 3, 'Got a list with the right number of properties for site page data'); + $this->assertTrue(isset($list['front']) && isset($list['403']) && isset($list['404']), 'Got a list with the right properties for site page data.'); + $this->assertEqual($list['front']->getValue(), 'user', 'Got the right value for page.front data from the list.'); + + // Now let's try something more complex, with nested objects. + $wrapper = new ConfigWrapper('image.style.large'); + $effects = $wrapper->get('effects'); + debug($effects); + debug($wrapper); + + $this->assertTrue(is_array($effects) && count($effects) == 1, 'Got an array with effects for image.style.large data'); + $ieid = key($effects); + $effect = $wrapper->get('effects.' . $ieid); + debug($effect); + + $this->assertTrue(is_array($effect) && is_array($effect['data']) && $effect['name']->getValue() == 'image.style.effects.scale', 'Got data for the image scale effect from metadata.'); + $this->assertEqual($effect['data']['width']->getType(), 'integer', 'Got the right type for the scale effect width.'); + $this->assertEqual($effect['data']['width']->getValue(), 480, 'Got the right value for the scale effect width.' ); + + // Finally update some object using a configuration wrapper. + $new_slogan = 'Site slogan for testing configuration metadata'; + $wrapper = new ConfigWrapper('system.site'); + $site_slogan = $wrapper->get('slogan'); + $site_slogan->setValue($new_slogan); + $wrapper->set('slogan', $new_slogan); + $data = $wrapper->getConfigData(); + $this->assertEqual($data['slogan'], $new_slogan, 'Successfully updated the contained configuration data'); + } + +} diff --git a/core/modules/image/config/image.style.large.yml b/core/modules/image/config/image.style.large.yml index 3a1260d..f6ea671 100644 --- a/core/modules/image/config/image.style.large.yml +++ b/core/modules/image/config/image.style.large.yml @@ -1,7 +1,7 @@ name: large effects: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d: - name: image_scale + name: image.style.effects.scale data: width: '480' height: '480' diff --git a/core/modules/image/config/image.style.medium.yml b/core/modules/image/config/image.style.medium.yml index 3f2b445..44e882a 100644 --- a/core/modules/image/config/image.style.medium.yml +++ b/core/modules/image/config/image.style.medium.yml @@ -1,7 +1,7 @@ name: medium effects: bddf0d06-42f9-4c75-a700-a33cafa25ea0: - name: image_scale + name: image.style.effects.scale data: width: '220' height: '220' diff --git a/core/modules/image/config/image.style.thumbnail.yml b/core/modules/image/config/image.style.thumbnail.yml index 83e6730..de61ab5 100644 --- a/core/modules/image/config/image.style.thumbnail.yml +++ b/core/modules/image/config/image.style.thumbnail.yml @@ -1,7 +1,7 @@ name: thumbnail effects: 1cfec298-8620-4749-b100-ccb6c4500779: - name: image_scale + name: image.style.effects.scale data: width: '100' height: '100' diff --git a/core/modules/image/image.effects.inc b/core/modules/image/image.effects.inc index 35a6a74..d491796 100644 --- a/core/modules/image/image.effects.inc +++ b/core/modules/image/image.effects.inc @@ -10,7 +10,7 @@ */ function image_image_effect_info() { $effects = array( - 'image_resize' => array( + 'image.style.effects.resize' => array( 'label' => t('Resize'), 'help' => t('Resizing will make images an exact set of dimensions. This may cause images to be stretched or shrunk disproportionately.'), 'effect callback' => 'image_resize_effect', @@ -18,7 +18,7 @@ function image_image_effect_info() { 'form callback' => 'image_resize_form', 'summary theme' => 'image_resize_summary', ), - 'image_scale' => array( + 'image.style.effects.scale' => array( 'label' => t('Scale'), 'help' => t('Scaling will maintain the aspect-ratio of the original image. If only a single dimension is specified, the other dimension will be calculated.'), 'effect callback' => 'image_scale_effect', @@ -26,7 +26,7 @@ function image_image_effect_info() { 'form callback' => 'image_scale_form', 'summary theme' => 'image_scale_summary', ), - 'image_scale_and_crop' => array( + 'image.style.effects.scale_and_crop' => array( 'label' => t('Scale and crop'), 'help' => t('Scale and crop will maintain the aspect-ratio of the original image, then crop the larger dimension. This is most useful for creating perfectly square thumbnails without stretching the image.'), 'effect callback' => 'image_scale_and_crop_effect', @@ -34,7 +34,7 @@ function image_image_effect_info() { 'form callback' => 'image_resize_form', 'summary theme' => 'image_resize_summary', ), - 'image_crop' => array( + 'image.style.effects.crop' => array( 'label' => t('Crop'), 'help' => t('Cropping will remove portions of an image to make it the specified dimensions.'), 'effect callback' => 'image_crop_effect', @@ -42,13 +42,13 @@ function image_image_effect_info() { 'form callback' => 'image_crop_form', 'summary theme' => 'image_crop_summary', ), - 'image_desaturate' => array( + 'image.style.effects.desaturate' => array( 'label' => t('Desaturate'), 'help' => t('Desaturate converts an image to grayscale.'), 'effect callback' => 'image_desaturate_effect', 'dimensions passthrough' => TRUE, ), - 'image_rotate' => array( + 'image.style.effects.rotate' => array( 'label' => t('Rotate'), 'help' => t('Rotating an image may cause the dimensions of an image to increase to fit the diagonal.'), 'effect callback' => 'image_rotate_effect', diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php index f2f8b0b..860cf33 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php @@ -67,28 +67,28 @@ class ImageAdminStylesTest extends ImageFieldTestBase { $style_name = strtolower($this->randomName(10)); $style_path = 'admin/config/media/image-styles/edit/' . $style_name; $effect_edits = array( - 'image_resize' => array( + 'image.style.effects.resize' => array( 'data[width]' => 100, 'data[height]' => 101, ), - 'image_scale' => array( + 'image.style.effects.scale' => array( 'data[width]' => 110, 'data[height]' => 111, 'data[upscale]' => 1, ), - 'image_scale_and_crop' => array( + 'image.style.effects.scale_and_crop' => array( 'data[width]' => 120, 'data[height]' => 121, ), - 'image_crop' => array( + 'image.style.effects.crop' => array( 'data[width]' => 130, 'data[height]' => 131, 'data[anchor]' => 'center-center', ), - 'image_desaturate' => array( + 'image.style.effects.desaturate' => array( // No options for desaturate. ), - 'image_rotate' => array( + 'image.style.effects.rotate' => array( 'data[degrees]' => 5, 'data[random]' => 1, 'data[bgcolor]' => '#FFFF00', @@ -266,7 +266,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase { // Add a scale effect. $this->drupalGet('admin/config/media/image-styles/add'); $this->drupalPost(NULL, array('name' => 'test_style_effect_edit'), t('Create new style')); - $this->drupalPost(NULL, array('new' => 'image_scale_and_crop'), t('Add')); + $this->drupalPost(NULL, array('new' => 'image.style.effects.scale_and_crop'), t('Add')); $this->drupalPost(NULL, array('data[width]' => '300', 'data[height]' => '200'), t('Add effect')); $this->assertText(t('Scale and crop 300x200')); @@ -281,13 +281,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase { // Add another scale effect. $this->drupalGet('admin/config/media/image-styles/add'); $this->drupalPost(NULL, array('name' => 'test_style_scale_edit_scale'), t('Create new style')); - $this->drupalPost(NULL, array('new' => 'image_scale'), t('Add')); + $this->drupalPost(NULL, array('new' => 'image.style.effects.scale'), t('Add')); $this->drupalPost(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect')); // Edit the scale effect that was just added. $this->clickLink(t('edit')); $this->drupalPost(NULL, array('data[width]' => '24', 'data[height]' => '19'), t('Update effect')); - $this->drupalPost(NULL, array('new' => 'image_scale'), t('Add')); + $this->drupalPost(NULL, array('new' => 'image.style.effects.scale'), t('Add')); // Add another scale effect and make sure both exist. $this->drupalPost(NULL, array('data[width]' => '12', 'data[height]' => '19'), t('Add effect')); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php index 76110cf..c7e68b9 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php @@ -58,7 +58,7 @@ class ImageDimensionsTest extends WebTestBase { // Scale an image that is wider than it is high. $effect = array( - 'name' => 'image_scale', + 'name' => 'image.style.effects.scale', 'data' => array( 'width' => 120, 'height' => 90, @@ -80,7 +80,7 @@ class ImageDimensionsTest extends WebTestBase { // Rotate 90 degrees anticlockwise. $effect = array( - 'name' => 'image_rotate', + 'name' => 'image.style.effects.rotate', 'data' => array( 'degrees' => -90, 'random' => FALSE, @@ -101,7 +101,7 @@ class ImageDimensionsTest extends WebTestBase { // Scale an image that is higher than it is wide (rotated by previous effect). $effect = array( - 'name' => 'image_scale', + 'name' => 'image.style.effects.scale', 'data' => array( 'width' => 120, 'height' => 90, @@ -123,7 +123,7 @@ class ImageDimensionsTest extends WebTestBase { // Test upscale disabled. $effect = array( - 'name' => 'image_scale', + 'name' => 'image.style.effects.scale', 'data' => array( 'width' => 400, 'height' => 200, @@ -145,7 +145,7 @@ class ImageDimensionsTest extends WebTestBase { // Add a desaturate effect. $effect = array( - 'name' => 'image_desaturate', + 'name' => 'image.style.effects.desaturate', 'data' => array(), 'weight' => 4, ); @@ -163,7 +163,7 @@ class ImageDimensionsTest extends WebTestBase { // Add a random rotate effect. $effect = array( - 'name' => 'image_rotate', + 'name' => 'image.style.effects.rotate', 'data' => array( 'degrees' => 180, 'random' => TRUE, @@ -182,7 +182,7 @@ class ImageDimensionsTest extends WebTestBase { // Add a crop effect. $effect = array( - 'name' => 'image_crop', + 'name' => 'image.style.effects.crop', 'data' => array( 'width' => 30, 'height' => 30, @@ -204,7 +204,7 @@ class ImageDimensionsTest extends WebTestBase { // Rotate to a non-multiple of 90 degrees. $effect = array( - 'name' => 'image_rotate', + 'name' => 'image.style.effects.rotate', 'data' => array( 'degrees' => 57, 'random' => FALSE, diff --git a/core/modules/image/meta/image.style.__.yml b/core/modules/image/meta/image.style.__.yml new file mode 100644 index 0000000..736effc --- /dev/null +++ b/core/modules/image/meta/image.style.__.yml @@ -0,0 +1,7 @@ +name: + label: 'Machine name' + type: 'machine_name' +effects: + label: 'Style effects' + type: 'config_nested' + config_name: 'image.style.effects.*' diff --git a/core/modules/image/meta/image.style.effects.__.yml b/core/modules/image/meta/image.style.effects.__.yml new file mode 100644 index 0000000..df403a6 --- /dev/null +++ b/core/modules/image/meta/image.style.effects.__.yml @@ -0,0 +1,11 @@ +name: + label: 'Style name' +data: + label: 'Data' + type: 'config_subkeys' +weight: + label: 'Weight' + type: 'integer' +ieid: + label: 'IEID' + type: 'ieid' diff --git a/core/modules/image/meta/image.style.effects.scale.yml b/core/modules/image/meta/image.style.effects.scale.yml new file mode 100644 index 0000000..ad140c1 --- /dev/null +++ b/core/modules/image/meta/image.style.effects.scale.yml @@ -0,0 +1,9 @@ +data.width: + label: 'Width' + type: 'integer' +data.height: + label: 'Height' + type: 'integer' +data.upscale: + label: 'Upscale' + type: 'boolean' diff --git a/core/modules/system/meta/system.maintenance.yml b/core/modules/system/meta/system.maintenance.yml new file mode 100644 index 0000000..0f4cd6d --- /dev/null +++ b/core/modules/system/meta/system.maintenance.yml @@ -0,0 +1,6 @@ +enabled: + label: 'Put site into maintenance mode' + type: 'boolean' +message: + label: 'Message to display when in maintenance mode' + type: 'string' diff --git a/core/modules/system/meta/system.site.yml b/core/modules/system/meta/system.site.yml new file mode 100644 index 0000000..f09e316 --- /dev/null +++ b/core/modules/system/meta/system.site.yml @@ -0,0 +1,21 @@ +name: + label: 'Site name' + type: 'string' +mail: + label: 'Site mail' + type: 'email' +slogan: + label: 'Site slogan' + type: 'string' +page: + label: 'Error pages' + type: config_subkeys +page.403: + label: 'Default 403 (access denied) page' + type: 'path' +page.404: + label: 'Default 404 (not found) page' + type: 'path' +page.front: + label: 'Default front page' + type: 'path' \ No newline at end of file