Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

ContainerBuilder.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 35.42 KiB


 0001  <?php
 0002   
 0003  /*
 0004   * This file is part of the Symfony package.
 0005   *
 0006   * (c) Fabien Potencier <fabien@symfony.com>
 0007   *
 0008   * For the full copyright and license information, please view the LICENSE
 0009   * file that was distributed with this source code.
 0010   */
 0011   
 0012  namespace Symfony\Component\DependencyInjection;
 0013   
 0014  use Symfony\Component\DependencyInjection\Compiler\Compiler;
 0015  use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 0016  use Symfony\Component\DependencyInjection\Compiler\PassConfig;
 0017  use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
 0018  use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 0019  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 0020  use Symfony\Component\DependencyInjection\Exception\LogicException;
 0021  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 0022  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 0023  use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
 0024  use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
 0025  use Symfony\Component\Config\Resource\FileResource;
 0026  use Symfony\Component\Config\Resource\ResourceInterface;
 0027  use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
 0028  use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
 0029  use Symfony\Component\ExpressionLanguage\Expression;
 0030  use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 0031   
 0032  /**
 0033   * ContainerBuilder is a DI container that provides an API to easily describe services.
 0034   *
 0035   * @author Fabien Potencier <fabien@symfony.com>
 0036   */
 0037  class ContainerBuilder extends Container implements TaggedContainerInterface
 0038  {
 0039      /**
 0040       * @var ExtensionInterface[]
 0041       */
 0042      private $extensions = array();
 0043   
 0044      /**
 0045       * @var ExtensionInterface[]
 0046       */
 0047      private $extensionsByNs = array();
 0048   
 0049      /**
 0050       * @var Definition[]
 0051       */
 0052      private $definitions = array();
 0053   
 0054      /**
 0055       * @var Definition[]
 0056       */
 0057      private $obsoleteDefinitions = array();
 0058   
 0059      /**
 0060       * @var Alias[]
 0061       */
 0062      private $aliasDefinitions = array();
 0063   
 0064      /**
 0065       * @var ResourceInterface[]
 0066       */
 0067      private $resources = array();
 0068   
 0069      private $extensionConfigs = array();
 0070   
 0071      /**
 0072       * @var Compiler
 0073       */
 0074      private $compiler;
 0075   
 0076      private $trackResources = true;
 0077   
 0078      /**
 0079       * @var InstantiatorInterface|null
 0080       */
 0081      private $proxyInstantiator;
 0082   
 0083      /**
 0084       * @var ExpressionLanguage|null
 0085       */
 0086      private $expressionLanguage;
 0087   
 0088      /**
 0089       * @var ExpressionFunctionProviderInterface[]
 0090       */
 0091      private $expressionLanguageProviders = array();
 0092   
 0093      /**
 0094       * @var string[] with tag names used by findTaggedServiceIds
 0095       */
 0096      private $usedTags = array();
 0097   
 0098      /**
 0099       * Sets the track resources flag.
 0100       *
 0101       * If you are not using the loaders and therefore don't want
 0102       * to depend on the Config component, set this flag to false.
 0103       *
 0104       * @param bool $track true if you want to track resources, false otherwise
 0105       */
 0106      public function setResourceTracking($track)
 0107      {
 0108          $this->trackResources = (bool) $track;
 0109      }
 0110   
 0111      /**
 0112       * Checks if resources are tracked.
 0113       *
 0114       * @return bool true if resources are tracked, false otherwise
 0115       */
 0116      public function isTrackingResources()
 0117      {
 0118          return $this->trackResources;
 0119      }
 0120   
 0121      /**
 0122       * Sets the instantiator to be used when fetching proxies.
 0123       *
 0124       * @param InstantiatorInterface $proxyInstantiator
 0125       */
 0126      public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator)
 0127      {
 0128          $this->proxyInstantiator = $proxyInstantiator;
 0129      }
 0130   
 0131      /**
 0132       * Registers an extension.
 0133       *
 0134       * @param ExtensionInterface $extension An extension instance
 0135       */
 0136      public function registerExtension(ExtensionInterface $extension)
 0137      {
 0138          $this->extensions[$extension->getAlias()] = $extension;
 0139   
 0140          if (false !== $extension->getNamespace()) {
 0141              $this->extensionsByNs[$extension->getNamespace()] = $extension;
 0142          }
 0143      }
 0144   
 0145      /**
 0146       * Returns an extension by alias or namespace.
 0147       *
 0148       * @param string $name An alias or a namespace
 0149       *
 0150       * @return ExtensionInterface An extension instance
 0151       *
 0152       * @throws LogicException if the extension is not registered
 0153       */
 0154      public function getExtension($name)
 0155      {
 0156          if (isset($this->extensions[$name])) {
 0157              return $this->extensions[$name];
 0158          }
 0159   
 0160          if (isset($this->extensionsByNs[$name])) {
 0161              return $this->extensionsByNs[$name];
 0162          }
 0163   
 0164          throw new LogicException(sprintf('Container extension "%s" is not registered', $name));
 0165      }
 0166   
 0167      /**
 0168       * Returns all registered extensions.
 0169       *
 0170       * @return ExtensionInterface[] An array of ExtensionInterface
 0171       */
 0172      public function getExtensions()
 0173      {
 0174          return $this->extensions;
 0175      }
 0176   
 0177      /**
 0178       * Checks if we have an extension.
 0179       *
 0180       * @param string $name The name of the extension
 0181       *
 0182       * @return bool If the extension exists
 0183       */
 0184      public function hasExtension($name)
 0185      {
 0186          return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
 0187      }
 0188   
 0189      /**
 0190       * Returns an array of resources loaded to build this configuration.
 0191       *
 0192       * @return ResourceInterface[] An array of resources
 0193       */
 0194      public function getResources()
 0195      {
 0196          return array_unique($this->resources);
 0197      }
 0198   
 0199      /**
 0200       * Adds a resource for this configuration.
 0201       *
 0202       * @param ResourceInterface $resource A resource instance
 0203       *
 0204       * @return ContainerBuilder The current instance
 0205       */
 0206      public function addResource(ResourceInterface $resource)
 0207      {
 0208          if (!$this->trackResources) {
 0209              return $this;
 0210          }
 0211   
 0212          $this->resources[] = $resource;
 0213   
 0214          return $this;
 0215      }
 0216   
 0217      /**
 0218       * Sets the resources for this configuration.
 0219       *
 0220       * @param ResourceInterface[] $resources An array of resources
 0221       *
 0222       * @return ContainerBuilder The current instance
 0223       */
 0224      public function setResources(array $resources)
 0225      {
 0226          if (!$this->trackResources) {
 0227              return $this;
 0228          }
 0229   
 0230          $this->resources = $resources;
 0231   
 0232          return $this;
 0233      }
 0234   
 0235      /**
 0236       * Adds the object class hierarchy as resources.
 0237       *
 0238       * @param object $object An object instance
 0239       *
 0240       * @return ContainerBuilder The current instance
 0241       */
 0242      public function addObjectResource($object)
 0243      {
 0244          if ($this->trackResources) {
 0245              $this->addClassResource(new \ReflectionClass($object));
 0246          }
 0247   
 0248          return $this;
 0249      }
 0250   
 0251      /**
 0252       * Adds the given class hierarchy as resources.
 0253       *
 0254       * @param \ReflectionClass $class
 0255       *
 0256       * @return ContainerBuilder The current instance
 0257       */
 0258      public function addClassResource(\ReflectionClass $class)
 0259      {
 0260          if (!$this->trackResources) {
 0261              return $this;
 0262          }
 0263   
 0264          do {
 0265              if (is_file($class->getFileName())) {
 0266                  $this->addResource(new FileResource($class->getFileName()));
 0267              }
 0268          } while ($class = $class->getParentClass());
 0269   
 0270          return $this;
 0271      }
 0272   
 0273      /**
 0274       * Loads the configuration for an extension.
 0275       *
 0276       * @param string $extension The extension alias or namespace
 0277       * @param array  $values    An array of values that customizes the extension
 0278       *
 0279       * @return ContainerBuilder The current instance
 0280       *
 0281       * @throws BadMethodCallException When this ContainerBuilder is frozen
 0282       * @throws \LogicException        if the container is frozen
 0283       */
 0284      public function loadFromExtension($extension, array $values = array())
 0285      {
 0286          if ($this->isFrozen()) {
 0287              throw new BadMethodCallException('Cannot load from an extension on a frozen container.');
 0288          }
 0289   
 0290          $namespace = $this->getExtension($extension)->getAlias();
 0291   
 0292          $this->extensionConfigs[$namespace][] = $values;
 0293   
 0294          return $this;
 0295      }
 0296   
 0297      /**
 0298       * Adds a compiler pass.
 0299       *
 0300       * @param CompilerPassInterface $pass A compiler pass
 0301       * @param string                $type The type of compiler pass
 0302       *
 0303       * @return ContainerBuilder The current instance
 0304       */
 0305      public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
 0306      {
 0307          $this->getCompiler()->addPass($pass, $type);
 0308   
 0309          $this->addObjectResource($pass);
 0310   
 0311          return $this;
 0312      }
 0313   
 0314      /**
 0315       * Returns the compiler pass config which can then be modified.
 0316       *
 0317       * @return PassConfig The compiler pass config
 0318       */
 0319      public function getCompilerPassConfig()
 0320      {
 0321          return $this->getCompiler()->getPassConfig();
 0322      }
 0323   
 0324      /**
 0325       * Returns the compiler.
 0326       *
 0327       * @return Compiler The compiler
 0328       */
 0329      public function getCompiler()
 0330      {
 0331          if (null === $this->compiler) {
 0332              $this->compiler = new Compiler();
 0333          }
 0334   
 0335          return $this->compiler;
 0336      }
 0337   
 0338      /**
 0339       * Returns all Scopes.
 0340       *
 0341       * @return array An array of scopes
 0342       *
 0343       * @deprecated since version 2.8, to be removed in 3.0.
 0344       */
 0345      public function getScopes($triggerDeprecationError = true)
 0346      {
 0347          if ($triggerDeprecationError) {
 0348              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
 0349          }
 0350   
 0351          return $this->scopes;
 0352      }
 0353   
 0354      /**
 0355       * Returns all Scope children.
 0356       *
 0357       * @return array An array of scope children
 0358       *
 0359       * @deprecated since version 2.8, to be removed in 3.0.
 0360       */
 0361      public function getScopeChildren($triggerDeprecationError = true)
 0362      {
 0363          if ($triggerDeprecationError) {
 0364              @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
 0365          }
 0366   
 0367          return $this->scopeChildren;
 0368      }
 0369   
 0370      /**
 0371       * Sets a service.
 0372       *
 0373       * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0.
 0374       *
 0375       * @param string $id      The service identifier
 0376       * @param object $service The service instance
 0377       * @param string $scope   The scope
 0378       *
 0379       * @throws BadMethodCallException When this ContainerBuilder is frozen
 0380       */
 0381      public function set($id, $service, $scope = self::SCOPE_CONTAINER)
 0382      {
 0383          $id = strtolower($id);
 0384          $set = isset($this->definitions[$id]);
 0385   
 0386          if ($this->isFrozen() && ($set || isset($this->obsoleteDefinitions[$id])) && !$this->{$set ? 'definitions' : 'obsoleteDefinitions'}[$id]->isSynthetic()) {
 0387              // setting a synthetic service on a frozen container is alright
 0388              throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
 0389          }
 0390   
 0391          if ($set) {
 0392              $this->obsoleteDefinitions[$id] = $this->definitions[$id];
 0393          }
 0394   
 0395          unset($this->definitions[$id], $this->aliasDefinitions[$id]);
 0396   
 0397          parent::set($id, $service, $scope);
 0398   
 0399          if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized(false)) {
 0400              $this->synchronize($id);
 0401          }
 0402      }
 0403   
 0404      /**
 0405       * Removes a service definition.
 0406       *
 0407       * @param string $id The service identifier
 0408       */
 0409      public function removeDefinition($id)
 0410      {
 0411          unset($this->definitions[strtolower($id)]);
 0412      }
 0413   
 0414      /**
 0415       * Returns true if the given service is defined.
 0416       *
 0417       * @param string $id The service identifier
 0418       *
 0419       * @return bool true if the service is defined, false otherwise
 0420       */
 0421      public function has($id)
 0422      {
 0423          $id = strtolower($id);
 0424   
 0425          return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
 0426      }
 0427   
 0428      /**
 0429       * Gets a service.
 0430       *
 0431       * @param string $id              The service identifier
 0432       * @param int    $invalidBehavior The behavior when the service does not exist
 0433       *
 0434       * @return object The associated service
 0435       *
 0436       * @throws InvalidArgumentException          when no definitions are available
 0437       * @throws ServiceCircularReferenceException When a circular reference is detected
 0438       * @throws ServiceNotFoundException          When the service is not defined
 0439       * @throws \Exception
 0440       *
 0441       * @see Reference
 0442       */
 0443      public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
 0444      {
 0445          $id = strtolower($id);
 0446   
 0447          if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
 0448              return $service;
 0449          }
 0450   
 0451          if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) {
 0452              return $this->get($this->aliasDefinitions[$id]);
 0453          }
 0454   
 0455          try {
 0456              $definition = $this->getDefinition($id);
 0457          } catch (ServiceNotFoundException $e) {
 0458              if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
 0459                  return;
 0460              }
 0461   
 0462              throw $e;
 0463          }
 0464   
 0465          $this->loading[$id] = true;
 0466   
 0467          try {
 0468              $service = $this->createService($definition, $id);
 0469          } catch (\Exception $e) {
 0470              unset($this->loading[$id]);
 0471   
 0472              if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
 0473                  return;
 0474              }
 0475   
 0476              throw $e;
 0477          } catch (\Throwable $e) {
 0478              unset($this->loading[$id]);
 0479   
 0480              throw $e;
 0481          }
 0482   
 0483          unset($this->loading[$id]);
 0484   
 0485          return $service;
 0486      }
 0487   
 0488      /**
 0489       * Merges a ContainerBuilder with the current ContainerBuilder configuration.
 0490       *
 0491       * Service definitions overrides the current defined ones.
 0492       *
 0493       * But for parameters, they are overridden by the current ones. It allows
 0494       * the parameters passed to the container constructor to have precedence
 0495       * over the loaded ones.
 0496       *
 0497       * $container = new ContainerBuilder(array('foo' => 'bar'));
 0498       * $loader = new LoaderXXX($container);
 0499       * $loader->load('resource_name');
 0500       * $container->register('foo', new stdClass());
 0501       *
 0502       * In the above example, even if the loaded resource defines a foo
 0503       * parameter, the value will still be 'bar' as defined in the ContainerBuilder
 0504       * constructor.
 0505       *
 0506       * @param ContainerBuilder $container The ContainerBuilder instance to merge
 0507       *
 0508       * @throws BadMethodCallException When this ContainerBuilder is frozen
 0509       */
 0510      public function merge(ContainerBuilder $container)
 0511      {
 0512          if ($this->isFrozen()) {
 0513              throw new BadMethodCallException('Cannot merge on a frozen container.');
 0514          }
 0515   
 0516          $this->addDefinitions($container->getDefinitions());
 0517          $this->addAliases($container->getAliases());
 0518          $this->getParameterBag()->add($container->getParameterBag()->all());
 0519   
 0520          if ($this->trackResources) {
 0521              foreach ($container->getResources() as $resource) {
 0522                  $this->addResource($resource);
 0523              }
 0524          }
 0525   
 0526          foreach ($this->extensions as $name => $extension) {
 0527              if (!isset($this->extensionConfigs[$name])) {
 0528                  $this->extensionConfigs[$name] = array();
 0529              }
 0530   
 0531              $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
 0532          }
 0533      }
 0534   
 0535      /**
 0536       * Returns the configuration array for the given extension.
 0537       *
 0538       * @param string $name The name of the extension
 0539       *
 0540       * @return array An array of configuration
 0541       */
 0542      public function getExtensionConfig($name)
 0543      {
 0544          if (!isset($this->extensionConfigs[$name])) {
 0545              $this->extensionConfigs[$name] = array();
 0546          }
 0547   
 0548          return $this->extensionConfigs[$name];
 0549      }
 0550   
 0551      /**
 0552       * Prepends a config array to the configs of the given extension.
 0553       *
 0554       * @param string $name   The name of the extension
 0555       * @param array  $config The config to set
 0556       */
 0557      public function prependExtensionConfig($name, array $config)
 0558      {
 0559          if (!isset($this->extensionConfigs[$name])) {
 0560              $this->extensionConfigs[$name] = array();
 0561          }
 0562   
 0563          array_unshift($this->extensionConfigs[$name], $config);
 0564      }
 0565   
 0566      /**
 0567       * Compiles the container.
 0568       *
 0569       * This method passes the container to compiler
 0570       * passes whose job is to manipulate and optimize
 0571       * the container.
 0572       *
 0573       * The main compiler passes roughly do four things:
 0574       *
 0575       *  * The extension configurations are merged;
 0576       *  * Parameter values are resolved;
 0577       *  * The parameter bag is frozen;
 0578       *  * Extension loading is disabled.
 0579       */
 0580      public function compile()
 0581      {
 0582          $compiler = $this->getCompiler();
 0583   
 0584          if ($this->trackResources) {
 0585              foreach ($compiler->getPassConfig()->getPasses() as $pass) {
 0586                  $this->addObjectResource($pass);
 0587              }
 0588          }
 0589   
 0590          $compiler->compile($this);
 0591   
 0592          if ($this->trackResources) {
 0593              foreach ($this->definitions as $definition) {
 0594                  if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
 0595                      $this->addClassResource(new \ReflectionClass($class));
 0596                  }
 0597              }
 0598          }
 0599   
 0600          $this->extensionConfigs = array();
 0601   
 0602          parent::compile();
 0603      }
 0604   
 0605      /**
 0606       * Gets all service ids.
 0607       *
 0608       * @return array An array of all defined service ids
 0609       */
 0610      public function getServiceIds()
 0611      {
 0612          return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()));
 0613      }
 0614   
 0615      /**
 0616       * Adds the service aliases.
 0617       *
 0618       * @param array $aliases An array of aliases
 0619       */
 0620      public function addAliases(array $aliases)
 0621      {
 0622          foreach ($aliases as $alias => $id) {
 0623              $this->setAlias($alias, $id);
 0624          }
 0625      }
 0626   
 0627      /**
 0628       * Sets the service aliases.
 0629       *
 0630       * @param array $aliases An array of aliases
 0631       */
 0632      public function setAliases(array $aliases)
 0633      {
 0634          $this->aliasDefinitions = array();
 0635          $this->addAliases($aliases);
 0636      }
 0637   
 0638      /**
 0639       * Sets an alias for an existing service.
 0640       *
 0641       * @param string       $alias The alias to create
 0642       * @param string|Alias $id    The service to alias
 0643       *
 0644       * @throws InvalidArgumentException if the id is not a string or an Alias
 0645       * @throws InvalidArgumentException if the alias is for itself
 0646       */
 0647      public function setAlias($alias, $id)
 0648      {
 0649          $alias = strtolower($alias);
 0650   
 0651          if (is_string($id)) {
 0652              $id = new Alias($id);
 0653          } elseif (!$id instanceof Alias) {
 0654              throw new InvalidArgumentException('$id must be a string, or an Alias object.');
 0655          }
 0656   
 0657          if ($alias === (string) $id) {
 0658              throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
 0659          }
 0660   
 0661          unset($this->definitions[$alias]);
 0662   
 0663          $this->aliasDefinitions[$alias] = $id;
 0664      }
 0665   
 0666      /**
 0667       * Removes an alias.
 0668       *
 0669       * @param string $alias The alias to remove
 0670       */
 0671      public function removeAlias($alias)
 0672      {
 0673          unset($this->aliasDefinitions[strtolower($alias)]);
 0674      }
 0675   
 0676      /**
 0677       * Returns true if an alias exists under the given identifier.
 0678       *
 0679       * @param string $id The service identifier
 0680       *
 0681       * @return bool true if the alias exists, false otherwise
 0682       */
 0683      public function hasAlias($id)
 0684      {
 0685          return isset($this->aliasDefinitions[strtolower($id)]);
 0686      }
 0687   
 0688      /**
 0689       * Gets all defined aliases.
 0690       *
 0691       * @return Alias[] An array of aliases
 0692       */
 0693      public function getAliases()
 0694      {
 0695          return $this->aliasDefinitions;
 0696      }
 0697   
 0698      /**
 0699       * Gets an alias.
 0700       *
 0701       * @param string $id The service identifier
 0702       *
 0703       * @return Alias An Alias instance
 0704       *
 0705       * @throws InvalidArgumentException if the alias does not exist
 0706       */
 0707      public function getAlias($id)
 0708      {
 0709          $id = strtolower($id);
 0710   
 0711          if (!isset($this->aliasDefinitions[$id])) {
 0712              throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
 0713          }
 0714   
 0715          return $this->aliasDefinitions[$id];
 0716      }
 0717   
 0718      /**
 0719       * Registers a service definition.
 0720       *
 0721       * This methods allows for simple registration of service definition
 0722       * with a fluid interface.
 0723       *
 0724       * @param string $id    The service identifier
 0725       * @param string $class The service class
 0726       *
 0727       * @return Definition A Definition instance
 0728       */
 0729      public function register($id, $class = null)
 0730      {
 0731          return $this->setDefinition($id, new Definition($class));
 0732      }
 0733   
 0734      /**
 0735       * Adds the service definitions.
 0736       *
 0737       * @param Definition[] $definitions An array of service definitions
 0738       */
 0739      public function addDefinitions(array $definitions)
 0740      {
 0741          foreach ($definitions as $id => $definition) {
 0742              $this->setDefinition($id, $definition);
 0743          }
 0744      }
 0745   
 0746      /**
 0747       * Sets the service definitions.
 0748       *
 0749       * @param Definition[] $definitions An array of service definitions
 0750       */
 0751      public function setDefinitions(array $definitions)
 0752      {
 0753          $this->definitions = array();
 0754          $this->addDefinitions($definitions);
 0755      }
 0756   
 0757      /**
 0758       * Gets all service definitions.
 0759       *
 0760       * @return Definition[] An array of Definition instances
 0761       */
 0762      public function getDefinitions()
 0763      {
 0764          return $this->definitions;
 0765      }
 0766   
 0767      /**
 0768       * Sets a service definition.
 0769       *
 0770       * @param string     $id         The service identifier
 0771       * @param Definition $definition A Definition instance
 0772       *
 0773       * @return Definition the service definition
 0774       *
 0775       * @throws BadMethodCallException When this ContainerBuilder is frozen
 0776       */
 0777      public function setDefinition($id, Definition $definition)
 0778      {
 0779          if ($this->isFrozen()) {
 0780              throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
 0781          }
 0782   
 0783          $id = strtolower($id);
 0784   
 0785          unset($this->aliasDefinitions[$id]);
 0786   
 0787          return $this->definitions[$id] = $definition;
 0788      }
 0789   
 0790      /**
 0791       * Returns true if a service definition exists under the given identifier.
 0792       *
 0793       * @param string $id The service identifier
 0794       *
 0795       * @return bool true if the service definition exists, false otherwise
 0796       */
 0797      public function hasDefinition($id)
 0798      {
 0799          return array_key_exists(strtolower($id), $this->definitions);
 0800      }
 0801   
 0802      /**
 0803       * Gets a service definition.
 0804       *
 0805       * @param string $id The service identifier
 0806       *
 0807       * @return Definition A Definition instance
 0808       *
 0809       * @throws ServiceNotFoundException if the service definition does not exist
 0810       */
 0811      public function getDefinition($id)
 0812      {
 0813          $id = strtolower($id);
 0814   
 0815          if (!array_key_exists($id, $this->definitions)) {
 0816              throw new ServiceNotFoundException($id);
 0817          }
 0818   
 0819          return $this->definitions[$id];
 0820      }
 0821   
 0822      /**
 0823       * Gets a service definition by id or alias.
 0824       *
 0825       * The method "unaliases" recursively to return a Definition instance.
 0826       *
 0827       * @param string $id The service identifier or alias
 0828       *
 0829       * @return Definition A Definition instance
 0830       *
 0831       * @throws ServiceNotFoundException if the service definition does not exist
 0832       */
 0833      public function findDefinition($id)
 0834      {
 0835          $id = strtolower($id);
 0836   
 0837          while (isset($this->aliasDefinitions[$id])) {
 0838              $id = (string) $this->aliasDefinitions[$id];
 0839          }
 0840   
 0841          return $this->getDefinition($id);
 0842      }
 0843   
 0844      /**
 0845       * Creates a service for a service definition.
 0846       *
 0847       * @param Definition $definition A service definition instance
 0848       * @param string     $id         The service identifier
 0849       * @param bool       $tryProxy   Whether to try proxying the service with a lazy proxy
 0850       *
 0851       * @return object The service described by the service definition
 0852       *
 0853       * @throws RuntimeException         When the scope is inactive
 0854       * @throws RuntimeException         When the factory definition is incomplete
 0855       * @throws RuntimeException         When the service is a synthetic service
 0856       * @throws InvalidArgumentException When configure callable is not callable
 0857       *
 0858       * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code
 0859       */
 0860      public function createService(Definition $definition, $id, $tryProxy = true)
 0861      {
 0862          if ('Symfony\Component\DependencyInjection\Definition' !== get_class($definition)) {
 0863              throw new RuntimeException(sprintf('Constructing service "%s" from a %s is not supported at build time.', $id, get_class($definition)));
 0864          }
 0865   
 0866          if ($definition->isSynthetic()) {
 0867              throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
 0868          }
 0869   
 0870          if ($definition->isDeprecated()) {
 0871              @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
 0872          }
 0873   
 0874          if ($tryProxy && $definition->isLazy()) {
 0875              $container = $this;
 0876   
 0877              $proxy = $this
 0878                  ->getProxyInstantiator()
 0879                  ->instantiateProxy(
 0880                      $container,
 0881                      $definition,
 0882                      $id, function () use ($definition, $id, $container) {
 0883                          return $container->createService($definition, $id, false);
 0884                      }
 0885                  );
 0886              $this->shareService($definition, $proxy, $id);
 0887   
 0888              return $proxy;
 0889          }
 0890   
 0891          $parameterBag = $this->getParameterBag();
 0892   
 0893          if (null !== $definition->getFile()) {
 0894              require_once $parameterBag->resolveValue($definition->getFile());
 0895          }
 0896   
 0897          $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
 0898   
 0899          if (null !== $factory = $definition->getFactory()) {
 0900              if (is_array($factory)) {
 0901                  $factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]);
 0902              } elseif (!is_string($factory)) {
 0903                  throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
 0904              }
 0905   
 0906              $service = call_user_func_array($factory, $arguments);
 0907   
 0908              if (!$definition->isDeprecated() && is_array($factory) && is_string($factory[0])) {
 0909                  $r = new \ReflectionClass($factory[0]);
 0910   
 0911                  if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
 0912                      @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);
 0913                  }
 0914              }
 0915          } elseif (null !== $definition->getFactoryMethod(false)) {
 0916              if (null !== $definition->getFactoryClass(false)) {
 0917                  $factory = $parameterBag->resolveValue($definition->getFactoryClass(false));
 0918              } elseif (null !== $definition->getFactoryService(false)) {
 0919                  $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService(false)));
 0920              } else {
 0921                  throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id));
 0922              }
 0923   
 0924              $service = call_user_func_array(array($factory, $definition->getFactoryMethod(false)), $arguments);
 0925          } else {
 0926              $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
 0927   
 0928              $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
 0929   
 0930              if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
 0931                  @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);
 0932              }
 0933          }
 0934   
 0935          if ($tryProxy || !$definition->isLazy()) {
 0936              // share only if proxying failed, or if not a proxy
 0937              $this->shareService($definition, $service, $id);
 0938          }
 0939   
 0940          foreach ($definition->getMethodCalls() as $call) {
 0941              $this->callMethod($service, $call);
 0942          }
 0943   
 0944          $properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())));
 0945          foreach ($properties as $name => $value) {
 0946              $service->$name = $value;
 0947          }
 0948   
 0949          if ($callable = $definition->getConfigurator()) {
 0950              if (is_array($callable)) {
 0951                  $callable[0] = $parameterBag->resolveValue($callable[0]);
 0952   
 0953                  if ($callable[0] instanceof Reference) {
 0954                      $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior());
 0955                  } elseif ($callable[0] instanceof Definition) {
 0956                      $callable[0] = $this->createService($callable[0], null);
 0957                  }
 0958              }
 0959   
 0960              if (!is_callable($callable)) {
 0961                  throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
 0962              }
 0963   
 0964              call_user_func($callable, $service);
 0965          }
 0966   
 0967          return $service;
 0968      }
 0969   
 0970      /**
 0971       * Replaces service references by the real service instance and evaluates expressions.
 0972       *
 0973       * @param mixed $value A value
 0974       *
 0975       * @return mixed The same value with all service references replaced by
 0976       *               the real service instances and all expressions evaluated
 0977       */
 0978      public function resolveServices($value)
 0979      {
 0980          if (is_array($value)) {
 0981              foreach ($value as $k => $v) {
 0982                  $value[$k] = $this->resolveServices($v);
 0983              }
 0984          } elseif ($value instanceof Reference) {
 0985              $value = $this->get((string) $value, $value->getInvalidBehavior());
 0986          } elseif ($value instanceof Definition) {
 0987              $value = $this->createService($value, null);
 0988          } elseif ($value instanceof Expression) {
 0989              $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
 0990          }
 0991   
 0992          return $value;
 0993      }
 0994   
 0995      /**
 0996       * Returns service ids for a given tag.
 0997       *
 0998       * Example:
 0999       *
 1000       * $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
 1001       *
 1002       * $serviceIds = $container->findTaggedServiceIds('my.tag');
 1003       * foreach ($serviceIds as $serviceId => $tags) {
 1004       *     foreach ($tags as $tag) {
 1005       *         echo $tag['hello'];
 1006       *     }
 1007       * }
 1008       *
 1009       * @param string $name The tag name
 1010       *
 1011       * @return array An array of tags with the tagged service as key, holding a list of attribute arrays
 1012       */
 1013      public function findTaggedServiceIds($name)
 1014      {
 1015          $this->usedTags[] = $name;
 1016          $tags = array();
 1017          foreach ($this->getDefinitions() as $id => $definition) {
 1018              if ($definition->hasTag($name)) {
 1019                  $tags[$id] = $definition->getTag($name);
 1020              }
 1021          }
 1022   
 1023          return $tags;
 1024      }
 1025   
 1026      /**
 1027       * Returns all tags the defined services use.
 1028       *
 1029       * @return array An array of tags
 1030       */
 1031      public function findTags()
 1032      {
 1033          $tags = array();
 1034          foreach ($this->getDefinitions() as $id => $definition) {
 1035              $tags = array_merge(array_keys($definition->getTags()), $tags);
 1036          }
 1037   
 1038          return array_unique($tags);
 1039      }
 1040   
 1041      /**
 1042       * Returns all tags not queried by findTaggedServiceIds.
 1043       *
 1044       * @return string[] An array of tags
 1045       */
 1046      public function findUnusedTags()
 1047      {
 1048          return array_values(array_diff($this->findTags(), $this->usedTags));
 1049      }
 1050   
 1051      public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
 1052      {
 1053          $this->expressionLanguageProviders[] = $provider;
 1054      }
 1055   
 1056      /**
 1057       * @return ExpressionFunctionProviderInterface[]
 1058       */
 1059      public function getExpressionLanguageProviders()
 1060      {
 1061          return $this->expressionLanguageProviders;
 1062      }
 1063   
 1064      /**
 1065       * Returns the Service Conditionals.
 1066       *
 1067       * @param mixed $value An array of conditionals to return
 1068       *
 1069       * @return array An array of Service conditionals
 1070       */
 1071      public static function getServiceConditionals($value)
 1072      {
 1073          $services = array();
 1074   
 1075          if (is_array($value)) {
 1076              foreach ($value as $v) {
 1077                  $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
 1078              }
 1079          } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
 1080              $services[] = (string) $value;
 1081          }
 1082   
 1083          return $services;
 1084      }
 1085   
 1086      /**
 1087       * Retrieves the currently set proxy instantiator or instantiates one.
 1088       *
 1089       * @return InstantiatorInterface
 1090       */
 1091      private function getProxyInstantiator()
 1092      {
 1093          if (!$this->proxyInstantiator) {
 1094              $this->proxyInstantiator = new RealServiceInstantiator();
 1095          }
 1096   
 1097          return $this->proxyInstantiator;
 1098      }
 1099   
 1100      /**
 1101       * Synchronizes a service change.
 1102       *
 1103       * This method updates all services that depend on the given
 1104       * service by calling all methods referencing it.
 1105       *
 1106       * @param string $id A service id
 1107       *
 1108       * @deprecated since version 2.7, will be removed in 3.0.
 1109       */
 1110      private function synchronize($id)
 1111      {
 1112          if ('request' !== $id) {
 1113              @trigger_error('The '.__METHOD__.' method is deprecated in version 2.7 and will be removed in version 3.0.', E_USER_DEPRECATED);
 1114          }
 1115   
 1116          foreach ($this->definitions as $definitionId => $definition) {
 1117              // only check initialized services
 1118              if (!$this->initialized($definitionId)) {
 1119                  continue;
 1120              }
 1121   
 1122              foreach ($definition->getMethodCalls() as $call) {
 1123                  foreach ($call[1] as $argument) {
 1124                      if ($argument instanceof Reference && $id == (string) $argument) {
 1125                          $this->callMethod($this->get($definitionId), $call);
 1126                      }
 1127                  }
 1128              }
 1129          }
 1130      }
 1131   
 1132      private function callMethod($service, $call)
 1133      {
 1134          $services = self::getServiceConditionals($call[1]);
 1135   
 1136          foreach ($services as $s) {
 1137              if (!$this->has($s)) {
 1138                  return;
 1139              }
 1140          }
 1141   
 1142          call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1]))));
 1143      }
 1144   
 1145      /**
 1146       * Shares a given service in the container.
 1147       *
 1148       * @param Definition $definition
 1149       * @param mixed      $service
 1150       * @param string     $id
 1151       *
 1152       * @throws InactiveScopeException
 1153       */
 1154      private function shareService(Definition $definition, $service, $id)
 1155      {
 1156          if ($definition->isShared() && self::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
 1157              if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
 1158                  throw new InactiveScopeException($id, $scope);
 1159              }
 1160   
 1161              $this->services[$lowerId = strtolower($id)] = $service;
 1162   
 1163              if (self::SCOPE_CONTAINER !== $scope) {
 1164                  $this->scopedServices[$scope][$lowerId] = $service;
 1165              }
 1166          }
 1167      }
 1168   
 1169      private function getExpressionLanguage()
 1170      {
 1171          if (null === $this->expressionLanguage) {
 1172              if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
 1173                  throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
 1174              }
 1175              $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
 1176          }
 1177   
 1178          return $this->expressionLanguage;
 1179      }
 1180  }
 1181