1111
1212namespace Symfony \Bundle \MakerBundle \Maker ;
1313
14- use Psr \Container \ContainerInterface ;
1514use Symfony \Bundle \MakerBundle \ConsoleStyle ;
1615use Symfony \Bundle \MakerBundle \DependencyBuilder ;
16+ use Symfony \Bundle \MakerBundle \DependencyInjection \DecoratorHelper ;
17+ use Symfony \Bundle \MakerBundle \Exception \RuntimeCommandException ;
1718use Symfony \Bundle \MakerBundle \Generator ;
1819use Symfony \Bundle \MakerBundle \InputConfiguration ;
1920use Symfony \Bundle \MakerBundle \Str ;
2223use Symfony \Component \Console \Command \Command ;
2324use Symfony \Component \Console \Input \InputArgument ;
2425use Symfony \Component \Console \Input \InputInterface ;
26+ use Symfony \Component \Console \Input \InputOption ;
27+ use Symfony \Component \Console \Question \ConfirmationQuestion ;
2528use Symfony \Component \Console \Question \Question ;
2629use Symfony \Component \DependencyInjection \Attribute \AsDecorator ;
2730
3033 */
3134final class MakeDecorator extends AbstractMaker
3235{
33- /**
34- * @param array<string> $ids
35- */
3636 public function __construct (
37- private readonly ContainerInterface $ container ,
38- private readonly array $ ids ,
37+ private readonly DecoratorHelper $ helper ,
3938 ) {
4039 }
4140
@@ -46,16 +45,21 @@ public static function getCommandName(): string
4645
4746 public static function getCommandDescription (): string
4847 {
49- return 'Create CRUD for Doctrine entity class ' ;
48+ return 'Create a decorator of a service ' ;
5049 }
5150
5251 public function configureCommand (Command $ command , InputConfiguration $ inputConfig ): void
5352 {
5453 $ command
5554 ->addArgument ('id ' , InputArgument::OPTIONAL , 'The ID of the service to decorate. ' )
5655 ->addArgument ('decorator-class ' , InputArgument::OPTIONAL , \sprintf ('The class name of the service to create (e.g. <fg=yellow>%sDecorator</>) ' , Str::asClassName (Str::getRandomTerm ())))
56+ ->addOption ('priority ' , null , InputOption::VALUE_REQUIRED , 'The priority of this decoration when multiple decorators are declared for the same service. ' )
57+ ->addOption ('on-invalid ' , null , InputOption::VALUE_REQUIRED , 'The behavior to adopt when the decoration is invalid. ' )
5758 ->setHelp ($ this ->getHelpFileContents ('MakeDecorator.txt ' ))
5859 ;
60+
61+ $ inputConfig ->setArgumentAsNonInteractive ('id ' );
62+ $ inputConfig ->setArgumentAsNonInteractive ('decorator-class ' );
5963 }
6064
6165 public function configureDependencies (DependencyBuilder $ dependencies ): void
@@ -73,14 +77,36 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma
7377 $ argument = $ command ->getDefinition ()->getArgument ('id ' );
7478
7579 ($ question = new Question ($ argument ->getDescription ()))
76- ->setAutocompleterValues ($ this ->ids )
77- ->setValidator (fn ($ answer ) => Validator::serviceExists ($ answer , $ this -> ids ))
80+ ->setAutocompleterValues ($ suggestIds = $ this ->helper -> suggestIds () )
81+ ->setValidator (fn ($ answer ) => Validator::serviceExists ($ answer , $ suggestIds ))
7882 ->setMaxAttempts (3 );
7983
8084 $ input ->setArgument ('id ' , $ io ->askQuestion ($ question ));
8185 }
8286
8387 $ id = $ input ->getArgument ('id ' );
88+ if (null === $ realId = $ this ->helper ->getRealId ($ id )) {
89+ $ guessCount = \count ($ guessRealIds = $ this ->helper ->guessRealIds ($ id ));
90+
91+ if (0 === $ guessCount ) {
92+ throw new RuntimeCommandException (\sprintf ('Cannot find nor guess service for given id "%s". ' , $ id ));
93+ } elseif (1 === $ guessCount ) {
94+ $ question = new ConfirmationQuestion (\sprintf ('<fg=green>Did you mean</> <fg=yellow>"%s"</> <fg=green>?</> ' , $ guessRealIds [0 ]), true );
95+
96+ if (!$ io ->askQuestion ($ question )) {
97+ throw new RuntimeCommandException (\sprintf ('Cannot find nor guess service for given id "%s". ' , $ id ));
98+ }
99+
100+ $ input ->setArgument ('id ' , $ id = $ guessRealIds [0 ]);
101+ } else {
102+ $ input ->setArgument (
103+ 'id ' ,
104+ $ id = $ io ->choice (\sprintf ('Multiple services found for "%s", choice which one you want to decorate? ' , $ id ), $ guessRealIds ),
105+ );
106+ }
107+ } else {
108+ $ input ->setArgument ('id ' , $ id = $ realId );
109+ }
84110
85111 // Ask for decorator classname.
86112 if (null === $ input ->getArgument ('decorator-class ' )) {
@@ -111,7 +137,17 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
111137 '' ,
112138 );
113139
114- $ decoratedInfo = $ this ->createDecoratorInfo ($ id , $ classNameDetails ->getFullName ());
140+ $ priority = $ input ->getOption ('priority ' );
141+ $ onInvalid = $ input ->getOption ('on-invalid ' );
142+
143+ $ decoratedInfo = new DecoratorInfo (
144+ $ classNameDetails ->getFullName (),
145+ $ id ,
146+ $ this ->helper ->getClass ($ id ),
147+ empty ($ priority ) ? null : $ priority ,
148+ null === $ onInvalid || 1 === $ onInvalid ? null : $ onInvalid ,
149+ );
150+
115151 $ classData = $ decoratedInfo ->getClassData ();
116152
117153 $ generator ->generateClassFromClassData (
@@ -126,16 +162,4 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen
126162
127163 $ this ->writeSuccessMessage ($ io );
128164 }
129-
130- private function createDecoratorInfo (string $ id , string $ decoratorClass ): DecoratorInfo
131- {
132- return new DecoratorInfo (
133- $ decoratorClass ,
134- match (true ) {
135- class_exists ($ id ), interface_exists ($ id ) => $ id ,
136- default => $ this ->container ->get ($ id )::class,
137- },
138- $ id ,
139- );
140- }
141165}
0 commit comments