DrupalConfig.php 5.68 KB
Newer Older
gdd's avatar
gdd committed
1 2 3 4 5
<?php

namespace Drupal\Core\Config;

use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
6
use Drupal\Core\Config\ConfigException;
gdd's avatar
gdd committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

/**
 * Represents the default configuration storage object.
 */
class DrupalConfig {

  /**
   * The storage engine to save this config object to.
   *
   * @var DrupalConfigVerifiedStorageInterface
   */
  protected $_verifiedStorage;

  protected $data = array();

  /**
   * Constructs a DrupalConfig object.
   *
   * @param DrupalConfigVerifiedStorageInterface $verified_storage
   *   The storage engine where this config object should be saved.
sun's avatar
sun committed
27 28
   *
   * @todo $this should really know about $name and make it publicly accessible.
gdd's avatar
gdd committed
29 30 31 32 33 34 35 36 37 38 39 40
   */
  public function __construct(DrupalConfigVerifiedStorageInterface $verified_storage) {
    $this->_verifiedStorage = $verified_storage;
    $this->read();
  }

  /**
   * Reads config data from the active store into our object.
   */
  public function read() {
    $active = (array) config_decode($this->_verifiedStorage->read());
    foreach ($active as $key => $value) {
41 42 43 44 45 46
      // If the setting is empty, return an empty string rather than an array.
      // This is necessary because SimpleXML's default behavior is to return
      // an empty array instead of a string.
      if (is_array($value) && empty($value)) {
        $value = '';
      }
gdd's avatar
gdd committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
      $this->set($key, $value);
    }
  }

  /**
   * Checks whether a particular value is overridden.
   *
   * @param $key
   *   @todo
   *
   * @return
   *   @todo
   */
  public function isOverridden($key) {
    return isset($this->_overrides[$key]);
  }

  /**
   * Gets data from this config object.
   *
   * @param $key
sun's avatar
sun committed
68
   *   A string that maps to a key within the configuration data.
gdd's avatar
gdd committed
69
   *   For instance in the following XML:
sun's avatar
sun committed
70
   *   @code
gdd's avatar
gdd committed
71 72 73
   *   <foo>
   *     <bar>baz</bar>
   *   </foo>
sun's avatar
sun committed
74 75 76 77
   *   @endcode
   *   A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo'
   *   would return array('bar' => 'baz').
   *   If no key is specified, then the entire data array is returned.
gdd's avatar
gdd committed
78
   *
sun's avatar
sun committed
79 80 81 82
   * The configuration system does not retain data types. Every saved value is
   * casted to a string. In most cases this is not an issue; however, it can
   * cause issues with Booleans, which are casted to "1" (TRUE) or "0" (FALSE).
   * In particular, code relying on === or !== will no longer function properly.
83
   *
84
   * @see http://php.net/manual/language.operators.comparison.php.
85
   *
gdd's avatar
gdd committed
86 87 88 89
   * @return
   *   The data that was requested.
   */
  public function get($key = '') {
90 91 92 93 94 95 96 97 98 99
    global $conf;

    $name = $this->_verifiedStorage->getName();
    if (isset($conf[$name])) {
      $merged_data = drupal_array_merge_deep($this->data, $conf[$name]);
    }
    else {
      $merged_data = $this->data;
    }

gdd's avatar
gdd committed
100
    if (empty($key)) {
101
      return $merged_data;
gdd's avatar
gdd committed
102 103 104 105
    }
    else {
      $parts = explode('.', $key);
      if (count($parts) == 1) {
106
        return isset($merged_data[$key]) ? $merged_data[$key] : NULL;
gdd's avatar
gdd committed
107 108
      }
      else {
109
        $key_exists = NULL;
110
        $value = drupal_array_get_nested_value($merged_data, $parts, $key_exists);
111
        return $key_exists ? $value : NULL;
sun's avatar
sun committed
112
      }
gdd's avatar
gdd committed
113 114 115 116 117 118 119 120 121 122 123 124
    }
  }

  /**
   * Sets value in this config object.
   *
   * @param $key
   *   @todo
   * @param $value
   *   @todo
   */
  public function set($key, $value) {
125 126 127 128 129 130 131
    // Remove all non-alphanumeric characters from the key.
    // @todo Reverse this and throw an exception when encountering a key with
    //   invalid name. The identical validation also needs to happen in get().
    //   Furthermore, the dot/period is a reserved character; it may appear
    //   between keys, but not within keys.
    $key = preg_replace('@[^a-zA-Z0-9_.-]@', '', $key);

132 133 134
    // Type-cast value into a string.
    $value = $this->castValue($value);

gdd's avatar
gdd committed
135 136 137 138 139 140 141
    $parts = explode('.', $key);
    if (count($parts) == 1) {
      $this->data[$key] = $value;
    }
    else {
      drupal_array_set_nested_value($this->data, $parts, $value);
    }
sun's avatar
sun committed
142
    return $this;
gdd's avatar
gdd committed
143 144
  }

gdd's avatar
gdd committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
  /**
   * Casts a saved value to a string.
   *
   * The configuration system only saves strings or arrays. Any scalar
   * non-string value is cast to a string. The one exception is boolean FALSE
   * which would normally become '' when cast to a string, but is manually
   * cast to '0' here for convenience and consistency.
   *
   * Any non-scalar value that is not an array (aka objects) gets cast
   * to an array.
   *
   * @param $value
   *   A value being saved into the configuration system.
   * @param $value
   *   The value cast to a string or array.
   */
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  public function castValue($value) {
    if (is_scalar($value)) {
      // Handle special case of FALSE, which should be '0' instead of ''.
      if ($value === FALSE) {
        $value = '0';
      }
      else {
        $value = (string) $value;
      }
    }
    else {
      // Any non-scalar value must be an array.
      if (!is_array($value)) {
        $value = (array) $value;
      }
      // Recurse into any nested keys.
      foreach ($value as $key => $nested_value) {
        $value[$key] = $this->castValue($nested_value);
      }
    }
    return $value;
  }

gdd's avatar
gdd committed
184 185 186 187
  /**
   * Unsets value in this config object.
   *
   * @param $key
gdd's avatar
gdd committed
188
   *   Name of the key whose value should be unset.
gdd's avatar
gdd committed
189
   */
190
  public function clear($key) {
gdd's avatar
gdd committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    $parts = explode('.', $key);
    if (count($parts) == 1) {
      unset($this->data[$key]);
    }
    else {
      drupal_array_unset_nested_value($this->data, $parts);
    }
  }

  /**
   * Saves the configuration object to disk as XML.
   */
  public function save() {
    $this->_verifiedStorage->write(config_encode($this->data));
  }

  /**
   * Deletes the configuration object on disk.
   */
  public function delete() {
211
    $this->data = array();
gdd's avatar
gdd committed
212 213 214
    $this->_verifiedStorage->delete();
  }
}