diff -u b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php --- b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php +++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php @@ -157,29 +157,22 @@ */ public function getProperties($include_computed = FALSE) { $properties = []; - $property_definitions = $this->definition->getPropertyDefinitions(); - if (!empty($property_definitions)) { - foreach ($property_definitions as $name => $definition) { - if ($include_computed || !$definition->isComputed()) { - $properties[$name] = $this->get($name); - } - } - } // If module creator send an array to map dataType and don't define setPropertyDefinition, // Auto creating the PropertyDefinition so that it can be normalized - elseif (get_class($this->getDataDefinition()) == 'Drupal\Core\TypedData\MapDataDefinition') { - $values = $this->values; + $property_definitions = $this->definition->getPropertyDefinitions(); + if (empty($property_definitions) && get_class($this->getDataDefinition()) == 'Drupal\Core\TypedData\MapDataDefinition') { + $values = $this->getValue(); if (is_array($values)) { foreach ($values as $key => $value) { if (!empty($value) && is_array($value)) { - $properties[$key] = \Drupal::typedDataManager()->create( + $data = \Drupal::typedDataManager()->create( MapDataDefinition::create(), $value, $key ); } else { - $properties[$key] = \Drupal::typedDataManager()->create( + $data = \Drupal::typedDataManager()->create( // Give array's value a DataType,So that drupal can find which normalizer to be used to normalize it // Because we don't know the type of the value,so we use 'any', // If you don't want to use 'any',Please define it by yourself use setPropertyDefinition @@ -188,7 +181,13 @@ $key ); } - }; + $this->definition->setPropertyDefinition($key, $data->getDataDefinition()); + } + } + } + foreach ($this->definition->getPropertyDefinitions() as $name => $definition) { + if ($include_computed || !$definition->isComputed()) { + $properties[$name] = $this->get($name); } } @@ -198,7 +197,8 @@ /** * {@inheritdoc} */ - public function toArray() { + public + function toArray() { $values = []; foreach ($this->getProperties() as $name => $property) { $values[$name] = $property->getValue(); @@ -209,14 +209,16 @@ /** * {@inheritdoc} */ - public function getIterator() { + public + function getIterator() { return new \ArrayIterator($this->getProperties()); } /** * {@inheritdoc} */ - public function isEmpty() { + public + function isEmpty() { foreach ($this->properties as $property) { $definition = $property->getDataDefinition(); if (!$definition->isComputed() && $property->getValue() !== NULL) { @@ -236,7 +238,8 @@ /** * Magic method: Implements a deep clone. */ - public function __clone() { + public + function __clone() { foreach ($this->properties as $name => $property) { $this->properties[$name] = clone $property; $this->properties[$name]->setContext($name, $this); @@ -251,7 +254,8 @@ * TRUE. By passing FALSE, overrides of this method can re-use the logic * of parent classes without triggering notification. */ - public function onChange($property_name, $notify = TRUE) { + public + function onChange($property_name, $notify = TRUE) { // Notify the parent of changes. if ($notify && isset($this->parent)) { $this->parent->onChange($this->name); @@ -261,7 +265,8 @@ /** * {@inheritdoc} */ - public function applyDefaultValue($notify = TRUE) { + public + function applyDefaultValue($notify = TRUE) { // Apply the default value of all properties. foreach ($this->getProperties() as $property) { $property->applyDefaultValue(FALSE);