diff --git a/core/includes/config.inc b/core/includes/config.inc index 39094f8..8b43120 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -3,6 +3,8 @@ use Drupal\Core\Config\Config; use Drupal\Core\Config\FileStorage; use Drupal\Core\Config\NullStorage; +use Drupal\Core\Config\Metadata\ConfigWrapper; +use Drupal\Core\Config\Metadata\MetadataLookup; use Drupal\Core\Config\StorageInterface; /** @@ -104,6 +106,36 @@ function config_sync_get_changes(StorageInterface $source_storage, StorageInterf } /** + * Retrieves a metadata object for a configuration object or key. + * + * @param $name + * The name of the configuration object for which we want to build a metadata object. + * + * @return Drupal\Core\Config\ConfigMetadata + * An metadata object that contains the full metadata for the reguested name. + */ +function config_metadata($name) { + $metadata = &drupal_static(__FUNCTION__); + if (!$metadata) { + $metadata = new MetadataLookup(); + } + return $metadata[$name]; +} + +/** + * Retrieves a configuration wrapper object to access data as typed properties. + * + * @param $name + * The name of the configuration object to retrieve. + * + * @return Drupal\Core\Config\Metadata\Wrapper + * A configuration wrapper object. + */ +function config_wrapper($name) { + return new ConfigWrapper(config($name)); +} + +/** * Writes an array of config file changes from a source storage to a target storage. * * @param array $config_changes diff --git a/core/lib/Drupal/Core/Config/Metadata/ArrayConfigData.php b/core/lib/Drupal/Core/Config/Metadata/ArrayConfigData.php new file mode 100644 index 0000000..ddf74e0 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/ArrayConfigData.php @@ -0,0 +1,192 @@ +definition = $definition; + } + + /** + * Set parent configuration data and relative key. + * + * @param Drupal\Core\Config\Metadata\ConfigDataInterface $parent + * Parent ConfigDataInterface object. + * @param string $key + * The key of the configuration object being constructed. + * + * @return Drupal\Core\Config\Metadata\NestedConfigData + * The called object. + */ + public function setParent($parent, $key) { + $this->parentConfigData = $parent; + $this->key = $key; + return $this; + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getKey(). + */ + public function getKey($key = '') { + return $this->key . ($key ? '.' . $key : ''); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getConfigData(). + */ + public function getConfigData($key = '') { + return $this->parentConfigData->getConfigData($this->getKey($key)); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getConfigKey(). + */ + public function getConfigKey() { + $parent = $this->parentConfigData->getConfigKey(); + return ($parent ? $parent . '.' : '') . $this->getKey(); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getMetadata(). + */ + public function getMetadata() { + return $this->parentConfigData->getElementMetadata($this->getKey()); + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::set(). + */ + public function set($property_name, $value) { + // Set the value in the parent object that holds the Config. + $this->parentConfigData->set($this->getKey($property_name), $value); + return $this; + } + + /** + * Implements TypedDataInterface::getType(). + */ + public function getType() { + return $this->definition['type']; + } + + /** + * Implements TypedDataInterface::getDefinition(). + */ + public function getDefinition() { + return $this->definition; + } + + /** + * Implements TypedDataInterface::getValue(). + */ + public function getValue() { + return $this->getConfigData(); + } + + /** + * Implements TypedDataInterface::setValue(). + */ + public function setValue($value) { + $this->parentConfigData->set($this->getKey(), $value); + } + + /** + * Implements TypedDataInterface::getString(). + */ + public function getString() { + return (string) $this->getValue(); + } + + /** + * Implements TypedDataInterface::validate(). + */ + public function validate() { + // This will be ok if we have any config data at all. + $data = $this->getConfigData(); + return isset($data); + } +} diff --git a/core/lib/Drupal/Core/Config/Metadata/ConfigData.php b/core/lib/Drupal/Core/Config/Metadata/ConfigData.php new file mode 100644 index 0000000..f1c4a8c --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/ConfigData.php @@ -0,0 +1,277 @@ +getElementMetadata($key); + list($basemeta, $children) = $this->splitMetadata($metadata); + + switch ($basemeta['type']) { + case 'config_structure': + $nested = new ArrayConfigData($metadata); + $nested->setParent($this, $key); + return $nested; + + case 'config_nested': + $nested = new NestedConfigData($metadata); + $nested->setParent($this, $key); + return $nested; + + default: + // The element has no children so it is an end property and the metadata + // will be the property definition. We add a default type just in case. + return $this->buildProperty($key, $basemeta); + } + } + + /** + * Split metadata in base element's properties and children. + * + * These are the properties that are not arrays, thus they're this element's metadata. + */ + protected static function splitMetadata($metadata) { + // Children elements will be arrays of metadata themselves. + $children = array_filter($metadata, 'is_array'); + // Parent properties will be scalar values. + $basemeta = array_filter($metadata, 'is_scalar'); + // The default type will depend on whether we've got children or not. + $basemeta += array('type' => $children ? 'config_structure' : 'undefined'); + return array($basemeta, $children); + } + + /** + * Builds property as typed data. + * + * @param string $key + * Property key in the configuration data. + * @return Drupal\Core\TypedData\DataInterface + * Property as typed data. + */ + protected function buildProperty($key, array $definition = array()) { + $value = $this->getConfigData($key); + $definition += array('type' => 'undefined'); + $context = array( + 'name' => $key, + 'parent' => $this, + ); + return typed_data()->create($definition, $value, $context); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getElementMetadata(). + */ + public function getElementMetadata($key) { + $metadata = $this->getMetadata(); + return isset($metadata[$key]) ? $metadata[$key] : array(); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::toList(). + */ + public function toList() { + $list = array(); + foreach ($this->getProperties() as $key => $property) { + if ($property instanceof ConfigData) { + foreach ($property->toList() as $index => $value) { + $list[$key . '.' . $index] = $value; + } + } + else { + $list[$key] = $property; + } + } + return $list; + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::get(). + */ + public function get($property_name) { + $parts = explode('.', $property_name); + $first = array_shift($parts); + $data = $this->getConfigData($first); + if (isset($data)) { + // We have data and metadata, built typed data. + $element = $this->buildElement($first); + $key = implode('.', $parts); + if (!$key) { + return $element; + } + elseif ($element instanceof ConfigDataInterface) { + return $element->get($key); + } + } + else { + throw new InvalidArgumentException("The configuration property $property_name doesn't exist."); + } + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::getProperties(). + */ + public function getProperties($include_computed = FALSE) { + $array = array(); + foreach (array_keys($this->getConfigData()) as $key) { + $array[$key] = $this->buildElement($key); + } + return $array; + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::getPropertyValues(). + */ + public function getPropertyValues() { + return $this->getConfigData(); + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::setPropertyValues(). + */ + public function setPropertyValues($values) { + foreach ($values as $name => $value) { + $this->set($name, $value); + } + return $this; + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinition(). + */ + public function getPropertyDefinition($name) { + if ($meta = $this->getMetadata($name)) { + return $this->getBaseMetadata($meta); + } + else { + return FALSE; + } + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions(). + */ + public function getPropertyDefinitions() { + return $this->getChildrenMetadata($this->getMetadata()); + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::toArray(). + */ + public function toArray() { + return $this->getConfigData(); + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::isEmpty(). + */ + public function isEmpty() { + return !(bool)$this->getConfigData(); + } + + /** + * Implements IteratorAggregate::getIterator(). + */ + public function getIterator() { + return new ArrayIterator($this->getProperties()); + } + + /** + * Implements ArrayAccess::offsetExists(). + */ + public function offsetExists($offset) { + $data = $this->getConfigData($offset); + return isset($data); + } + + /** + * Implements ArrayAccess::offsetGet(). + */ + public function offsetGet($offset) { + return $this->get($offset); + } + + /** + * Implements ArrayAccess::offsetSet(). + */ + public function offsetSet($offset, $value) { + $this->set($offset, $value); + } + + /** + * Implements ArrayAccess::offsetUnset(). + */ + public function offsetUnset($offset) { + $this->set($offset, NULL); + } + + /** + * Implements Countable::count(). + */ + public function count() { + return count($this->getConfigData()); + } +} \ No newline at end of file diff --git a/core/lib/Drupal/Core/Config/Metadata/ConfigDataInterface.php b/core/lib/Drupal/Core/Config/Metadata/ConfigDataInterface.php new file mode 100644 index 0000000..9e99835 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/ConfigDataInterface.php @@ -0,0 +1,84 @@ +config = $config; + } + + /** + * Gets the configuration object for this data. + * + * @return Drupal\Core\Config\Config + */ + public function getConfig() { + return $this->config; + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getKey(). + */ + public function getKey($key = '') { + // As this is the parent structure, there is no base key. + return $key; + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getMetadata(). + */ + public function getMetadata() { + if (!isset($this->metadata)) { + $this->metadata = config_metadata($this->getConfig()->getName()); + } + return $this->metadata; + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getConfigData(). + */ + public function getConfigData($key = '') { + // As this is the parent structure, we get it right from the config object. + return $this->config->get($key); + } + + /** + * Implements Drupal\Core\Config\Metadata\ConfigDataInterface::getConfigData(). + */ + public function getConfigKey() { + // This is the parent ConfigDataInterface so the key is empty. + return ''; + } + + /** + * Implements Drupal\Core\TypedData\ComplexDataInterface::set(). + */ + public function set($property_name, $value) { + // Set the data into the configuration object but behave according + // to the interface specification when we've got a null value. + if (isset($value)) { + $this->config->set($property_name, $value); + } + else { + $this->config->clear($property_name); + } + return $this; + } +} diff --git a/core/lib/Drupal/Core/Config/Metadata/MetadataLookup.php b/core/lib/Drupal/Core/Config/Metadata/MetadataLookup.php new file mode 100644 index 0000000..f7f0639 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/MetadataLookup.php @@ -0,0 +1,102 @@ +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) { + if (!isset($this->metadataStorage)) { + $this->metadataStorage = new MetadataStorage(); + } + try { + return $this->metadataStorage->read($name); + } + catch (Symfony\Component\Yaml\Exception\ParseException $e) { + // @todo Just log an error, but return empty array. + } + return array(); + } +} diff --git a/core/lib/Drupal/Core/Config/Metadata/MetadataStorage.php b/core/lib/Drupal/Core/Config/Metadata/MetadataStorage.php new file mode 100644 index 0000000..1806a01 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/MetadataStorage.php @@ -0,0 +1,50 @@ +directory = drupal_get_path('module', $module) . '/meta'; + return parent::listAll($prefix); + } + } +} \ No newline at end of file diff --git a/core/lib/Drupal/Core/Config/Metadata/NestedConfigData.php b/core/lib/Drupal/Core/Config/Metadata/NestedConfigData.php new file mode 100644 index 0000000..0609aa5 --- /dev/null +++ b/core/lib/Drupal/Core/Config/Metadata/NestedConfigData.php @@ -0,0 +1,107 @@ +getBaseMetadata(); + //This will depend on the actual data and the property we are using to map + // it to the configuration metadata name. + if ($name = $this->getMetadataName($key)) { + return NestedArray::mergeDeep($metadata, config_metadata($name)); + } + else { + return $metadata; + } + } + + /** + * Gets base metadata for all nested keys. + */ + protected function getBaseMetadata() { + $definition = $this->getDefinition(); + if (isset($this->definition['config_base'])) { + return config_metadata($this->definition['config_base']); + } + else { + return array(); + } + } + + /** + * Gets the metadata name that maps to a configuration data key. + * + * @param string $key + * Element's key in the configuration data. + * + * @return string|null + * Configuration metadata name for that element. + */ + protected function getMetadataName($key) { + if (isset($this->definition['config_key'])) { + return $this->getConfigData($key . '.' . $this->definition['config_key']); + } + } +} diff --git a/core/lib/Drupal/Core/TypedData/Primitive.php b/core/lib/Drupal/Core/TypedData/Primitive.php index 523a047..d47f4a0 100644 --- a/core/lib/Drupal/Core/TypedData/Primitive.php +++ b/core/lib/Drupal/Core/TypedData/Primitive.php @@ -13,6 +13,11 @@ namespace Drupal\Core\TypedData; final class Primitive { /** + * The UNDEFINED primitive data type. + */ + const UNDEFINED = 0; + + /** * The BOOLEAN primitive data type. */ const BOOLEAN = 1; diff --git a/core/lib/Drupal/Core/TypedData/Type/Undefined.php b/core/lib/Drupal/Core/TypedData/Type/Undefined.php new file mode 100644 index 0000000..4539da1 --- /dev/null +++ b/core/lib/Drupal/Core/TypedData/Type/Undefined.php @@ -0,0 +1,40 @@ +value = $value; + } + + /** + * Implements TypedDataInterface::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..3c97d65 --- /dev/null +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigMetadataTest.php @@ -0,0 +1,147 @@ + 'Configuration 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', + ), + 'label' => array( + 'label' => 'Label', + 'type' => 'string' + ), + 'effects' => array( + 'label' => 'Style effects', + 'type' => 'config_nested', + 'config_base' => 'image.style.effects.*', + 'config_key' => 'name' + ) + ); + $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', + 'width' => array( + 'label' => 'Width', + 'type' => 'integer' + ), + 'height' => array( + 'label' => 'Height', + 'type' => 'integer', + ), + 'upscale' => array( + 'label' => 'Upscale', + 'type' => 'boolean', + ) + ), + 'weight' => array( + 'label' => 'Weight', + 'type' => 'integer' + ), + 'ieid' => array( + 'label' => 'IEID', + ), + + ); + $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 = config_wrapper('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\Undefined'), 'Got the right wrapper fo the page.front property.'); + $this->assertEqual($property->getType(), 'undefined', 'Got the right type for page.front data (undefined).'); + $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 = config_wrapper('image.style.large'); + $effects = $wrapper->get('effects'); + // The function is_array() doesn't work with ArrayAccess, so we use count(). + $this->assertTrue(count($effects) == 1, 'Got an array with effects for image.style.large data'); + $ieid = key($effects->getProperties()); + $effect = $wrapper->get('effects.' . $ieid); + $this->assertTrue(count($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.' ); + // Try config key and getting nested properties. + $key = 'effects.' . $ieid . '.data'; + $this->assertEqual($effect['data']->getConfigKey(), $key, 'Got the right configuration key for a nested image styple effect'); + $this->assertEqual($effect['data'], $wrapper->get($key), 'Got the same object using different keys with dot notation.'); + + // Finally update some object using a configuration wrapper. + $new_slogan = 'Site slogan for testing configuration metadata'; + $wrapper = config_wrapper('system.site'); + $wrapper->set('slogan', $new_slogan); + $site_slogan = $wrapper->get('slogan'); + $this->assertEqual($site_slogan->getValue(), $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 012af17..99e1056 100644 --- a/core/modules/image/config/image.style.large.yml +++ b/core/modules/image/config/image.style.large.yml @@ -2,7 +2,7 @@ name: large label: Large (480x480) 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 941ab85..1b5ad6e 100644 --- a/core/modules/image/config/image.style.medium.yml +++ b/core/modules/image/config/image.style.medium.yml @@ -2,7 +2,7 @@ name: medium label: Medium (220x220) 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 a454200..19f8652 100644 --- a/core/modules/image/config/image.style.thumbnail.yml +++ b/core/modules/image/config/image.style.thumbnail.yml @@ -2,7 +2,7 @@ name: thumbnail label: Thumbnail (100x100) 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 7437b10..1e614a6 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php @@ -70,28 +70,28 @@ class ImageAdminStylesTest extends ImageFieldTestBase { $style_label = $this->randomString(); $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', @@ -275,7 +275,7 @@ class ImageAdminStylesTest extends ImageFieldTestBase { // Add a scale effect. $this->drupalGet('admin/config/media/image-styles/add'); $this->drupalPost(NULL, array('label' => 'Test style effect edit', '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')); @@ -290,13 +290,13 @@ class ImageAdminStylesTest extends ImageFieldTestBase { // Add another scale effect. $this->drupalGet('admin/config/media/image-styles/add'); $this->drupalPost(NULL, array('label' => 'Test style scale edit scale', '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 c2734f0..d49946c 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..d7ac8e9 --- /dev/null +++ b/core/modules/image/meta/image.style.%.yml @@ -0,0 +1,11 @@ +name: + label: 'Machine name' +label: + label: 'Label' + type: 'string' +effects: + label: 'Style effects' + type: 'config_nested' + config_base: 'image.style.effects.*' + config_key: 'name' + \ No newline at end of file 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..618963e --- /dev/null +++ b/core/modules/image/meta/image.style.effects.%.yml @@ -0,0 +1,9 @@ +name: + label: 'Style name' +data: + label: 'Data' +weight: + label: 'Weight' + type: 'integer' +ieid: + label: '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..3fda284 --- /dev/null +++ b/core/modules/image/meta/image.style.effects.scale.yml @@ -0,0 +1,10 @@ +data: + width: + label: 'Width' + type: 'integer' + height: + label: 'Height' + type: 'integer' + 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..f03d92f --- /dev/null +++ b/core/modules/system/meta/system.site.yml @@ -0,0 +1,15 @@ +name: + label: 'Site name' + type: 'string' +mail: + label: 'Site mail' +slogan: + label: 'Site slogan' + type: 'string' +page: + 403: + label: 'Default 403 (access denied) page' + 404: + label: 'Default 404 (not found) page' + front: + label: 'Default front page' \ No newline at end of file diff --git a/core/modules/system/system.module b/core/modules/system/system.module index bfa91db..2ed75ab 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1947,6 +1947,11 @@ function system_stream_wrappers() { */ function system_data_type_info() { return array( + 'undefined' => array( + 'label' => t('Undefined'), + 'class' => '\Drupal\Core\TypedData\Type\Undefined', + 'primitive type' => Primitive::UNDEFINED, + ), 'boolean' => array( 'label' => t('Boolean'), 'class' => '\Drupal\Core\TypedData\Type\Boolean',