diff --git a/core/lib/Drupal/Core/Config/Schema/Sequence.php b/core/lib/Drupal/Core/Config/Schema/Sequence.php index 79e27ba..ed82d74 100644 --- a/core/lib/Drupal/Core/Config/Schema/Sequence.php +++ b/core/lib/Drupal/Core/Config/Schema/Sequence.php @@ -48,7 +48,7 @@ public function isEmpty() { public function getItemDefinition() { if (!isset($this->itemDefinition)) { $definition = isset($this->definition['sequence'][0]) ? $this->definition['sequence'][0] : array(); - $this->itemDefinition = $this->buildDataDefinition($definition); + $this->itemDefinition = $this->buildDataDefinition($definition, NULL); } return $this->itemDefinition; } diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php index 66b7332..938593c 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -92,24 +92,9 @@ public function get($name) { } /** - * Creates a new data definition object from a type definition array and - * actual configuration data. - * - * @param array $definition - * The base type definition array, for which a data definition should be created. - * @param $value - * Optional value of the configuraiton element. - * @param string $name - * Optional name of the configuration element. - * @param object $parent - * Optional parent element - * - * @return \Drupal\Core\TypedData\DataDefinitionInterface - * A data definition for the given data type. - * - * @see \Drupal\Core\TypedData\TypedDataManager::createListDataDefinition() + * {@inheritdoc} */ - public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL) { + public function buildDataDefinition(array $definition, $value, $name = NULL, $parent = NULL) { // Add default values for data type and replace variables. $definition += array('type' => 'undefined'); diff --git a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php index 8b0da5e..f475c02 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php @@ -56,7 +56,7 @@ public function createInstance($data_type, array $configuration = array()); * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition * The data definition of the typed data object. * @param mixed $value - * (optional) The data value. If set, it has to match one of the supported + * The data value. If set, it has to match one of the supported * data type format as documented for the data type classes. * @param string $name * (optional) If a property or list item is to be created, the name of the @@ -69,26 +69,27 @@ public function createInstance($data_type, array $configuration = array()); * @return \Drupal\Core\Config\Schema\Element * The instantiated typed data object. */ - public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL); + public function create(DataDefinitionInterface $definition, $value, $name = NULL, $parent = NULL); /** * Creates a new data definition object from a type definition array and * actual configuration data. Since type definitions may contain variables - * to be replaced, we need the full data to create it. + * to be replaced, we need the configuration value to create it. * * @param array $definition - * The base type definition array, for which a data definition should be created. + * The base type definition array, for which a data definition should be + * created. * @param $value * Optional value of the configuraiton element. * @param string $name * Optional name of the configuration element. * @param object $parent - * Optional parent element + * Optional parent element. * * @return \Drupal\Core\TypedData\DataDefinitionInterface * A data definition for the given data type. */ - public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL); + public function buildDataDefinition(array $definition, $value, $name = NULL, $parent = NULL); /** * Checks if the configuration schema with the given config name exists. diff --git a/core/modules/config/src/Tests/ConfigSchemaTest.php b/core/modules/config/src/Tests/ConfigSchemaTest.php index 14161bb..cef3d0d 100644 --- a/core/modules/config/src/Tests/ConfigSchemaTest.php +++ b/core/modules/config/src/Tests/ConfigSchemaTest.php @@ -48,6 +48,8 @@ function testSchemaMapping() { $expected = array(); $expected['label'] = 'Undefined'; $expected['class'] = '\Drupal\Core\Config\Schema\Undefined'; + $expected['type'] = 'undefined'; + $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for nonexistent configuration.'); // Configuration file without schema will return Undefined as well. @@ -63,21 +65,25 @@ function testSchemaMapping() { $expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; $expected['mapping']['testitem'] = array('label' => 'Test item'); $expected['mapping']['testlist'] = array('label' => 'Test list'); + $expected['type'] = 'config_schema_test.someschema'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with only some schema.'); // Check type detection on elements with undefined types. $config = \Drupal::service('config.typed')->get('config_schema_test.someschema'); - $definition = $config['testitem']->getDataDefinition(); + $definition = $config['testitem']->getDataDefinition()->toArray(); $expected = array(); $expected['label'] = 'Test item'; $expected['class'] = '\Drupal\Core\Config\Schema\Undefined'; $expected['type'] = 'undefined'; + $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; $this->assertEqual($definition, $expected, 'Automatic type detected for a scalar is undefined.'); - $definition = $config['testlist']->getDataDefinition(); + $definition = $config['testlist']->getDataDefinition()->toArray(); $expected = array(); $expected['label'] = 'Test list'; $expected['class'] = '\Drupal\Core\Config\Schema\Undefined'; $expected['type'] = 'undefined'; + $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; $this->assertEqual($definition, $expected, 'Automatic type detected for a list is undefined.'); // Simple case, straight metadata. @@ -93,6 +99,8 @@ function testSchemaMapping() { 'label' => 'Default language', 'type' => 'string', ); + $expected['type'] = 'system.maintenance'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for system.maintenance'); // Mixed schema with ignore elements. @@ -100,6 +108,7 @@ function testSchemaMapping() { $expected = array(); $expected['label'] = 'Ignore test'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $expected['mapping']['label'] = array( 'label' => 'Label', 'type' => 'label', @@ -116,16 +125,19 @@ function testSchemaMapping() { 'label' => 'Weight', 'type' => 'integer', ); + $expected['type'] = 'config_schema_test.ignore'; + $this->assertEqual($definition, $expected); // The ignore elements themselves. - $definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('irrelevant')->getDataDefinition(); + $definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('irrelevant')->getDataDefinition()->toArray(); $expected = array(); $expected['type'] = 'ignore'; $expected['label'] = 'Irrelevant'; $expected['class'] = '\Drupal\Core\Config\Schema\Ignore'; + $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; $this->assertEqual($definition, $expected); - $definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('indescribable')->getDataDefinition(); + $definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('indescribable')->getDataDefinition()->toArray(); $expected['label'] = 'Indescribable'; $this->assertEqual($definition, $expected); @@ -134,6 +146,7 @@ function testSchemaMapping() { $expected = array(); $expected['label'] = 'Image style'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $expected['mapping']['name']['type'] = 'string'; $expected['mapping']['id']['label'] = 'ID'; $expected['mapping']['id']['type'] = 'string'; @@ -154,6 +167,7 @@ function testSchemaMapping() { $expected['mapping']['effects']['sequence'][0]['mapping']['data']['type'] = 'image.effect.[%parent.id]'; $expected['mapping']['effects']['sequence'][0]['mapping']['weight']['type'] = 'integer'; $expected['mapping']['effects']['sequence'][0]['mapping']['uuid']['type'] = 'string'; + $expected['type'] = 'image.style.*'; $this->assertEqual($definition, $expected); @@ -163,18 +177,21 @@ function testSchemaMapping() { $expected = array(); $expected['label'] = 'Image scale'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $expected['mapping']['width']['type'] = 'integer'; $expected['mapping']['width']['label'] = 'Width'; $expected['mapping']['height']['type'] = 'integer'; $expected['mapping']['height']['label'] = 'Height'; $expected['mapping']['upscale']['type'] = 'boolean'; $expected['mapping']['upscale']['label'] = 'Upscale'; + $expected['type'] = 'image.effect.image_scale'; + $this->assertEqual($definition, $expected, 'Retrieved the right metadata for image.effect.image_scale'); // Most complex case, get metadata for actual configuration element. $effects = \Drupal::service('config.typed')->get('image.style.medium')->get('effects'); - $definition = $effects['bddf0d06-42f9-4c75-a700-a33cafa25ea0']['data']->getDataDefinition(); + $definition = $effects['bddf0d06-42f9-4c75-a700-a33cafa25ea0']['data']->getDataDefinition()->toArray(); // This should be the schema for image.effect.image_scale, reuse previous one. $expected['type'] = 'image.effect.image_scale'; @@ -190,6 +207,8 @@ function testSchemaMapping() { $expected['mapping']['testid']['label'] = 'ID'; $expected['mapping']['testdescription']['type'] = 'text'; $expected['mapping']['testdescription']['label'] = 'Description'; + $expected['type'] = 'config_schema_test.someschema.somemodule.*.*'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.someschema.somemodule.section_one.subsection'); @@ -206,31 +225,34 @@ function testSchemaMappingWithParents() { // Test fetching parent one level up. $entry = $config_data->get('one_level'); - $definition = $entry['testitem']->getDataDefinition(); + $definition = $entry['testitem']->getDataDefinition()->toArray(); $expected = array( 'type' => 'config_schema_test.someschema.with_parents.key_1', 'label' => 'Test item nested one level', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', + 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', ); $this->assertEqual($definition, $expected); // Test fetching parent two levels up. $entry = $config_data->get('two_levels'); - $definition = $entry['wrapper']['testitem']->getDataDefinition(); + $definition = $entry['wrapper']['testitem']->getDataDefinition()->toArray(); $expected = array( 'type' => 'config_schema_test.someschema.with_parents.key_2', 'label' => 'Test item nested two levels', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', + 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', ); $this->assertEqual($definition, $expected); // Test fetching parent three levels up. $entry = $config_data->get('three_levels'); - $definition = $entry['wrapper_1']['wrapper_2']['testitem']->getDataDefinition(); + $definition = $entry['wrapper_1']['wrapper_2']['testitem']->getDataDefinition()->toArray(); $expected = array( 'type' => 'config_schema_test.someschema.with_parents.key_3', 'label' => 'Test item nested three levels', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', + 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', ); $this->assertEqual($definition, $expected); } @@ -361,10 +383,12 @@ function testSchemaFallback() { $expected = array(); $expected['label'] = 'Schema wildcard fallback test'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; + $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; $expected['mapping']['testid']['type'] = 'string'; $expected['mapping']['testid']['label'] = 'ID'; $expected['mapping']['testdescription']['type'] = 'text'; $expected['mapping']['testdescription']['label'] = 'Description'; + $expected['type'] = 'config_schema_test.wildcard_fallback.*'; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.wildcard_fallback.something'); diff --git a/core/modules/config/src/Tests/ConfigSchemaTestBase.php b/core/modules/config/src/Tests/ConfigSchemaTestBase.php index eac1a75..6c763d4 100644 --- a/core/modules/config/src/Tests/ConfigSchemaTestBase.php +++ b/core/modules/config/src/Tests/ConfigSchemaTestBase.php @@ -61,7 +61,8 @@ public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $c return; } $definition = $typed_config->getDefinition($config_name); - $this->schema = $typed_config->create($definition, $config_data); + $data_definition = $typed_config->buildDataDefinition($definition, $config_data); + $this->schema = $typed_config->create($data_definition, $config_data); $this->configPass = TRUE; foreach ($config_data as $key => $value) { $this->checkValue($key, $value); diff --git a/core/modules/config_translation/src/ConfigMapperManager.php b/core/modules/config_translation/src/ConfigMapperManager.php index 04e1507..1e4273c 100644 --- a/core/modules/config_translation/src/ConfigMapperManager.php +++ b/core/modules/config_translation/src/ConfigMapperManager.php @@ -129,6 +129,13 @@ public function processDefinition(&$definition, $plugin_id) { /** * {@inheritdoc} */ + public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL) { + return $this->typedConfigManager->buildDataDefinition($definition, $value, $name, $parent); + } + + /** + * {@inheritdoc} + */ protected function findDefinitions() { $definitions = $this->discovery->getDefinitions(); foreach ($definitions as $plugin_id => &$definition) { diff --git a/core/modules/config_translation/src/Form/ConfigTranslationFormBase.php b/core/modules/config_translation/src/Form/ConfigTranslationFormBase.php index 921e704..26cf8b0 100644 --- a/core/modules/config_translation/src/Form/ConfigTranslationFormBase.php +++ b/core/modules/config_translation/src/Form/ConfigTranslationFormBase.php @@ -272,7 +272,10 @@ protected function buildConfigForm(Element $schema, $config_data, $base_config_d foreach ($schema as $key => $element) { // Make the specific element key, "$base_key.$key". $element_key = implode('.', array_filter(array($base_key, $key))); - $definition = $element->getDataDefinition() + array('label' => $this->t('N/A')); + $definition = $element->getDataDefinition(); + if (!$definition->getLabel()) { + $definition->setLabel($this->t('N/A')); + } if ($element instanceof Element) { // Build sub-structure and include it with a wrapper in the form // if there are any translatable elements there. @@ -336,7 +339,9 @@ protected function buildConfigForm(Element $schema, $config_data, $base_config_d '#type' => 'item', ); - $definition += array('form_element_class' => '\Drupal\config_translation\FormElement\Textfield'); + if (!isset($definition['form_element_class'])) { + $definition['form_element_class'] = '\Drupal\config_translation\FormElement\Textfield'; + } /** @var \Drupal\config_translation\FormElement\ElementInterface $form_element */ $form_element = new $definition['form_element_class'](); diff --git a/core/modules/config_translation/src/FormElement/DateFormat.php b/core/modules/config_translation/src/FormElement/DateFormat.php index 762968b..b9d4973 100644 --- a/core/modules/config_translation/src/FormElement/DateFormat.php +++ b/core/modules/config_translation/src/FormElement/DateFormat.php @@ -12,6 +12,7 @@ use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Language\Language; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Defines the date format element for the configuration translation interface. @@ -22,7 +23,7 @@ class DateFormat implements ElementInterface { /** * {@inheritdoc} */ - public function getFormElement(array $definition, Language $language, $value) { + public function getFormElement(DataDefinitionInterface $definition, Language $language, $value) { $description = $this->t('A user-defined date format. See the PHP manual for available options.', array('@url' => 'http://php.net/manual/function.date.php')); $format = $this->t('Displayed as %date_format', array('%date_format' => \Drupal::service('date')->format(REQUEST_TIME, 'custom', $value))); return array( diff --git a/core/modules/config_translation/src/FormElement/ElementInterface.php b/core/modules/config_translation/src/FormElement/ElementInterface.php index 9072cfc..5ea9420 100644 --- a/core/modules/config_translation/src/FormElement/ElementInterface.php +++ b/core/modules/config_translation/src/FormElement/ElementInterface.php @@ -8,6 +8,7 @@ namespace Drupal\config_translation\FormElement; use Drupal\Core\Language\Language; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Provides an interface for configuration translation form elements. @@ -17,7 +18,7 @@ /** * Returns the translation form element for a given configuration definition. * - * @param array $definition + * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition * Configuration schema type definition of the element. * @param \Drupal\Core\Language\Language $language * Language object to display the translation form for. @@ -27,6 +28,6 @@ * @return array * Form API array to represent the form element. */ - public function getFormElement(array $definition, Language $language, $value); + public function getFormElement(DataDefinitionInterface $definition, Language $language, $value); } diff --git a/core/modules/config_translation/src/FormElement/Textarea.php b/core/modules/config_translation/src/FormElement/Textarea.php index b796685..f36c467 100644 --- a/core/modules/config_translation/src/FormElement/Textarea.php +++ b/core/modules/config_translation/src/FormElement/Textarea.php @@ -9,6 +9,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Defines the textarea element for the configuration translation interface. @@ -19,7 +20,7 @@ class Textarea implements ElementInterface { /** * {@inheritdoc} */ - public function getFormElement(array $definition, Language $language, $value) { + public function getFormElement(DataDefinitionInterface $definition, Language $language, $value) { // Estimate a comfortable size of the input textarea. $rows_words = ceil(str_word_count($value) / 5); $rows_newlines = substr_count($value, "\n" ) + 1; diff --git a/core/modules/config_translation/src/FormElement/Textfield.php b/core/modules/config_translation/src/FormElement/Textfield.php index 46d71fe..e2015b6 100644 --- a/core/modules/config_translation/src/FormElement/Textfield.php +++ b/core/modules/config_translation/src/FormElement/Textfield.php @@ -9,6 +9,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Defines the textfield element for the configuration translation interface. @@ -19,7 +20,7 @@ class Textfield implements ElementInterface { /** * {@inheritdoc} */ - public function getFormElement(array $definition, Language $language, $value) { + public function getFormElement(DataDefinitionInterface $definition, Language $language, $value) { return array( '#type' => 'textfield', '#default_value' => $value, diff --git a/core/modules/config_translation/tests/src/ConfigMapperManagerTest.php b/core/modules/config_translation/tests/src/ConfigMapperManagerTest.php index 8a55f2d..4fb7fc8 100644 --- a/core/modules/config_translation/tests/src/ConfigMapperManagerTest.php +++ b/core/modules/config_translation/tests/src/ConfigMapperManagerTest.php @@ -11,6 +11,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\TypedData\TypedDataInterface; use Drupal\Tests\UnitTestCase; +use Drupal\Core\TypedData\DataDefinitionInterface; /** * Tests ConfigMapperManager. @@ -161,10 +162,11 @@ public function providerTestHasTranslatable() { * The mocked schema element. */ protected function getElement(array $definition) { + $data_definition = $this->typedConfigManager->buildDataDefinition($definition, NULL); $element = $this->getMock('Drupal\Core\TypedData\TypedDataInterface'); $element->expects($this->any()) ->method('getDataDefinition') - ->will($this->returnValue($definition)); + ->will($this->returnValue($data_definition)); return $element; } diff --git a/core/modules/locale/src/LocaleConfigManager.php b/core/modules/locale/src/LocaleConfigManager.php index 5b0aa4e..a6bc965 100644 --- a/core/modules/locale/src/LocaleConfigManager.php +++ b/core/modules/locale/src/LocaleConfigManager.php @@ -96,9 +96,10 @@ public function get($name) { // We get only the data that didn't change from default. $data = $this->compareConfigData($default, $updated); $definition = $this->getDefinition($name); + $data_definition = $this->buildDataDefinition($definition, $data); // Unless the configuration has a explicit language code we assume English. $langcode = isset($default['langcode']) ? $default['langcode'] : 'en'; - $wrapper = new LocaleTypedConfig($definition, $name, $langcode, $this); + $wrapper = new LocaleTypedConfig($data_definition, $name, $langcode, $this); $wrapper->setValue($data); return $wrapper; } diff --git a/core/modules/locale/src/LocaleTypedConfig.php b/core/modules/locale/src/LocaleTypedConfig.php index c0095f1..8980e73 100644 --- a/core/modules/locale/src/LocaleTypedConfig.php +++ b/core/modules/locale/src/LocaleTypedConfig.php @@ -9,6 +9,7 @@ use Drupal\Core\Language\Language; use Drupal\Core\TypedData\ContextAwareInterface; +use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\Config\Schema\Element; use Drupal\Core\Config\Schema\ArrayElement; @@ -50,7 +51,7 @@ class LocaleTypedConfig extends Element { * @param \Drupal\locale\LocaleConfigManager $localeConfig; * The locale configuration manager object. */ - public function __construct($definition, $name, $langcode, LocaleConfigManager $localeConfig) { + public function __construct(DataDefinitionInterface $definition, $name, $langcode, LocaleConfigManager $localeConfig) { parent::__construct($definition, $name); $this->langcode = $langcode; $this->localeConfig = $localeConfig;