2257ef615ca88a3bfbf98da08bb30b1cb6f6e3e3
[yaffs-website] / vendor / consolidation / config / src / Util / ConfigOverlay.php
1 <?php
2 namespace Consolidation\Config\Util;
3
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;
9
10 /**
11  * Overlay different configuration objects that implement ConfigInterface
12  * to make a priority-based, merged configuration object.
13  *
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.
17  */
18 class ConfigOverlay implements ConfigInterface, ConfigInterpolatorInterface
19 {
20     use ConfigInterpolatorTrait;
21     protected $contexts = [];
22
23     const DEFAULT_CONTEXT = 'default';
24     const PROCESS_CONTEXT = 'process';
25
26     public function __construct()
27     {
28         $this->contexts[self::DEFAULT_CONTEXT] = new Config();
29         $this->contexts[self::PROCESS_CONTEXT] = new Config();
30     }
31
32     /**
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
36      * highest priority.
37      *
38      * If a context has already been added, its priority will not change.
39      */
40     public function addContext($name, ConfigInterface $config)
41     {
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;
46
47         return $this;
48     }
49
50     /**
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().
55      *
56      * @param string $name
57      * @return $this
58      */
59     public function addPlaceholder($name)
60     {
61         return $this->addContext($name, new Config());
62     }
63
64     /**
65      * Increase the priority of the named context such that it is higher
66      * in priority than any existing context except for the 'process'
67      * context.
68      *
69      * @param string $name
70      * @return $this
71      */
72     public function increasePriority($name)
73     {
74         $config = $this->getContext($name);
75         unset($this->contexts[$name]);
76         return $this->addContext($name, $config);
77     }
78
79     public function hasContext($name)
80     {
81         return isset($this->contexts[$name]);
82     }
83
84     public function getContext($name)
85     {
86         if ($this->hasContext($name)) {
87             return $this->contexts[$name];
88         }
89         return new Config();
90     }
91
92     public function removeContext($name)
93     {
94         unset($this->contexts[$name]);
95     }
96
97     /**
98      * Determine if a non-default config value exists.
99      */
100     public function findContext($key)
101     {
102         foreach (array_reverse($this->contexts) as $name => $config) {
103             if ($config->has($key)) {
104                 return $config;
105             }
106         }
107         return false;
108     }
109
110     /**
111      * @inheritdoc
112      */
113     public function has($key)
114     {
115         return $this->findContext($key) != false;
116     }
117
118     /**
119      * @inheritdoc
120      */
121     public function get($key, $default = null)
122     {
123         if (is_array($default)) {
124             return $this->getUnion($key);
125         }
126         return $this->getSingle($key, $default);
127     }
128
129     public function getSingle($key, $default = null)
130     {
131         $context = $this->findContext($key);
132         if ($context) {
133             return $context->get($key, $default);
134         }
135         return $default;
136     }
137
138     public function getUnion($key)
139     {
140         $result = [];
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);
145             }
146         }
147         return $result;
148     }
149
150     /**
151      * @inheritdoc
152      */
153     public function set($key, $value)
154     {
155         $this->contexts[self::PROCESS_CONTEXT]->set($key, $value);
156         return $this;
157     }
158
159     /**
160      * @inheritdoc
161      */
162     public function import($data)
163     {
164         $this->unsupported(__FUNCTION__);
165     }
166
167     /**
168      * @inheritdoc
169      */
170     public function replace($data)
171     {
172         $this->unsupported(__FUNCTION__);
173     }
174
175     /**
176      * @inheritdoc
177      */
178     public function combine($data)
179     {
180         $this->unsupported(__FUNCTION__);
181     }
182
183     /**
184      * @inheritdoc
185      */
186     protected function unsupported($fn)
187     {
188         throw new \Exception("The method '$fn' is not supported for the ConfigOverlay class.");
189     }
190
191     /**
192      * @inheritdoc
193      */
194     public function export()
195     {
196         $export = [];
197         foreach ($this->contexts as $name => $config) {
198             $exportToMerge = $config->export();
199             $export = \array_replace_recursive($export, $exportToMerge);
200         }
201         return $export;
202     }
203
204     /**
205      * @inheritdoc
206      */
207     public function hasDefault($key)
208     {
209         return $this->contexts[self::DEFAULT_CONTEXT]->has($key);
210     }
211
212     /**
213      * @inheritdoc
214      */
215     public function getDefault($key, $default = null)
216     {
217         return $this->contexts[self::DEFAULT_CONTEXT]->get($key, $default);
218     }
219
220     /**
221      * @inheritdoc
222      */
223     public function setDefault($key, $value)
224     {
225         $this->contexts[self::DEFAULT_CONTEXT]->set($key, $value);
226         return $this;
227     }
228 }