Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / DependencyInjection / ContainerBuilder.php
1 <?php
2 // @codingStandardsIgnoreFile
3
4 namespace Drupal\Core\DependencyInjection;
5
6 use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyContainerBuilder;
7 use Symfony\Component\DependencyInjection\Container as SymfonyContainer;
8 use Symfony\Component\DependencyInjection\Definition;
9 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
10 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11
12 /**
13  * Drupal's dependency injection container builder.
14  *
15  * @todo Submit upstream patches to Symfony to not require these overrides.
16  *
17  * @ingroup container
18  */
19 class ContainerBuilder extends SymfonyContainerBuilder {
20
21   /**
22    * @var \Doctrine\Instantiator\InstantiatorInterface|null
23    */
24   private $proxyInstantiator;
25
26   /**
27    * {@inheritdoc}
28    */
29   public function __construct(ParameterBagInterface $parameterBag = NULL) {
30     parent::__construct($parameterBag);
31     $this->setResourceTracking(FALSE);
32   }
33
34   /**
35    * Retrieves the currently set proxy instantiator or instantiates one.
36    *
37    * @return InstantiatorInterface
38    */
39   private function getProxyInstantiator()
40   {
41     if (!$this->proxyInstantiator) {
42       $this->proxyInstantiator = new RealServiceInstantiator();
43     }
44
45     return $this->proxyInstantiator;
46   }
47
48   /**
49    * A 1to1 copy of parent::shareService.
50    *
51    * @todo https://www.drupal.org/project/drupal/issues/2937010 Since Symfony
52    *   3.4 this is not a 1to1 copy.
53    */
54   protected function shareService(Definition $definition, $service, $id, array &$inlineServices)
55   {
56     if ($definition->isShared()) {
57       $this->services[$lowerId = strtolower($id)] = $service;
58     }
59   }
60
61   /**
62    * Overrides Symfony\Component\DependencyInjection\ContainerBuilder::set().
63    *
64    * Drupal's container builder can be used at runtime after compilation, so we
65    * override Symfony's ContainerBuilder's restriction on setting services in a
66    * frozen builder.
67    *
68    * @todo Restrict this to synthetic services only. Ideally, the upstream
69    *   ContainerBuilder class should be fixed to allow setting synthetic
70    *   services in a frozen builder.
71    */
72   public function set($id, $service) {
73     if (strtolower($id) !== $id) {
74       throw new \InvalidArgumentException("Service ID names must be lowercase: $id");
75     }
76     SymfonyContainer::set($id, $service);
77
78     // Ensure that the _serviceId property is set on synthetic services as well.
79     if (isset($this->services[$id]) && is_object($this->services[$id]) && !isset($this->services[$id]->_serviceId)) {
80       $this->services[$id]->_serviceId = $id;
81     }
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public function register($id, $class = null) {
88     if (strtolower($id) !== $id) {
89       throw new \InvalidArgumentException("Service ID names must be lowercase: $id");
90     }
91     return parent::register($id, $class);
92   }
93
94   /**
95    * {@inheritdoc}
96    */
97   public function setAlias($alias, $id) {
98     $alias = parent::setAlias($alias, $id);
99     // As of Symfony 3.4 all aliases are private by default.
100     $alias->setPublic(TRUE);
101     return $alias;
102   }
103
104   /**
105    * {@inheritdoc}
106    */
107   public function setDefinition($id, Definition $definition) {
108     $definition = parent::setDefinition($id, $definition);
109     // As of Symfony 3.4 all definitions are private by default.
110     // \Symfony\Component\DependencyInjection\Compiler\ResolvePrivatesPassOnly
111     // removes services marked as private from the container even if they are
112     // also marked as public. Drupal requires services that are public to
113     // remain in the container and not be removed.
114     if ($definition->isPublic()) {
115       $definition->setPrivate(FALSE);
116     }
117     return $definition;
118   }
119
120   /**
121    * {@inheritdoc}
122    */
123   public function setParameter($name, $value) {
124     if (strtolower($name) !== $name) {
125       throw new \InvalidArgumentException("Parameter names must be lowercase: $name");
126     }
127     parent::setParameter($name, $value);
128   }
129
130   /**
131    * A 1to1 copy of parent::callMethod.
132    *
133    * @todo https://www.drupal.org/project/drupal/issues/2937010 Since Symfony
134    *   3.4 this is not a 1to1 copy.
135    */
136   protected function callMethod($service, $call, array &$inlineServices = array()) {
137     $services = self::getServiceConditionals($call[1]);
138
139     foreach ($services as $s) {
140       if (!$this->has($s)) {
141         return;
142       }
143     }
144
145     call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
146   }
147
148   /**
149    * {@inheritdoc}
150    */
151   public function __sleep() {
152     assert(FALSE, 'The container was serialized.');
153     return array_keys(get_object_vars($this));
154   }
155
156 }