Config.php 8.41 KB
Newer Older
1 2
<?php

3 4
/**
 * @file
5
 * Contains \Drupal\Core\Config\Config.
6
 */
7

8
namespace Drupal\Core\Config;
9

10
use Drupal\Component\Utility\NestedArray;
11
use Drupal\Core\Cache\Cache;
12
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
13

14
/**
15
 * Defines the default configuration object.
16 17 18 19 20
 *
 * Encapsulates all capabilities needed for configuration handling for a
 * specific configuration object, including support for runtime overrides. The
 * overrides are handled on top of the stored configuration so they are not
 * saved back to storage.
21 22
 *
 * @ingroup config_api
23
 */
24
class Config extends StorableConfigBase {
25

26 27 28
  /**
   * An event dispatcher instance to use for configuration events.
   *
29
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
30 31 32
   */
  protected $eventDispatcher;

33
  /**
34 35
   * The current runtime data.
   *
36 37
   * The configuration data from storage merged with module and settings
   * overrides.
38 39 40 41
   *
   * @var array
   */
  protected $overriddenData;
42

43
  /**
44
   * The current module overrides.
45
   *
46
   * @var array
47
   */
48 49 50
  protected $moduleOverrides;

  /**
51
   * The current settings overrides.
52
   *
53
   * @var array
54
   */
55
  protected $settingsOverrides;
56

57 58
  /**
   * Constructs a configuration object.
59
   *
60 61
   * @param string $name
   *   The name of the configuration object being constructed.
62
   * @param \Drupal\Core\Config\StorageInterface $storage
63
   *   A storage object to use for reading and writing the
64
   *   configuration data.
65
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
66
   *   An event dispatcher instance to use for configuration events.
67
   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
68
   *   The typed configuration manager service.
69
   */
70
  public function __construct($name, StorageInterface $storage, EventDispatcherInterface $event_dispatcher, TypedConfigManagerInterface $typed_config) {
71
    $this->name = $name;
72
    $this->storage = $storage;
73
    $this->eventDispatcher = $event_dispatcher;
74
    $this->typedConfigManager = $typed_config;
75 76
  }

77
  /**
78
   * {@inheritdoc}
79 80
   */
  public function initWithData(array $data) {
81
    parent::initWithData($data);
82 83
    $this->settingsOverrides = array();
    $this->moduleOverrides = array();
84 85 86
    return $this;
  }

87
  /**
88
   * {@inheritdoc}
89 90
   */
  public function get($key = '') {
91 92
    if (!isset($this->overriddenData)) {
      $this->setOverriddenData();
93 94
    }
    if (empty($key)) {
95
      return $this->overriddenData;
96 97 98 99
    }
    else {
      $parts = explode('.', $key);
      if (count($parts) == 1) {
100
        return isset($this->overriddenData[$key]) ? $this->overriddenData[$key] : NULL;
101 102
      }
      else {
103
        $value = NestedArray::getValue($this->overriddenData, $parts, $key_exists);
104 105 106 107 108 109
        return $key_exists ? $value : NULL;
      }
    }
  }

  /**
110
   * {@inheritdoc}
111
   */
112 113
  public function setData(array $data, $validate_keys = TRUE) {
    parent::setData($data, $validate_keys);
114 115 116 117 118
    $this->resetOverriddenData();
    return $this;
  }

  /**
119
   * Sets settings.php overrides for this configuration object.
120 121 122 123 124
   *
   * The overridden data only applies to this configuration object.
   *
   * @param array $data
   *   The overridden values of the configuration data.
125
   *
126
   * @return \Drupal\Core\Config\Config
127
   *   The configuration object.
128
   */
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
  public function setSettingsOverride(array $data) {
    $this->settingsOverrides = $data;
    $this->resetOverriddenData();
    return $this;
  }

  /**
   * Sets module overrides for this configuration object.
   *
   * @param array $data
   *   The overridden values of the configuration data.
   *
   * @return \Drupal\Core\Config\Config
   *   The configuration object.
   */
  public function setModuleOverride(array $data) {
    $this->moduleOverrides = $data;
    $this->resetOverriddenData();
    return $this;
  }

150 151 152
  /**
   * Sets the current data for this configuration object.
   *
153 154 155 156
   * Configuration overrides operate at two distinct layers: modules and
   * settings.php. Overrides in settings.php take precedence over values
   * provided by modules. Precedence or different module overrides is
   * determined by the priority of the config.factory.override tagged services.
157
   *
158
   * @return \Drupal\Core\Config\Config
159
   *   The configuration object.
160 161 162
   */
  protected function setOverriddenData() {
    $this->overriddenData = $this->data;
163 164 165 166 167
    if (isset($this->moduleOverrides) && is_array($this->moduleOverrides)) {
      $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->moduleOverrides), TRUE);
    }
    if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) {
      $this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->settingsOverrides), TRUE);
168 169 170 171 172 173 174 175 176
    }
    return $this;
  }

  /**
   * Resets the current data, so overrides are re-applied.
   *
   * This method should be called after the original data or the overridden data
   * has been changed.
177
   *
178
   * @return \Drupal\Core\Config\Config
179
   *   The configuration object.
180 181 182
   */
  protected function resetOverriddenData() {
    unset($this->overriddenData);
183 184 185 186
    return $this;
  }

  /**
187
   * {@inheritdoc}
188 189
   */
  public function set($key, $value) {
190
    parent::set($key, $value);
191
    $this->resetOverriddenData();
192 193 194 195
    return $this;
  }

  /**
196
   * {@inheritdoc}
197 198
   */
  public function clear($key) {
199
    parent::clear($key);
200
    $this->resetOverriddenData();
201 202 203
    return $this;
  }

204
  /**
205
   * {@inheritdoc}
206 207
   */
  public function save() {
208 209
    // Validate the configuration object name before saving.
    static::validateName($this->name);
210 211 212 213 214 215 216 217 218 219

    // If there is a schema for this configuration object, cast all values to
    // conform to the schema.
    if ($this->typedConfigManager->hasConfigSchema($this->name)) {
      // Ensure that the schema wrapper has the latest data.
      $this->schemaWrapper = NULL;
      foreach ($this->data as $key => $value) {
        $this->data[$key] = $this->castValue($key, $value);
      }
    }
220 221 222 223 224
    else {
      foreach ($this->data as $key => $value) {
        $this->validateValue($key, $value);
      }
    }
225

226
    $this->storage->write($this->name, $this->data);
227 228 229
    if (!$this->isNew) {
      Cache::invalidateTags($this->getCacheTags());
    }
230
    $this->isNew = FALSE;
231
    $this->eventDispatcher->dispatch(ConfigEvents::SAVE, new ConfigCrudEvent($this));
232
    $this->originalData = $this->data;
233 234 235
    return $this;
  }

236 237
  /**
   * Deletes the configuration object.
238
   *
239
   * @return \Drupal\Core\Config\Config
240
   *   The configuration object.
241 242 243
   */
  public function delete() {
    $this->data = array();
244
    $this->storage->delete($this->name);
245
    Cache::invalidateTags($this->getCacheTags());
246
    $this->isNew = TRUE;
247
    $this->resetOverriddenData();
248
    $this->eventDispatcher->dispatch(ConfigEvents::DELETE, new ConfigCrudEvent($this));
249
    $this->originalData = $this->data;
250
    return $this;
251
  }
252

253 254 255 256 257 258 259 260 261 262
  /**
   * Gets the raw data without overrides.
   *
   * @return array
   *   The raw data.
   */
  public function getRawData() {
    return $this->data;
  }

263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
  /**
   * Gets original data from this configuration object.
   *
   * Original data is the data as it is immediately after loading from
   * configuration storage before any changes. If this is a new configuration
   * object it will be an empty array.
   *
   * @see \Drupal\Core\Config\Config::get()
   *
   * @param string $key
   *   A string that maps to a key within the configuration data.
   * @param bool $apply_overrides
   *   Apply any overrides to the original data. Defaults to TRUE.
   *
   * @return mixed
   *   The data that was requested.
   */
  public function getOriginal($key = '', $apply_overrides = TRUE) {
281
    $original_data = $this->originalData;
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    if ($apply_overrides) {
      // Apply overrides.
      if (isset($this->moduleOverrides) && is_array($this->moduleOverrides)) {
        $original_data = NestedArray::mergeDeepArray(array($original_data, $this->moduleOverrides), TRUE);
      }
      if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) {
        $original_data = NestedArray::mergeDeepArray(array($original_data, $this->settingsOverrides), TRUE);
      }
    }

    if (empty($key)) {
      return $original_data;
    }
    else {
      $parts = explode('.', $key);
      if (count($parts) == 1) {
        return isset($original_data[$key]) ? $original_data[$key] : NULL;
      }
      else {
        $value = NestedArray::getValue($original_data, $parts, $key_exists);
        return $key_exists ? $value : NULL;
      }
    }
  }
306
}