PluginProbe
Boxzilla – WordPress Popup Builder / 3.0
Boxzilla – WordPress Popup Builder v3.0
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
boxzilla / src / di / class-container.php

class-container.php in Boxzilla – WordPress Popup Builder 3.0, at src/di/class-container.php

282 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of Pimple.
5 *
6 * Copyright (c) 2009 Fabien Potencier
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is furnished
13 * to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in all
16 * copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27 namespace Boxzilla\DI;
28
29 /**
30 * Container main class.
31 *
32 * @author Fabien Potencier
33 */
34 class Container implements \ArrayAccess
35 {
36 private $values = array();
37 private $factories;
38 private $protected;
39 private $frozen = array();
40 private $raw = array();
41 private $keys = array();
42
43 /**
44 * Instantiate the container.
45 *
46 * Objects and parameters can be passed as argument to the constructor.
47 *
48 * @param array $values The parameters or objects.
49 */
50 public function __construct(array $values = array())
51 {
52 $this->factories = new \SplObjectStorage();
53 $this->protected = new \SplObjectStorage();
54
55 foreach ($values as $key => $value) {
56 $this->offsetSet($key, $value);
57 }
58 }
59
60 /**
61 * Sets a parameter or an object.
62 *
63 * Objects must be defined as Closures.
64 *
65 * Allowing any PHP callable leads to difficult to debug problems
66 * as function names (strings) are callable (creating a function with
67 * the same name as an existing parameter would break your container).
68 *
69 * @param string $id The unique identifier for the parameter or object
70 * @param mixed $value The value of the parameter or a closure to define an object
71 * @throws \RuntimeException Prevent override of a frozen service
72 */
73 public function offsetSet($id, $value)
74 {
75 if (isset($this->frozen[$id])) {
76 throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id));
77 }
78
79 $this->values[$id] = $value;
80 $this->keys[$id] = true;
81 }
82
83 /**
84 * Gets a parameter or an object.
85 *
86 * @param string $id The unique identifier for the parameter or object
87 *
88 * @return mixed The value of the parameter or an object
89 *
90 * @throws \InvalidArgumentException if the identifier is not defined
91 */
92 public function offsetGet($id)
93 {
94 if (!isset($this->keys[$id])) {
95 throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
96 }
97
98 if (
99 isset($this->raw[$id])
100 || !is_object($this->values[$id])
101 || isset($this->protected[$this->values[$id]])
102 || !method_exists($this->values[$id], '__invoke')
103 ) {
104 return $this->values[$id];
105 }
106
107 if (isset($this->factories[$this->values[$id]])) {
108 return $this->values[$id]($this);
109 }
110
111 $raw = $this->values[$id];
112 $val = $this->values[$id] = $raw($this);
113 $this->raw[$id] = $raw;
114
115 $this->frozen[$id] = true;
116
117 return $val;
118 }
119
120 /**
121 * Checks if a parameter or an object is set.
122 *
123 * @param string $id The unique identifier for the parameter or object
124 *
125 * @return bool
126 */
127 public function offsetExists($id)
128 {
129 return isset($this->keys[$id]);
130 }
131
132 /**
133 * Unsets a parameter or an object.
134 *
135 * @param string $id The unique identifier for the parameter or object
136 */
137 public function offsetUnset($id)
138 {
139 if (isset($this->keys[$id])) {
140 if (is_object($this->values[$id])) {
141 unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);
142 }
143
144 unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);
145 }
146 }
147
148 /**
149 * Marks a callable as being a factory service.
150 *
151 * @param callable $callable A service definition to be used as a factory
152 *
153 * @return callable The passed callable
154 *
155 * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
156 */
157 public function factory($callable)
158 {
159 if (!is_object($callable) || !method_exists($callable, '__invoke')) {
160 throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.');
161 }
162
163 $this->factories->attach($callable);
164
165 return $callable;
166 }
167
168 /**
169 * Protects a callable from being interpreted as a service.
170 *
171 * This is useful when you want to store a callable as a parameter.
172 *
173 * @param callable $callable A callable to protect from being evaluated
174 *
175 * @return callable The passed callable
176 *
177 * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
178 */
179 public function protect($callable)
180 {
181 if (!is_object($callable) || !method_exists($callable, '__invoke')) {
182 throw new \InvalidArgumentException('Callable is not a Closure or invokable object.');
183 }
184
185 $this->protected->attach($callable);
186
187 return $callable;
188 }
189
190 /**
191 * Gets a parameter or the closure defining an object.
192 *
193 * @param string $id The unique identifier for the parameter or object
194 *
195 * @return mixed The value of the parameter or the closure defining an object
196 *
197 * @throws \InvalidArgumentException if the identifier is not defined
198 */
199 public function raw($id)
200 {
201 if (!isset($this->keys[$id])) {
202 throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
203 }
204
205 if (isset($this->raw[$id])) {
206 return $this->raw[$id];
207 }
208
209 return $this->values[$id];
210 }
211
212 /**
213 * Extends an object definition.
214 *
215 * Useful when you want to extend an existing object definition,
216 * without necessarily loading that object.
217 *
218 * @param string $id The unique identifier for the object
219 * @param callable $callable A service definition to extend the original
220 *
221 * @return callable The wrapped callable
222 *
223 * @throws \InvalidArgumentException if the identifier is not defined or not a service definition
224 */
225 public function extend($id, $callable)
226 {
227 if (!isset($this->keys[$id])) {
228 throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
229 }
230
231 if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) {
232 throw new \InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id));
233 }
234
235 if (!is_object($callable) || !method_exists($callable, '__invoke')) {
236 throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.');
237 }
238
239 $factory = $this->values[$id];
240
241 $extended = function ($c) use ($callable, $factory) {
242 return $callable($factory($c), $c);
243 };
244
245 if (isset($this->factories[$factory])) {
246 $this->factories->detach($factory);
247 $this->factories->attach($extended);
248 }
249
250 return $this[$id] = $extended;
251 }
252
253 /**
254 * Returns all defined value names.
255 *
256 * @return array An array of value names
257 */
258 public function keys()
259 {
260 return array_keys($this->values);
261 }
262
263 /**
264 * Registers a service provider.
265 *
266 * @param ServiceProviderInterface $provider A ServiceProviderInterface instance
267 * @param array $values An array of values that customizes the provider
268 *
269 * @return static
270 */
271 public function register(ServiceProviderInterface $provider, array $values = array())
272 {
273 $provider->register($this);
274
275 foreach ($values as $key => $value) {
276 $this[$key] = $value;
277 }
278
279 return $this;
280 }
281 }
282