2015-08-17 17:00:26 -07:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\DependencyInjection\Compiler ;
use Symfony\Component\DependencyInjection\Definition ;
use Symfony\Component\DependencyInjection\DefinitionDecorator ;
use Symfony\Component\DependencyInjection\ContainerBuilder ;
use Symfony\Component\DependencyInjection\Exception\RuntimeException ;
/**
* This replaces all DefinitionDecorator instances with their equivalent fully
* merged Definition instance .
*
* @ author Johannes M . Schmitt < schmittjoh @ gmail . com >
2016-04-20 09:56:34 -07:00
* @ author Nicolas Grekas < p @ tchwork . com >
2015-08-17 17:00:26 -07:00
*/
class ResolveDefinitionTemplatesPass implements CompilerPassInterface
{
private $compiler ;
private $formatter ;
2016-04-20 09:56:34 -07:00
private $currentId ;
2015-08-17 17:00:26 -07:00
/**
* Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances .
*
* @ param ContainerBuilder $container
*/
public function process ( ContainerBuilder $container )
{
$this -> compiler = $container -> getCompiler ();
$this -> formatter = $this -> compiler -> getLoggingFormatter ();
2016-04-20 09:56:34 -07:00
$container -> setDefinitions ( $this -> resolveArguments ( $container , $container -> getDefinitions (), true ));
}
2015-08-17 17:00:26 -07:00
2016-04-20 09:56:34 -07:00
/**
* Resolves definition decorator arguments .
*
* @ param ContainerBuilder $container The ContainerBuilder
* @ param array $arguments An array of arguments
* @ param bool $isRoot If we are processing the root definitions or not
*
* @ return array
*/
private function resolveArguments ( ContainerBuilder $container , array $arguments , $isRoot = false )
{
foreach ( $arguments as $k => $argument ) {
if ( $isRoot ) {
// yes, we are specifically fetching the definition from the
// container to ensure we are not operating on stale data
$arguments [ $k ] = $argument = $container -> getDefinition ( $k );
$this -> currentId = $k ;
}
if ( is_array ( $argument )) {
$arguments [ $k ] = $this -> resolveArguments ( $container , $argument );
} elseif ( $argument instanceof Definition ) {
if ( $argument instanceof DefinitionDecorator ) {
$arguments [ $k ] = $argument = $this -> resolveDefinition ( $container , $argument );
if ( $isRoot ) {
$container -> setDefinition ( $k , $argument );
}
}
$argument -> setArguments ( $this -> resolveArguments ( $container , $argument -> getArguments ()));
$argument -> setMethodCalls ( $this -> resolveArguments ( $container , $argument -> getMethodCalls ()));
$argument -> setProperties ( $this -> resolveArguments ( $container , $argument -> getProperties ()));
$configurator = $this -> resolveArguments ( $container , array ( $argument -> getConfigurator ()));
$argument -> setConfigurator ( $configurator [ 0 ]);
$factory = $this -> resolveArguments ( $container , array ( $argument -> getFactory ()));
$argument -> setFactory ( $factory [ 0 ]);
}
2015-08-17 17:00:26 -07:00
}
2016-04-20 09:56:34 -07:00
return $arguments ;
2015-08-17 17:00:26 -07:00
}
/**
* Resolves the definition .
*
2016-04-20 09:56:34 -07:00
* @ param ContainerBuilder $container The ContainerBuilder
2015-08-17 17:00:26 -07:00
* @ param DefinitionDecorator $definition
*
* @ return Definition
*
* @ throws \RuntimeException When the definition is invalid
*/
2016-04-20 09:56:34 -07:00
private function resolveDefinition ( ContainerBuilder $container , DefinitionDecorator $definition )
2015-08-17 17:00:26 -07:00
{
2016-04-20 09:56:34 -07:00
if ( ! $container -> hasDefinition ( $parent = $definition -> getParent ())) {
throw new RuntimeException ( sprintf ( 'The parent definition "%s" defined for definition "%s" does not exist.' , $parent , $this -> currentId ));
2015-08-17 17:00:26 -07:00
}
2016-04-20 09:56:34 -07:00
$parentDef = $container -> getDefinition ( $parent );
2015-08-17 17:00:26 -07:00
if ( $parentDef instanceof DefinitionDecorator ) {
2016-04-20 09:56:34 -07:00
$id = $this -> currentId ;
$this -> currentId = $parent ;
$parentDef = $this -> resolveDefinition ( $container , $parentDef );
$container -> setDefinition ( $parent , $parentDef );
$this -> currentId = $id ;
2015-08-17 17:00:26 -07:00
}
2016-04-20 09:56:34 -07:00
$this -> compiler -> addLogMessage ( $this -> formatter -> formatResolveInheritance ( $this , $this -> currentId , $parent ));
2015-08-17 17:00:26 -07:00
$def = new Definition ();
// merge in parent definition
// purposely ignored attributes: scope, abstract, tags
$def -> setClass ( $parentDef -> getClass ());
$def -> setArguments ( $parentDef -> getArguments ());
$def -> setMethodCalls ( $parentDef -> getMethodCalls ());
$def -> setProperties ( $parentDef -> getProperties ());
2016-04-20 09:56:34 -07:00
$def -> setAutowiringTypes ( $parentDef -> getAutowiringTypes ());
2015-08-17 17:00:26 -07:00
if ( $parentDef -> getFactoryClass ( false )) {
$def -> setFactoryClass ( $parentDef -> getFactoryClass ( false ));
}
if ( $parentDef -> getFactoryMethod ( false )) {
$def -> setFactoryMethod ( $parentDef -> getFactoryMethod ( false ));
}
if ( $parentDef -> getFactoryService ( false )) {
$def -> setFactoryService ( $parentDef -> getFactoryService ( false ));
}
2016-04-20 09:56:34 -07:00
if ( $parentDef -> isDeprecated ()) {
$def -> setDeprecated ( true , $parentDef -> getDeprecationMessage ( '%service_id%' ));
}
2015-08-17 17:00:26 -07:00
$def -> setFactory ( $parentDef -> getFactory ());
$def -> setConfigurator ( $parentDef -> getConfigurator ());
$def -> setFile ( $parentDef -> getFile ());
$def -> setPublic ( $parentDef -> isPublic ());
$def -> setLazy ( $parentDef -> isLazy ());
2017-02-02 16:28:38 -08:00
$def -> setAutowired ( $parentDef -> isAutowired ());
2015-08-17 17:00:26 -07:00
// overwrite with values specified in the decorator
$changes = $definition -> getChanges ();
if ( isset ( $changes [ 'class' ])) {
$def -> setClass ( $definition -> getClass ());
}
if ( isset ( $changes [ 'factory_class' ])) {
$def -> setFactoryClass ( $definition -> getFactoryClass ( false ));
}
if ( isset ( $changes [ 'factory_method' ])) {
$def -> setFactoryMethod ( $definition -> getFactoryMethod ( false ));
}
if ( isset ( $changes [ 'factory_service' ])) {
$def -> setFactoryService ( $definition -> getFactoryService ( false ));
}
if ( isset ( $changes [ 'factory' ])) {
$def -> setFactory ( $definition -> getFactory ());
}
if ( isset ( $changes [ 'configurator' ])) {
$def -> setConfigurator ( $definition -> getConfigurator ());
}
if ( isset ( $changes [ 'file' ])) {
$def -> setFile ( $definition -> getFile ());
}
if ( isset ( $changes [ 'public' ])) {
$def -> setPublic ( $definition -> isPublic ());
}
if ( isset ( $changes [ 'lazy' ])) {
$def -> setLazy ( $definition -> isLazy ());
}
2016-04-20 09:56:34 -07:00
if ( isset ( $changes [ 'deprecated' ])) {
$def -> setDeprecated ( $definition -> isDeprecated (), $definition -> getDeprecationMessage ( '%service_id%' ));
}
2017-02-02 16:28:38 -08:00
if ( isset ( $changes [ 'autowire' ])) {
$def -> setAutowired ( $definition -> isAutowired ());
}
2015-08-27 12:03:05 -07:00
if ( isset ( $changes [ 'decorated_service' ])) {
$decoratedService = $definition -> getDecoratedService ();
if ( null === $decoratedService ) {
$def -> setDecoratedService ( $decoratedService );
} else {
2017-02-02 16:28:38 -08:00
$def -> setDecoratedService ( $decoratedService [ 0 ], $decoratedService [ 1 ], $decoratedService [ 2 ]);
2015-08-27 12:03:05 -07:00
}
}
2015-08-17 17:00:26 -07:00
// merge arguments
foreach ( $definition -> getArguments () as $k => $v ) {
if ( is_numeric ( $k )) {
$def -> addArgument ( $v );
continue ;
}
if ( 0 !== strpos ( $k , 'index_' )) {
throw new RuntimeException ( sprintf ( 'Invalid argument key "%s" found.' , $k ));
}
$index = ( int ) substr ( $k , strlen ( 'index_' ));
$def -> replaceArgument ( $index , $v );
}
// merge properties
foreach ( $definition -> getProperties () as $k => $v ) {
$def -> setProperty ( $k , $v );
}
// append method calls
if ( count ( $calls = $definition -> getMethodCalls ()) > 0 ) {
$def -> setMethodCalls ( array_merge ( $def -> getMethodCalls (), $calls ));
}
2016-04-20 09:56:34 -07:00
// merge autowiring types
foreach ( $definition -> getAutowiringTypes () as $autowiringType ) {
$def -> addAutowiringType ( $autowiringType );
}
2015-08-17 17:00:26 -07:00
// these attributes are always taken from the child
$def -> setAbstract ( $definition -> isAbstract ());
2016-04-20 09:56:34 -07:00
$def -> setScope ( $definition -> getScope ( false ), false );
$def -> setShared ( $definition -> isShared ());
2015-08-17 17:00:26 -07:00
$def -> setTags ( $definition -> getTags ());
return $def ;
}
}