Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\DependencyInjection;
|
Chris@0
|
13
|
Chris@0
|
14 use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
|
Chris@0
|
15 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
Chris@14
|
16 use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
|
Chris@17
|
17 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
Chris@0
|
18 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
Chris@0
|
19 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
Chris@0
|
20 use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
Chris@17
|
21 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
Chris@0
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * Container is a dependency injection container.
|
Chris@0
|
25 *
|
Chris@0
|
26 * It gives access to object instances (services).
|
Chris@0
|
27 * Services and parameters are simple key/pair stores.
|
Chris@14
|
28 * The container can have four possible behaviors when a service
|
Chris@14
|
29 * does not exist (or is not initialized for the last case):
|
Chris@0
|
30 *
|
Chris@0
|
31 * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
|
Chris@0
|
32 * * NULL_ON_INVALID_REFERENCE: Returns null
|
Chris@0
|
33 * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference
|
Chris@0
|
34 * (for instance, ignore a setter if the service does not exist)
|
Chris@14
|
35 * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references
|
Chris@0
|
36 *
|
Chris@0
|
37 * @author Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
38 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
Chris@0
|
39 */
|
Chris@0
|
40 class Container implements ResettableContainerInterface
|
Chris@0
|
41 {
|
Chris@0
|
42 protected $parameterBag;
|
Chris@17
|
43 protected $services = [];
|
Chris@17
|
44 protected $fileMap = [];
|
Chris@17
|
45 protected $methodMap = [];
|
Chris@17
|
46 protected $aliases = [];
|
Chris@17
|
47 protected $loading = [];
|
Chris@17
|
48 protected $resolving = [];
|
Chris@17
|
49 protected $syntheticIds = [];
|
Chris@0
|
50
|
Chris@12
|
51 /**
|
Chris@12
|
52 * @internal
|
Chris@12
|
53 */
|
Chris@17
|
54 protected $privates = [];
|
Chris@12
|
55
|
Chris@14
|
56 /**
|
Chris@14
|
57 * @internal
|
Chris@14
|
58 */
|
Chris@17
|
59 protected $normalizedIds = [];
|
Chris@14
|
60
|
Chris@17
|
61 private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_'];
|
Chris@17
|
62 private $envCache = [];
|
Chris@14
|
63 private $compiled = false;
|
Chris@14
|
64 private $getEnv;
|
Chris@0
|
65
|
Chris@0
|
66 public function __construct(ParameterBagInterface $parameterBag = null)
|
Chris@0
|
67 {
|
Chris@0
|
68 $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag();
|
Chris@0
|
69 }
|
Chris@0
|
70
|
Chris@0
|
71 /**
|
Chris@0
|
72 * Compiles the container.
|
Chris@0
|
73 *
|
Chris@0
|
74 * This method does two things:
|
Chris@0
|
75 *
|
Chris@0
|
76 * * Parameter values are resolved;
|
Chris@0
|
77 * * The parameter bag is frozen.
|
Chris@0
|
78 */
|
Chris@0
|
79 public function compile()
|
Chris@0
|
80 {
|
Chris@0
|
81 $this->parameterBag->resolve();
|
Chris@0
|
82
|
Chris@0
|
83 $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
|
Chris@14
|
84
|
Chris@14
|
85 $this->compiled = true;
|
Chris@14
|
86 }
|
Chris@14
|
87
|
Chris@14
|
88 /**
|
Chris@14
|
89 * Returns true if the container is compiled.
|
Chris@14
|
90 *
|
Chris@14
|
91 * @return bool
|
Chris@14
|
92 */
|
Chris@14
|
93 public function isCompiled()
|
Chris@14
|
94 {
|
Chris@14
|
95 return $this->compiled;
|
Chris@0
|
96 }
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * Returns true if the container parameter bag are frozen.
|
Chris@0
|
100 *
|
Chris@14
|
101 * @deprecated since version 3.3, to be removed in 4.0.
|
Chris@14
|
102 *
|
Chris@0
|
103 * @return bool true if the container parameter bag are frozen, false otherwise
|
Chris@0
|
104 */
|
Chris@0
|
105 public function isFrozen()
|
Chris@0
|
106 {
|
Chris@14
|
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);
|
Chris@14
|
108
|
Chris@0
|
109 return $this->parameterBag instanceof FrozenParameterBag;
|
Chris@0
|
110 }
|
Chris@0
|
111
|
Chris@0
|
112 /**
|
Chris@0
|
113 * Gets the service container parameter bag.
|
Chris@0
|
114 *
|
Chris@0
|
115 * @return ParameterBagInterface A ParameterBagInterface instance
|
Chris@0
|
116 */
|
Chris@0
|
117 public function getParameterBag()
|
Chris@0
|
118 {
|
Chris@0
|
119 return $this->parameterBag;
|
Chris@0
|
120 }
|
Chris@0
|
121
|
Chris@0
|
122 /**
|
Chris@0
|
123 * Gets a parameter.
|
Chris@0
|
124 *
|
Chris@0
|
125 * @param string $name The parameter name
|
Chris@0
|
126 *
|
Chris@0
|
127 * @return mixed The parameter value
|
Chris@0
|
128 *
|
Chris@0
|
129 * @throws InvalidArgumentException if the parameter is not defined
|
Chris@0
|
130 */
|
Chris@0
|
131 public function getParameter($name)
|
Chris@0
|
132 {
|
Chris@0
|
133 return $this->parameterBag->get($name);
|
Chris@0
|
134 }
|
Chris@0
|
135
|
Chris@0
|
136 /**
|
Chris@0
|
137 * Checks if a parameter exists.
|
Chris@0
|
138 *
|
Chris@0
|
139 * @param string $name The parameter name
|
Chris@0
|
140 *
|
Chris@0
|
141 * @return bool The presence of parameter in container
|
Chris@0
|
142 */
|
Chris@0
|
143 public function hasParameter($name)
|
Chris@0
|
144 {
|
Chris@0
|
145 return $this->parameterBag->has($name);
|
Chris@0
|
146 }
|
Chris@0
|
147
|
Chris@0
|
148 /**
|
Chris@0
|
149 * Sets a parameter.
|
Chris@0
|
150 *
|
Chris@0
|
151 * @param string $name The parameter name
|
Chris@0
|
152 * @param mixed $value The parameter value
|
Chris@0
|
153 */
|
Chris@0
|
154 public function setParameter($name, $value)
|
Chris@0
|
155 {
|
Chris@0
|
156 $this->parameterBag->set($name, $value);
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 /**
|
Chris@0
|
160 * Sets a service.
|
Chris@0
|
161 *
|
Chris@18
|
162 * Setting a synthetic service to null resets it: has() returns false and get()
|
Chris@0
|
163 * behaves in the same way as if the service was never created.
|
Chris@0
|
164 *
|
Chris@0
|
165 * @param string $id The service identifier
|
Chris@0
|
166 * @param object $service The service instance
|
Chris@0
|
167 */
|
Chris@0
|
168 public function set($id, $service)
|
Chris@0
|
169 {
|
Chris@14
|
170 // Runs the internal initializer; used by the dumped container to include always-needed files
|
Chris@14
|
171 if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) {
|
Chris@14
|
172 $initialize = $this->privates['service_container'];
|
Chris@14
|
173 unset($this->privates['service_container']);
|
Chris@14
|
174 $initialize();
|
Chris@14
|
175 }
|
Chris@14
|
176
|
Chris@14
|
177 $id = $this->normalizeId($id);
|
Chris@0
|
178
|
Chris@0
|
179 if ('service_container' === $id) {
|
Chris@0
|
180 throw new InvalidArgumentException('You cannot set service "service_container".');
|
Chris@0
|
181 }
|
Chris@0
|
182
|
Chris@14
|
183 if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
|
Chris@14
|
184 if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) {
|
Chris@14
|
185 // no-op
|
Chris@14
|
186 } elseif (null === $service) {
|
Chris@14
|
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);
|
Chris@14
|
188 unset($this->privates[$id]);
|
Chris@14
|
189 } else {
|
Chris@14
|
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);
|
Chris@14
|
191 }
|
Chris@14
|
192 } elseif (isset($this->services[$id])) {
|
Chris@14
|
193 if (null === $service) {
|
Chris@14
|
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);
|
Chris@14
|
195 } else {
|
Chris@14
|
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);
|
Chris@14
|
197 }
|
Chris@14
|
198 }
|
Chris@14
|
199
|
Chris@0
|
200 if (isset($this->aliases[$id])) {
|
Chris@0
|
201 unset($this->aliases[$id]);
|
Chris@0
|
202 }
|
Chris@0
|
203
|
Chris@0
|
204 if (null === $service) {
|
Chris@0
|
205 unset($this->services[$id]);
|
Chris@14
|
206
|
Chris@14
|
207 return;
|
Chris@0
|
208 }
|
Chris@0
|
209
|
Chris@14
|
210 $this->services[$id] = $service;
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 /**
|
Chris@0
|
214 * Returns true if the given service is defined.
|
Chris@0
|
215 *
|
Chris@0
|
216 * @param string $id The service identifier
|
Chris@0
|
217 *
|
Chris@0
|
218 * @return bool true if the service is defined, false otherwise
|
Chris@0
|
219 */
|
Chris@0
|
220 public function has($id)
|
Chris@0
|
221 {
|
Chris@0
|
222 for ($i = 2;;) {
|
Chris@12
|
223 if (isset($this->privates[$id])) {
|
Chris@14
|
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);
|
Chris@12
|
225 }
|
Chris@14
|
226 if (isset($this->aliases[$id])) {
|
Chris@14
|
227 $id = $this->aliases[$id];
|
Chris@14
|
228 }
|
Chris@14
|
229 if (isset($this->services[$id])) {
|
Chris@14
|
230 return true;
|
Chris@14
|
231 }
|
Chris@14
|
232 if ('service_container' === $id) {
|
Chris@0
|
233 return true;
|
Chris@0
|
234 }
|
Chris@0
|
235
|
Chris@14
|
236 if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
|
Chris@0
|
237 return true;
|
Chris@0
|
238 }
|
Chris@0
|
239
|
Chris@14
|
240 if (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
|
Chris@14
|
241 $id = $normalizedId;
|
Chris@0
|
242 continue;
|
Chris@0
|
243 }
|
Chris@0
|
244
|
Chris@0
|
245 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
|
Chris@0
|
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)
|
Chris@0
|
247 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) {
|
Chris@14
|
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);
|
Chris@0
|
249
|
Chris@0
|
250 return true;
|
Chris@0
|
251 }
|
Chris@0
|
252
|
Chris@0
|
253 return false;
|
Chris@0
|
254 }
|
Chris@0
|
255 }
|
Chris@0
|
256
|
Chris@0
|
257 /**
|
Chris@0
|
258 * Gets a service.
|
Chris@0
|
259 *
|
Chris@0
|
260 * If a service is defined both through a set() method and
|
Chris@0
|
261 * with a get{$id}Service() method, the former has always precedence.
|
Chris@0
|
262 *
|
Chris@0
|
263 * @param string $id The service identifier
|
Chris@0
|
264 * @param int $invalidBehavior The behavior when the service does not exist
|
Chris@0
|
265 *
|
Chris@0
|
266 * @return object The associated service
|
Chris@0
|
267 *
|
Chris@0
|
268 * @throws ServiceCircularReferenceException When a circular reference is detected
|
Chris@0
|
269 * @throws ServiceNotFoundException When the service is not defined
|
Chris@0
|
270 * @throws \Exception if an exception has been thrown when the service has been resolved
|
Chris@0
|
271 *
|
Chris@0
|
272 * @see Reference
|
Chris@0
|
273 */
|
Chris@14
|
274 public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
|
Chris@0
|
275 {
|
Chris@0
|
276 // Attempt to retrieve the service by checking first aliases then
|
Chris@0
|
277 // available services. Service IDs are case insensitive, however since
|
Chris@0
|
278 // this method can be called thousands of times during a request, avoid
|
Chris@14
|
279 // calling $this->normalizeId($id) unless necessary.
|
Chris@0
|
280 for ($i = 2;;) {
|
Chris@12
|
281 if (isset($this->privates[$id])) {
|
Chris@14
|
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);
|
Chris@0
|
283 }
|
Chris@0
|
284 if (isset($this->aliases[$id])) {
|
Chris@0
|
285 $id = $this->aliases[$id];
|
Chris@0
|
286 }
|
Chris@12
|
287
|
Chris@0
|
288 // Re-use shared service instance if it exists.
|
Chris@0
|
289 if (isset($this->services[$id])) {
|
Chris@0
|
290 return $this->services[$id];
|
Chris@0
|
291 }
|
Chris@12
|
292 if ('service_container' === $id) {
|
Chris@12
|
293 return $this;
|
Chris@12
|
294 }
|
Chris@0
|
295
|
Chris@0
|
296 if (isset($this->loading[$id])) {
|
Chris@17
|
297 throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id]));
|
Chris@0
|
298 }
|
Chris@0
|
299
|
Chris@0
|
300 $this->loading[$id] = true;
|
Chris@0
|
301
|
Chris@0
|
302 try {
|
Chris@14
|
303 if (isset($this->fileMap[$id])) {
|
Chris@14
|
304 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
|
Chris@14
|
305 } elseif (isset($this->methodMap[$id])) {
|
Chris@14
|
306 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
|
Chris@14
|
307 } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
|
Chris@14
|
308 unset($this->loading[$id]);
|
Chris@14
|
309 $id = $normalizedId;
|
Chris@14
|
310 continue;
|
Chris@14
|
311 } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
|
Chris@14
|
312 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
|
Chris@14
|
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)
|
Chris@14
|
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);
|
Chris@14
|
315
|
Chris@14
|
316 return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$method}();
|
Chris@14
|
317 }
|
Chris@14
|
318
|
Chris@14
|
319 break;
|
Chris@0
|
320 } catch (\Exception $e) {
|
Chris@0
|
321 unset($this->services[$id]);
|
Chris@0
|
322
|
Chris@0
|
323 throw $e;
|
Chris@0
|
324 } finally {
|
Chris@0
|
325 unset($this->loading[$id]);
|
Chris@0
|
326 }
|
Chris@14
|
327 }
|
Chris@0
|
328
|
Chris@14
|
329 if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) {
|
Chris@14
|
330 if (!$id) {
|
Chris@14
|
331 throw new ServiceNotFoundException($id);
|
Chris@14
|
332 }
|
Chris@14
|
333 if (isset($this->syntheticIds[$id])) {
|
Chris@17
|
334 throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id));
|
Chris@14
|
335 }
|
Chris@14
|
336 if (isset($this->getRemovedIds()[$id])) {
|
Chris@17
|
337 throw new ServiceNotFoundException($id, null, null, [], 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));
|
Chris@14
|
338 }
|
Chris@14
|
339
|
Chris@17
|
340 $alternatives = [];
|
Chris@14
|
341 foreach ($this->getServiceIds() as $knownId) {
|
Chris@14
|
342 $lev = levenshtein($id, $knownId);
|
Chris@17
|
343 if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) {
|
Chris@14
|
344 $alternatives[] = $knownId;
|
Chris@14
|
345 }
|
Chris@14
|
346 }
|
Chris@14
|
347
|
Chris@14
|
348 throw new ServiceNotFoundException($id, null, null, $alternatives);
|
Chris@0
|
349 }
|
Chris@0
|
350 }
|
Chris@0
|
351
|
Chris@0
|
352 /**
|
Chris@0
|
353 * Returns true if the given service has actually been initialized.
|
Chris@0
|
354 *
|
Chris@0
|
355 * @param string $id The service identifier
|
Chris@0
|
356 *
|
Chris@0
|
357 * @return bool true if service has already been initialized, false otherwise
|
Chris@0
|
358 */
|
Chris@0
|
359 public function initialized($id)
|
Chris@0
|
360 {
|
Chris@14
|
361 $id = $this->normalizeId($id);
|
Chris@14
|
362
|
Chris@14
|
363 if (isset($this->privates[$id])) {
|
Chris@14
|
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);
|
Chris@14
|
365 }
|
Chris@0
|
366
|
Chris@12
|
367 if (isset($this->aliases[$id])) {
|
Chris@12
|
368 $id = $this->aliases[$id];
|
Chris@12
|
369 }
|
Chris@12
|
370
|
Chris@0
|
371 if ('service_container' === $id) {
|
Chris@0
|
372 return false;
|
Chris@0
|
373 }
|
Chris@0
|
374
|
Chris@0
|
375 return isset($this->services[$id]);
|
Chris@0
|
376 }
|
Chris@0
|
377
|
Chris@0
|
378 /**
|
Chris@0
|
379 * {@inheritdoc}
|
Chris@0
|
380 */
|
Chris@0
|
381 public function reset()
|
Chris@0
|
382 {
|
Chris@17
|
383 $this->services = [];
|
Chris@0
|
384 }
|
Chris@0
|
385
|
Chris@0
|
386 /**
|
Chris@0
|
387 * Gets all service ids.
|
Chris@0
|
388 *
|
Chris@0
|
389 * @return array An array of all defined service ids
|
Chris@0
|
390 */
|
Chris@0
|
391 public function getServiceIds()
|
Chris@0
|
392 {
|
Chris@17
|
393 $ids = [];
|
Chris@0
|
394
|
Chris@0
|
395 if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) {
|
Chris@0
|
396 // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
|
Chris@0
|
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)
|
Chris@14
|
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);
|
Chris@0
|
399
|
Chris@0
|
400 foreach (get_class_methods($this) as $method) {
|
Chris@0
|
401 if (preg_match('/^get(.+)Service$/', $method, $match)) {
|
Chris@0
|
402 $ids[] = self::underscore($match[1]);
|
Chris@0
|
403 }
|
Chris@0
|
404 }
|
Chris@0
|
405 }
|
Chris@0
|
406 $ids[] = 'service_container';
|
Chris@0
|
407
|
Chris@14
|
408 return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services)));
|
Chris@14
|
409 }
|
Chris@14
|
410
|
Chris@14
|
411 /**
|
Chris@14
|
412 * Gets service ids that existed at compile time.
|
Chris@14
|
413 *
|
Chris@14
|
414 * @return array
|
Chris@14
|
415 */
|
Chris@14
|
416 public function getRemovedIds()
|
Chris@14
|
417 {
|
Chris@17
|
418 return [];
|
Chris@0
|
419 }
|
Chris@0
|
420
|
Chris@0
|
421 /**
|
Chris@0
|
422 * Camelizes a string.
|
Chris@0
|
423 *
|
Chris@0
|
424 * @param string $id A string to camelize
|
Chris@0
|
425 *
|
Chris@0
|
426 * @return string The camelized string
|
Chris@0
|
427 */
|
Chris@0
|
428 public static function camelize($id)
|
Chris@0
|
429 {
|
Chris@17
|
430 return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']);
|
Chris@0
|
431 }
|
Chris@0
|
432
|
Chris@0
|
433 /**
|
Chris@0
|
434 * A string to underscore.
|
Chris@0
|
435 *
|
Chris@0
|
436 * @param string $id The string to underscore
|
Chris@0
|
437 *
|
Chris@0
|
438 * @return string The underscored string
|
Chris@0
|
439 */
|
Chris@0
|
440 public static function underscore($id)
|
Chris@0
|
441 {
|
Chris@17
|
442 return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], str_replace('_', '.', $id)));
|
Chris@0
|
443 }
|
Chris@0
|
444
|
Chris@0
|
445 /**
|
Chris@14
|
446 * Creates a service by requiring its factory file.
|
Chris@14
|
447 *
|
Chris@14
|
448 * @return object The service created by the file
|
Chris@14
|
449 */
|
Chris@14
|
450 protected function load($file)
|
Chris@14
|
451 {
|
Chris@14
|
452 return require $file;
|
Chris@14
|
453 }
|
Chris@14
|
454
|
Chris@14
|
455 /**
|
Chris@0
|
456 * Fetches a variable from the environment.
|
Chris@0
|
457 *
|
Chris@14
|
458 * @param string $name The name of the environment variable
|
Chris@0
|
459 *
|
Chris@14
|
460 * @return mixed The value to use for the provided environment variable name
|
Chris@0
|
461 *
|
Chris@0
|
462 * @throws EnvNotFoundException When the environment variable is not found and has no default value
|
Chris@0
|
463 */
|
Chris@0
|
464 protected function getEnv($name)
|
Chris@0
|
465 {
|
Chris@14
|
466 if (isset($this->resolving[$envName = "env($name)"])) {
|
Chris@14
|
467 throw new ParameterCircularReferenceException(array_keys($this->resolving));
|
Chris@14
|
468 }
|
Chris@18
|
469 if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) {
|
Chris@0
|
470 return $this->envCache[$name];
|
Chris@0
|
471 }
|
Chris@14
|
472 if (!$this->has($id = 'container.env_var_processors_locator')) {
|
Chris@17
|
473 $this->set($id, new ServiceLocator([]));
|
Chris@0
|
474 }
|
Chris@14
|
475 if (!$this->getEnv) {
|
Chris@14
|
476 $this->getEnv = new \ReflectionMethod($this, __FUNCTION__);
|
Chris@14
|
477 $this->getEnv->setAccessible(true);
|
Chris@14
|
478 $this->getEnv = $this->getEnv->getClosure($this);
|
Chris@0
|
479 }
|
Chris@14
|
480 $processors = $this->get($id);
|
Chris@14
|
481
|
Chris@14
|
482 if (false !== $i = strpos($name, ':')) {
|
Chris@14
|
483 $prefix = substr($name, 0, $i);
|
Chris@14
|
484 $localName = substr($name, 1 + $i);
|
Chris@14
|
485 } else {
|
Chris@14
|
486 $prefix = 'string';
|
Chris@14
|
487 $localName = $name;
|
Chris@14
|
488 }
|
Chris@14
|
489 $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
|
Chris@14
|
490
|
Chris@14
|
491 $this->resolving[$envName] = true;
|
Chris@14
|
492 try {
|
Chris@14
|
493 return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
|
Chris@14
|
494 } finally {
|
Chris@14
|
495 unset($this->resolving[$envName]);
|
Chris@14
|
496 }
|
Chris@14
|
497 }
|
Chris@14
|
498
|
Chris@14
|
499 /**
|
Chris@14
|
500 * Returns the case sensitive id used at registration time.
|
Chris@14
|
501 *
|
Chris@14
|
502 * @param string $id
|
Chris@14
|
503 *
|
Chris@14
|
504 * @return string
|
Chris@14
|
505 *
|
Chris@14
|
506 * @internal
|
Chris@14
|
507 */
|
Chris@14
|
508 public function normalizeId($id)
|
Chris@14
|
509 {
|
Chris@14
|
510 if (!\is_string($id)) {
|
Chris@14
|
511 $id = (string) $id;
|
Chris@14
|
512 }
|
Chris@14
|
513 if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) {
|
Chris@14
|
514 $normalizedId = $this->normalizedIds[$normalizedId];
|
Chris@14
|
515 if ($id !== $normalizedId) {
|
Chris@14
|
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);
|
Chris@14
|
517 }
|
Chris@14
|
518 } else {
|
Chris@14
|
519 $normalizedId = $this->normalizedIds[$normalizedId] = $id;
|
Chris@0
|
520 }
|
Chris@0
|
521
|
Chris@14
|
522 return $normalizedId;
|
Chris@0
|
523 }
|
Chris@0
|
524
|
Chris@0
|
525 private function __clone()
|
Chris@0
|
526 {
|
Chris@0
|
527 }
|
Chris@0
|
528 }
|