3 namespace Drupal\Core\Config;
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Component\Render\MarkupInterface;
7 use Drupal\Core\Cache\Cache;
8 use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
9 use Drupal\Core\Cache\RefinableCacheableDependencyTrait;
10 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
13 * Provides a base class for configuration objects with get/set support.
15 * Encapsulates all capabilities needed for runtime configuration handling for
16 * a specific configuration object.
18 * Extend directly from this class for non-storable configuration where the
19 * configuration API is desired but storage is not possible; for example, if
20 * the data is derived at runtime. For storable configuration, extend
21 * \Drupal\Core\Config\StorableConfigBase.
23 * @see \Drupal\Core\Config\StorableConfigBase
24 * @see \Drupal\Core\Config\Config
25 * @see \Drupal\Core\Theme\ThemeSettings
27 abstract class ConfigBase implements RefinableCacheableDependencyInterface {
28 use DependencySerializationTrait;
29 use RefinableCacheableDependencyTrait;
32 * The name of the configuration object.
39 * The data of the configuration object.
46 * The maximum length of a configuration object name.
48 * Many filesystems (including HFS, NTFS, and ext4) have a maximum file name
49 * length of 255 characters. To ensure that no configuration objects
50 * incompatible with this limitation are created, we enforce a maximum name
51 * length of 250 characters (leaving 5 characters for the file extension).
53 * @see http://wikipedia.org/wiki/Comparison_of_file_systems
55 * Configuration objects not stored on the filesystem should still be
56 * restricted in name length so name can be used as a cache key.
58 const MAX_NAME_LENGTH = 250;
61 * Returns the name of this configuration object.
64 * The name of the configuration object.
66 public function getName() {
71 * Sets the name of this configuration object.
74 * The name of the configuration object.
77 * The configuration object.
79 public function setName($name) {
85 * Validates the configuration object name.
88 * The name of the configuration object.
90 * @throws \Drupal\Core\Config\ConfigNameException
92 * @see Config::MAX_NAME_LENGTH
94 public static function validateName($name) {
95 // The name must be namespaced by owner.
96 if (strpos($name, '.') === FALSE) {
97 throw new ConfigNameException("Missing namespace in Config object name $name.");
99 // The name must be shorter than Config::MAX_NAME_LENGTH characters.
100 if (strlen($name) > self::MAX_NAME_LENGTH) {
101 throw new ConfigNameException("Config object name $name exceeds maximum allowed length of " . static::MAX_NAME_LENGTH . " characters.");
104 // The name must not contain any of the following characters:
106 if (preg_match('/[:?*<>"\'\/\\\\]/', $name)) {
107 throw new ConfigNameException("Invalid character in Config object name $name.");
112 * Gets data from this configuration object.
115 * A string that maps to a key within the configuration data.
116 * For instance in the following configuration array:
124 * A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo'
125 * would return array('bar' => 'baz').
126 * If no key is specified, then the entire data array is returned.
129 * The data that was requested.
131 public function get($key = '') {
136 $parts = explode('.', $key);
137 if (count($parts) == 1) {
138 return isset($this->data[$key]) ? $this->data[$key] : NULL;
141 $value = NestedArray::getValue($this->data, $parts, $key_exists);
142 return $key_exists ? $value : NULL;
148 * Replaces the data of this configuration object.
151 * The new configuration data.
154 * The configuration object.
156 * @throws \Drupal\Core\Config\ConfigValueException
157 * If any key in $data in any depth contains a dot.
159 public function setData(array $data) {
160 $data = $this->castSafeStrings($data);
161 $this->validateKeys($data);
167 * Sets a value in this configuration object.
170 * Identifier to store value in configuration.
171 * @param mixed $value
172 * Value to associate with identifier.
175 * The configuration object.
177 * @throws \Drupal\Core\Config\ConfigValueException
178 * If $value is an array and any of its keys in any depth contains a dot.
180 public function set($key, $value) {
181 $value = $this->castSafeStrings($value);
182 // The dot/period is a reserved character; it may appear between keys, but
184 if (is_array($value)) {
185 $this->validateKeys($value);
187 $parts = explode('.', $key);
188 if (count($parts) == 1) {
189 $this->data[$key] = $value;
192 NestedArray::setValue($this->data, $parts, $value);
198 * Validates all keys in a passed in config array structure.
201 * Configuration array structure.
205 * @throws \Drupal\Core\Config\ConfigValueException
206 * If any key in $data in any depth contains a dot.
208 protected function validateKeys(array $data) {
209 foreach ($data as $key => $value) {
210 if (strpos($key, '.') !== FALSE) {
211 throw new ConfigValueException("$key key contains a dot which is not supported.");
213 if (is_array($value)) {
214 $this->validateKeys($value);
220 * Unsets a value in this configuration object.
223 * Name of the key whose value should be unset.
226 * The configuration object.
228 public function clear($key) {
229 $parts = explode('.', $key);
230 if (count($parts) == 1) {
231 unset($this->data[$key]);
234 NestedArray::unsetValue($this->data, $parts);
240 * Merges data into a configuration object.
242 * @param array $data_to_merge
243 * An array containing data to merge.
246 * The configuration object.
248 public function merge(array $data_to_merge) {
249 // Preserve integer keys so that configuration keys are not changed.
250 $this->setData(NestedArray::mergeDeepArray([$this->data, $data_to_merge], TRUE));
257 public function getCacheContexts() {
258 return $this->cacheContexts;
264 public function getCacheTags() {
265 return Cache::mergeTags(['config:' . $this->name], $this->cacheTags);
271 public function getCacheMaxAge() {
272 return $this->cacheMaxAge;
276 * Casts any objects that implement MarkupInterface to string.
279 * The configuration data.
282 * The data with any safe strings cast to string.
284 protected function castSafeStrings($data) {
285 if ($data instanceof MarkupInterface) {
286 $data = (string) $data;
288 elseif (is_array($data)) {
289 array_walk_recursive($data, function (&$value) {
290 if ($value instanceof MarkupInterface) {
291 $value = (string) $value;