2 namespace Consolidation\Config\Util;
4 use Consolidation\Config\Config;
5 use Consolidation\Config\ConfigInterface;
6 use Consolidation\Config\Util\ArrayUtil;
7 use Consolidation\Config\Util\ConfigInterpolatorInterface;
8 use Consolidation\Config\Util\ConfigInterpolatorTrait;
11 * Overlay different configuration objects that implement ConfigInterface
12 * to make a priority-based, merged configuration object.
14 * Note that using a ConfigOverlay hides the defaults stored in each
15 * individual configuration context. When using overlays, always call
16 * getDefault / setDefault on the ConfigOverlay object itself.
18 class ConfigOverlay implements ConfigInterface, ConfigInterpolatorInterface
20 use ConfigInterpolatorTrait;
21 protected $contexts = [];
23 const DEFAULT_CONTEXT = 'default';
24 const PROCESS_CONTEXT = 'process';
26 public function __construct()
28 $this->contexts[self::DEFAULT_CONTEXT] = new Config();
29 $this->contexts[self::PROCESS_CONTEXT] = new Config();
33 * Add a named configuration object to the configuration overlay.
34 * Configuration objects added LAST have HIGHEST priority, with the
35 * exception of the fact that the process context always has the
38 * If a context has already been added, its priority will not change.
40 public function addContext($name, ConfigInterface $config)
42 $process = $this->contexts[self::PROCESS_CONTEXT];
43 unset($this->contexts[self::PROCESS_CONTEXT]);
44 $this->contexts[$name] = $config;
45 $this->contexts[self::PROCESS_CONTEXT] = $process;
51 * Add a placeholder context that will be prioritized higher than
52 * existing contexts. This is done to ensure that contexts added
53 * later will maintain a higher priority if the placeholder context
54 * is later relaced with a different configuration set via addContext().
59 public function addPlaceholder($name)
61 return $this->addContext($name, new Config());
65 * Increase the priority of the named context such that it is higher
66 * in priority than any existing context except for the 'process'
72 public function increasePriority($name)
74 $config = $this->getContext($name);
75 unset($this->contexts[$name]);
76 return $this->addContext($name, $config);
79 public function hasContext($name)
81 return isset($this->contexts[$name]);
84 public function getContext($name)
86 if ($this->hasContext($name)) {
87 return $this->contexts[$name];
92 public function removeContext($name)
94 unset($this->contexts[$name]);
98 * Determine if a non-default config value exists.
100 public function findContext($key)
102 foreach (array_reverse($this->contexts) as $name => $config) {
103 if ($config->has($key)) {
113 public function has($key)
115 return $this->findContext($key) != false;
121 public function get($key, $default = null)
123 if (is_array($default)) {
124 return $this->getUnion($key);
126 return $this->getSingle($key, $default);
129 public function getSingle($key, $default = null)
131 $context = $this->findContext($key);
133 return $context->get($key, $default);
138 public function getUnion($key)
141 foreach (array_reverse($this->contexts) as $name => $config) {
142 $item = (array) $config->get($key, []);
143 if ($item !== null) {
144 $result = array_merge($result, $item);
153 public function set($key, $value)
155 $this->contexts[self::PROCESS_CONTEXT]->set($key, $value);
162 public function import($data)
164 $this->unsupported(__FUNCTION__);
170 public function replace($data)
172 $this->unsupported(__FUNCTION__);
178 public function combine($data)
180 $this->unsupported(__FUNCTION__);
186 protected function unsupported($fn)
188 throw new \Exception("The method '$fn' is not supported for the ConfigOverlay class.");
194 public function export()
197 foreach ($this->contexts as $name => $config) {
198 $exportToMerge = $config->export();
199 $export = \array_replace_recursive($export, $exportToMerge);
207 public function hasDefault($key)
209 return $this->contexts[self::DEFAULT_CONTEXT]->has($key);
215 public function getDefault($key, $default = null)
217 return $this->contexts[self::DEFAULT_CONTEXT]->get($key, $default);
223 public function setDefault($key, $value)
225 $this->contexts[self::DEFAULT_CONTEXT]->set($key, $value);