Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/dependency-injection/Container.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | 7a779792577d |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
11 | 11 |
12 namespace Symfony\Component\DependencyInjection; | 12 namespace Symfony\Component\DependencyInjection; |
13 | 13 |
14 use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; | 14 use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; |
15 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; | 15 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; |
16 use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; | |
16 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; | 17 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; |
17 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; | 18 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; |
18 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; | 19 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; |
19 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; | 20 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; |
20 use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; | 21 use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; |
21 | 22 |
22 /** | 23 /** |
23 * Container is a dependency injection container. | 24 * Container is a dependency injection container. |
24 * | 25 * |
25 * It gives access to object instances (services). | 26 * It gives access to object instances (services). |
26 * | |
27 * Services and parameters are simple key/pair stores. | 27 * Services and parameters are simple key/pair stores. |
28 * | 28 * The container can have four possible behaviors when a service |
29 * Parameter and service keys are case insensitive. | 29 * does not exist (or is not initialized for the last case): |
30 * | |
31 * A service can also be defined by creating a method named | |
32 * getXXXService(), where XXX is the camelized version of the id: | |
33 * | |
34 * <ul> | |
35 * <li>request -> getRequestService()</li> | |
36 * <li>mysql_session_storage -> getMysqlSessionStorageService()</li> | |
37 * <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li> | |
38 * </ul> | |
39 * | |
40 * The container can have three possible behaviors when a service does not exist: | |
41 * | 30 * |
42 * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) | 31 * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) |
43 * * NULL_ON_INVALID_REFERENCE: Returns null | 32 * * NULL_ON_INVALID_REFERENCE: Returns null |
44 * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference | 33 * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference |
45 * (for instance, ignore a setter if the service does not exist) | 34 * (for instance, ignore a setter if the service does not exist) |
35 * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references | |
46 * | 36 * |
47 * @author Fabien Potencier <fabien@symfony.com> | 37 * @author Fabien Potencier <fabien@symfony.com> |
48 * @author Johannes M. Schmitt <schmittjoh@gmail.com> | 38 * @author Johannes M. Schmitt <schmittjoh@gmail.com> |
49 */ | 39 */ |
50 class Container implements ResettableContainerInterface | 40 class Container implements ResettableContainerInterface |
51 { | 41 { |
52 /** | |
53 * @var ParameterBagInterface | |
54 */ | |
55 protected $parameterBag; | 42 protected $parameterBag; |
56 | |
57 protected $services = array(); | 43 protected $services = array(); |
44 protected $fileMap = array(); | |
58 protected $methodMap = array(); | 45 protected $methodMap = array(); |
59 protected $aliases = array(); | 46 protected $aliases = array(); |
60 protected $loading = array(); | 47 protected $loading = array(); |
48 protected $resolving = array(); | |
49 protected $syntheticIds = array(); | |
61 | 50 |
62 /** | 51 /** |
63 * @internal | 52 * @internal |
64 */ | 53 */ |
65 protected $privates = array(); | 54 protected $privates = array(); |
55 | |
56 /** | |
57 * @internal | |
58 */ | |
59 protected $normalizedIds = array(); | |
66 | 60 |
67 private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); | 61 private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); |
68 private $envCache = array(); | 62 private $envCache = array(); |
69 | 63 private $compiled = false; |
70 /** | 64 private $getEnv; |
71 * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance | 65 |
72 */ | |
73 public function __construct(ParameterBagInterface $parameterBag = null) | 66 public function __construct(ParameterBagInterface $parameterBag = null) |
74 { | 67 { |
75 $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag(); | 68 $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag(); |
76 } | 69 } |
77 | 70 |
86 public function compile() | 79 public function compile() |
87 { | 80 { |
88 $this->parameterBag->resolve(); | 81 $this->parameterBag->resolve(); |
89 | 82 |
90 $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); | 83 $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); |
84 | |
85 $this->compiled = true; | |
86 } | |
87 | |
88 /** | |
89 * Returns true if the container is compiled. | |
90 * | |
91 * @return bool | |
92 */ | |
93 public function isCompiled() | |
94 { | |
95 return $this->compiled; | |
91 } | 96 } |
92 | 97 |
93 /** | 98 /** |
94 * Returns true if the container parameter bag are frozen. | 99 * Returns true if the container parameter bag are frozen. |
95 * | 100 * |
101 * @deprecated since version 3.3, to be removed in 4.0. | |
102 * | |
96 * @return bool true if the container parameter bag are frozen, false otherwise | 103 * @return bool true if the container parameter bag are frozen, false otherwise |
97 */ | 104 */ |
98 public function isFrozen() | 105 public function isFrozen() |
99 { | 106 { |
107 @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); | |
108 | |
100 return $this->parameterBag instanceof FrozenParameterBag; | 109 return $this->parameterBag instanceof FrozenParameterBag; |
101 } | 110 } |
102 | 111 |
103 /** | 112 /** |
104 * Gets the service container parameter bag. | 113 * Gets the service container parameter bag. |
156 * @param string $id The service identifier | 165 * @param string $id The service identifier |
157 * @param object $service The service instance | 166 * @param object $service The service instance |
158 */ | 167 */ |
159 public function set($id, $service) | 168 public function set($id, $service) |
160 { | 169 { |
161 $id = strtolower($id); | 170 // Runs the internal initializer; used by the dumped container to include always-needed files |
171 if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { | |
172 $initialize = $this->privates['service_container']; | |
173 unset($this->privates['service_container']); | |
174 $initialize(); | |
175 } | |
176 | |
177 $id = $this->normalizeId($id); | |
162 | 178 |
163 if ('service_container' === $id) { | 179 if ('service_container' === $id) { |
164 throw new InvalidArgumentException('You cannot set service "service_container".'); | 180 throw new InvalidArgumentException('You cannot set service "service_container".'); |
165 } | 181 } |
166 | 182 |
183 if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { | |
184 if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) { | |
185 // no-op | |
186 } elseif (null === $service) { | |
187 @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); | |
188 unset($this->privates[$id]); | |
189 } else { | |
190 @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); | |
191 } | |
192 } elseif (isset($this->services[$id])) { | |
193 if (null === $service) { | |
194 @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); | |
195 } else { | |
196 @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); | |
197 } | |
198 } | |
199 | |
167 if (isset($this->aliases[$id])) { | 200 if (isset($this->aliases[$id])) { |
168 unset($this->aliases[$id]); | 201 unset($this->aliases[$id]); |
169 } | 202 } |
170 | 203 |
171 $this->services[$id] = $service; | |
172 | |
173 if (null === $service) { | 204 if (null === $service) { |
174 unset($this->services[$id]); | 205 unset($this->services[$id]); |
175 } | 206 |
176 | 207 return; |
177 if (isset($this->privates[$id])) { | 208 } |
178 if (null === $service) { | 209 |
179 @trigger_error(sprintf('Unsetting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); | 210 $this->services[$id] = $service; |
180 unset($this->privates[$id]); | |
181 } else { | |
182 @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0. A new public service will be created instead.', $id), E_USER_DEPRECATED); | |
183 } | |
184 } | |
185 } | 211 } |
186 | 212 |
187 /** | 213 /** |
188 * Returns true if the given service is defined. | 214 * Returns true if the given service is defined. |
189 * | 215 * |
193 */ | 219 */ |
194 public function has($id) | 220 public function has($id) |
195 { | 221 { |
196 for ($i = 2;;) { | 222 for ($i = 2;;) { |
197 if (isset($this->privates[$id])) { | 223 if (isset($this->privates[$id])) { |
198 @trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); | 224 @trigger_error(sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); |
199 } | 225 } |
200 | 226 if (isset($this->aliases[$id])) { |
201 if ('service_container' === $id | 227 $id = $this->aliases[$id]; |
202 || isset($this->aliases[$id]) | 228 } |
203 || isset($this->services[$id]) | 229 if (isset($this->services[$id])) { |
204 ) { | |
205 return true; | 230 return true; |
206 } | 231 } |
207 | 232 if ('service_container' === $id) { |
208 if (isset($this->methodMap[$id])) { | |
209 return true; | 233 return true; |
210 } | 234 } |
211 | 235 |
212 if (--$i && $id !== $lcId = strtolower($id)) { | 236 if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { |
213 $id = $lcId; | 237 return true; |
238 } | |
239 | |
240 if (--$i && $id !== $normalizedId = $this->normalizeId($id)) { | |
241 $id = $normalizedId; | |
214 continue; | 242 continue; |
215 } | 243 } |
216 | 244 |
217 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, | 245 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, |
218 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) | 246 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) |
219 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) { | 247 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) { |
220 @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); | 248 @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); |
221 | 249 |
222 return true; | 250 return true; |
223 } | 251 } |
224 | 252 |
225 return false; | 253 return false; |
241 * @throws ServiceNotFoundException When the service is not defined | 269 * @throws ServiceNotFoundException When the service is not defined |
242 * @throws \Exception if an exception has been thrown when the service has been resolved | 270 * @throws \Exception if an exception has been thrown when the service has been resolved |
243 * | 271 * |
244 * @see Reference | 272 * @see Reference |
245 */ | 273 */ |
246 public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) | 274 public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1) |
247 { | 275 { |
248 // Attempt to retrieve the service by checking first aliases then | 276 // Attempt to retrieve the service by checking first aliases then |
249 // available services. Service IDs are case insensitive, however since | 277 // available services. Service IDs are case insensitive, however since |
250 // this method can be called thousands of times during a request, avoid | 278 // this method can be called thousands of times during a request, avoid |
251 // calling strtolower() unless necessary. | 279 // calling $this->normalizeId($id) unless necessary. |
252 for ($i = 2;;) { | 280 for ($i = 2;;) { |
253 if (isset($this->privates[$id])) { | 281 if (isset($this->privates[$id])) { |
254 @trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); | 282 @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), E_USER_DEPRECATED); |
255 } | 283 } |
256 if (isset($this->aliases[$id])) { | 284 if (isset($this->aliases[$id])) { |
257 $id = $this->aliases[$id]; | 285 $id = $this->aliases[$id]; |
258 } | 286 } |
259 | 287 |
267 | 295 |
268 if (isset($this->loading[$id])) { | 296 if (isset($this->loading[$id])) { |
269 throw new ServiceCircularReferenceException($id, array_keys($this->loading)); | 297 throw new ServiceCircularReferenceException($id, array_keys($this->loading)); |
270 } | 298 } |
271 | 299 |
272 if (isset($this->methodMap[$id])) { | 300 $this->loading[$id] = true; |
273 $method = $this->methodMap[$id]; | 301 |
274 } elseif (--$i && $id !== $lcId = strtolower($id)) { | 302 try { |
275 $id = $lcId; | 303 if (isset($this->fileMap[$id])) { |
276 continue; | 304 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); |
277 } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { | 305 } elseif (isset($this->methodMap[$id])) { |
278 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, | 306 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); |
279 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) | 307 } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { |
280 @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); | 308 unset($this->loading[$id]); |
281 // $method is set to the right value, proceed | 309 $id = $normalizedId; |
282 } else { | 310 continue; |
283 if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { | 311 } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { |
284 if (!$id) { | 312 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, |
285 throw new ServiceNotFoundException($id); | 313 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) |
286 } | 314 @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); |
287 | 315 |
288 $alternatives = array(); | 316 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$method}(); |
289 foreach ($this->getServiceIds() as $knownId) { | |
290 $lev = levenshtein($id, $knownId); | |
291 if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { | |
292 $alternatives[] = $knownId; | |
293 } | |
294 } | |
295 | |
296 throw new ServiceNotFoundException($id, null, null, $alternatives); | |
297 } | 317 } |
298 | 318 |
299 return; | 319 break; |
300 } | |
301 | |
302 $this->loading[$id] = true; | |
303 | |
304 try { | |
305 $service = $this->$method(); | |
306 } catch (\Exception $e) { | 320 } catch (\Exception $e) { |
307 unset($this->services[$id]); | 321 unset($this->services[$id]); |
308 | 322 |
309 throw $e; | 323 throw $e; |
310 } finally { | 324 } finally { |
311 unset($this->loading[$id]); | 325 unset($this->loading[$id]); |
312 } | 326 } |
313 | 327 } |
314 return $service; | 328 |
329 if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) { | |
330 if (!$id) { | |
331 throw new ServiceNotFoundException($id); | |
332 } | |
333 if (isset($this->syntheticIds[$id])) { | |
334 throw new ServiceNotFoundException($id, null, null, array(), sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); | |
335 } | |
336 if (isset($this->getRemovedIds()[$id])) { | |
337 throw new ServiceNotFoundException($id, null, null, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); | |
338 } | |
339 | |
340 $alternatives = array(); | |
341 foreach ($this->getServiceIds() as $knownId) { | |
342 $lev = levenshtein($id, $knownId); | |
343 if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { | |
344 $alternatives[] = $knownId; | |
345 } | |
346 } | |
347 | |
348 throw new ServiceNotFoundException($id, null, null, $alternatives); | |
315 } | 349 } |
316 } | 350 } |
317 | 351 |
318 /** | 352 /** |
319 * Returns true if the given service has actually been initialized. | 353 * Returns true if the given service has actually been initialized. |
322 * | 356 * |
323 * @return bool true if service has already been initialized, false otherwise | 357 * @return bool true if service has already been initialized, false otherwise |
324 */ | 358 */ |
325 public function initialized($id) | 359 public function initialized($id) |
326 { | 360 { |
327 $id = strtolower($id); | 361 $id = $this->normalizeId($id); |
362 | |
363 if (isset($this->privates[$id])) { | |
364 @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); | |
365 } | |
328 | 366 |
329 if (isset($this->aliases[$id])) { | 367 if (isset($this->aliases[$id])) { |
330 $id = $this->aliases[$id]; | 368 $id = $this->aliases[$id]; |
331 } | 369 } |
332 | 370 |
355 $ids = array(); | 393 $ids = array(); |
356 | 394 |
357 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) { | 395 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) { |
358 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, | 396 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, |
359 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) | 397 // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) |
360 @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); | 398 @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); |
361 | 399 |
362 foreach (get_class_methods($this) as $method) { | 400 foreach (get_class_methods($this) as $method) { |
363 if (preg_match('/^get(.+)Service$/', $method, $match)) { | 401 if (preg_match('/^get(.+)Service$/', $method, $match)) { |
364 $ids[] = self::underscore($match[1]); | 402 $ids[] = self::underscore($match[1]); |
365 } | 403 } |
366 } | 404 } |
367 } | 405 } |
368 $ids[] = 'service_container'; | 406 $ids[] = 'service_container'; |
369 | 407 |
370 return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->services))); | 408 return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services))); |
409 } | |
410 | |
411 /** | |
412 * Gets service ids that existed at compile time. | |
413 * | |
414 * @return array | |
415 */ | |
416 public function getRemovedIds() | |
417 { | |
418 return array(); | |
371 } | 419 } |
372 | 420 |
373 /** | 421 /** |
374 * Camelizes a string. | 422 * Camelizes a string. |
375 * | 423 * |
393 { | 441 { |
394 return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id))); | 442 return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id))); |
395 } | 443 } |
396 | 444 |
397 /** | 445 /** |
446 * Creates a service by requiring its factory file. | |
447 * | |
448 * @return object The service created by the file | |
449 */ | |
450 protected function load($file) | |
451 { | |
452 return require $file; | |
453 } | |
454 | |
455 /** | |
398 * Fetches a variable from the environment. | 456 * Fetches a variable from the environment. |
399 * | 457 * |
400 * @param string The name of the environment variable | 458 * @param string $name The name of the environment variable |
401 * | 459 * |
402 * @return scalar The value to use for the provided environment variable name | 460 * @return mixed The value to use for the provided environment variable name |
403 * | 461 * |
404 * @throws EnvNotFoundException When the environment variable is not found and has no default value | 462 * @throws EnvNotFoundException When the environment variable is not found and has no default value |
405 */ | 463 */ |
406 protected function getEnv($name) | 464 protected function getEnv($name) |
407 { | 465 { |
466 if (isset($this->resolving[$envName = "env($name)"])) { | |
467 throw new ParameterCircularReferenceException(array_keys($this->resolving)); | |
468 } | |
408 if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { | 469 if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { |
409 return $this->envCache[$name]; | 470 return $this->envCache[$name]; |
410 } | 471 } |
411 if (isset($_ENV[$name])) { | 472 if (!$this->has($id = 'container.env_var_processors_locator')) { |
412 return $this->envCache[$name] = $_ENV[$name]; | 473 $this->set($id, new ServiceLocator(array())); |
413 } | 474 } |
414 if (false !== $env = getenv($name)) { | 475 if (!$this->getEnv) { |
415 return $this->envCache[$name] = $env; | 476 $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); |
416 } | 477 $this->getEnv->setAccessible(true); |
417 if (!$this->hasParameter("env($name)")) { | 478 $this->getEnv = $this->getEnv->getClosure($this); |
418 throw new EnvNotFoundException($name); | 479 } |
419 } | 480 $processors = $this->get($id); |
420 | 481 |
421 return $this->envCache[$name] = $this->getParameter("env($name)"); | 482 if (false !== $i = strpos($name, ':')) { |
483 $prefix = substr($name, 0, $i); | |
484 $localName = substr($name, 1 + $i); | |
485 } else { | |
486 $prefix = 'string'; | |
487 $localName = $name; | |
488 } | |
489 $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this); | |
490 | |
491 $this->resolving[$envName] = true; | |
492 try { | |
493 return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); | |
494 } finally { | |
495 unset($this->resolving[$envName]); | |
496 } | |
497 } | |
498 | |
499 /** | |
500 * Returns the case sensitive id used at registration time. | |
501 * | |
502 * @param string $id | |
503 * | |
504 * @return string | |
505 * | |
506 * @internal | |
507 */ | |
508 public function normalizeId($id) | |
509 { | |
510 if (!\is_string($id)) { | |
511 $id = (string) $id; | |
512 } | |
513 if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) { | |
514 $normalizedId = $this->normalizedIds[$normalizedId]; | |
515 if ($id !== $normalizedId) { | |
516 @trigger_error(sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), E_USER_DEPRECATED); | |
517 } | |
518 } else { | |
519 $normalizedId = $this->normalizedIds[$normalizedId] = $id; | |
520 } | |
521 | |
522 return $normalizedId; | |
422 } | 523 } |
423 | 524 |
424 private function __clone() | 525 private function __clone() |
425 { | 526 { |
426 } | 527 } |