3 namespace Drupal\Core\Config\Schema;
5 use Drupal\Core\TypedData\ComplexDataInterface;
8 * Defines a generic configuration element that contains multiple properties.
10 abstract class ArrayElement extends Element implements \IteratorAggregate, TypedConfigInterface, ComplexDataInterface {
18 * Gets valid configuration data keys.
21 * Array of valid configuration data keys.
23 protected function getAllKeys() {
24 return is_array($this->value) ? array_keys($this->value) : [];
28 * Builds an array of contained elements.
30 * @return \Drupal\Core\TypedData\TypedDataInterface[]
31 * An array of elements contained in this element.
33 protected function parse() {
35 foreach ($this->getAllKeys() as $key) {
36 $value = isset($this->value[$key]) ? $this->value[$key] : NULL;
37 $definition = $this->getElementDefinition($key);
38 $elements[$key] = $this->createElement($definition, $value, $key);
44 * Gets data definition object for contained element.
46 * @param int|string $key
47 * Property name or index of the element.
49 * @return \Drupal\Core\TypedData\DataDefinitionInterface
51 abstract protected function getElementDefinition($key);
56 public function get($name) {
57 $parts = explode('.', $name);
58 $root_key = array_shift($parts);
59 $elements = $this->getElements();
60 if (isset($elements[$root_key])) {
61 $element = $elements[$root_key];
62 // If $property_name contained a dot recurse into the keys.
63 while ($element && ($key = array_shift($parts)) !== NULL) {
64 if ($element instanceof TypedConfigInterface) {
65 $element = $element->get($key);
72 if (isset($element)) {
76 throw new \InvalidArgumentException("The configuration property $name doesn't exist.");
83 public function getElements() {
84 if (!isset($this->elements)) {
85 $this->elements = $this->parse();
87 return $this->elements;
93 public function isEmpty() {
94 return empty($this->value);
100 public function toArray() {
101 return isset($this->value) ? $this->value : [];
107 public function onChange($name) {
108 // Notify the parent of changes.
109 if (isset($this->parent)) {
110 $this->parent->onChange($this->name);
117 public function getIterator() {
118 return new \ArrayIterator($this->getElements());
122 * Creates a contained typed configuration object.
124 * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
125 * The data definition object.
126 * @param mixed $value
127 * (optional) The data value. If set, it has to match one of the supported
128 * data type format as documented for the data type classes.
130 * The key of the contained element.
132 * @return \Drupal\Core\TypedData\TypedDataInterface
134 protected function createElement($definition, $value, $key) {
135 return $this->getTypedDataManager()->create($definition, $value, $key, $this);
139 * Creates a new data definition object from a type definition array and
140 * actual configuration data.
142 * @param array $definition
143 * The base type definition array, for which a data definition should be
146 * The value of the configuration element.
148 * The key of the contained element.
150 * @return \Drupal\Core\TypedData\DataDefinitionInterface
152 protected function buildDataDefinition($definition, $value, $key) {
153 return $this->getTypedDataManager()->buildDataDefinition($definition, $value, $key, $this);
157 * Determines if this element allows NULL as a value.
160 * TRUE if NULL is a valid value, FALSE otherwise.
162 public function isNullable() {
163 return isset($this->definition['nullable']) && $this->definition['nullable'] == TRUE;
169 public function set($property_name, $value, $notify = TRUE) {
170 $this->value[$property_name] = $value;
171 // Config schema elements do not make use of notifications. Thus, we skip
172 // notifying parents.
179 public function getProperties($include_computed = FALSE) {
181 foreach (array_keys($this->value) as $name) {
182 $properties[$name] = $this->get($name);