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\ContainerBuilder ;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException ;
use Symfony\Component\DependencyInjection\Reference ;
/**
* Replaces aliases with actual service definitions , effectively removing these
* aliases .
*
* @ author Johannes M . Schmitt < schmittjoh @ gmail . com >
*/
class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
{
private $compiler ;
private $formatter ;
/**
* Process the Container to replace aliases with service definitions .
*
* @ param ContainerBuilder $container
*
* @ throws InvalidArgumentException if the service definition does not exist
*/
public function process ( ContainerBuilder $container )
{
2017-02-02 16:28:38 -08:00
// Setup
2015-08-17 17:00:26 -07:00
$this -> compiler = $container -> getCompiler ();
$this -> formatter = $this -> compiler -> getLoggingFormatter ();
2017-02-02 16:28:38 -08:00
// First collect all alias targets that need to be replaced
$seenAliasTargets = array ();
$replacements = array ();
foreach ( $container -> getAliases () as $definitionId => $target ) {
$targetId = ( string ) $target ;
// Special case: leave this target alone
if ( 'service_container' === $targetId ) {
continue ;
}
// Check if target needs to be replaces
if ( isset ( $replacements [ $targetId ])) {
$container -> setAlias ( $definitionId , $replacements [ $targetId ]);
}
// No neeed to process the same target twice
if ( isset ( $seenAliasTargets [ $targetId ])) {
continue ;
}
// Process new target
$seenAliasTargets [ $targetId ] = true ;
2015-08-17 17:00:26 -07:00
try {
2017-02-02 16:28:38 -08:00
$definition = $container -> getDefinition ( $targetId );
2015-08-17 17:00:26 -07:00
} catch ( InvalidArgumentException $e ) {
2017-02-02 16:28:38 -08:00
throw new InvalidArgumentException ( sprintf ( 'Unable to replace alias "%s" with actual definition "%s".' , $definitionId , $targetId ), null , $e );
2015-08-17 17:00:26 -07:00
}
if ( $definition -> isPublic ()) {
continue ;
}
2017-02-02 16:28:38 -08:00
// Remove private definition and schedule for replacement
2015-08-17 17:00:26 -07:00
$definition -> setPublic ( true );
2017-02-02 16:28:38 -08:00
$container -> setDefinition ( $definitionId , $definition );
$container -> removeDefinition ( $targetId );
$replacements [ $targetId ] = $definitionId ;
2015-08-17 17:00:26 -07:00
}
2017-02-02 16:28:38 -08:00
// Now replace target instances in all definitions
foreach ( $container -> getDefinitions () as $definitionId => $definition ) {
$definition -> setArguments ( $this -> updateArgumentReferences ( $replacements , $definitionId , $definition -> getArguments ()));
$definition -> setMethodCalls ( $this -> updateArgumentReferences ( $replacements , $definitionId , $definition -> getMethodCalls ()));
$definition -> setProperties ( $this -> updateArgumentReferences ( $replacements , $definitionId , $definition -> getProperties ()));
$definition -> setFactoryService ( $this -> updateFactoryReferenceId ( $replacements , $definition -> getFactoryService ( false )), false );
$definition -> setFactory ( $this -> updateFactoryReference ( $replacements , $definition -> getFactory ()));
2015-08-17 17:00:26 -07:00
}
}
/**
2017-02-02 16:28:38 -08:00
* Recursively updates references in an array .
2015-08-17 17:00:26 -07:00
*
2017-02-02 16:28:38 -08:00
* @ param array $replacements Table of aliases to replace
* @ param string $definitionId Identifier of this definition
* @ param array $arguments Where to replace the aliases
2015-08-17 17:00:26 -07:00
*
* @ return array
*/
2017-02-02 16:28:38 -08:00
private function updateArgumentReferences ( array $replacements , $definitionId , array $arguments )
2015-08-17 17:00:26 -07:00
{
foreach ( $arguments as $k => $argument ) {
2017-02-02 16:28:38 -08:00
// Handle recursion step
2015-08-17 17:00:26 -07:00
if ( is_array ( $argument )) {
2017-02-02 16:28:38 -08:00
$arguments [ $k ] = $this -> updateArgumentReferences ( $replacements , $definitionId , $argument );
continue ;
}
// Skip arguments that don't need replacement
if ( ! $argument instanceof Reference ) {
continue ;
2015-08-17 17:00:26 -07:00
}
2017-02-02 16:28:38 -08:00
$referenceId = ( string ) $argument ;
if ( ! isset ( $replacements [ $referenceId ])) {
continue ;
}
// Perform the replacement
$newId = $replacements [ $referenceId ];
$arguments [ $k ] = new Reference ( $newId , $argument -> getInvalidBehavior ());
$this -> compiler -> addLogMessage ( $this -> formatter -> formatUpdateReference ( $this , $definitionId , $referenceId , $newId ));
2015-08-17 17:00:26 -07:00
}
return $arguments ;
}
2016-04-20 09:56:34 -07:00
2017-02-02 16:28:38 -08:00
/**
* Returns the updated reference for the factory service .
*
* @ param array $replacements Table of aliases to replace
* @ param string | null $referenceId Factory service reference identifier
*
* @ return string | null
*/
private function updateFactoryReferenceId ( array $replacements , $referenceId )
2016-04-20 09:56:34 -07:00
{
2017-02-02 16:28:38 -08:00
if ( null === $referenceId ) {
2016-04-20 09:56:34 -07:00
return ;
}
2017-02-02 16:28:38 -08:00
return isset ( $replacements [ $referenceId ]) ? $replacements [ $referenceId ] : $referenceId ;
2016-04-20 09:56:34 -07:00
}
2017-02-02 16:28:38 -08:00
private function updateFactoryReference ( array $replacements , $factory )
2016-04-20 09:56:34 -07:00
{
2017-02-02 16:28:38 -08:00
if ( is_array ( $factory ) && $factory [ 0 ] instanceof Reference && isset ( $replacements [ $referenceId = ( string ) $factory [ 0 ]])) {
$factory [ 0 ] = new Reference ( $replacements [ $referenceId ], $factory [ 0 ] -> getInvalidBehavior ());
2016-04-20 09:56:34 -07:00
}
return $factory ;
}
2015-08-17 17:00:26 -07:00
}