comparison vendor/symfony/dependency-injection/ContainerBuilder.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents c2387f117808
children af1871eacc83
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
10 */ 10 */
11 11
12 namespace Symfony\Component\DependencyInjection; 12 namespace Symfony\Component\DependencyInjection;
13 13
14 use Psr\Container\ContainerInterface as PsrContainerInterface; 14 use Psr\Container\ContainerInterface as PsrContainerInterface;
15 use Symfony\Component\Config\Resource\ClassExistenceResource;
16 use Symfony\Component\Config\Resource\ComposerResource;
17 use Symfony\Component\Config\Resource\DirectoryResource;
18 use Symfony\Component\Config\Resource\FileExistenceResource;
19 use Symfony\Component\Config\Resource\FileResource;
20 use Symfony\Component\Config\Resource\GlobResource;
21 use Symfony\Component\Config\Resource\ReflectionClassResource;
22 use Symfony\Component\Config\Resource\ResourceInterface;
15 use Symfony\Component\DependencyInjection\Argument\IteratorArgument; 23 use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
16 use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; 24 use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
17 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; 25 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
18 use Symfony\Component\DependencyInjection\Compiler\Compiler; 26 use Symfony\Component\DependencyInjection\Compiler\Compiler;
19 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; 27 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
24 use Symfony\Component\DependencyInjection\Exception\LogicException; 32 use Symfony\Component\DependencyInjection\Exception\LogicException;
25 use Symfony\Component\DependencyInjection\Exception\RuntimeException; 33 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
26 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; 34 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
27 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; 35 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
28 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 36 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
37 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
38 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
29 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; 39 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
30 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; 40 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
31 use Symfony\Component\Config\Resource\ClassExistenceResource;
32 use Symfony\Component\Config\Resource\ComposerResource;
33 use Symfony\Component\Config\Resource\DirectoryResource;
34 use Symfony\Component\Config\Resource\FileExistenceResource;
35 use Symfony\Component\Config\Resource\FileResource;
36 use Symfony\Component\Config\Resource\GlobResource;
37 use Symfony\Component\Config\Resource\ReflectionClassResource;
38 use Symfony\Component\Config\Resource\ResourceInterface;
39 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
40 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
41 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; 41 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
42 use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; 42 use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
43 use Symfony\Component\ExpressionLanguage\Expression; 43 use Symfony\Component\ExpressionLanguage\Expression;
44 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 44 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
45 45
51 class ContainerBuilder extends Container implements TaggedContainerInterface 51 class ContainerBuilder extends Container implements TaggedContainerInterface
52 { 52 {
53 /** 53 /**
54 * @var ExtensionInterface[] 54 * @var ExtensionInterface[]
55 */ 55 */
56 private $extensions = array(); 56 private $extensions = [];
57 57
58 /** 58 /**
59 * @var ExtensionInterface[] 59 * @var ExtensionInterface[]
60 */ 60 */
61 private $extensionsByNs = array(); 61 private $extensionsByNs = [];
62 62
63 /** 63 /**
64 * @var Definition[] 64 * @var Definition[]
65 */ 65 */
66 private $definitions = array(); 66 private $definitions = [];
67 67
68 /** 68 /**
69 * @var Alias[] 69 * @var Alias[]
70 */ 70 */
71 private $aliasDefinitions = array(); 71 private $aliasDefinitions = [];
72 72
73 /** 73 /**
74 * @var ResourceInterface[] 74 * @var ResourceInterface[]
75 */ 75 */
76 private $resources = array(); 76 private $resources = [];
77 77
78 private $extensionConfigs = array(); 78 private $extensionConfigs = [];
79 79
80 /** 80 /**
81 * @var Compiler 81 * @var Compiler
82 */ 82 */
83 private $compiler; 83 private $compiler;
95 private $expressionLanguage; 95 private $expressionLanguage;
96 96
97 /** 97 /**
98 * @var ExpressionFunctionProviderInterface[] 98 * @var ExpressionFunctionProviderInterface[]
99 */ 99 */
100 private $expressionLanguageProviders = array(); 100 private $expressionLanguageProviders = [];
101 101
102 /** 102 /**
103 * @var string[] with tag names used by findTaggedServiceIds 103 * @var string[] with tag names used by findTaggedServiceIds
104 */ 104 */
105 private $usedTags = array(); 105 private $usedTags = [];
106 106
107 /** 107 /**
108 * @var string[][] a map of env var names to their placeholders 108 * @var string[][] a map of env var names to their placeholders
109 */ 109 */
110 private $envPlaceholders = array(); 110 private $envPlaceholders = [];
111 111
112 /** 112 /**
113 * @var int[] a map of env vars to their resolution counter 113 * @var int[] a map of env vars to their resolution counter
114 */ 114 */
115 private $envCounters = array(); 115 private $envCounters = [];
116 116
117 /** 117 /**
118 * @var string[] the list of vendor directories 118 * @var string[] the list of vendor directories
119 */ 119 */
120 private $vendors; 120 private $vendors;
121 121
122 private $autoconfiguredInstanceof = array(); 122 private $autoconfiguredInstanceof = [];
123 123
124 private $removedIds = array(); 124 private $removedIds = [];
125 private $alreadyLoading = array(); 125
126 126 private static $internalTypes = [
127 private static $internalTypes = array(
128 'int' => true, 127 'int' => true,
129 'float' => true, 128 'float' => true,
130 'string' => true, 129 'string' => true,
131 'bool' => true, 130 'bool' => true,
132 'resource' => true, 131 'resource' => true,
134 'array' => true, 133 'array' => true,
135 'null' => true, 134 'null' => true,
136 'callable' => true, 135 'callable' => true,
137 'iterable' => true, 136 'iterable' => true,
138 'mixed' => true, 137 'mixed' => true,
139 ); 138 ];
140 139
141 public function __construct(ParameterBagInterface $parameterBag = null) 140 public function __construct(ParameterBagInterface $parameterBag = null)
142 { 141 {
143 parent::__construct($parameterBag); 142 parent::__construct($parameterBag);
144 143
291 * @return $this 290 * @return $this
292 */ 291 */
293 public function addObjectResource($object) 292 public function addObjectResource($object)
294 { 293 {
295 if ($this->trackResources) { 294 if ($this->trackResources) {
296 if (is_object($object)) { 295 if (\is_object($object)) {
297 $object = get_class($object); 296 $object = \get_class($object);
298 } 297 }
299 if (!isset($this->classReflectors[$object])) { 298 if (!isset($this->classReflectors[$object])) {
300 $this->classReflectors[$object] = new \ReflectionClass($object); 299 $this->classReflectors[$object] = new \ReflectionClass($object);
301 } 300 }
302 $class = $this->classReflectors[$object]; 301 $class = $this->classReflectors[$object];
363 $resource = null; 362 $resource = null;
364 363
365 try { 364 try {
366 if (isset($this->classReflectors[$class])) { 365 if (isset($this->classReflectors[$class])) {
367 $classReflector = $this->classReflectors[$class]; 366 $classReflector = $this->classReflectors[$class];
368 } elseif ($this->trackResources) { 367 } elseif (class_exists(ClassExistenceResource::class)) {
369 $resource = new ClassExistenceResource($class, false); 368 $resource = new ClassExistenceResource($class, false);
370 $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); 369 $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
371 } else { 370 } else {
372 $classReflector = new \ReflectionClass($class); 371 $classReflector = class_exists($class) ? new \ReflectionClass($class) : false;
373 } 372 }
374 } catch (\ReflectionException $e) { 373 } catch (\ReflectionException $e) {
375 if ($throw) { 374 if ($throw) {
376 throw $e; 375 throw $e;
377 } 376 }
419 return $exists; 418 return $exists;
420 } 419 }
421 420
422 if (is_dir($path)) { 421 if (is_dir($path)) {
423 if ($trackContents) { 422 if ($trackContents) {
424 $this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null)); 423 $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null));
425 } else { 424 } else {
426 $this->addResource(new GlobResource($path, '/*', false)); 425 $this->addResource(new GlobResource($path, '/*', false));
427 } 426 }
428 } elseif ($trackContents) { 427 } elseif ($trackContents) {
429 $this->addResource(new FileResource($path)); 428 $this->addResource(new FileResource($path));
447 { 446 {
448 if ($this->isCompiled()) { 447 if ($this->isCompiled()) {
449 throw new BadMethodCallException('Cannot load from an extension on a compiled container.'); 448 throw new BadMethodCallException('Cannot load from an extension on a compiled container.');
450 } 449 }
451 450
452 if (func_num_args() < 2) { 451 if (\func_num_args() < 2) {
453 $values = array(); 452 $values = [];
454 } 453 }
455 454
456 $namespace = $this->getExtension($extension)->getAlias(); 455 $namespace = $this->getExtension($extension)->getAlias();
457 456
458 $this->extensionConfigs[$namespace][] = $values; 457 $this->extensionConfigs[$namespace][] = $values;
469 * 468 *
470 * @return $this 469 * @return $this
471 */ 470 */
472 public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) 471 public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
473 { 472 {
474 if (func_num_args() >= 3) { 473 if (\func_num_args() >= 3) {
475 $priority = func_get_arg(2); 474 $priority = func_get_arg(2);
476 } else { 475 } else {
477 if (__CLASS__ !== get_class($this)) { 476 if (__CLASS__ !== \get_class($this)) {
478 $r = new \ReflectionMethod($this, __FUNCTION__); 477 $r = new \ReflectionMethod($this, __FUNCTION__);
479 if (__CLASS__ !== $r->getDeclaringClass()->getName()) { 478 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
480 @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED); 479 @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
481 } 480 }
482 } 481 }
586 } 585 }
587 586
588 return $this->doGet($id, $invalidBehavior); 587 return $this->doGet($id, $invalidBehavior);
589 } 588 }
590 589
591 private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = array()) 590 private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, $isConstructorArgument = false)
592 { 591 {
593 $id = $this->normalizeId($id); 592 $id = $this->normalizeId($id);
594 593
595 if (isset($inlineServices[$id])) { 594 if (isset($inlineServices[$id])) {
596 return $inlineServices[$id]; 595 return $inlineServices[$id];
597 } 596 }
598 if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { 597 if (null === $inlineServices) {
599 return parent::get($id, $invalidBehavior); 598 $isConstructorArgument = true;
600 } 599 $inlineServices = [];
601 if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { 600 }
602 return $service; 601 try {
602 if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
603 return parent::get($id, $invalidBehavior);
604 }
605 if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
606 return $service;
607 }
608 } catch (ServiceCircularReferenceException $e) {
609 if ($isConstructorArgument) {
610 throw $e;
611 }
603 } 612 }
604 613
605 if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) { 614 if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
606 return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices); 615 return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
607 } 616 }
608 617
609 try { 618 try {
610 $definition = $this->getDefinition($id); 619 $definition = $this->getDefinition($id);
611 } catch (ServiceNotFoundException $e) { 620 } catch (ServiceNotFoundException $e) {
614 } 623 }
615 624
616 throw $e; 625 throw $e;
617 } 626 }
618 627
619 $loading = isset($this->alreadyLoading[$id]) ? 'loading' : 'alreadyLoading'; 628 if ($isConstructorArgument) {
620 $this->{$loading}[$id] = true; 629 $this->loading[$id] = true;
630 }
621 631
622 try { 632 try {
623 $service = $this->createService($definition, $inlineServices, $id); 633 return $this->createService($definition, $inlineServices, $isConstructorArgument, $id);
624 } finally { 634 } finally {
625 unset($this->{$loading}[$id]); 635 if ($isConstructorArgument) {
626 } 636 unset($this->loading[$id]);
627 637 }
628 return $service; 638 }
629 } 639 }
630 640
631 /** 641 /**
632 * Merges a ContainerBuilder with the current ContainerBuilder configuration. 642 * Merges a ContainerBuilder with the current ContainerBuilder configuration.
633 * 643 *
635 * 645 *
636 * But for parameters, they are overridden by the current ones. It allows 646 * But for parameters, they are overridden by the current ones. It allows
637 * the parameters passed to the container constructor to have precedence 647 * the parameters passed to the container constructor to have precedence
638 * over the loaded ones. 648 * over the loaded ones.
639 * 649 *
640 * $container = new ContainerBuilder(array('foo' => 'bar')); 650 * $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar']));
641 * $loader = new LoaderXXX($container); 651 * $loader = new LoaderXXX($container);
642 * $loader->load('resource_name'); 652 * $loader->load('resource_name');
643 * $container->register('foo', new stdClass()); 653 * $container->register('foo', 'stdClass');
644 * 654 *
645 * In the above example, even if the loaded resource defines a foo 655 * In the above example, even if the loaded resource defines a foo
646 * parameter, the value will still be 'bar' as defined in the ContainerBuilder 656 * parameter, the value will still be 'bar' as defined in the ContainerBuilder
647 * constructor. 657 * constructor.
648 * 658 *
664 } 674 }
665 } 675 }
666 676
667 foreach ($this->extensions as $name => $extension) { 677 foreach ($this->extensions as $name => $extension) {
668 if (!isset($this->extensionConfigs[$name])) { 678 if (!isset($this->extensionConfigs[$name])) {
669 $this->extensionConfigs[$name] = array(); 679 $this->extensionConfigs[$name] = [];
670 } 680 }
671 681
672 $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); 682 $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
673 } 683 }
674 684
675 if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) { 685 if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
676 $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders(); 686 $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders();
677 $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag()); 687 $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
678 } else { 688 } else {
679 $envPlaceholders = array(); 689 $envPlaceholders = [];
680 } 690 }
681 691
682 foreach ($container->envCounters as $env => $count) { 692 foreach ($container->envCounters as $env => $count) {
683 if (!$count && !isset($envPlaceholders[$env])) { 693 if (!$count && !isset($envPlaceholders[$env])) {
684 continue; 694 continue;
707 * @return array An array of configuration 717 * @return array An array of configuration
708 */ 718 */
709 public function getExtensionConfig($name) 719 public function getExtensionConfig($name)
710 { 720 {
711 if (!isset($this->extensionConfigs[$name])) { 721 if (!isset($this->extensionConfigs[$name])) {
712 $this->extensionConfigs[$name] = array(); 722 $this->extensionConfigs[$name] = [];
713 } 723 }
714 724
715 return $this->extensionConfigs[$name]; 725 return $this->extensionConfigs[$name];
716 } 726 }
717 727
722 * @param array $config The config to set 732 * @param array $config The config to set
723 */ 733 */
724 public function prependExtensionConfig($name, array $config) 734 public function prependExtensionConfig($name, array $config)
725 { 735 {
726 if (!isset($this->extensionConfigs[$name])) { 736 if (!isset($this->extensionConfigs[$name])) {
727 $this->extensionConfigs[$name] = array(); 737 $this->extensionConfigs[$name] = [];
728 } 738 }
729 739
730 array_unshift($this->extensionConfigs[$name], $config); 740 array_unshift($this->extensionConfigs[$name], $config);
731 } 741 }
732 742
749 * Set to "true" when you want to use the current ContainerBuilder 759 * Set to "true" when you want to use the current ContainerBuilder
750 * directly, keep to "false" when the container is dumped instead. 760 * directly, keep to "false" when the container is dumped instead.
751 */ 761 */
752 public function compile(/*$resolveEnvPlaceholders = false*/) 762 public function compile(/*$resolveEnvPlaceholders = false*/)
753 { 763 {
754 if (1 <= func_num_args()) { 764 if (1 <= \func_num_args()) {
755 $resolveEnvPlaceholders = func_get_arg(0); 765 $resolveEnvPlaceholders = func_get_arg(0);
756 } else { 766 } else {
757 if (__CLASS__ !== static::class) { 767 if (__CLASS__ !== static::class) {
758 $r = new \ReflectionMethod($this, __FUNCTION__); 768 $r = new \ReflectionMethod($this, __FUNCTION__);
759 if (__CLASS__ !== $r->getDeclaringClass()->getName() && (1 > $r->getNumberOfParameters() || 'resolveEnvPlaceholders' !== $r->getParameters()[0]->name)) { 769 if (__CLASS__ !== $r->getDeclaringClass()->getName() && (1 > $r->getNumberOfParameters() || 'resolveEnvPlaceholders' !== $r->getParameters()[0]->name)) {
781 if ($this->trackResources && $definition->isLazy()) { 791 if ($this->trackResources && $definition->isLazy()) {
782 $this->getReflectionClass($definition->getClass()); 792 $this->getReflectionClass($definition->getClass());
783 } 793 }
784 } 794 }
785 795
786 $this->extensionConfigs = array(); 796 $this->extensionConfigs = [];
787 797
788 if ($bag instanceof EnvPlaceholderParameterBag) { 798 if ($bag instanceof EnvPlaceholderParameterBag) {
789 if ($resolveEnvPlaceholders) { 799 if ($resolveEnvPlaceholders) {
790 $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); 800 $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true));
791 } 801 }
835 /** 845 /**
836 * Sets the service aliases. 846 * Sets the service aliases.
837 */ 847 */
838 public function setAliases(array $aliases) 848 public function setAliases(array $aliases)
839 { 849 {
840 $this->aliasDefinitions = array(); 850 $this->aliasDefinitions = [];
841 $this->addAliases($aliases); 851 $this->addAliases($aliases);
842 } 852 }
843 853
844 /** 854 /**
845 * Sets an alias for an existing service. 855 * Sets an alias for an existing service.
854 */ 864 */
855 public function setAlias($alias, $id) 865 public function setAlias($alias, $id)
856 { 866 {
857 $alias = $this->normalizeId($alias); 867 $alias = $this->normalizeId($alias);
858 868
859 if (is_string($id)) { 869 if (\is_string($id)) {
860 $id = new Alias($this->normalizeId($id)); 870 $id = new Alias($this->normalizeId($id));
861 } elseif (!$id instanceof Alias) { 871 } elseif (!$id instanceof Alias) {
862 throw new InvalidArgumentException('$id must be a string, or an Alias object.'); 872 throw new InvalidArgumentException('$id must be a string, or an Alias object.');
863 } 873 }
864 874
947 * 957 *
948 * This method implements a shortcut for using setDefinition() with 958 * This method implements a shortcut for using setDefinition() with
949 * an autowired definition. 959 * an autowired definition.
950 * 960 *
951 * @param string $id The service identifier 961 * @param string $id The service identifier
952 * @param null|string $class The service class 962 * @param string|null $class The service class
953 * 963 *
954 * @return Definition The created definition 964 * @return Definition The created definition
955 */ 965 */
956 public function autowire($id, $class = null) 966 public function autowire($id, $class = null)
957 { 967 {
975 * 985 *
976 * @param Definition[] $definitions An array of service definitions 986 * @param Definition[] $definitions An array of service definitions
977 */ 987 */
978 public function setDefinitions(array $definitions) 988 public function setDefinitions(array $definitions)
979 { 989 {
980 $this->definitions = array(); 990 $this->definitions = [];
981 $this->addDefinitions($definitions); 991 $this->addDefinitions($definitions);
982 } 992 }
983 993
984 /** 994 /**
985 * Gets all service definitions. 995 * Gets all service definitions.
1059 */ 1069 */
1060 public function findDefinition($id) 1070 public function findDefinition($id)
1061 { 1071 {
1062 $id = $this->normalizeId($id); 1072 $id = $this->normalizeId($id);
1063 1073
1064 $seen = array(); 1074 $seen = [];
1065 while (isset($this->aliasDefinitions[$id])) { 1075 while (isset($this->aliasDefinitions[$id])) {
1066 $id = (string) $this->aliasDefinitions[$id]; 1076 $id = (string) $this->aliasDefinitions[$id];
1067 1077
1068 if (isset($seen[$id])) { 1078 if (isset($seen[$id])) {
1069 $seen = array_values($seen); 1079 $seen = array_values($seen);
1070 $seen = array_slice($seen, array_search($id, $seen)); 1080 $seen = \array_slice($seen, array_search($id, $seen));
1071 $seen[] = $id; 1081 $seen[] = $id;
1072 1082
1073 throw new ServiceCircularReferenceException($id, $seen); 1083 throw new ServiceCircularReferenceException($id, $seen);
1074 } 1084 }
1075 1085
1090 * 1100 *
1091 * @throws RuntimeException When the factory definition is incomplete 1101 * @throws RuntimeException When the factory definition is incomplete
1092 * @throws RuntimeException When the service is a synthetic service 1102 * @throws RuntimeException When the service is a synthetic service
1093 * @throws InvalidArgumentException When configure callable is not callable 1103 * @throws InvalidArgumentException When configure callable is not callable
1094 */ 1104 */
1095 private function createService(Definition $definition, array &$inlineServices, $id = null, $tryProxy = true) 1105 private function createService(Definition $definition, array &$inlineServices, $isConstructorArgument = false, $id = null, $tryProxy = true)
1096 { 1106 {
1097 if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) { 1107 if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
1098 return $inlineServices[$h]; 1108 return $inlineServices[$h];
1099 } 1109 }
1100 1110
1108 1118
1109 if ($definition->isDeprecated()) { 1119 if ($definition->isDeprecated()) {
1110 @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED); 1120 @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
1111 } 1121 }
1112 1122
1113 if ($tryProxy && $definition->isLazy()) { 1123 if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) {
1114 $proxy = $this 1124 $proxy = $proxy->instantiateProxy(
1115 ->getProxyInstantiator() 1125 $this,
1116 ->instantiateProxy( 1126 $definition,
1117 $this, 1127 $id, function () use ($definition, &$inlineServices, $id) {
1118 $definition, 1128 return $this->createService($definition, $inlineServices, true, $id, false);
1119 $id, function () use ($definition, &$inlineServices, $id) { 1129 }
1120 return $this->createService($definition, $inlineServices, $id, false); 1130 );
1121 }
1122 );
1123 $this->shareService($definition, $proxy, $id, $inlineServices); 1131 $this->shareService($definition, $proxy, $id, $inlineServices);
1124 1132
1125 return $proxy; 1133 return $proxy;
1126 } 1134 }
1127 1135
1129 1137
1130 if (null !== $definition->getFile()) { 1138 if (null !== $definition->getFile()) {
1131 require_once $parameterBag->resolveValue($definition->getFile()); 1139 require_once $parameterBag->resolveValue($definition->getFile());
1132 } 1140 }
1133 1141
1134 $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices); 1142 $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument);
1143
1144 if (null !== $factory = $definition->getFactory()) {
1145 if (\is_array($factory)) {
1146 $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]];
1147 } elseif (!\is_string($factory)) {
1148 throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
1149 }
1150 }
1135 1151
1136 if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) { 1152 if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
1137 return $this->services[$id]; 1153 return $this->services[$id];
1138 } 1154 }
1139 1155
1140 if (null !== $factory = $definition->getFactory()) { 1156 if (null !== $factory) {
1141 if (is_array($factory)) { 1157 $service = \call_user_func_array($factory, $arguments);
1142 $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices), $factory[1]); 1158
1143 } elseif (!is_string($factory)) { 1159 if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
1144 throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
1145 }
1146
1147 $service = call_user_func_array($factory, $arguments);
1148
1149 if (!$definition->isDeprecated() && is_array($factory) && is_string($factory[0])) {
1150 $r = new \ReflectionClass($factory[0]); 1160 $r = new \ReflectionClass($factory[0]);
1151 1161
1152 if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { 1162 if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
1153 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED); 1163 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED);
1154 } 1164 }
1157 $r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass())); 1167 $r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass()));
1158 1168
1159 $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); 1169 $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
1160 // don't trigger deprecations for internal uses 1170 // don't trigger deprecations for internal uses
1161 // @deprecated since version 3.3, to be removed in 4.0 along with the deprecated class 1171 // @deprecated since version 3.3, to be removed in 4.0 along with the deprecated class
1162 $deprecationWhitelist = array('event_dispatcher' => ContainerAwareEventDispatcher::class); 1172 $deprecationWhitelist = ['event_dispatcher' => ContainerAwareEventDispatcher::class];
1163 1173
1164 if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ") && (!isset($deprecationWhitelist[$id]) || $deprecationWhitelist[$id] !== $class)) { 1174 if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ") && (!isset($deprecationWhitelist[$id]) || $deprecationWhitelist[$id] !== $class)) {
1165 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED); 1175 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED);
1166 } 1176 }
1167 } 1177 }
1179 foreach ($definition->getMethodCalls() as $call) { 1189 foreach ($definition->getMethodCalls() as $call) {
1180 $this->callMethod($service, $call, $inlineServices); 1190 $this->callMethod($service, $call, $inlineServices);
1181 } 1191 }
1182 1192
1183 if ($callable = $definition->getConfigurator()) { 1193 if ($callable = $definition->getConfigurator()) {
1184 if (is_array($callable)) { 1194 if (\is_array($callable)) {
1185 $callable[0] = $parameterBag->resolveValue($callable[0]); 1195 $callable[0] = $parameterBag->resolveValue($callable[0]);
1186 1196
1187 if ($callable[0] instanceof Reference) { 1197 if ($callable[0] instanceof Reference) {
1188 $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices); 1198 $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices);
1189 } elseif ($callable[0] instanceof Definition) { 1199 } elseif ($callable[0] instanceof Definition) {
1190 $callable[0] = $this->createService($callable[0], $inlineServices); 1200 $callable[0] = $this->createService($callable[0], $inlineServices);
1191 } 1201 }
1192 } 1202 }
1193 1203
1194 if (!is_callable($callable)) { 1204 if (!\is_callable($callable)) {
1195 throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); 1205 throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', \get_class($service)));
1196 } 1206 }
1197 1207
1198 call_user_func($callable, $service); 1208 \call_user_func($callable, $service);
1199 } 1209 }
1200 1210
1201 return $service; 1211 return $service;
1202 } 1212 }
1203 1213
1212 public function resolveServices($value) 1222 public function resolveServices($value)
1213 { 1223 {
1214 return $this->doResolveServices($value); 1224 return $this->doResolveServices($value);
1215 } 1225 }
1216 1226
1217 private function doResolveServices($value, array &$inlineServices = array()) 1227 private function doResolveServices($value, array &$inlineServices = [], $isConstructorArgument = false)
1218 { 1228 {
1219 if (is_array($value)) { 1229 if (\is_array($value)) {
1220 foreach ($value as $k => $v) { 1230 foreach ($value as $k => $v) {
1221 $value[$k] = $this->doResolveServices($v, $inlineServices); 1231 $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument);
1222 } 1232 }
1223 } elseif ($value instanceof ServiceClosureArgument) { 1233 } elseif ($value instanceof ServiceClosureArgument) {
1224 $reference = $value->getValues()[0]; 1234 $reference = $value->getValues()[0];
1225 $value = function () use ($reference) { 1235 $value = function () use ($reference) {
1226 return $this->resolveServices($reference); 1236 return $this->resolveServices($reference);
1259 } 1269 }
1260 1270
1261 return $count; 1271 return $count;
1262 }); 1272 });
1263 } elseif ($value instanceof Reference) { 1273 } elseif ($value instanceof Reference) {
1264 $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices); 1274 $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument);
1265 } elseif ($value instanceof Definition) { 1275 } elseif ($value instanceof Definition) {
1266 $value = $this->createService($value, $inlineServices); 1276 $value = $this->createService($value, $inlineServices, $isConstructorArgument);
1267 } elseif ($value instanceof Parameter) { 1277 } elseif ($value instanceof Parameter) {
1268 $value = $this->getParameter((string) $value); 1278 $value = $this->getParameter((string) $value);
1269 } elseif ($value instanceof Expression) { 1279 } elseif ($value instanceof Expression) {
1270 $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); 1280 $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]);
1271 } 1281 }
1272 1282
1273 return $value; 1283 return $value;
1274 } 1284 }
1275 1285
1276 /** 1286 /**
1277 * Returns service ids for a given tag. 1287 * Returns service ids for a given tag.
1278 * 1288 *
1279 * Example: 1289 * Example:
1280 * 1290 *
1281 * $container->register('foo')->addTag('my.tag', array('hello' => 'world')); 1291 * $container->register('foo')->addTag('my.tag', ['hello' => 'world']);
1282 * 1292 *
1283 * $serviceIds = $container->findTaggedServiceIds('my.tag'); 1293 * $serviceIds = $container->findTaggedServiceIds('my.tag');
1284 * foreach ($serviceIds as $serviceId => $tags) { 1294 * foreach ($serviceIds as $serviceId => $tags) {
1285 * foreach ($tags as $tag) { 1295 * foreach ($tags as $tag) {
1286 * echo $tag['hello']; 1296 * echo $tag['hello'];
1297 * }
1287 * } 1298 * }
1288 * }
1289 * 1299 *
1290 * @param string $name 1300 * @param string $name
1291 * @param bool $throwOnAbstract 1301 * @param bool $throwOnAbstract
1292 * 1302 *
1293 * @return array An array of tags with the tagged service as key, holding a list of attribute arrays 1303 * @return array An array of tags with the tagged service as key, holding a list of attribute arrays
1294 */ 1304 */
1295 public function findTaggedServiceIds($name, $throwOnAbstract = false) 1305 public function findTaggedServiceIds($name, $throwOnAbstract = false)
1296 { 1306 {
1297 $this->usedTags[] = $name; 1307 $this->usedTags[] = $name;
1298 $tags = array(); 1308 $tags = [];
1299 foreach ($this->getDefinitions() as $id => $definition) { 1309 foreach ($this->getDefinitions() as $id => $definition) {
1300 if ($definition->hasTag($name)) { 1310 if ($definition->hasTag($name)) {
1301 if ($throwOnAbstract && $definition->isAbstract()) { 1311 if ($throwOnAbstract && $definition->isAbstract()) {
1302 throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name)); 1312 throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name));
1303 } 1313 }
1313 * 1323 *
1314 * @return array An array of tags 1324 * @return array An array of tags
1315 */ 1325 */
1316 public function findTags() 1326 public function findTags()
1317 { 1327 {
1318 $tags = array(); 1328 $tags = [];
1319 foreach ($this->getDefinitions() as $id => $definition) { 1329 foreach ($this->getDefinitions() as $id => $definition) {
1320 $tags = array_merge(array_keys($definition->getTags()), $tags); 1330 $tags = array_merge(array_keys($definition->getTags()), $tags);
1321 } 1331 }
1322 1332
1323 return array_unique($tags); 1333 return array_unique($tags);
1393 if (true === $format) { 1403 if (true === $format) {
1394 $value = $bag->resolveValue($value); 1404 $value = $bag->resolveValue($value);
1395 } 1405 }
1396 1406
1397 if (\is_array($value)) { 1407 if (\is_array($value)) {
1398 $result = array(); 1408 $result = [];
1399 foreach ($value as $k => $v) { 1409 foreach ($value as $k => $v) {
1400 $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs); 1410 $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
1401 } 1411 }
1402 1412
1403 return $result; 1413 return $result;
1419 } 1429 }
1420 if ($placeholder === $value) { 1430 if ($placeholder === $value) {
1421 $value = $resolved; 1431 $value = $resolved;
1422 $completed = true; 1432 $completed = true;
1423 } else { 1433 } else {
1424 if (!is_string($resolved) && !is_numeric($resolved)) { 1434 if (!\is_string($resolved) && !is_numeric($resolved)) {
1425 throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, gettype($resolved), $this->resolveEnvPlaceholders($value))); 1435 throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, \gettype($resolved), $this->resolveEnvPlaceholders($value)));
1426 } 1436 }
1427 $value = str_ireplace($placeholder, $resolved, $value); 1437 $value = str_ireplace($placeholder, $resolved, $value);
1428 } 1438 }
1429 $usedEnvs[$env] = $env; 1439 $usedEnvs[$env] = $env;
1430 $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; 1440 $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1;
1461 /** 1471 /**
1462 * @internal 1472 * @internal
1463 */ 1473 */
1464 public function getNormalizedIds() 1474 public function getNormalizedIds()
1465 { 1475 {
1466 $normalizedIds = array(); 1476 $normalizedIds = [];
1467 1477
1468 foreach ($this->normalizedIds as $k => $v) { 1478 foreach ($this->normalizedIds as $k => $v) {
1469 if ($v !== (string) $k) { 1479 if ($v !== (string) $k) {
1470 $normalizedIds[$k] = $v; 1480 $normalizedIds[$k] = $v;
1471 } 1481 }
1503 * 1513 *
1504 * @internal since version 3.4 1514 * @internal since version 3.4
1505 */ 1515 */
1506 public static function getServiceConditionals($value) 1516 public static function getServiceConditionals($value)
1507 { 1517 {
1508 $services = array(); 1518 $services = [];
1509 1519
1510 if (is_array($value)) { 1520 if (\is_array($value)) {
1511 foreach ($value as $v) { 1521 foreach ($value as $v) {
1512 $services = array_unique(array_merge($services, self::getServiceConditionals($v))); 1522 $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
1513 } 1523 }
1514 } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { 1524 } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
1515 $services[] = (string) $value; 1525 $services[] = (string) $value;
1527 * 1537 *
1528 * @internal 1538 * @internal
1529 */ 1539 */
1530 public static function getInitializedConditionals($value) 1540 public static function getInitializedConditionals($value)
1531 { 1541 {
1532 $services = array(); 1542 $services = [];
1533 1543
1534 if (is_array($value)) { 1544 if (\is_array($value)) {
1535 foreach ($value as $v) { 1545 foreach ($value as $v) {
1536 $services = array_unique(array_merge($services, self::getInitializedConditionals($v))); 1546 $services = array_unique(array_merge($services, self::getInitializedConditionals($v)));
1537 } 1547 }
1538 } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) { 1548 } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) {
1539 $services[] = (string) $value; 1549 $services[] = (string) $value;
1551 */ 1561 */
1552 public static function hash($value) 1562 public static function hash($value)
1553 { 1563 {
1554 $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); 1564 $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7);
1555 1565
1556 return str_replace(array('/', '+'), array('.', '_'), strtolower($hash)); 1566 return str_replace(['/', '+'], ['.', '_'], strtolower($hash));
1557 } 1567 }
1558 1568
1559 /** 1569 /**
1560 * {@inheritdoc} 1570 * {@inheritdoc}
1561 */ 1571 */
1562 protected function getEnv($name) 1572 protected function getEnv($name)
1563 { 1573 {
1564 $value = parent::getEnv($name); 1574 $value = parent::getEnv($name);
1565 $bag = $this->getParameterBag(); 1575 $bag = $this->getParameterBag();
1566 1576
1567 if (!is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) { 1577 if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) {
1568 return $value; 1578 return $value;
1569 } 1579 }
1570 1580
1571 foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { 1581 foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
1572 if (isset($placeholders[$value])) { 1582 if (isset($placeholders[$value])) {
1582 } finally { 1592 } finally {
1583 unset($this->resolving["env($name)"]); 1593 unset($this->resolving["env($name)"]);
1584 } 1594 }
1585 } 1595 }
1586 1596
1587 /**
1588 * Retrieves the currently set proxy instantiator or instantiates one.
1589 *
1590 * @return InstantiatorInterface
1591 */
1592 private function getProxyInstantiator()
1593 {
1594 if (!$this->proxyInstantiator) {
1595 $this->proxyInstantiator = new RealServiceInstantiator();
1596 }
1597
1598 return $this->proxyInstantiator;
1599 }
1600
1601 private function callMethod($service, $call, array &$inlineServices) 1597 private function callMethod($service, $call, array &$inlineServices)
1602 { 1598 {
1603 foreach (self::getServiceConditionals($call[1]) as $s) { 1599 foreach (self::getServiceConditionals($call[1]) as $s) {
1604 if (!$this->has($s)) { 1600 if (!$this->has($s)) {
1605 return; 1601 return;
1609 if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { 1605 if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
1610 return; 1606 return;
1611 } 1607 }
1612 } 1608 }
1613 1609
1614 call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); 1610 \call_user_func_array([$service, $call[0]], $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
1615 } 1611 }
1616 1612
1617 /** 1613 /**
1618 * Shares a given service in the container. 1614 * Shares a given service in the container.
1619 * 1615 *
1625 { 1621 {
1626 $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service; 1622 $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service;
1627 1623
1628 if (null !== $id && $definition->isShared()) { 1624 if (null !== $id && $definition->isShared()) {
1629 $this->services[$id] = $service; 1625 $this->services[$id] = $service;
1630 unset($this->loading[$id], $this->alreadyLoading[$id]); 1626 unset($this->loading[$id]);
1631 } 1627 }
1632 } 1628 }
1633 1629
1634 private function getExpressionLanguage() 1630 private function getExpressionLanguage()
1635 { 1631 {
1651 $this->addResource($resource); 1647 $this->addResource($resource);
1652 } 1648 }
1653 $path = realpath($path) ?: $path; 1649 $path = realpath($path) ?: $path;
1654 1650
1655 foreach ($this->vendors as $vendor) { 1651 foreach ($this->vendors as $vendor) {
1656 if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) { 1652 if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
1657 return true; 1653 return true;
1658 } 1654 }
1659 } 1655 }
1660 1656
1661 return false; 1657 return false;