diff --git a/packages/CakePHPToSymfony/src/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector.php b/packages/CakePHPToSymfony/src/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector.php index 7acf08db73b..879587e4c41 100644 --- a/packages/CakePHPToSymfony/src/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector.php +++ b/packages/CakePHPToSymfony/src/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector.php @@ -6,11 +6,10 @@ namespace Rector\CakePHPToSymfony\Rector\Class_; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\ClassMethod; use Rector\BetterPhpDocParser\PhpDocNode\Symfony\SymfonyRouteTagValueNode; use Rector\CakePHPToSymfony\Rector\AbstractCakePHPRector; +use Rector\FrameworkMigration\Symfony\ImplicitToExplicitRoutingAnnotationDecorator; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\PHPStan\Type\FullyQualifiedObjectType; use Rector\RectorDefinition\CodeSample; use Rector\RectorDefinition\RectorDefinition; use Rector\Util\RectorStrings; @@ -24,9 +23,15 @@ use Rector\Util\RectorStrings; final class CakePHPImplicitRouteToExplicitRouteAnnotationRector extends AbstractCakePHPRector { /** - * @var string + * @var ImplicitToExplicitRoutingAnnotationDecorator */ - private const HAS_FRESH_ROUTE_ANNOTATION_ATTRIBUTE = 'has_fresh_route_annotation'; + private $implicitToExplicitRoutingAnnotationDecorator; + + public function __construct( + ImplicitToExplicitRoutingAnnotationDecorator $implicitToExplicitRoutingAnnotationDecorator + ) { + $this->implicitToExplicitRoutingAnnotationDecorator = $implicitToExplicitRoutingAnnotationDecorator; + } public function getDefinition(): RectorDefinition { @@ -92,7 +97,11 @@ PHP $name = RectorStrings::camelCaseToUnderscore($combined); $symfonyRoutePhpDocTagValueNode = $this->createSymfonyRoutePhpDocTagValueNode($path, $name); - $this->addSymfonyRouteShortTagNodeWithUse($symfonyRoutePhpDocTagValueNode, $classMethod); + + $this->implicitToExplicitRoutingAnnotationDecorator->decorateClassMethodWithRouteAnnotation( + $classMethod, + $symfonyRoutePhpDocTagValueNode + ); } return $node; @@ -102,20 +111,4 @@ PHP { return new SymfonyRouteTagValueNode($path, $name); } - - /** - * @todo reuse from RouterListToControllerAnnotationsRector - */ - private function addSymfonyRouteShortTagNodeWithUse( - SymfonyRouteTagValueNode $symfonyRouteTagValueNode, - ClassMethod $classMethod - ): void { - // @todo use empty phpdoc info - $this->docBlockManipulator->addTagValueNodeWithShortName($classMethod, $symfonyRouteTagValueNode); - - $symfonyRouteUseObjectType = new FullyQualifiedObjectType(SymfonyRouteTagValueNode::CLASS_NAME); - $this->addUseType($symfonyRouteUseObjectType, $classMethod); - - $classMethod->setAttribute(self::HAS_FRESH_ROUTE_ANNOTATION_ATTRIBUTE, true); - } } diff --git a/packages/CakePHPToSymfony/tests/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector/Fixture/skip_private.php.inc b/packages/CakePHPToSymfony/tests/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector/Fixture/skip_private.php.inc new file mode 100644 index 00000000000..a81833440c5 --- /dev/null +++ b/packages/CakePHPToSymfony/tests/Rector/Class_/CakePHPImplicitRouteToExplicitRouteAnnotationRector/Fixture/skip_private.php.inc @@ -0,0 +1,10 @@ +docBlockManipulator = $docBlockManipulator; + $this->useAddingCommander = $useAddingCommander; + } + + public function decorateClassMethodWithRouteAnnotation( + ClassMethod $classMethod, + SymfonyRouteTagValueNode $symfonyRouteTagValueNode + ): void { + $this->docBlockManipulator->addTagValueNodeWithShortName($classMethod, $symfonyRouteTagValueNode); + + $symfonyRouteUseObjectType = new FullyQualifiedObjectType(SymfonyRouteTagValueNode::CLASS_NAME); + $this->addUseType($symfonyRouteUseObjectType, $classMethod); + + // remove + $this->useAddingCommander->removeShortUse($classMethod, 'Route'); + + $classMethod->setAttribute(self::HAS_ROUTE_ANNOTATION, true); + } + + /** + * @param FullyQualifiedObjectType|AliasedObjectType $objectType + */ + private function addUseType(ObjectType $objectType, Node $positionNode): void + { + assert($objectType instanceof FullyQualifiedObjectType || $objectType instanceof AliasedObjectType); + + $this->useAddingCommander->addUseImport($positionNode, $objectType); + } } diff --git a/packages/NetteToSymfony/src/Rector/ClassMethod/RouterListToControllerAnnotationsRector.php b/packages/NetteToSymfony/src/Rector/ClassMethod/RouterListToControllerAnnotationsRector.php index 3e7426c8206..92016f6e056 100644 --- a/packages/NetteToSymfony/src/Rector/ClassMethod/RouterListToControllerAnnotationsRector.php +++ b/packages/NetteToSymfony/src/Rector/ClassMethod/RouterListToControllerAnnotationsRector.php @@ -15,11 +15,11 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Type\ObjectType; use Rector\BetterPhpDocParser\PhpDocNode\Symfony\SymfonyRouteTagValueNode; +use Rector\FrameworkMigration\Symfony\ImplicitToExplicitRoutingAnnotationDecorator; use Rector\NetteToSymfony\Route\RouteInfoFactory; use Rector\NetteToSymfony\ValueObject\RouteInfo; use Rector\NodeContainer\ParsedNodesByType; use Rector\NodeTypeResolver\Node\AttributeKey; -use Rector\PHPStan\Type\FullyQualifiedObjectType; use Rector\Rector\AbstractRector; use Rector\RectorDefinition\CodeSample; use Rector\RectorDefinition\RectorDefinition; @@ -35,11 +35,6 @@ use ReflectionMethod; */ final class RouterListToControllerAnnotationsRector extends AbstractRector { - /** - * @var string - */ - private const HAS_FRESH_ROUTE_ANNOTATION_ATTRIBUTE = 'has_fresh_route_annotation'; - /** * @var ParsedNodesByType */ @@ -55,14 +50,21 @@ final class RouterListToControllerAnnotationsRector extends AbstractRector */ private $returnTypeInferer; + /** + * @var ImplicitToExplicitRoutingAnnotationDecorator + */ + private $implicitToExplicitRoutingAnnotationDecorator; + public function __construct( ParsedNodesByType $parsedNodesByType, RouteInfoFactory $routeInfoFactory, - ReturnTypeInferer $returnTypeInferer + ReturnTypeInferer $returnTypeInferer, + ImplicitToExplicitRoutingAnnotationDecorator $implicitToExplicitRoutingAnnotationDecorator ) { $this->parsedNodesByType = $parsedNodesByType; $this->routeInfoFactory = $routeInfoFactory; $this->returnTypeInferer = $returnTypeInferer; + $this->implicitToExplicitRoutingAnnotationDecorator = $implicitToExplicitRoutingAnnotationDecorator; } public function getDefinition(): RectorDefinition @@ -163,7 +165,10 @@ PHP $symfonyRoutePhpDocTagValueNode = $this->createSymfonyRoutePhpDocTagValueNode($routeInfo); - $this->addSymfonyRouteShortTagNodeWithUse($symfonyRoutePhpDocTagValueNode, $classMethod); + $this->implicitToExplicitRoutingAnnotationDecorator->decorateClassMethodWithRouteAnnotation( + $classMethod, + $symfonyRoutePhpDocTagValueNode + ); } // complete all other non-explicit methods, from "/" @@ -240,21 +245,6 @@ PHP return new SymfonyRouteTagValueNode($routeInfo->getPath(), null, $routeInfo->getHttpMethods()); } - private function addSymfonyRouteShortTagNodeWithUse( - SymfonyRouteTagValueNode $symfonyRouteTagValueNode, - ClassMethod $classMethod - ): void { - $this->docBlockManipulator->addTagValueNodeWithShortName($classMethod, $symfonyRouteTagValueNode); - - $symfonyRouteUseObjectType = new FullyQualifiedObjectType(SymfonyRouteTagValueNode::CLASS_NAME); - $this->addUseType($symfonyRouteUseObjectType, $classMethod); - - // remove - $this->removeShortUse('Route', $classMethod); - - $classMethod->setAttribute(self::HAS_FRESH_ROUTE_ANNOTATION_ATTRIBUTE, true); - } - private function completeImplicitRoutes(): void { $presenterClasses = $this->classLikeParsedNodesFinder->findClassesBySuffix('Presenter'); @@ -268,14 +258,14 @@ PHP $path = $this->resolvePathFromClassAndMethodNodes($presenterClass, $classMethod); $symfonyRoutePhpDocTagValueNode = new SymfonyRouteTagValueNode($path); - $this->addSymfonyRouteShortTagNodeWithUse($symfonyRoutePhpDocTagValueNode, $classMethod); + $this->implicitToExplicitRoutingAnnotationDecorator->decorateClassMethodWithRouteAnnotation( + $classMethod, + $symfonyRoutePhpDocTagValueNode + ); } } } - /** - * @todo allow extension with custom resolvers - */ private function isRouteStaticCallMatch(StaticCall $staticCall): bool { $className = $this->getName($staticCall->class); @@ -319,7 +309,7 @@ PHP return true; } - if ($node->getAttribute(self::HAS_FRESH_ROUTE_ANNOTATION_ATTRIBUTE)) { + if ($node->getAttribute(ImplicitToExplicitRoutingAnnotationDecorator::HAS_ROUTE_ANNOTATION)) { return true; } diff --git a/src/Rector/AbstractRector/NodeCommandersTrait.php b/src/Rector/AbstractRector/NodeCommandersTrait.php index 829e1dca10b..47c2064119d 100644 --- a/src/Rector/AbstractRector/NodeCommandersTrait.php +++ b/src/Rector/AbstractRector/NodeCommandersTrait.php @@ -87,11 +87,6 @@ trait NodeCommandersTrait $this->useAddingCommander->addUseImport($positionNode, $objectType); } - protected function removeShortUse(string $shortUse, Node $positionNode): void - { - $this->useAddingCommander->removeShortUse($positionNode, $shortUse); - } - protected function addNodeAfterNode(Node $newNode, Node $positionNode): void { $this->nodeAddingCommander->addNodeAfterNode($newNode, $positionNode);