55namespace Rector \Symfony \Symfony73 \Rector \Class_ ;
66
77use PhpParser \Node ;
8- use PhpParser \Node \Attribute ;
9- use PhpParser \Node \Expr \ClassConstFetch ;
10- use PhpParser \Node \Expr \ConstFetch ;
118use PhpParser \Node \Expr \MethodCall ;
129use PhpParser \Node \Expr \Variable ;
1310use PhpParser \Node \Identifier ;
1411use PhpParser \Node \Name ;
15- use PhpParser \Node \Scalar \String_ ;
1612use PhpParser \Node \Stmt \Class_ ;
1713use PhpParser \Node \Stmt \ClassMethod ;
1814use PhpParser \Node \Stmt \Expression ;
1915use Rector \Doctrine \NodeAnalyzer \AttributeFinder ;
20- use Rector \Exception \ShouldNotHappenException ;
21- use Rector \PhpParser \Node \Value \ValueResolver ;
2216use Rector \Privatization \NodeManipulator \VisibilityManipulator ;
2317use Rector \Rector \AbstractRector ;
2418use Rector \Symfony \Enum \CommandMethodName ;
2519use Rector \Symfony \Enum \SymfonyAttribute ;
2620use Rector \Symfony \Enum \SymfonyClass ;
2721use Rector \Symfony \Symfony73 \NodeAnalyzer \CommandArgumentsAndOptionsResolver ;
2822use Rector \Symfony \Symfony73 \NodeFactory \CommandInvokeParamsFactory ;
23+ use Rector \Symfony \Symfony73 \NodeTransformer \ConsoleOptionAndArgumentMethodCallVariableReplacer ;
24+ use Rector \Symfony \Symfony73 \NodeTransformer \OutputInputSymfonyStyleReplacer ;
2925use Rector \ValueObject \MethodName ;
3026use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
3127use Symplify \RuleDocGenerator \ValueObject \RuleDefinition ;
@@ -46,8 +42,9 @@ public function __construct(
4642 private readonly AttributeFinder $ attributeFinder ,
4743 private readonly CommandArgumentsAndOptionsResolver $ commandArgumentsAndOptionsResolver ,
4844 private readonly CommandInvokeParamsFactory $ commandInvokeParamsFactory ,
49- private readonly ValueResolver $ valueResolver ,
45+ private readonly ConsoleOptionAndArgumentMethodCallVariableReplacer $ consoleOptionAndArgumentMethodCallVariableReplacer ,
5046 private readonly VisibilityManipulator $ visibilityManipulator ,
47+ private readonly OutputInputSymfonyStyleReplacer $ outputInputSymfonyStyleReplacer
5148 ) {
5249 }
5350
@@ -162,7 +159,7 @@ public function refactor(Node $node): ?Class_
162159 $ commandOptions = $ this ->commandArgumentsAndOptionsResolver ->collectCommandOptions ($ configureClassMethod );
163160
164161 // 4. remove configure() method
165- $ this ->removeConfigureClassMethod ($ node );
162+ $ this ->removeConfigureClassMethodIfNotUseful ($ node );
166163
167164 // 5. decorate __invoke method with attributes
168165 $ invokeParams = $ this ->commandInvokeParamsFactory ->createParams ($ commandArguments , $ commandOptions );
@@ -189,7 +186,7 @@ public function refactor(Node $node): ?Class_
189186
190187 if ($ configureClassMethod instanceof ClassMethod) {
191188 // 7. replace input->getArgument() and input->getOption() calls with direct variable access
192- $ this ->replaceInputArgumentOptionFetchWithVariables ($ executeClassMethod );
189+ $ this ->consoleOptionAndArgumentMethodCallVariableReplacer -> replace ($ executeClassMethod );
193190 }
194191
195192 return $ node ;
@@ -207,7 +204,7 @@ private function isComplexCommand(Class_ $class): bool
207204 return $ class ->getMethod (CommandMethodName::INITIALIZE ) instanceof ClassMethod;
208205 }
209206
210- private function removeConfigureClassMethod (Class_ $ class ): void
207+ private function removeConfigureClassMethodIfNotUseful (Class_ $ class ): void
211208 {
212209 foreach ($ class ->stmts as $ key => $ stmt ) {
213210 if (! $ stmt instanceof ClassMethod) {
@@ -239,7 +236,7 @@ private function removeConfigureClassMethod(Class_ $class): void
239236 }
240237 }
241238
242- // 2. if configure() has become empty → remove the method itself
239+ // 2. if configure() has became empty → remove the method itself
243240 if ($ stmt ->stmts === [] || $ stmt ->stmts === null ) {
244241 unset($ class ->stmts [$ key ]);
245242 }
@@ -248,39 +245,6 @@ private function removeConfigureClassMethod(Class_ $class): void
248245 }
249246 }
250247
251- private function replaceInputArgumentOptionFetchWithVariables (ClassMethod $ executeClassMethod ): void
252- {
253- $ this ->traverseNodesWithCallable ($ executeClassMethod ->stmts , function (Node $ node ): ?Variable {
254- if (! $ node instanceof MethodCall) {
255- return null ;
256- }
257-
258- if (! $ this ->isName ($ node ->var , 'input ' )) {
259- return null ;
260- }
261-
262- if (! $ this ->isNames ($ node ->name , ['getOption ' , 'getArgument ' ])) {
263- return null ;
264- }
265-
266- $ firstArgValue = $ node ->getArgs ()[0 ]
267- ->value ;
268-
269- if ($ firstArgValue instanceof ClassConstFetch || $ firstArgValue instanceof ConstFetch) {
270- $ variableName = $ this ->valueResolver ->getValue ($ firstArgValue );
271- return new Variable (str_replace ('- ' , '_ ' , $ variableName ));
272- }
273-
274- if (! $ firstArgValue instanceof String_) {
275- // unable to resolve argument/option name
276- throw new ShouldNotHappenException ();
277- }
278-
279- $ variableName = $ firstArgValue ->value ;
280- return new Variable (str_replace ('- ' , '_ ' , $ variableName ));
281- });
282- }
283-
284248 private function isFluentArgumentOptionChain (MethodCall $ methodCall ): bool
285249 {
286250 $ current = $ methodCall ;
@@ -291,7 +255,8 @@ private function isFluentArgumentOptionChain(MethodCall $methodCall): bool
291255 return false ;
292256 }
293257
294- $ current = $ current ->var ; // go one step left
258+ // go one step left
259+ $ current = $ current ->var ;
295260 }
296261
297262 // the left-most var must be $this
0 commit comments