vendor/symfony/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\DependencyInjection;
       
    13 
       
    14 use Symfony\Component\DependencyInjection\Compiler\Compiler;
       
    15 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
       
    16 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
       
    17 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
       
    18 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
       
    19 use Symfony\Component\Config\Resource\FileResource;
       
    20 use Symfony\Component\Config\Resource\ResourceInterface;
       
    21 
       
    22 /**
       
    23  * ContainerBuilder is a DI container that provides an API to easily describe services.
       
    24  *
       
    25  * @author Fabien Potencier <fabien@symfony.com>
       
    26  *
       
    27  * @api
       
    28  */
       
    29 class ContainerBuilder extends Container implements TaggedContainerInterface
       
    30 {
       
    31     private $extensions       = array();
       
    32     private $extensionsByNs   = array();
       
    33     private $definitions      = array();
       
    34     private $aliases          = array();
       
    35     private $resources        = array();
       
    36     private $extensionConfigs = array();
       
    37     private $injectors        = array();
       
    38     private $compiler;
       
    39 
       
    40     /**
       
    41      * Registers an extension.
       
    42      *
       
    43      * @param ExtensionInterface $extension An extension instance
       
    44      *
       
    45      * @api
       
    46      */
       
    47     public function registerExtension(ExtensionInterface $extension)
       
    48     {
       
    49         $this->extensions[$extension->getAlias()] = $extension;
       
    50 
       
    51         if (false !== $extension->getNamespace()) {
       
    52             $this->extensionsByNs[$extension->getNamespace()] = $extension;
       
    53         }
       
    54     }
       
    55 
       
    56     /**
       
    57      * Returns an extension by alias or namespace.
       
    58      *
       
    59      * @param string $name An alias or a namespace
       
    60      *
       
    61      * @return ExtensionInterface An extension instance
       
    62      *
       
    63      * @api
       
    64      */
       
    65     public function getExtension($name)
       
    66     {
       
    67         if (isset($this->extensions[$name])) {
       
    68             return $this->extensions[$name];
       
    69         }
       
    70 
       
    71         if (isset($this->extensionsByNs[$name])) {
       
    72             return $this->extensionsByNs[$name];
       
    73         }
       
    74 
       
    75         throw new \LogicException(sprintf('Container extension "%s" is not registered', $name));
       
    76     }
       
    77 
       
    78     /**
       
    79      * Returns all registered extensions.
       
    80      *
       
    81      * @return array An array of ExtensionInterface
       
    82      *
       
    83      * @api
       
    84      */
       
    85     public function getExtensions()
       
    86     {
       
    87         return $this->extensions;
       
    88     }
       
    89 
       
    90     /**
       
    91      * Checks if we have an extension.
       
    92      *
       
    93      * @param string $name The name of the extension
       
    94      * @return Boolean If the extension exists
       
    95      *
       
    96      * @api
       
    97      */
       
    98     public function hasExtension($name)
       
    99     {
       
   100         return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
       
   101     }
       
   102 
       
   103     /**
       
   104      * Returns an array of resources loaded to build this configuration.
       
   105      *
       
   106      * @return ResourceInterface[] An array of resources
       
   107      *
       
   108      * @api
       
   109      */
       
   110     public function getResources()
       
   111     {
       
   112         return array_unique($this->resources);
       
   113     }
       
   114 
       
   115     /**
       
   116      * Adds a resource for this configuration.
       
   117      *
       
   118      * @param ResourceInterface $resource A resource instance
       
   119      *
       
   120      * @return ContainerBuilder The current instance
       
   121      *
       
   122      * @api
       
   123      */
       
   124     public function addResource(ResourceInterface $resource)
       
   125     {
       
   126         $this->resources[] = $resource;
       
   127 
       
   128         return $this;
       
   129     }
       
   130 
       
   131     /**
       
   132      * Adds the object class hierarchy as resources.
       
   133      *
       
   134      * @param object $object An object instance
       
   135      *
       
   136      * @api
       
   137      */
       
   138     public function addObjectResource($object)
       
   139     {
       
   140         $parent = new \ReflectionObject($object);
       
   141         do {
       
   142             $this->addResource(new FileResource($parent->getFileName()));
       
   143         } while ($parent = $parent->getParentClass());
       
   144     }
       
   145 
       
   146     /**
       
   147      * Loads the configuration for an extension.
       
   148      *
       
   149      * @param string $extension The extension alias or namespace
       
   150      * @param array  $values    An array of values that customizes the extension
       
   151      *
       
   152      * @return ContainerBuilder The current instance
       
   153      *
       
   154      * @api
       
   155      */
       
   156     public function loadFromExtension($extension, array $values = array())
       
   157     {
       
   158         if (true === $this->isFrozen()) {
       
   159             throw new \LogicException('Cannot load from an extension on a frozen container.');
       
   160         }
       
   161 
       
   162         $namespace = $this->getExtension($extension)->getAlias();
       
   163 
       
   164         $this->extensionConfigs[$namespace][] = $values;
       
   165 
       
   166         return $this;
       
   167     }
       
   168 
       
   169     /**
       
   170      * Adds a compiler pass.
       
   171      *
       
   172      * @param CompilerPassInterface $pass A compiler pass
       
   173      * @param string                $type The type of compiler pass
       
   174      *
       
   175      * @api
       
   176      */
       
   177     public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
       
   178     {
       
   179         if (null === $this->compiler) {
       
   180             $this->compiler = new Compiler();
       
   181         }
       
   182 
       
   183         $this->compiler->addPass($pass, $type);
       
   184 
       
   185         $this->addObjectResource($pass);
       
   186     }
       
   187 
       
   188     /**
       
   189      * Returns the compiler pass config which can then be modified.
       
   190      *
       
   191      * @return PassConfig The compiler pass config
       
   192      *
       
   193      * @api
       
   194      */
       
   195     public function getCompilerPassConfig()
       
   196     {
       
   197         if (null === $this->compiler) {
       
   198             $this->compiler = new Compiler();
       
   199         }
       
   200 
       
   201         return $this->compiler->getPassConfig();
       
   202     }
       
   203 
       
   204     /**
       
   205      * Returns the compiler.
       
   206      *
       
   207      * @return Compiler The compiler
       
   208      *
       
   209      * @api
       
   210      */
       
   211     public function getCompiler()
       
   212     {
       
   213         if (null === $this->compiler) {
       
   214             $this->compiler = new Compiler();
       
   215         }
       
   216 
       
   217         return $this->compiler;
       
   218     }
       
   219 
       
   220     /**
       
   221      * Returns all Scopes.
       
   222      *
       
   223      * @return array An array of scopes
       
   224      *
       
   225      * @api
       
   226      */
       
   227     public function getScopes()
       
   228     {
       
   229         return $this->scopes;
       
   230     }
       
   231 
       
   232     /**
       
   233      * Returns all Scope children.
       
   234      *
       
   235      * @return array An array of scope children.
       
   236      *
       
   237      * @api
       
   238      */
       
   239     public function getScopeChildren()
       
   240     {
       
   241         return $this->scopeChildren;
       
   242     }
       
   243 
       
   244     /**
       
   245      * Sets a service.
       
   246      *
       
   247      * @param string $id      The service identifier
       
   248      * @param object $service The service instance
       
   249      * @param string $scope   The scope
       
   250      *
       
   251      * @throws BadMethodCallException
       
   252      *
       
   253      * @api
       
   254      */
       
   255     public function set($id, $service, $scope = self::SCOPE_CONTAINER)
       
   256     {
       
   257         if ($this->isFrozen()) {
       
   258             throw new \BadMethodCallException('Setting service on a frozen container is not allowed');
       
   259         }
       
   260 
       
   261         $id = strtolower($id);
       
   262 
       
   263         unset($this->definitions[$id], $this->aliases[$id]);
       
   264 
       
   265         parent::set($id, $service, $scope);
       
   266     }
       
   267 
       
   268     /**
       
   269      * Removes a service definition.
       
   270      *
       
   271      * @param string $id The service identifier
       
   272      *
       
   273      * @api
       
   274      */
       
   275     public function removeDefinition($id)
       
   276     {
       
   277         unset($this->definitions[strtolower($id)]);
       
   278     }
       
   279 
       
   280     /**
       
   281      * Returns true if the given service is defined.
       
   282      *
       
   283      * @param  string  $id      The service identifier
       
   284      *
       
   285      * @return Boolean true if the service is defined, false otherwise
       
   286      *
       
   287      * @api
       
   288      */
       
   289     public function has($id)
       
   290     {
       
   291         $id = strtolower($id);
       
   292 
       
   293         return isset($this->definitions[$id]) || isset($this->aliases[$id]) || parent::has($id);
       
   294     }
       
   295 
       
   296     /**
       
   297      * Gets a service.
       
   298      *
       
   299      * @param  string  $id              The service identifier
       
   300      * @param  integer $invalidBehavior The behavior when the service does not exist
       
   301      *
       
   302      * @return object The associated service
       
   303      *
       
   304      * @throws \InvalidArgumentException if the service is not defined
       
   305      * @throws \LogicException if the service has a circular reference to itself
       
   306      *
       
   307      * @see Reference
       
   308      *
       
   309      * @api
       
   310      */
       
   311     public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
       
   312     {
       
   313         $id = strtolower($id);
       
   314 
       
   315         try {
       
   316             return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
       
   317         } catch (\InvalidArgumentException $e) {
       
   318             if (isset($this->loading[$id])) {
       
   319                 throw new \LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e);
       
   320             }
       
   321 
       
   322             if (!$this->hasDefinition($id) && isset($this->aliases[$id])) {
       
   323                 return $this->get($this->aliases[$id]);
       
   324             }
       
   325 
       
   326             try {
       
   327                 $definition = $this->getDefinition($id);
       
   328             } catch (\InvalidArgumentException $e) {
       
   329                 if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
       
   330                     return null;
       
   331                 }
       
   332 
       
   333                 throw $e;
       
   334             }
       
   335 
       
   336             $this->loading[$id] = true;
       
   337 
       
   338             $service = $this->createService($definition, $id);
       
   339 
       
   340             unset($this->loading[$id]);
       
   341 
       
   342             return $service;
       
   343         }
       
   344     }
       
   345 
       
   346     /**
       
   347      * Merges a ContainerBuilder with the current ContainerBuilder configuration.
       
   348      *
       
   349      * Service definitions overrides the current defined ones.
       
   350      *
       
   351      * But for parameters, they are overridden by the current ones. It allows
       
   352      * the parameters passed to the container constructor to have precedence
       
   353      * over the loaded ones.
       
   354      *
       
   355      * $container = new ContainerBuilder(array('foo' => 'bar'));
       
   356      * $loader = new LoaderXXX($container);
       
   357      * $loader->load('resource_name');
       
   358      * $container->register('foo', new stdClass());
       
   359      *
       
   360      * In the above example, even if the loaded resource defines a foo
       
   361      * parameter, the value will still be 'bar' as defined in the ContainerBuilder
       
   362      * constructor.
       
   363      *
       
   364      * @param ContainerBuilder $container The ContainerBuilder instance to merge.
       
   365      * @throws \LogicException when this ContainerBuilder is frozen
       
   366      *
       
   367      * @api
       
   368      */
       
   369     public function merge(ContainerBuilder $container)
       
   370     {
       
   371         if (true === $this->isFrozen()) {
       
   372             throw new \LogicException('Cannot merge on a frozen container.');
       
   373         }
       
   374 
       
   375         $this->addDefinitions($container->getDefinitions());
       
   376         $this->addAliases($container->getAliases());
       
   377         $this->getParameterBag()->add($container->getParameterBag()->all());
       
   378 
       
   379         foreach ($container->getResources() as $resource) {
       
   380             $this->addResource($resource);
       
   381         }
       
   382 
       
   383         foreach ($this->extensions as $name => $extension) {
       
   384             if (!isset($this->extensionConfigs[$name])) {
       
   385                 $this->extensionConfigs[$name] = array();
       
   386             }
       
   387 
       
   388             $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
       
   389         }
       
   390     }
       
   391 
       
   392     /**
       
   393      * Returns the configuration array for the given extension.
       
   394      *
       
   395      * @param string $name The name of the extension
       
   396      *
       
   397      * @return array An array of configuration
       
   398      *
       
   399      * @api
       
   400      */
       
   401     public function getExtensionConfig($name)
       
   402     {
       
   403         if (!isset($this->extensionConfigs[$name])) {
       
   404             $this->extensionConfigs[$name] = array();
       
   405         }
       
   406 
       
   407         return $this->extensionConfigs[$name];
       
   408     }
       
   409 
       
   410     /**
       
   411      * Compiles the container.
       
   412      *
       
   413      * This method passes the container to compiler
       
   414      * passes whose job is to manipulate and optimize
       
   415      * the container.
       
   416      *
       
   417      * The main compiler passes roughly do four things:
       
   418      *
       
   419      *  * The extension configurations are merged;
       
   420      *  * Parameter values are resolved;
       
   421      *  * The parameter bag is frozen;
       
   422      *  * Extension loading is disabled.
       
   423      *
       
   424      * @api
       
   425      */
       
   426     public function compile()
       
   427     {
       
   428         if (null === $this->compiler) {
       
   429             $this->compiler = new Compiler();
       
   430         }
       
   431 
       
   432         foreach ($this->compiler->getPassConfig()->getPasses() as $pass) {
       
   433             $this->addObjectResource($pass);
       
   434         }
       
   435 
       
   436         $this->compiler->compile($this);
       
   437 
       
   438         $this->extensionConfigs = array();
       
   439 
       
   440         parent::compile();
       
   441     }
       
   442 
       
   443     /**
       
   444      * Gets all service ids.
       
   445      *
       
   446      * @return array An array of all defined service ids
       
   447      */
       
   448     public function getServiceIds()
       
   449     {
       
   450         return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliases), parent::getServiceIds()));
       
   451     }
       
   452 
       
   453     /**
       
   454      * Adds the service aliases.
       
   455      *
       
   456      * @param array $aliases An array of aliases
       
   457      *
       
   458      * @api
       
   459      */
       
   460     public function addAliases(array $aliases)
       
   461     {
       
   462         foreach ($aliases as $alias => $id) {
       
   463             $this->setAlias($alias, $id);
       
   464         }
       
   465     }
       
   466 
       
   467     /**
       
   468      * Sets the service aliases.
       
   469      *
       
   470      * @param array $aliases An array of service definitions
       
   471      *
       
   472      * @api
       
   473      */
       
   474     public function setAliases(array $aliases)
       
   475     {
       
   476         $this->aliases = array();
       
   477         $this->addAliases($aliases);
       
   478     }
       
   479 
       
   480     /**
       
   481      * Sets an alias for an existing service.
       
   482      *
       
   483      * @param string $alias The alias to create
       
   484      * @param mixed  $id    The service to alias
       
   485      *
       
   486      * @api
       
   487      */
       
   488     public function setAlias($alias, $id)
       
   489     {
       
   490         $alias = strtolower($alias);
       
   491 
       
   492         if (is_string($id)) {
       
   493             $id = new Alias($id);
       
   494         } else if (!$id instanceof Alias) {
       
   495             throw new \InvalidArgumentException('$id must be a string, or an Alias object.');
       
   496         }
       
   497 
       
   498         if ($alias === strtolower($id)) {
       
   499             throw new \InvalidArgumentException('An alias can not reference itself, got a circular reference on "'.$alias.'".');
       
   500         }
       
   501 
       
   502         unset($this->definitions[$alias]);
       
   503 
       
   504         $this->aliases[$alias] = $id;
       
   505     }
       
   506 
       
   507     /**
       
   508      * Removes an alias.
       
   509      *
       
   510      * @param string $alias The alias to remove
       
   511      *
       
   512      * @api
       
   513      */
       
   514     public function removeAlias($alias)
       
   515     {
       
   516         unset($this->aliases[strtolower($alias)]);
       
   517     }
       
   518 
       
   519     /**
       
   520      * Returns true if an alias exists under the given identifier.
       
   521      *
       
   522      * @param  string  $id The service identifier
       
   523      *
       
   524      * @return Boolean true if the alias exists, false otherwise
       
   525      *
       
   526      * @api
       
   527      */
       
   528     public function hasAlias($id)
       
   529     {
       
   530         return isset($this->aliases[strtolower($id)]);
       
   531     }
       
   532 
       
   533     /**
       
   534      * Gets all defined aliases.
       
   535      *
       
   536      * @return array An array of aliases
       
   537      *
       
   538      * @api
       
   539      */
       
   540     public function getAliases()
       
   541     {
       
   542         return $this->aliases;
       
   543     }
       
   544 
       
   545     /**
       
   546      * Gets an alias.
       
   547      *
       
   548      * @param  string  $id The service identifier
       
   549      *
       
   550      * @return string The aliased service identifier
       
   551      *
       
   552      * @throws \InvalidArgumentException if the alias does not exist
       
   553      *
       
   554      * @api
       
   555      */
       
   556     public function getAlias($id)
       
   557     {
       
   558         $id = strtolower($id);
       
   559 
       
   560         if (!$this->hasAlias($id)) {
       
   561             throw new \InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
       
   562         }
       
   563 
       
   564         return $this->aliases[$id];
       
   565     }
       
   566 
       
   567     /**
       
   568      * Registers a service definition.
       
   569      *
       
   570      * This methods allows for simple registration of service definition
       
   571      * with a fluid interface.
       
   572      *
       
   573      * @param  string $id    The service identifier
       
   574      * @param  string $class The service class
       
   575      *
       
   576      * @return Definition A Definition instance
       
   577      *
       
   578      * @api
       
   579      */
       
   580     public function register($id, $class = null)
       
   581     {
       
   582         return $this->setDefinition(strtolower($id), new Definition($class));
       
   583     }
       
   584 
       
   585     /**
       
   586      * Adds the service definitions.
       
   587      *
       
   588      * @param Definition[] $definitions An array of service definitions
       
   589      *
       
   590      * @api
       
   591      */
       
   592     public function addDefinitions(array $definitions)
       
   593     {
       
   594         foreach ($definitions as $id => $definition) {
       
   595             $this->setDefinition($id, $definition);
       
   596         }
       
   597     }
       
   598 
       
   599     /**
       
   600      * Sets the service definitions.
       
   601      *
       
   602      * @param array $definitions An array of service definitions
       
   603      *
       
   604      * @api
       
   605      */
       
   606     public function setDefinitions(array $definitions)
       
   607     {
       
   608         $this->definitions = array();
       
   609         $this->addDefinitions($definitions);
       
   610     }
       
   611 
       
   612     /**
       
   613      * Gets all service definitions.
       
   614      *
       
   615      * @return array An array of Definition instances
       
   616      *
       
   617      * @api
       
   618      */
       
   619     public function getDefinitions()
       
   620     {
       
   621         return $this->definitions;
       
   622     }
       
   623 
       
   624     /**
       
   625      * Sets a service definition.
       
   626      *
       
   627      * @param  string     $id         The service identifier
       
   628      * @param  Definition $definition A Definition instance
       
   629      *
       
   630      * @throws BadMethodCallException
       
   631      *
       
   632      * @api
       
   633      */
       
   634     public function setDefinition($id, Definition $definition)
       
   635     {
       
   636         if ($this->isFrozen()) {
       
   637             throw new \BadMethodCallException('Adding definition to a frozen container is not allowed');
       
   638         }
       
   639 
       
   640         $id = strtolower($id);
       
   641 
       
   642         unset($this->aliases[$id]);
       
   643 
       
   644         return $this->definitions[$id] = $definition;
       
   645     }
       
   646 
       
   647     /**
       
   648      * Returns true if a service definition exists under the given identifier.
       
   649      *
       
   650      * @param  string  $id The service identifier
       
   651      *
       
   652      * @return Boolean true if the service definition exists, false otherwise
       
   653      *
       
   654      * @api
       
   655      */
       
   656     public function hasDefinition($id)
       
   657     {
       
   658         return array_key_exists(strtolower($id), $this->definitions);
       
   659     }
       
   660 
       
   661     /**
       
   662      * Gets a service definition.
       
   663      *
       
   664      * @param  string  $id The service identifier
       
   665      *
       
   666      * @return Definition A Definition instance
       
   667      *
       
   668      * @throws \InvalidArgumentException if the service definition does not exist
       
   669      *
       
   670      * @api
       
   671      */
       
   672     public function getDefinition($id)
       
   673     {
       
   674         $id = strtolower($id);
       
   675 
       
   676         if (!$this->hasDefinition($id)) {
       
   677             throw new \InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id));
       
   678         }
       
   679 
       
   680         return $this->definitions[$id];
       
   681     }
       
   682 
       
   683     /**
       
   684      * Gets a service definition by id or alias.
       
   685      *
       
   686      * The method "unaliases" recursively to return a Definition instance.
       
   687      *
       
   688      * @param  string  $id The service identifier or alias
       
   689      *
       
   690      * @return Definition A Definition instance
       
   691      *
       
   692      * @throws \InvalidArgumentException if the service definition does not exist
       
   693      *
       
   694      * @api
       
   695      */
       
   696     public function findDefinition($id)
       
   697     {
       
   698         while ($this->hasAlias($id)) {
       
   699             $id = (string) $this->getAlias($id);
       
   700         }
       
   701 
       
   702         return $this->getDefinition($id);
       
   703     }
       
   704 
       
   705     /**
       
   706      * Creates a service for a service definition.
       
   707      *
       
   708      * @param  Definition $definition A service definition instance
       
   709      * @param  string     $id         The service identifier
       
   710      *
       
   711      * @return object              The service described by the service definition
       
   712      *
       
   713      * @throws \InvalidArgumentException When configure callable is not callable
       
   714      */
       
   715     private function createService(Definition $definition, $id)
       
   716     {
       
   717         if (null !== $definition->getFile()) {
       
   718             require_once $this->getParameterBag()->resolveValue($definition->getFile());
       
   719         }
       
   720 
       
   721         $arguments = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getArguments()));
       
   722 
       
   723         if (null !== $definition->getFactoryMethod()) {
       
   724             if (null !== $definition->getFactoryClass()) {
       
   725                 $factory = $this->getParameterBag()->resolveValue($definition->getFactoryClass());
       
   726             } elseif (null !== $definition->getFactoryService()) {
       
   727                 $factory = $this->get($this->getParameterBag()->resolveValue($definition->getFactoryService()));
       
   728             } else {
       
   729                 throw new \RuntimeException('Cannot create service from factory method without a factory service or factory class.');
       
   730             }
       
   731 
       
   732             $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments);
       
   733         } else {
       
   734             $r = new \ReflectionClass($this->getParameterBag()->resolveValue($definition->getClass()));
       
   735 
       
   736             $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
       
   737         }
       
   738 
       
   739         if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) {
       
   740             if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
       
   741                 throw new \RuntimeException('You tried to create a service of an inactive scope.');
       
   742             }
       
   743 
       
   744             $this->services[$lowerId = strtolower($id)] = $service;
       
   745 
       
   746             if (self::SCOPE_CONTAINER !== $scope) {
       
   747                 $this->scopedServices[$scope][$lowerId] = $service;
       
   748             }
       
   749         }
       
   750 
       
   751         foreach ($definition->getMethodCalls() as $call) {
       
   752             $services = self::getServiceConditionals($call[1]);
       
   753 
       
   754             $ok = true;
       
   755             foreach ($services as $s) {
       
   756                 if (!$this->has($s)) {
       
   757                     $ok = false;
       
   758                     break;
       
   759                 }
       
   760             }
       
   761 
       
   762             if ($ok) {
       
   763                 call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
       
   764             }
       
   765         }
       
   766 
       
   767         $properties = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getProperties()));
       
   768         foreach ($properties as $name => $value) {
       
   769             $service->$name = $value;
       
   770         }
       
   771 
       
   772         if ($callable = $definition->getConfigurator()) {
       
   773             if (is_array($callable) && is_object($callable[0]) && $callable[0] instanceof Reference) {
       
   774                 $callable[0] = $this->get((string) $callable[0]);
       
   775             } elseif (is_array($callable)) {
       
   776                 $callable[0] = $this->getParameterBag()->resolveValue($callable[0]);
       
   777             }
       
   778 
       
   779             if (!is_callable($callable)) {
       
   780                 throw new \InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
       
   781             }
       
   782 
       
   783             call_user_func($callable, $service);
       
   784         }
       
   785 
       
   786         return $service;
       
   787     }
       
   788 
       
   789     /**
       
   790      * Replaces service references by the real service instance.
       
   791      *
       
   792      * @param  mixed $value A value
       
   793      *
       
   794      * @return mixed The same value with all service references replaced by the real service instances
       
   795      */
       
   796     public function resolveServices($value)
       
   797     {
       
   798         if (is_array($value)) {
       
   799             foreach ($value as &$v) {
       
   800                 $v = $this->resolveServices($v);
       
   801             }
       
   802         } elseif (is_object($value) && $value instanceof Reference) {
       
   803             $value = $this->get((string) $value, $value->getInvalidBehavior());
       
   804         } elseif (is_object($value) && $value instanceof Definition) {
       
   805             $value = $this->createService($value, null);
       
   806         }
       
   807 
       
   808         return $value;
       
   809     }
       
   810 
       
   811     /**
       
   812      * Returns service ids for a given tag.
       
   813      *
       
   814      * @param string $name The tag name
       
   815      *
       
   816      * @return array An array of tags
       
   817      *
       
   818      * @api
       
   819      */
       
   820     public function findTaggedServiceIds($name)
       
   821     {
       
   822         $tags = array();
       
   823         foreach ($this->getDefinitions() as $id => $definition) {
       
   824             if ($definition->getTag($name)) {
       
   825                 $tags[$id] = $definition->getTag($name);
       
   826             }
       
   827         }
       
   828 
       
   829         return $tags;
       
   830     }
       
   831 
       
   832     /**
       
   833      * Returns the Service Conditionals.
       
   834      *
       
   835      * @param mixed $value An array of conditionals to return.
       
   836      * @return array An array of Service conditionals
       
   837      */
       
   838     static public function getServiceConditionals($value)
       
   839     {
       
   840         $services = array();
       
   841 
       
   842         if (is_array($value)) {
       
   843             foreach ($value as $v) {
       
   844                 $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
       
   845             }
       
   846         } elseif (is_object($value) && $value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
       
   847             $services[] = (string) $value;
       
   848         }
       
   849 
       
   850         return $services;
       
   851     }
       
   852 }