Issue #2277945 by Jose Reyero: Fixed Typed configuration implements TypedDataInterface improperly.
parent
1e467aad6d
commit
9b32d95bfd
|
@ -42,9 +42,11 @@ uri:
|
|||
mapping:
|
||||
label: Mapping
|
||||
class: '\Drupal\Core\Config\Schema\Mapping'
|
||||
definition_class: '\Drupal\Core\TypedData\MapDataDefinition'
|
||||
sequence:
|
||||
label: Sequence
|
||||
class: '\Drupal\Core\Config\Schema\Sequence'
|
||||
definition_class: '\Drupal\Core\TypedData\ListDataDefinition'
|
||||
|
||||
# Simple extended data types:
|
||||
|
||||
|
@ -110,7 +112,6 @@ filter:
|
|||
settings:
|
||||
type: filter_settings.[%parent.id]
|
||||
|
||||
|
||||
# System action configuration base.
|
||||
action_configuration_default:
|
||||
type: sequence
|
||||
|
|
|
@ -28,4 +28,13 @@ abstract class Element extends TypedData {
|
|||
return \Drupal::service('config.typed')->create($definition, $data, $key, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build data definition object for contained elements.
|
||||
*
|
||||
* @return \Drupal\Core\TypedData\DataDefinitionInterface
|
||||
*/
|
||||
protected function buildDataDefinition($definition, $value, $key) {
|
||||
return \Drupal::service('config.typed')->buildDataDefinition($definition, $value, $key, $this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,12 +19,21 @@ use Drupal\Component\Utility\String;
|
|||
*/
|
||||
class Mapping extends ArrayElement implements ComplexDataInterface {
|
||||
|
||||
/**
|
||||
* An array of data definitions.
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\DataDefinitionInterface[]
|
||||
*/
|
||||
protected $propertyDefinitions;
|
||||
|
||||
/**
|
||||
* Overrides ArrayElement::parse()
|
||||
*
|
||||
* Note this only returns elements that have a data definition.
|
||||
*/
|
||||
protected function parse() {
|
||||
$elements = array();
|
||||
foreach ($this->definition['mapping'] as $key => $definition) {
|
||||
foreach ($this->getPropertyDefinitions() as $key => $definition) {
|
||||
if (isset($this->value[$key]) || array_key_exists($key, $this->value)) {
|
||||
$elements[$key] = $this->parseElement($key, $this->value[$key], $definition);
|
||||
}
|
||||
|
@ -103,13 +112,12 @@ class Mapping extends ArrayElement implements ComplexDataInterface {
|
|||
* @param string $name
|
||||
* The name of property.
|
||||
*
|
||||
* @return array|null
|
||||
* @return \Drupal\Core\TypedData\DataDefinitionInterface|null
|
||||
* The definition of the property or NULL if the property does not exist.
|
||||
*/
|
||||
public function getPropertyDefinition($name) {
|
||||
if (isset($this->definition['mapping'][$name])) {
|
||||
return $this->definition['mapping'][$name];
|
||||
}
|
||||
$definitions = $this->getPropertyDefinitions();
|
||||
return isset($definitions[$name]) ? isset($definitions[$name]) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,11 +128,14 @@ class Mapping extends ArrayElement implements ComplexDataInterface {
|
|||
* property name.
|
||||
*/
|
||||
public function getPropertyDefinitions() {
|
||||
$list = array();
|
||||
foreach ($this->getAllKeys() as $key) {
|
||||
$list[$key] = $this->getPropertyDefinition($key);
|
||||
if (!isset($this->propertyDefinitions)) {
|
||||
$this->propertyDefinitions = array();
|
||||
foreach ($this->definition['mapping'] as $key => $definition) {
|
||||
$value = isset($this->value[$key]) ? $this->value[$key] : NULL;
|
||||
$this->propertyDefinitions[$key] = $this->buildDataDefinition($definition, $value, $key);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
return $this->propertyDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,7 +53,8 @@ trait SchemaCheckTrait {
|
|||
return FALSE;
|
||||
}
|
||||
$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);
|
||||
$errors = array();
|
||||
foreach ($config_data as $key => $value) {
|
||||
$errors = array_merge($errors, $this->checkValue($key, $value));
|
||||
|
|
|
@ -14,14 +14,26 @@ use Drupal\Core\TypedData\ListInterface;
|
|||
*/
|
||||
class Sequence extends ArrayElement implements ListInterface {
|
||||
|
||||
/**
|
||||
* Data definition
|
||||
*
|
||||
* @var \Drupal\Core\TypedData\DataDefinitionInterface
|
||||
*/
|
||||
protected $itemDefinition;
|
||||
|
||||
/**
|
||||
* Overrides ArrayElement::parse()
|
||||
*/
|
||||
protected function parse() {
|
||||
$definition = $this->getItemDefinition();
|
||||
// Creates a new data definition object for each item from the generic type
|
||||
// definition array and actual configuration data for that item. Type
|
||||
// definitions may contain variables to be replaced and those depend on
|
||||
// each item's data.
|
||||
$definition = isset($this->definition['sequence'][0]) ? $this->definition['sequence'][0] : array();
|
||||
$elements = array();
|
||||
foreach ($this->value as $key => $value) {
|
||||
$elements[$key] = $this->parseElement($key, $value, $definition);
|
||||
$data_definition = $this->buildDataDefinition($definition, $value, $key);
|
||||
$elements[$key] = $this->parseElement($key, $value, $data_definition);
|
||||
}
|
||||
return $elements;
|
||||
}
|
||||
|
@ -37,7 +49,11 @@ class Sequence extends ArrayElement implements ListInterface {
|
|||
* Implements Drupal\Core\TypedData\ListInterface::getItemDefinition().
|
||||
*/
|
||||
public function getItemDefinition() {
|
||||
return $this->definition['sequence'][0];
|
||||
if (!isset($this->itemDefinition)) {
|
||||
$definition = isset($this->definition['sequence'][0]) ? $this->definition['sequence'][0] : array();
|
||||
$this->itemDefinition = $this->buildDataDefinition($definition, NULL);
|
||||
}
|
||||
return $this->itemDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -128,7 +128,8 @@ abstract class StorableConfigBase extends ConfigBase {
|
|||
protected function getSchemaWrapper() {
|
||||
if (!isset($this->schemaWrapper)) {
|
||||
$definition = $this->typedConfigManager->getDefinition($this->name);
|
||||
$this->schemaWrapper = $this->typedConfigManager->create($definition, $this->data);
|
||||
$data_definition = $this->typedConfigManager->buildDataDefinition($definition, $this->data);
|
||||
$this->schemaWrapper = $this->typedConfigManager->create($data_definition, $this->data);
|
||||
}
|
||||
return $this->schemaWrapper;
|
||||
}
|
||||
|
|
|
@ -7,16 +7,14 @@
|
|||
|
||||
namespace Drupal\Core\Config;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Drupal\Component\Plugin\PluginManagerBase;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\TypedData\TypedDataManager;
|
||||
|
||||
/**
|
||||
* Manages config type plugins.
|
||||
*/
|
||||
class TypedConfigManager extends PluginManagerBase implements TypedConfigManagerInterface {
|
||||
class TypedConfigManager extends TypedDataManager implements TypedConfigManagerInterface {
|
||||
|
||||
/**
|
||||
* The cache ID for the definitions.
|
||||
|
@ -80,19 +78,19 @@ class TypedConfigManager extends PluginManagerBase implements TypedConfigManager
|
|||
*/
|
||||
public function get($name) {
|
||||
$data = $this->configStorage->read($name);
|
||||
$definition = $this->getDefinition($name);
|
||||
return $this->create($definition, $data);
|
||||
$type_definition = $this->getDefinition($name);
|
||||
$data_definition = $this->buildDataDefinition($type_definition, $data);
|
||||
return $this->create($data_definition, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function create(array $definition, $value = NULL, $name = NULL, $parent = NULL) {
|
||||
if (!isset($definition['type'])) {
|
||||
// By default elements without a type are undefined.
|
||||
$definition['type'] = 'undefined';
|
||||
}
|
||||
elseif (strpos($definition['type'], ']')) {
|
||||
public function buildDataDefinition(array $definition, $value, $name = NULL, $parent = NULL) {
|
||||
// Add default values for data type and replace variables.
|
||||
$definition += array('type' => 'undefined');
|
||||
|
||||
if (strpos($definition['type'], ']')) {
|
||||
// Replace variable names in definition.
|
||||
$replace = is_array($value) ? $value : array();
|
||||
if (isset($parent)) {
|
||||
|
@ -103,45 +101,18 @@ class TypedConfigManager extends PluginManagerBase implements TypedConfigManager
|
|||
}
|
||||
$definition['type'] = $this->replaceName($definition['type'], $replace);
|
||||
}
|
||||
// Create typed config object.
|
||||
$wrapper = $this->createInstance($definition['type'], array(
|
||||
'data_definition' => $definition,
|
||||
'name' => $name,
|
||||
'parent' => $parent,
|
||||
));
|
||||
if (isset($value)) {
|
||||
$wrapper->setValue($value, FALSE);
|
||||
}
|
||||
return $wrapper;
|
||||
}
|
||||
// Add default values from type definition.
|
||||
$definition += $this->getDefinition($definition['type']);
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createInstance($data_type, array $configuration = array()) {
|
||||
$data_definition = $configuration['data_definition'];
|
||||
$type_definition = $this->getDefinition($data_type);
|
||||
$data_definition = $this->createDataDefinition($definition['type']);
|
||||
|
||||
if (!isset($type_definition)) {
|
||||
throw new \InvalidArgumentException(String::format('Invalid data type %plugin_id has been given.', array('%plugin_id' => $data_type)));
|
||||
// Pass remaining values from definition array to data definition.
|
||||
foreach ($definition as $key => $value) {
|
||||
if (!isset($data_definition[$key])) {
|
||||
$data_definition[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow per-data definition overrides of the used classes, i.e. take over
|
||||
// classes specified in the type definition.
|
||||
$data_definition += $type_definition;
|
||||
|
||||
$key = empty($data_definition['list']) ? 'class' : 'list class';
|
||||
if (isset($data_definition[$key])) {
|
||||
$class = $data_definition[$key];
|
||||
}
|
||||
elseif (isset($type_definition[$key])) {
|
||||
$class = $type_definition[$key];
|
||||
}
|
||||
|
||||
if (!isset($class)) {
|
||||
throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $data_type));
|
||||
}
|
||||
return new $class($data_definition, $configuration['name'], $configuration['parent']);
|
||||
return $data_definition;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +140,11 @@ class TypedConfigManager extends PluginManagerBase implements TypedConfigManager
|
|||
unset($definition['type']);
|
||||
$this->definitions[$type] = $definition;
|
||||
}
|
||||
return $definition;
|
||||
// Add type and default definition class.
|
||||
return $definition + array(
|
||||
'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
|
||||
'type' => $type,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\Core\Config;
|
|||
|
||||
use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
|
||||
use Drupal\Component\Plugin\PluginManagerInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Defines an interface for typed configuration manager.
|
||||
|
@ -36,7 +37,8 @@ Interface TypedConfigManagerInterface extends PluginManagerInterface, CachedDisc
|
|||
* instantiated.
|
||||
* @param array $configuration
|
||||
* The plugin configuration array, i.e. an array with the following keys:
|
||||
* - data definition: The data definition array.
|
||||
* - data definition: The data definition object, i.e. an instance of
|
||||
* \Drupal\Core\TypedData\DataDefinitionInterface.
|
||||
* - name: (optional) If a property or list item is to be created, the name
|
||||
* of the property or the delta of the list item.
|
||||
* - parent: (optional) If a property or list item is to be created, the
|
||||
|
@ -51,10 +53,10 @@ Interface TypedConfigManagerInterface extends PluginManagerInterface, CachedDisc
|
|||
/**
|
||||
* Creates a new typed configuration object instance.
|
||||
*
|
||||
* @param array $definition
|
||||
* The data definition of the typed data object
|
||||
* @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
|
||||
|
@ -67,7 +69,27 @@ Interface TypedConfigManagerInterface extends PluginManagerInterface, CachedDisc
|
|||
* @return \Drupal\Core\Config\Schema\Element
|
||||
* The instantiated typed data object.
|
||||
*/
|
||||
public function create(array $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 configuration value to create it.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function buildDataDefinition(array $definition, $value, $name = NULL, $parent = NULL);
|
||||
|
||||
/**
|
||||
* Checks if the configuration schema with the given config name exists.
|
||||
|
|
|
@ -48,6 +48,8 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
'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 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
'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 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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']['uuid']['type'] = 'string';
|
||||
$expected['mapping']['uuid']['label'] = 'UUID';
|
||||
|
@ -152,6 +165,7 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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);
|
||||
|
||||
|
@ -161,18 +175,21 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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';
|
||||
|
||||
|
@ -188,6 +205,8 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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');
|
||||
|
||||
|
@ -204,31 +223,34 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
|
||||
// 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);
|
||||
}
|
||||
|
@ -359,10 +381,12 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
|
|||
$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');
|
||||
|
||||
|
|
|
@ -128,6 +128,13 @@ class ConfigMapperManager extends DefaultPluginManager implements ConfigMapperMa
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL) {
|
||||
return $this->typedConfigManager->buildDataDefinition($definition, $value, $name, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -272,7 +272,10 @@ abstract class ConfigTranslationFormBase extends FormBase implements BaseFormIdI
|
|||
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 @@ abstract class ConfigTranslationFormBase extends FormBase implements BaseFormIdI
|
|||
'#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']();
|
||||
|
|
|
@ -12,6 +12,7 @@ use Drupal\Core\Ajax\AjaxResponse;
|
|||
use Drupal\Core\Ajax\ReplaceCommand;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
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, LanguageInterface $language, $value) {
|
||||
public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value) {
|
||||
$description = $this->t('A user-defined date format. See the <a href="@url">PHP manual</a> 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(
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\config_translation\FormElement;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for configuration translation form elements.
|
||||
|
@ -17,7 +18,7 @@ interface ElementInterface {
|
|||
/**
|
||||
* 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\LanguageInterface $language
|
||||
* Language object to display the translation form for.
|
||||
|
@ -27,6 +28,7 @@ interface ElementInterface {
|
|||
* @return array
|
||||
* Form API array to represent the form element.
|
||||
*/
|
||||
public function getFormElement(array $definition, LanguageInterface $language, $value);
|
||||
public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\config_translation\FormElement;
|
|||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
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, LanguageInterface $language, $value) {
|
||||
public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $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;
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\config_translation\FormElement;
|
|||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
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, LanguageInterface $language, $value) {
|
||||
public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value) {
|
||||
return array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $value,
|
||||
|
|
|
@ -12,6 +12,8 @@ use Drupal\Core\Language\Language;
|
|||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\Core\TypedData\DataDefinition;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
|
||||
/**
|
||||
* Tests ConfigMapperManager.
|
||||
|
@ -162,10 +164,11 @@ class ConfigMapperManagerTest extends UnitTestCase {
|
|||
* The mocked schema element.
|
||||
*/
|
||||
protected function getElement(array $definition) {
|
||||
$data_definition = new DataDefinition($definition);
|
||||
$element = $this->getMock('Drupal\Core\TypedData\TypedDataInterface');
|
||||
$element->expects($this->any())
|
||||
->method('getDataDefinition')
|
||||
->will($this->returnValue($definition));
|
||||
->will($this->returnValue($data_definition));
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,9 +96,10 @@ class LocaleConfigManager extends TypedConfigManager {
|
|||
// 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;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\locale;
|
||||
|
||||
use Drupal\Core\TypedData\ContextAwareInterface;
|
||||
use Drupal\Core\TypedData\DataDefinitionInterface;
|
||||
use Drupal\Core\Config\Schema\Element;
|
||||
use Drupal\Core\Config\Schema\ArrayElement;
|
||||
|
||||
|
@ -49,7 +50,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;
|
||||
|
|
Loading…
Reference in New Issue