2026-02-25 06:59:34 +00: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\Console\DependencyInjection ;
2026-02-27 00:03:00 +00:00
use Symfony\Component\Console\Attribute\AsCommand ;
2026-02-25 06:59:34 +00:00
use Symfony\Component\Console\Command\Command ;
use Symfony\Component\Console\Command\LazyCommand ;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader ;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument ;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface ;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass ;
use Symfony\Component\DependencyInjection\ContainerBuilder ;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException ;
use Symfony\Component\DependencyInjection\Reference ;
use Symfony\Component\DependencyInjection\TypedReference ;
/**
* Registers console commands .
*
* @ author Grégoire Pineau < lyrixx @ lyrixx . info >
*/
class AddConsoleCommandPass implements CompilerPassInterface
{
2026-02-27 00:03:00 +00:00
public function process ( ContainerBuilder $container ) : void
2026-02-25 06:59:34 +00:00
{
2026-02-27 00:03:00 +00:00
$commandServices = $container -> findTaggedServiceIds ( 'console.command' , true );
2026-02-25 06:59:34 +00:00
$lazyCommandMap = [];
$lazyCommandRefs = [];
$serviceIds = [];
foreach ( $commandServices as $id => $tags ) {
$definition = $container -> getDefinition ( $id );
$class = $container -> getParameterBag () -> resolveValue ( $definition -> getClass ());
2026-02-27 00:03:00 +00:00
if ( ! $r = $container -> getReflectionClass ( $class )) {
throw new InvalidArgumentException ( \sprintf ( 'Class "%s" used for service "%s" cannot be found.' , $class , $id ));
}
if ( ! $r -> isSubclassOf ( Command :: class )) {
if ( ! $r -> hasMethod ( '__invoke' )) {
throw new InvalidArgumentException ( \sprintf ( 'The service "%s" tagged "%s" must either be a subclass of "%s" or have an "__invoke()" method.' , $id , 'console.command' , Command :: class ));
2026-02-25 06:59:34 +00:00
}
2026-02-27 00:03:00 +00:00
$invokableRef = new Reference ( $id );
$definition = $container -> register ( $id .= '.command' , $class = Command :: class )
-> addMethodCall ( 'setCode' , [ $invokableRef ]);
} else {
$invokableRef = null ;
2026-02-25 06:59:34 +00:00
}
2026-02-27 00:03:00 +00:00
$definition -> addTag ( 'container.no_preload' );
/** @var AsCommand|null $attribute */
$attribute = ( $r -> getAttributes ( AsCommand :: class )[ 0 ] ? ? null ) ? -> newInstance ();
$defaultName = $attribute ? -> name ;
$aliases = str_replace ( '%' , '%%' , $tags [ 0 ][ 'command' ] ? ? $defaultName ? ? '' );
$aliases = explode ( '|' , $aliases );
2026-02-25 06:59:34 +00:00
$commandName = array_shift ( $aliases );
if ( $isHidden = '' === $commandName ) {
$commandName = array_shift ( $aliases );
}
if ( null === $commandName ) {
2026-02-27 00:03:00 +00:00
if ( $definition -> isPrivate () || $definition -> hasTag ( 'container.private' )) {
2026-02-25 06:59:34 +00:00
$commandId = 'console.command.public_alias.' . $id ;
$container -> setAlias ( $commandId , $id ) -> setPublic ( true );
$id = $commandId ;
}
$serviceIds [] = $id ;
continue ;
}
$description = $tags [ 0 ][ 'description' ] ? ? null ;
2026-02-27 00:03:00 +00:00
$help = $tags [ 0 ][ 'help' ] ? ? null ;
$usages = $tags [ 0 ][ 'usages' ] ? ? null ;
2026-02-25 06:59:34 +00:00
unset ( $tags [ 0 ]);
$lazyCommandMap [ $commandName ] = $id ;
$lazyCommandRefs [ $id ] = new TypedReference ( $id , $class );
foreach ( $aliases as $alias ) {
$lazyCommandMap [ $alias ] = $id ;
}
foreach ( $tags as $tag ) {
if ( isset ( $tag [ 'command' ])) {
$aliases [] = $tag [ 'command' ];
$lazyCommandMap [ $tag [ 'command' ]] = $id ;
}
2026-02-27 00:03:00 +00:00
$description ? ? = $tag [ 'description' ] ? ? null ;
$help ? ? = $tag [ 'help' ] ? ? null ;
$usages ? ? = $tag [ 'usages' ] ? ? null ;
2026-02-25 06:59:34 +00:00
}
$definition -> addMethodCall ( 'setName' , [ $commandName ]);
if ( $aliases ) {
$definition -> addMethodCall ( 'setAliases' , [ $aliases ]);
}
if ( $isHidden ) {
$definition -> addMethodCall ( 'setHidden' , [ true ]);
}
2026-02-27 00:03:00 +00:00
if ( $help && $invokableRef ) {
$definition -> addMethodCall ( 'setHelp' , [ str_replace ( '%' , '%%' , $help )]);
}
if ( $usages ) {
foreach ( $usages as $usage ) {
$definition -> addMethodCall ( 'addUsage' , [ $usage ]);
2026-02-25 06:59:34 +00:00
}
}
2026-02-27 00:03:00 +00:00
if ( $description ? ? = $attribute ? -> description ) {
$escapedDescription = str_replace ( '%' , '%%' , $description );
$definition -> addMethodCall ( 'setDescription' , [ $escapedDescription ]);
2026-02-25 06:59:34 +00:00
$container -> register ( '.' . $id . '.lazy' , LazyCommand :: class )
2026-02-27 00:03:00 +00:00
-> setArguments ([ $commandName , $aliases , $escapedDescription , $isHidden , new ServiceClosureArgument ( $lazyCommandRefs [ $id ])]);
2026-02-25 06:59:34 +00:00
$lazyCommandRefs [ $id ] = new Reference ( '.' . $id . '.lazy' );
}
}
$container
2026-02-27 00:03:00 +00:00
-> register ( 'console.command_loader' , ContainerCommandLoader :: class )
2026-02-25 06:59:34 +00:00
-> setPublic ( true )
2026-02-27 00:03:00 +00:00
-> addTag ( 'container.no_preload' )
2026-02-25 06:59:34 +00:00
-> setArguments ([ ServiceLocatorTagPass :: register ( $container , $lazyCommandRefs ), $lazyCommandMap ]);
$container -> setParameter ( 'console.command.ids' , $serviceIds );
}
}