153 lines
5.0 KiB
PHP
Raw Normal View History

2019-10-13 07:59:52 +02:00
<?php
declare(strict_types=1);
2019-08-30 20:21:21 +02:00
namespace Rector\BetterPhpDocParser\PhpDocManipulator;
2019-08-30 20:21:21 +02:00
use Nette\Utils\Strings;
use PhpParser\Node;
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
2019-08-30 21:41:21 +02:00
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher;
2019-08-30 20:21:21 +02:00
final class PhpDocClassRenamer
{
/**
* @var ClassAnnotationMatcher
*/
private $classAnnotationMatcher;
public function __construct(ClassAnnotationMatcher $classAnnotationMatcher)
{
$this->classAnnotationMatcher = $classAnnotationMatcher;
}
2019-08-30 20:21:21 +02:00
/**
* Covers annotations like @ORM, @Serializer, @Assert etc
* See https://github.com/rectorphp/rector/issues/1872
*
* @param string[] $oldToNewClasses
*/
public function changeTypeInAnnotationTypes(Node $node, PhpDocInfo $phpDocInfo, array $oldToNewClasses): void
2019-08-30 20:21:21 +02:00
{
$this->processAssertChoiceTagValueNode($oldToNewClasses, $phpDocInfo);
$this->processDoctrineRelationTagValueNode($node, $oldToNewClasses, $phpDocInfo);
2019-08-30 21:41:21 +02:00
$this->processSerializerTypeTagValueNode($oldToNewClasses, $phpDocInfo);
}
2019-08-30 20:21:21 +02:00
2019-08-30 21:41:21 +02:00
/**
* @param array<string, string> $oldToNewClasses
2019-08-30 21:41:21 +02:00
*/
private function processAssertChoiceTagValueNode(array $oldToNewClasses, PhpDocInfo $phpDocInfo): void
2019-08-30 21:41:21 +02:00
{
$assertChoiceTagValueNode = $phpDocInfo->getByAnnotationClass('Symfony\Component\Validator\Constraints\Choice');
if (! $assertChoiceTagValueNode instanceof DoctrineAnnotationTagValueNode) {
return;
}
$callback = $assertChoiceTagValueNode->getValueWithoutQuotes('callback');
if ($callback === null) {
2019-08-30 20:21:21 +02:00
return;
}
2019-08-30 21:41:21 +02:00
foreach ($oldToNewClasses as $oldClass => $newClass) {
if ($callback[0] !== $oldClass) {
2019-08-30 21:41:21 +02:00
continue;
}
$callback[0] = $newClass;
$assertChoiceTagValueNode->changeValue('callback', $callback);
2019-08-30 21:41:21 +02:00
break;
2019-08-30 20:21:21 +02:00
}
2019-08-30 21:41:21 +02:00
}
2019-08-30 20:21:21 +02:00
2019-08-30 21:41:21 +02:00
/**
* @param array<string, string> $oldToNewClasses
2019-08-30 21:41:21 +02:00
*/
private function processDoctrineRelationTagValueNode(
Node $node,
array $oldToNewClasses,
PhpDocInfo $phpDocInfo
): void {
$doctrineAnnotationTagValueNode = $phpDocInfo->getByAnnotationClasses([
'Doctrine\ORM\Mapping\OneToMany',
'Doctrine\ORM\Mapping\ManyToMany',
'Doctrine\ORM\Mapping\Embedded',
]);
if (! $doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
return;
}
$this->processDoctrineToMany($doctrineAnnotationTagValueNode, $node, $oldToNewClasses);
}
/**
* @param array<string, string> $oldToNewClasses
*/
private function processSerializerTypeTagValueNode(array $oldToNewClasses, PhpDocInfo $phpDocInfo): void
2019-08-30 21:41:21 +02:00
{
$doctrineAnnotationTagValueNode = $phpDocInfo->getByAnnotationClass('JMS\Serializer\Annotation\Type');
if (! $doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) {
2019-08-30 21:41:21 +02:00
return;
}
foreach ($oldToNewClasses as $oldClass => $newClass) {
$className = $doctrineAnnotationTagValueNode->getSilentValue();
if ($className) {
if ($className === $oldClass) {
$doctrineAnnotationTagValueNode->changeSilentValue($newClass);
continue;
}
$newContent = Strings::replace($className, '#\b' . preg_quote($oldClass, '#') . '\b#', $newClass);
if ($newContent === $className) {
continue;
}
$doctrineAnnotationTagValueNode->changeSilentValue($newContent);
2019-08-30 21:41:21 +02:00
continue;
}
$currentType = $doctrineAnnotationTagValueNode->getValueWithoutQuotes('type');
if ($currentType === $oldClass) {
$doctrineAnnotationTagValueNode->changeValue('type', $newClass);
continue;
}
}
2019-08-30 21:41:21 +02:00
}
/**
* @param array<string, string> $oldToNewClasses
2019-08-30 21:41:21 +02:00
*/
private function processDoctrineToMany(
DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode,
Node $node,
array $oldToNewClasses
): void {
if ($doctrineAnnotationTagValueNode->getAnnotationClass() === 'Doctrine\ORM\Mapping\Embedded') {
$classKey = 'class';
} else {
$classKey = 'targetEntity';
}
$targetEntity = $doctrineAnnotationTagValueNode->getValueWithoutQuotes($classKey);
if ($targetEntity === null) {
2019-08-30 21:41:21 +02:00
return;
}
// resolve to FQN
$tagFullyQualifiedName = $this->classAnnotationMatcher->resolveTagFullyQualifiedName($targetEntity, $node);
2019-08-30 21:41:21 +02:00
foreach ($oldToNewClasses as $oldClass => $newClass) {
if ($tagFullyQualifiedName !== $oldClass) {
continue;
2021-01-20 00:29:52 +01:00
}
$doctrineAnnotationTagValueNode->changeValue($classKey, $newClass);
2019-08-30 21:41:21 +02:00
}
2019-08-30 20:21:21 +02:00
}
}