ArrayElement.php 4.74 KB
Newer Older
1
2
3
4
5
6
7
8
<?php

/**
 * @file
 * Contains \Drupal\Core\Config\Schema\ArrayElement.
 */

namespace Drupal\Core\Config\Schema;
9
10
11
12

use Drupal\Component\Utility\String;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\TypedData\TypedData;
13
14
15
16

/**
 * Defines a generic configuration element that contains multiple properties.
 */
17
abstract class ArrayElement extends TypedData implements \IteratorAggregate, TypedConfigInterface {
18
19

  /**
20
21
22
   * The typed config manager.
   *
   * @var \Drupal\Core\Config\TypedConfigManagerInterface
23
   */
24
  protected $typedConfig;
25
26

  /**
27
   * The configuration value.
28
   *
29
   * @var mixed
30
   */
31
32
33
34
35
36
  protected $value;

  /**
   * Parsed elements.
   */
  protected $elements;
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  /**
   * Gets valid configuration data keys.
   *
   * @return array
   *   Array of valid configuration data keys.
   */
  protected function getAllKeys() {
    return is_array($this->value) ? array_keys($this->value) : array();
  }

  /**
   * Builds an array of contained elements.
   *
51
52
   * @return \Drupal\Core\TypedData\TypedDataInterface[]
   *   An array of elements contained in this element.
53
   */
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  protected function parse() {
    $elements = array();
    foreach ($this->getAllKeys() as $key) {
      $value = isset($this->value[$key]) ? $this->value[$key] : NULL;
      $definition = $this->getElementDefinition($key);
      $elements[$key] = $this->createElement($definition, $value, $key);
    }
    return $elements;
  }

  /**
   * Gets data definition object for contained element.
   *
   * @param int|string $key
   *   Property name or index of the element.
   *
   * @return \Drupal\Core\TypedData\DataDefinitionInterface
   */
  protected abstract function getElementDefinition($key);
73
74

  /**
75
   * {@inheritdoc}
76
   */
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  public function get($name) {
    $parts = explode('.', $name);
    $root_key = array_shift($parts);
    $elements = $this->getElements();
    if (isset($elements[$root_key])) {
      $element = $elements[$root_key];
      // If $property_name contained a dot recurse into the keys.
      while ($element && ($key = array_shift($parts)) !== NULL) {
        if ($element instanceof TypedConfigInterface) {
          $element = $element->get($key);
        }
        else {
          $element = NULL;
        }
91
92
      }
    }
93
94
95
96
97
98
    if (isset($element)) {
      return $element;
    }
    else {
      throw new \InvalidArgumentException(String::format("The configuration property @key doesn't exist.", array('@key' => $name)));
    }
99
100
101
  }

  /**
102
   * {@inheritdoc}
103
   */
104
105
106
107
108
  public function getElements() {
    if (!isset($this->elements)) {
      $this->elements = $this->parse();
    }
    return $this->elements;
109
110
111
  }

  /**
112
   * {@inheritdoc}
113
   */
114
115
  public function isEmpty() {
    return empty($this->value);
116
117
118
  }

  /**
119
   * {@inheritdoc}
120
   */
121
122
  public function toArray() {
    return isset($this->value) ? $this->value : array();
123
124
125
  }

  /**
126
   * {@inheritdoc}
127
   */
128
129
130
131
132
  public function onChange($name) {
    // Notify the parent of changes.
    if (isset($this->parent)) {
      $this->parent->onChange($this->name);
    }
133
134
135
136
137
138
  }

  /**
   * Implements IteratorAggregate::getIterator();
   */
  public function getIterator() {
139
    return new \ArrayIterator($this->getElements());
140
141
  }

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  /**
   * Creates a contained typed configuration object.
   *
   * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
   *   The data definition object.
   * @param mixed $value
   *   (optional) 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 $key
   *   The key of the contained element.
   *
   * @return \Drupal\Core\TypedData\TypedDataInterface
   */
  protected function createElement($definition, $value, $key) {
    return $this->typedConfig->create($definition, $value, $key, $this);
  }

  /**
   * 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
   *   The value of the configuration element.
   * @param string $key
   *   The key of the contained element.
   *
   * @return \Drupal\Core\TypedData\DataDefinitionInterface
   */
  protected function buildDataDefinition($definition, $value, $key) {
    return $this->typedConfig->buildDataDefinition($definition, $value, $key, $this);
  }


  /**
   * Sets the typed config manager on the instance.
   *
   * This must be called immediately after construction to enable
   * self::parseElement() and self::buildDataDefinition() to work.
   *
   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
   */
  public function setTypedConfig(TypedConfigManagerInterface $typed_config) {
    $this->typedConfig = $typed_config;
  }

190
}