From 3a39e28cf5722e046c86d17b9c164e5e7cc7e984 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 29 Aug 2019 14:53:30 +0200 Subject: [PATCH 1/5] Add uuid only to entities with id --- .../AddUuidToEntityWhereMissingRector.php | 5 ++ .../AddUuidToEntityWhereMissingRectorTest.php | 1 + .../add_single_table_inheritance.php.inc | 68 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance.php.inc diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php index e8d541fb2e2b..59d789f9a09a 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php @@ -70,6 +70,11 @@ public function refactor(Node $node): ?Node return null; } + // id is needed + if (! $this->classManipulator->getProperty($node, 'id')) { + return null; + } + // already has $uuid property if ($this->classManipulator->getProperty($node, 'uuid')) { return null; diff --git a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php index bf1179967a99..dae37821e816 100644 --- a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php +++ b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php @@ -14,6 +14,7 @@ public function test(): void __DIR__ . '/Fixture/already_has_constructor.php.inc', __DIR__ . '/Fixture/process_string_id.php.inc', __DIR__ . '/Fixture/with_parent_constructor.php.inc', + __DIR__ . '/Fixture/add_single_table_inheritance.php.inc', // skip __DIR__ . '/Fixture/skip_id_with_uuid_type.php.inc', __DIR__ . '/Fixture/skip_id_with_uuid_binary_type.php.inc', diff --git a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance.php.inc b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance.php.inc new file mode 100644 index 000000000000..bb1efab4171a --- /dev/null +++ b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance.php.inc @@ -0,0 +1,68 @@ + +----- +uuid = \Ramsey\Uuid\Uuid::uuid4(); + } + /** + * @var \Ramsey\Uuid\UuidInterface + * @ORM\Column (type="uuid_binary", unique=true, nullable=true) + */ + private $uuid; + /** + * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + private $id; +} + +/** + * @ORM\Entity + */ +class AddSingleTableInheritance extends ParentSingleTableInheritance +{ +} + +?> From fc99b78e5253a93c370021433edcf546947c1476 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 29 Aug 2019 15:08:27 +0200 Subject: [PATCH 2/5] Rename EntitiesWithAddedUuidPropertyCollector to more generic EntitiesWithAddedUuidPropertyCollector --- .../EntitiesWithAddedPropertyCollector.php | 24 ++++++++++ ...EntitiesWithAddedUuidPropertyCollector.php | 24 ---------- ...tiesWithAddedPropertiesFinishExtension.php | 45 +++++++++++++++++++ ...rtEntitiesWithAddedUuidFinishExtension.php | 40 ----------------- .../AddUuidToEntityWhereMissingRector.php | 12 ++--- 5 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php delete mode 100644 packages/Doctrine/src/Collector/EntitiesWithAddedUuidPropertyCollector.php create mode 100644 packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php delete mode 100644 packages/Doctrine/src/Extension/ReportEntitiesWithAddedUuidFinishExtension.php diff --git a/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php b/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php new file mode 100644 index 000000000000..d82073a29d71 --- /dev/null +++ b/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php @@ -0,0 +1,24 @@ +propertiesByClasses[$class][] = $property; + } + + /** + * @return string[] + */ + public function getPropertiesByClasses(): array + { + return $this->propertiesByClasses; + } +} diff --git a/packages/Doctrine/src/Collector/EntitiesWithAddedUuidPropertyCollector.php b/packages/Doctrine/src/Collector/EntitiesWithAddedUuidPropertyCollector.php deleted file mode 100644 index b896e38d6e85..000000000000 --- a/packages/Doctrine/src/Collector/EntitiesWithAddedUuidPropertyCollector.php +++ /dev/null @@ -1,24 +0,0 @@ -classes[] = $class; - } - - /** - * @return string[] - */ - public function getClasses(): array - { - return $this->classes; - } -} diff --git a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php new file mode 100644 index 000000000000..229886bd78c7 --- /dev/null +++ b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php @@ -0,0 +1,45 @@ +entitiesWithAddedPropertyCollector = $entitiesWithAddedPropertyCollector; + $this->symfonyStyle = $symfonyStyle; + } + + public function run(): void + { + $classes = $this->entitiesWithAddedPropertyCollector->getPropertiesByClasses(); + + if ($classes === []) { + return; + } + + $this->symfonyStyle->title('Entities with new properties'); + + foreach ($this->entitiesWithAddedPropertyCollector->getPropertiesByClasses() as $class => $properties) { + $this->symfonyStyle->section($class); + $this->symfonyStyle->listing($properties); + $this->symfonyStyle->newLine(1); + } + } +} diff --git a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedUuidFinishExtension.php b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedUuidFinishExtension.php deleted file mode 100644 index 3cd672d87be4..000000000000 --- a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedUuidFinishExtension.php +++ /dev/null @@ -1,40 +0,0 @@ -entitiesWithAddedUuidPropertyCollector = $entitiesWithAddedUuidPropertyCollector; - $this->symfonyStyle = $symfonyStyle; - } - - public function run(): void - { - $classes = $this->entitiesWithAddedUuidPropertyCollector->getClasses(); - - if ($classes === []) { - return; - } - - $this->symfonyStyle->section('Entities with new nullable $uuid property'); - $this->symfonyStyle->listing($classes); - } -} diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php index 59d789f9a09a..ac1a9f74de21 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php @@ -8,7 +8,7 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; -use Rector\Doctrine\Collector\EntitiesWithAddedUuidPropertyCollector; +use Rector\Doctrine\Collector\EntitiesWithAddedPropertyCollector; use Rector\Doctrine\NodeFactory\EntityUuidNodeFactory; use Rector\PhpParser\Node\Manipulator\ClassManipulator; use Rector\Rector\AbstractRector; @@ -30,18 +30,18 @@ final class AddUuidToEntityWhereMissingRector extends AbstractRector private $classManipulator; /** - * @var EntitiesWithAddedUuidPropertyCollector + * @var EntitiesWithAddedPropertyCollector */ - private $entitiesWithAddedUuidPropertyCollector; + private $entitiesWithAddedPropertyCollector; public function __construct( EntityUuidNodeFactory $entityUuidNodeFactory, ClassManipulator $classManipulator, - EntitiesWithAddedUuidPropertyCollector $entitiesWithAddedUuidPropertyCollector + EntitiesWithAddedPropertyCollector $entitiesWithAddedPropertyCollector ) { $this->entityUuidNodeFactory = $entityUuidNodeFactory; $this->classManipulator = $classManipulator; - $this->entitiesWithAddedUuidPropertyCollector = $entitiesWithAddedUuidPropertyCollector; + $this->entitiesWithAddedPropertyCollector = $entitiesWithAddedPropertyCollector; } public function getDefinition(): RectorDefinition @@ -100,7 +100,7 @@ public function refactor(Node $node): ?Node /** @var string $class */ $class = $this->getName($node); - $this->entitiesWithAddedUuidPropertyCollector->addClass($class); + $this->entitiesWithAddedPropertyCollector->addClassAndProperty($class, 'uuid'); return $node; } From 02237369489d00d6cef297dd24afaab354be2040 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 29 Aug 2019 15:26:58 +0200 Subject: [PATCH 3/5] make id name property detection independent on the property name --- .../src/AbstarctRector/DoctrineTrait.php | 19 ++++++ .../EntitiesWithAddedPropertyCollector.php | 4 +- .../PhpDocParser/DoctrineDocBlockResolver.php | 10 +++ .../AddUuidToEntityWhereMissingRector.php | 7 +- .../AddUuidToEntityWhereMissingRectorTest.php | 3 +- ..._table_inheritance_with_identifier.php.inc | 68 +++++++++++++++++++ .../src/PhpDocParser/OrmTagParser.php | 8 +-- 7 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance_with_identifier.php.inc diff --git a/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php b/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php index 1b06d4bd6bc1..cf097841b365 100644 --- a/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php +++ b/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php @@ -26,6 +26,25 @@ protected function isDoctrineEntityClass(Class_ $class): bool return $this->doctrineDocBlockResolver->isDoctrineEntityClass($class); } + protected function isDoctrineEntityClassWithIdProperty(Class_ $class): bool + { + if (! $this->doctrineDocBlockResolver->isDoctrineEntityClass($class)) { + return false; + } + + foreach ($class->stmts as $classStmt) { + if (! $classStmt instanceof Property) { + continue; + } + + if ($this->doctrineDocBlockResolver->hasPropertyDoctrineIdTag($classStmt)) { + return true; + } + } + + return false; + } + protected function getTargetEntity(Property $property): ?string { return $this->doctrineDocBlockResolver->getTargetEntity($property); diff --git a/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php b/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php index d82073a29d71..8b4ad07d1f1b 100644 --- a/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php +++ b/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php @@ -5,7 +5,7 @@ final class EntitiesWithAddedPropertyCollector { /** - * @var string[] + * @var string[][] */ private $propertiesByClasses = []; @@ -15,7 +15,7 @@ public function addClassAndProperty(string $class, string $property): void } /** - * @return string[] + * @return string[][] */ public function getPropertiesByClasses(): array { diff --git a/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php b/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php index 4cfcbf91bdf7..6f39ad25d721 100644 --- a/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php +++ b/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php @@ -41,6 +41,16 @@ public function getTargetEntity(Property $property): ?string return $doctrineRelationTagValueNode->getTargetEntity(); } + public function hasPropertyDoctrineIdTag(Property $property): bool + { + $propertyPhpDocInfo = $this->getPhpDocInfo($property); + if ($propertyPhpDocInfo === null) { + return false; + } + + return (bool) $propertyPhpDocInfo->getDoctrineIdTagValueNode(); + } + public function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRelationTagValueNodeInterface { $propertyPhpDocInfo = $this->getPhpDocInfo($property); diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php index ac1a9f74de21..c7e145ac3b66 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php @@ -66,12 +66,7 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (! $this->isDoctrineEntityClass($node)) { - return null; - } - - // id is needed - if (! $this->classManipulator->getProperty($node, 'id')) { + if (! $this->isDoctrineEntityClassWithIdProperty($node)) { return null; } diff --git a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php index dae37821e816..4393ce603d36 100644 --- a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php +++ b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/AddUuidToEntityWhereMissingRectorTest.php @@ -15,7 +15,8 @@ public function test(): void __DIR__ . '/Fixture/process_string_id.php.inc', __DIR__ . '/Fixture/with_parent_constructor.php.inc', __DIR__ . '/Fixture/add_single_table_inheritance.php.inc', - // skip + __DIR__ . '/Fixture/add_single_table_inheritance_with_identifier.php.inc', + // skip __DIR__ . '/Fixture/skip_id_with_uuid_type.php.inc', __DIR__ . '/Fixture/skip_id_with_uuid_binary_type.php.inc', ]); diff --git a/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance_with_identifier.php.inc b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance_with_identifier.php.inc new file mode 100644 index 000000000000..1ae4b921c1a0 --- /dev/null +++ b/packages/Doctrine/tests/Rector/Class_/AddUuidToEntityWhereMissingRector/Fixture/add_single_table_inheritance_with_identifier.php.inc @@ -0,0 +1,68 @@ + +----- +uuid = \Ramsey\Uuid\Uuid::uuid4(); + } + /** + * @var \Ramsey\Uuid\UuidInterface + * @ORM\Column (type="uuid_binary", unique=true, nullable=true) + */ + private $uuid; + /** + * @var int + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + private $identifier; +} + +/** + * @ORM\Entity + */ +class AddSingleTableInheritanceAgain extends ParentSingleTableInheritanceWithIdentifier +{ +} + +?> diff --git a/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php b/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php index c80c3bf412a8..f6b1ca0ff859 100644 --- a/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php +++ b/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php @@ -101,6 +101,10 @@ private function createPropertyTagValueNode( Property $property, string $annotationContent ): ?DoctrineTagNodeInterface { + if ($tag === IdTagValueNode::SHORT_NAME) { + return $this->createIdTagValueNode(); + } + if ($tag === ColumnTagValueNode::SHORT_NAME) { return $this->createColumnTagValueNode($property, $annotationContent); } @@ -129,10 +133,6 @@ private function createPropertyTagValueNode( return $this->createJoinTableTagValeNode($property, $annotationContent); } - if ($tag === IdTagValueNode::SHORT_NAME) { - return $this->createIdTagValueNode(); - } - return null; } From bc9f3759cd673480240f700311c3542ca0b35d38 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 29 Aug 2019 16:31:27 +0200 Subject: [PATCH 4/5] improve new entity props collecting --- .../src/AbstarctRector/DoctrineTrait.php | 6 ++++ .../EntitiesWithAddedPropertyCollector.php | 24 ------------- .../EntityWithAddedPropertyCollector.php | 34 +++++++++++++++++++ ...tiesWithAddedPropertiesFinishExtension.php | 29 ++++++++-------- ...AddUuidMirrorForRelationPropertyRector.php | 34 ++++++++++++++++--- .../AddUuidToEntityWhereMissingRector.php | 12 +++---- 6 files changed, 90 insertions(+), 49 deletions(-) delete mode 100644 packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php create mode 100644 packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php diff --git a/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php b/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php index cf097841b365..d2d02ec40bb4 100644 --- a/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php +++ b/packages/Doctrine/src/AbstarctRector/DoctrineTrait.php @@ -5,6 +5,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; use Rector\Doctrine\PhpDocParser\DoctrineDocBlockResolver; +use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface; trait DoctrineTrait { @@ -49,4 +50,9 @@ protected function getTargetEntity(Property $property): ?string { return $this->doctrineDocBlockResolver->getTargetEntity($property); } + + protected function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRelationTagValueNodeInterface + { + return $this->doctrineDocBlockResolver->getDoctrineRelationTagValueNode($property); + } } diff --git a/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php b/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php deleted file mode 100644 index 8b4ad07d1f1b..000000000000 --- a/packages/Doctrine/src/Collector/EntitiesWithAddedPropertyCollector.php +++ /dev/null @@ -1,24 +0,0 @@ -propertiesByClasses[$class][] = $property; - } - - /** - * @return string[][] - */ - public function getPropertiesByClasses(): array - { - return $this->propertiesByClasses; - } -} diff --git a/packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php b/packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php new file mode 100644 index 000000000000..95285f336d05 --- /dev/null +++ b/packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php @@ -0,0 +1,34 @@ +propertiesByClass[$class]['properties'][] = $property; + } + + public function addClassToManyRelationProperty(string $class, string $property): void + { + $this->propertiesByClass[$class]['to_many_relations'][] = $property; + } + + public function addClassToOneRelationProperty(string $class, string $property): void + { + $this->propertiesByClass[$class]['to_one_relations'][] = $property; + } + + /** + * @return string[][][] + */ + public function getPropertiesByClass(): array + { + return $this->propertiesByClass; + } +} diff --git a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php index 229886bd78c7..66f06d1ce7ea 100644 --- a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php +++ b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php @@ -2,16 +2,17 @@ namespace Rector\Doctrine\Extension; +use Nette\Utils\Json; use Rector\Contract\Extension\FinishingExtensionInterface; -use Rector\Doctrine\Collector\EntitiesWithAddedPropertyCollector; +use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; use Symfony\Component\Console\Style\SymfonyStyle; final class ReportEntitiesWithAddedPropertiesFinishExtension implements FinishingExtensionInterface { /** - * @var EntitiesWithAddedPropertyCollector + * @var EntityWithAddedPropertyCollector */ - private $entitiesWithAddedPropertyCollector; + private $entityWithAddedPropertyCollector; /** * @var SymfonyStyle @@ -19,27 +20,27 @@ final class ReportEntitiesWithAddedPropertiesFinishExtension implements Finishin private $symfonyStyle; public function __construct( - EntitiesWithAddedPropertyCollector $entitiesWithAddedPropertyCollector, + EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector, SymfonyStyle $symfonyStyle ) { - $this->entitiesWithAddedPropertyCollector = $entitiesWithAddedPropertyCollector; + $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; $this->symfonyStyle = $symfonyStyle; } public function run(): void { - $classes = $this->entitiesWithAddedPropertyCollector->getPropertiesByClasses(); - - if ($classes === []) { + $propertiesByClass = $this->entityWithAddedPropertyCollector->getPropertiesByClass(); + if ($propertiesByClass === []) { return; } - $this->symfonyStyle->title('Entities with new properties'); + $data = [ + 'title' => 'Entities with new properties', + 'added_properties_by_class' => $propertiesByClass, + ]; - foreach ($this->entitiesWithAddedPropertyCollector->getPropertiesByClasses() as $class => $properties) { - $this->symfonyStyle->section($class); - $this->symfonyStyle->listing($properties); - $this->symfonyStyle->newLine(1); - } + $jsonContent = Json::encode($data, Json::PRETTY); + + $this->symfonyStyle->writeln($jsonContent); } } diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php index f4583a2e0b53..054bc91d7c73 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php @@ -10,10 +10,12 @@ use PhpParser\Node\Stmt\PropertyProperty; use PhpParser\Node\VarLikeIdentifier; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; +use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; use Rector\Doctrine\PhpDocParser\Ast\PhpDoc\PhpDocTagNodeFactory; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\ToManyTagNodeInterface; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\ToOneTagNodeInterface; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator; use Rector\Rector\AbstractRector; use Rector\RectorDefinition\RectorDefinition; @@ -33,12 +35,19 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector */ private $phpDocTagNodeFactory; + /** + * @var EntityWithAddedPropertyCollector + */ + private $entityWithAddedPropertyCollector; + public function __construct( DocBlockManipulator $docBlockManipulator, - PhpDocTagNodeFactory $phpDocTagNodeFactory + PhpDocTagNodeFactory $phpDocTagNodeFactory, + EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector ) { $this->docBlockManipulator = $docBlockManipulator; $this->phpDocTagNodeFactory = $phpDocTagNodeFactory; + $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; } public function getDefinition(): RectorDefinition @@ -99,18 +108,18 @@ private function createMirrorNullable(Property $property): Property $newPropertyProperty = new PropertyProperty(new VarLikeIdentifier($uuidPropertyName)); $propertyWithUuid->props = [$newPropertyProperty]; + $this->addNewPropertyToCollector($property, $uuidPropertyName); + return $propertyWithUuid; } private function updateDocComment(Property $property): void { + /** @var PhpDocInfo $propertyPhpDocInfo */ $propertyPhpDocInfo = $this->getPhpDocInfo($property); - if ($propertyPhpDocInfo === null) { - return; - } /** @var DoctrineRelationTagValueNodeInterface $doctrineRelationTagValueNode */ - $doctrineRelationTagValueNode = $propertyPhpDocInfo->getDoctrineRelationTagValueNode(); + $doctrineRelationTagValueNode = $this->getDoctrineRelationTagValueNode($property); if ($doctrineRelationTagValueNode instanceof ToManyTagNodeInterface) { $this->refactorToManyPropertyPhpDocInfo($propertyPhpDocInfo, $property); @@ -189,4 +198,19 @@ private function shouldSkipProperty(Class_ $class, Property $property): bool return false; } + + private function addNewPropertyToCollector(Property $property, string $propertyName): void + { + /** @var string $className */ + $className = $property->getAttribute(AttributeKey::CLASS_NAME); + + /** @var DoctrineRelationTagValueNodeInterface $doctrineRelationTagValueNode */ + $doctrineRelationTagValueNode = $this->getDoctrineRelationTagValueNode($property); + + if ($doctrineRelationTagValueNode instanceof ToManyTagNodeInterface) { + $this->entityWithAddedPropertyCollector->addClassToManyRelationProperty($className, $propertyName); + } elseif ($doctrineRelationTagValueNode instanceof ToOneTagNodeInterface) { + $this->entityWithAddedPropertyCollector->addClassToOneRelationProperty($className, $propertyName); + } + } } diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php index c7e145ac3b66..05752ec0bbc2 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php @@ -8,7 +8,7 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; -use Rector\Doctrine\Collector\EntitiesWithAddedPropertyCollector; +use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; use Rector\Doctrine\NodeFactory\EntityUuidNodeFactory; use Rector\PhpParser\Node\Manipulator\ClassManipulator; use Rector\Rector\AbstractRector; @@ -30,18 +30,18 @@ final class AddUuidToEntityWhereMissingRector extends AbstractRector private $classManipulator; /** - * @var EntitiesWithAddedPropertyCollector + * @var EntityWithAddedPropertyCollector */ - private $entitiesWithAddedPropertyCollector; + private $entityWithAddedPropertyCollector; public function __construct( EntityUuidNodeFactory $entityUuidNodeFactory, ClassManipulator $classManipulator, - EntitiesWithAddedPropertyCollector $entitiesWithAddedPropertyCollector + EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector ) { $this->entityUuidNodeFactory = $entityUuidNodeFactory; $this->classManipulator = $classManipulator; - $this->entitiesWithAddedPropertyCollector = $entitiesWithAddedPropertyCollector; + $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; } public function getDefinition(): RectorDefinition @@ -95,7 +95,7 @@ public function refactor(Node $node): ?Node /** @var string $class */ $class = $this->getName($node); - $this->entitiesWithAddedPropertyCollector->addClassAndProperty($class, 'uuid'); + $this->entityWithAddedPropertyCollector->addClassAndProperty($class, 'uuid'); return $node; } From bf312a3dd0cb7d8635973051faa4a01ddb051616 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Thu, 29 Aug 2019 17:21:47 +0200 Subject: [PATCH 5/5] create table name based on @Table annotation --- .../src/PhpDocInfo/PhpDocInfo.php | 6 ++ ...tor.php => UuidMigrationDataCollector.php} | 11 ++- ...tiesWithAddedPropertiesFinishExtension.php | 12 +-- .../PhpDocParser/DoctrineDocBlockResolver.php | 11 +++ ...AddUuidMirrorForRelationPropertyRector.php | 33 +++++-- .../AddUuidToEntityWhereMissingRector.php | 12 +-- .../src/Uuid/UuidTableNameResolver.php | 46 +++++++-- .../Fixture/to_many.php.inc | 4 +- .../Ast/PhpDoc/Class_/EntityTagValueNode.php | 5 + .../PhpDoc/Property_/TableTagValueNode.php | 93 +++++++++++++++++++ .../src/PhpDocParser/OrmTagParser.php | 23 ++++- 11 files changed, 221 insertions(+), 35 deletions(-) rename packages/Doctrine/src/Collector/{EntityWithAddedPropertyCollector.php => UuidMigrationDataCollector.php} (79%) create mode 100644 packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Property_/TableTagValueNode.php diff --git a/packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php b/packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php index 7fbb5a419214..3de233d7669d 100644 --- a/packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php +++ b/packages/BetterPhpDocParser/src/PhpDocInfo/PhpDocInfo.php @@ -21,6 +21,7 @@ use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\ManyToOneTagValueNode; use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToManyTagValueNode; use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToOneTagValueNode; +use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\TableTagValueNode; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface; final class PhpDocInfo @@ -181,6 +182,11 @@ public function getDoctrineIdTagValueNode(): ?IdTagValueNode return $this->matchChildValueNodeOfType(IdTagValueNode::class); } + public function getDoctrineTableTagValueNode(): ?TableTagValueNode + { + return $this->matchChildValueNodeOfType(TableTagValueNode::class); + } + public function getDoctrineManyToManyTagValueNode(): ?ManyToManyTagValueNode { return $this->matchChildValueNodeOfType(ManyToManyTagValueNode::class); diff --git a/packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php b/packages/Doctrine/src/Collector/UuidMigrationDataCollector.php similarity index 79% rename from packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php rename to packages/Doctrine/src/Collector/UuidMigrationDataCollector.php index 95285f336d05..f2fb1138636e 100644 --- a/packages/Doctrine/src/Collector/EntityWithAddedPropertyCollector.php +++ b/packages/Doctrine/src/Collector/UuidMigrationDataCollector.php @@ -2,10 +2,10 @@ namespace Rector\Doctrine\Collector; -final class EntityWithAddedPropertyCollector +final class UuidMigrationDataCollector { /** - * @var string[][][] + * @var mixed[] */ private $propertiesByClass = []; @@ -14,9 +14,12 @@ public function addClassAndProperty(string $class, string $property): void $this->propertiesByClass[$class]['properties'][] = $property; } - public function addClassToManyRelationProperty(string $class, string $property): void + public function addClassToManyRelationProperty(string $class, string $property, string $tableName): void { - $this->propertiesByClass[$class]['to_many_relations'][] = $property; + $this->propertiesByClass[$class]['to_many_relations'][] = [ + 'property' => $property, + 'table_name' => $tableName, + ]; } public function addClassToOneRelationProperty(string $class, string $property): void diff --git a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php index 66f06d1ce7ea..3e8081a07a10 100644 --- a/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php +++ b/packages/Doctrine/src/Extension/ReportEntitiesWithAddedPropertiesFinishExtension.php @@ -4,15 +4,15 @@ use Nette\Utils\Json; use Rector\Contract\Extension\FinishingExtensionInterface; -use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; +use Rector\Doctrine\Collector\UuidMigrationDataCollector; use Symfony\Component\Console\Style\SymfonyStyle; final class ReportEntitiesWithAddedPropertiesFinishExtension implements FinishingExtensionInterface { /** - * @var EntityWithAddedPropertyCollector + * @var UuidMigrationDataCollector */ - private $entityWithAddedPropertyCollector; + private $uuidMigrationDataCollector; /** * @var SymfonyStyle @@ -20,16 +20,16 @@ final class ReportEntitiesWithAddedPropertiesFinishExtension implements Finishin private $symfonyStyle; public function __construct( - EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector, + UuidMigrationDataCollector $uuidMigrationDataCollector, SymfonyStyle $symfonyStyle ) { - $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; + $this->uuidMigrationDataCollector = $uuidMigrationDataCollector; $this->symfonyStyle = $symfonyStyle; } public function run(): void { - $propertiesByClass = $this->entityWithAddedPropertyCollector->getPropertiesByClass(); + $propertiesByClass = $this->uuidMigrationDataCollector->getPropertiesByClass(); if ($propertiesByClass === []) { return; } diff --git a/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php b/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php index 6f39ad25d721..0a56ceae3350 100644 --- a/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php +++ b/packages/Doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php @@ -6,6 +6,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; +use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\TableTagValueNode; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface; use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator; @@ -61,6 +62,16 @@ public function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRe return $propertyPhpDocInfo->getDoctrineRelationTagValueNode(); } + public function getDoctrineTableTagValueNode(Class_ $class): ?TableTagValueNode + { + $classPhpDocInfo = $this->getPhpDocInfo($class); + if ($classPhpDocInfo === null) { + return null; + } + + return $classPhpDocInfo->getDoctrineTableTagValueNode(); + } + private function getPhpDocInfo(Node $node): ?PhpDocInfo { if ($node->getDocComment() === null) { diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php index 054bc91d7c73..9718cab0b210 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidMirrorForRelationPropertyRector.php @@ -10,8 +10,9 @@ use PhpParser\Node\Stmt\PropertyProperty; use PhpParser\Node\VarLikeIdentifier; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; -use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; +use Rector\Doctrine\Collector\UuidMigrationDataCollector; use Rector\Doctrine\PhpDocParser\Ast\PhpDoc\PhpDocTagNodeFactory; +use Rector\Doctrine\Uuid\UuidTableNameResolver; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\ToManyTagNodeInterface; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\ToOneTagNodeInterface; @@ -36,18 +37,25 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector private $phpDocTagNodeFactory; /** - * @var EntityWithAddedPropertyCollector + * @var UuidMigrationDataCollector */ - private $entityWithAddedPropertyCollector; + private $uuidMigrationDataCollector; + + /** + * @var UuidTableNameResolver + */ + private $uuidTableNameResolver; public function __construct( DocBlockManipulator $docBlockManipulator, PhpDocTagNodeFactory $phpDocTagNodeFactory, - EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector + UuidMigrationDataCollector $uuidMigrationDataCollector, + UuidTableNameResolver $uuidTableNameResolver ) { $this->docBlockManipulator = $docBlockManipulator; $this->phpDocTagNodeFactory = $phpDocTagNodeFactory; - $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; + $this->uuidMigrationDataCollector = $uuidMigrationDataCollector; + $this->uuidTableNameResolver = $uuidTableNameResolver; } public function getDefinition(): RectorDefinition @@ -139,9 +147,8 @@ private function refactorToManyPropertyPhpDocInfo(PhpDocInfo $propertyPhpDocInfo $propertyPhpDocInfo->removeTagValueNodeFromNode($doctrineJoinColumnTagValueNode); } - $propertyPhpDocInfo->getPhpDocNode()->children[] = $this->phpDocTagNodeFactory->createJoinTableTagNode( - $property - ); + $joinTableTagNode = $this->phpDocTagNodeFactory->createJoinTableTagNode($property); + $propertyPhpDocInfo->getPhpDocNode()->children[] = $joinTableTagNode; } private function refactorToOnePropertyPhpDocInfo(PhpDocInfo $propertyPhpDocInfo): void @@ -207,10 +214,16 @@ private function addNewPropertyToCollector(Property $property, string $propertyN /** @var DoctrineRelationTagValueNodeInterface $doctrineRelationTagValueNode */ $doctrineRelationTagValueNode = $this->getDoctrineRelationTagValueNode($property); + $joinTableName = $this->uuidTableNameResolver->resolveManyToManyTableNameForProperty($property); + if ($doctrineRelationTagValueNode instanceof ToManyTagNodeInterface) { - $this->entityWithAddedPropertyCollector->addClassToManyRelationProperty($className, $propertyName); + $this->uuidMigrationDataCollector->addClassToManyRelationProperty( + $className, + $propertyName, + $joinTableName + ); } elseif ($doctrineRelationTagValueNode instanceof ToOneTagNodeInterface) { - $this->entityWithAddedPropertyCollector->addClassToOneRelationProperty($className, $propertyName); + $this->uuidMigrationDataCollector->addClassToOneRelationProperty($className, $propertyName); } } } diff --git a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php index 05752ec0bbc2..646fe8c51d01 100644 --- a/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php +++ b/packages/Doctrine/src/Rector/Class_/AddUuidToEntityWhereMissingRector.php @@ -8,7 +8,7 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; -use Rector\Doctrine\Collector\EntityWithAddedPropertyCollector; +use Rector\Doctrine\Collector\UuidMigrationDataCollector; use Rector\Doctrine\NodeFactory\EntityUuidNodeFactory; use Rector\PhpParser\Node\Manipulator\ClassManipulator; use Rector\Rector\AbstractRector; @@ -30,18 +30,18 @@ final class AddUuidToEntityWhereMissingRector extends AbstractRector private $classManipulator; /** - * @var EntityWithAddedPropertyCollector + * @var UuidMigrationDataCollector */ - private $entityWithAddedPropertyCollector; + private $uuidMigrationDataCollector; public function __construct( EntityUuidNodeFactory $entityUuidNodeFactory, ClassManipulator $classManipulator, - EntityWithAddedPropertyCollector $entityWithAddedPropertyCollector + UuidMigrationDataCollector $uuidMigrationDataCollector ) { $this->entityUuidNodeFactory = $entityUuidNodeFactory; $this->classManipulator = $classManipulator; - $this->entityWithAddedPropertyCollector = $entityWithAddedPropertyCollector; + $this->uuidMigrationDataCollector = $uuidMigrationDataCollector; } public function getDefinition(): RectorDefinition @@ -95,7 +95,7 @@ public function refactor(Node $node): ?Node /** @var string $class */ $class = $this->getName($node); - $this->entityWithAddedPropertyCollector->addClassAndProperty($class, 'uuid'); + $this->uuidMigrationDataCollector->addClassAndProperty($class, 'uuid'); return $node; } diff --git a/packages/Doctrine/src/Uuid/UuidTableNameResolver.php b/packages/Doctrine/src/Uuid/UuidTableNameResolver.php index b9fcafb687c8..5bb3cef4e187 100644 --- a/packages/Doctrine/src/Uuid/UuidTableNameResolver.php +++ b/packages/Doctrine/src/Uuid/UuidTableNameResolver.php @@ -3,9 +3,11 @@ namespace Rector\Doctrine\Uuid; use Nette\Utils\Strings; +use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\Property; use Rector\Doctrine\PhpDocParser\DoctrineDocBlockResolver; use Rector\Exception\ShouldNotHappenException; +use Rector\NodeContainer\ParsedNodesByType; use Rector\NodeTypeResolver\Node\AttributeKey; final class UuidTableNameResolver @@ -15,9 +17,17 @@ final class UuidTableNameResolver */ private $doctrineDocBlockResolver; - public function __construct(DoctrineDocBlockResolver $doctrineDocBlockResolver) - { + /** + * @var ParsedNodesByType + */ + private $parsedNodesByType; + + public function __construct( + DoctrineDocBlockResolver $doctrineDocBlockResolver, + ParsedNodesByType $parsedNodesByType + ) { $this->doctrineDocBlockResolver = $doctrineDocBlockResolver; + $this->parsedNodesByType = $parsedNodesByType; } /** @@ -25,18 +35,24 @@ public function __construct(DoctrineDocBlockResolver $doctrineDocBlockResolver) */ public function resolveManyToManyTableNameForProperty(Property $property): string { - /** @var string $currentClass */ - $currentClass = $property->getAttribute(AttributeKey::CLASS_NAME); - $shortCurrentClass = $this->resolveShortClassName($currentClass); + /** @var Class_ $currentClass */ + $currentClass = $property->getAttribute(AttributeKey::CLASS_NODE); + $currentTableName = $this->resolveTableNameFromClass($currentClass); $targetEntity = $this->doctrineDocBlockResolver->getTargetEntity($property); if ($targetEntity === null) { throw new ShouldNotHappenException(__METHOD__); } - $shortTargetEntity = $this->resolveShortClassName($targetEntity); + $targetEntityClass = $this->parsedNodesByType->findClass($targetEntity); + if ($targetEntityClass === null) { + // dummy fallback + $targetTableName = $this->resolveShortClassName($targetEntity); + } else { + $targetTableName = $this->resolveTableNameFromClass($targetEntityClass); + } - return strtolower($shortCurrentClass . '_uuid_' . $shortTargetEntity . '_uuid'); + return strtolower($currentTableName . '_' . $targetTableName . '_uuid'); } private function resolveShortClassName(string $currentClass): string @@ -47,4 +63,20 @@ private function resolveShortClassName(string $currentClass): string return (string) Strings::after($currentClass, '\\', -1); } + + private function resolveTableNameFromClass(Class_ $class): string + { + $tableTagValueNode = $this->doctrineDocBlockResolver->getDoctrineTableTagValueNode($class); + if ($tableTagValueNode !== null) { + $tableName = $tableTagValueNode->getName(); + if ($tableName !== null) { + return $tableName; + } + } + + /** @var string $className */ + $className = $class->getAttribute(AttributeKey::CLASS_NAME); + + return $this->resolveShortClassName($className); + } } diff --git a/packages/Doctrine/tests/Rector/Class_/AddUuidMirrorForRelationPropertyRector/Fixture/to_many.php.inc b/packages/Doctrine/tests/Rector/Class_/AddUuidMirrorForRelationPropertyRector/Fixture/to_many.php.inc index 5bd69ffde7f9..249c2065944a 100644 --- a/packages/Doctrine/tests/Rector/Class_/AddUuidMirrorForRelationPropertyRector/Fixture/to_many.php.inc +++ b/packages/Doctrine/tests/Rector/Class_/AddUuidMirrorForRelationPropertyRector/Fixture/to_many.php.inc @@ -6,6 +6,7 @@ use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity + * @ORM\Table(name="wohoo") */ class ToMany { @@ -25,6 +26,7 @@ use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity + * @ORM\Table(name="wohoo") */ class ToMany { @@ -34,7 +36,7 @@ class ToMany private $amenity; /** * @ORM\ManyToMany(targetEntity="Rector\Doctrine\Tests\Rector\Class_\AddUuidMirrorForRelationPropertyRector\Source\AnotherEntity", cascade={"persist", "merge"}) - * @ORM\JoinTable (name="tomany_uuid_anotherentity_uuid", joinColumns={@ORM\JoinColumn(referencedColumnName="uuid")}, inverseJoinColumns={@ORM\JoinColumn(referencedColumnName="uuid")}) + * @ORM\JoinTable (name="wohoo_anotherentity_uuid", joinColumns={@ORM\JoinColumn(referencedColumnName="uuid")}, inverseJoinColumns={@ORM\JoinColumn(referencedColumnName="uuid")}) */ private $amenityUuid; } diff --git a/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Class_/EntityTagValueNode.php b/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Class_/EntityTagValueNode.php index d7f1f4ee54bd..72e728084c83 100644 --- a/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Class_/EntityTagValueNode.php +++ b/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Class_/EntityTagValueNode.php @@ -6,6 +6,11 @@ final class EntityTagValueNode extends AbstractDoctrineTagValueNode { + /** + * @var string + */ + public const SHORT_NAME = '@ORM\Entity'; + /** * @var string|null */ diff --git a/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Property_/TableTagValueNode.php b/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Property_/TableTagValueNode.php new file mode 100644 index 000000000000..7ef47507da80 --- /dev/null +++ b/packages/DoctrinePhpDocParser/src/Ast/PhpDoc/Property_/TableTagValueNode.php @@ -0,0 +1,93 @@ +name = $name; + $this->schema = $schema; + $this->indexes = $indexes; + $this->uniqueConstaints = $uniqueConstaints; + $this->options = $options; + + if ($originalContent !== null) { + $this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($originalContent); + } + } + + public function __toString(): string + { + $contentItems = []; + + if ($this->name !== null) { + $contentItems['name'] = sprintf('name="%s"', $this->name); + } + + if ($this->schema !== null) { + $contentItems['schema'] = sprintf('schema="%s"', $this->schema); + } + + if ($this->indexes) { + $contentItems['indexes'] = $this->printArrayItem($this->indexes, 'indexes'); + } + + if ($this->uniqueConstaints) { + $contentItems['uniqueConstaints'] = $this->printArrayItem($this->uniqueConstaints, 'uniqueConstaints'); + } + + if ($this->options !== []) { + $contentItems['options'] = $this->printArrayItem($this->options, 'options'); + } + + return $this->printContentItems($contentItems); + } + + public function getName(): ?string + { + return $this->name; + } +} diff --git a/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php b/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php index f6b1ca0ff859..90618f12c1b3 100644 --- a/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php +++ b/packages/DoctrinePhpDocParser/src/PhpDocParser/OrmTagParser.php @@ -10,6 +10,7 @@ use Doctrine\ORM\Mapping\ManyToOne; use Doctrine\ORM\Mapping\OneToMany; use Doctrine\ORM\Mapping\OneToOne; +use Doctrine\ORM\Mapping\Table; use Nette\Utils\Strings; use PhpParser\Node; use PhpParser\Node\Stmt\Class_; @@ -28,6 +29,7 @@ use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\ManyToOneTagValueNode; use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToManyTagValueNode; use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\OneToOneTagValueNode; +use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\TableTagValueNode; use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -80,9 +82,13 @@ public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValu // Entity tags if ($node instanceof Class_) { - if ($tag === '@ORM\Entity') { + if ($tag === EntityTagValueNode::SHORT_NAME) { return $this->createEntityTagValueNode($node, $annotationContent); } + + if ($tag === TableTagValueNode::SHORT_NAME) { + return $this->createTableTagValueNode($node, $annotationContent); + } } // Property tags @@ -146,6 +152,21 @@ private function createEntityTagValueNode(Class_ $node, string $annotationConten )); } + private function createTableTagValueNode(Class_ $node, string $annotationContent): TableTagValueNode + { + /** @var Table $table */ + $table = $this->nodeAnnotationReader->readDoctrineClassAnnotation($node, Table::class); + + return new TableTagValueNode( + $table->name, + $table->schema, + $table->indexes, + $table->uniqueConstraints, + $table->options, + $annotationContent + ); + } + private function createColumnTagValueNode(Property $property, string $annotationContent): ColumnTagValueNode { /** @var Column $column */