[DoctrineGemoToKnplabs] Add LoggableBehaviorRector (#2601)

[DoctrineGemoToKnplabs] Add LoggableBehaviorRector
This commit is contained in:
Tomas Votruba 2020-01-07 14:41:37 +01:00 committed by GitHub
commit 21a37fd7b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 409 additions and 0 deletions

View File

@ -6,3 +6,4 @@ services:
Rector\DoctrineGedmoToKnplabs\Rector\Class_\TranslationBehaviorRector: null
Rector\DoctrineGedmoToKnplabs\Rector\Class_\SoftDeletableBehaviorRector: null
Rector\DoctrineGedmoToKnplabs\Rector\Class_\BlameableBehaviorRector: null
Rector\DoctrineGedmoToKnplabs\Rector\Class_\LoggableBehaviorRector: null

View File

@ -46,6 +46,9 @@ final class AnnotationReaderFactory
$annotationReader::addGlobalIgnoredName('Gedmo\Blameable');
$annotationReader::addGlobalIgnoredName('Blameable');
$annotationReader::addGlobalIgnoredName('Gedmo\Versioned');
$annotationReader::addGlobalIgnoredName('Versioned');
// nette @inject dummy annotation
$annotationReader::addGlobalIgnoredName('inject');

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNode\Gedmo;
use Gedmo\Mapping\Annotation\Loggable;
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
final class LoggableTagValueNode extends AbstractTagValueNode
{
/**
* @var string
*/
public const SHORT_NAME = '@Gedmo\Loggable';
/**
* @var string
*/
public const CLASS_NAME = Loggable::class;
/**
* @var string|null
*/
private $logEntryClass;
public function __construct(?string $logEntryClass)
{
$this->logEntryClass = $logEntryClass;
}
public function __toString(): string
{
$contentItems = [];
if ($this->logEntryClass !== null) {
$contentItems['logEntryClass'] = $this->logEntryClass;
}
return $this->printContentItems($contentItems);
}
}

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNode\Gedmo;
use Gedmo\Mapping\Annotation\Versioned;
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
final class VersionedTagValueNode extends AbstractTagValueNode
{
/**
* @var string
*/
public const SHORT_NAME = '@Gedmo\Versioned';
/**
* @var string
*/
public const CLASS_NAME = Versioned::class;
public function __toString(): string
{
return '';
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Gedmo;
use Gedmo\Mapping\Annotation\Loggable;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\LoggableTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractPhpDocNodeFactory;
final class LoggablePhpDocNodeFactory extends AbstractPhpDocNodeFactory
{
public function getClass(): string
{
return Loggable::class;
}
/**
* @return LoggableTagValueNode|null
*/
public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator): ?PhpDocTagValueNode
{
if (! $node instanceof Class_) {
return null;
}
/** @var Loggable|null $loggable */
$loggable = $this->nodeAnnotationReader->readClassAnnotation($node, $this->getClass());
if ($loggable === null) {
return null;
}
return new LoggableTagValueNode($loggable->logEntryClass);
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Gedmo;
use Gedmo\Mapping\Annotation\Versioned;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\VersionedTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractPhpDocNodeFactory;
final class VersionedPhpDocNodeFactory extends AbstractPhpDocNodeFactory
{
public function getClass(): string
{
return Versioned::class;
}
/**
* @return VersionedTagValueNode|null
*/
public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator): ?PhpDocTagValueNode
{
if (! $node instanceof Property) {
return null;
}
/** @var Versioned|null $loggable */
$loggable = $this->nodeAnnotationReader->readPropertyAnnotation($node, $this->getClass());
if ($loggable === null) {
return null;
}
return new VersionedTagValueNode();
}
}

View File

@ -0,0 +1,132 @@
<?php
declare(strict_types=1);
namespace Rector\DoctrineGedmoToKnplabs\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\LoggableTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\VersionedTagValueNode;
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/loggable.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/loggable.md
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\LoggableBehaviorRector\LoggableBehaviorRectorTest
*/
final class LoggableBehaviorRector extends AbstractRector
{
/**
* @var ClassManipulator
*/
private $classManipulator;
public function __construct(ClassManipulator $classManipulator)
{
$this->classManipulator = $classManipulator;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Change Loggable from gedmo/doctrine-extensions to knplabs/doctrine-behaviors', [
new CodeSample(
<<<'PHP'
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @Gedmo\Loggable
*/
class SomeClass
{
/**
* @Gedmo\Versioned
* @ORM\Column(name="title", type="string", length=8)
*/
private $title;
}
PHP
,
<<<'PHP'
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model\Loggable\LoggableTrait;
use Knp\DoctrineBehaviors\Contract\Entity\LoggableInterface;
/**
* @ORM\Entity
*/
class SomeClass implements LoggableInterface
{
use LoggableTrait;
/**
* @ORM\Column(name="title", type="string", length=8)
*/
private $title;
}
PHP
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
// change the node
$classPhpDocInfo = $this->getPhpDocInfo($node);
if ($classPhpDocInfo === null) {
return null;
}
if (! $classPhpDocInfo->hasByType(LoggableTagValueNode::class)) {
return null;
}
$classPhpDocInfo->removeByType(LoggableTagValueNode::class);
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $classPhpDocInfo);
// remove tag from properties
$this->removeVersionedTagFromProperties($node);
$this->classManipulator->addAsFirstTrait($node, 'Knp\DoctrineBehaviors\Model\Loggable\LoggableTrait');
$node->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\LoggableInterface');
return $node;
}
private function removeVersionedTagFromProperties(Class_ $class): void
{
foreach ($class->getProperties() as $property) {
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
if ($propertyPhpDocInfo === null) {
continue;
}
if (! $propertyPhpDocInfo->hasByType(VersionedTagValueNode::class)) {
continue;
}
$propertyPhpDocInfo->removeByType(VersionedTagValueNode::class);
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $propertyPhpDocInfo);
}
}
}

View File

@ -19,6 +19,9 @@ use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/sluggable.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/sluggable.md
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\SluggableBehaviorRector\SluggableBehaviorRectorTest
*/
final class SluggableBehaviorRector extends AbstractRector

View File

@ -14,6 +14,9 @@ use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/softdeleteable.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/soft-deletable.md
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\SoftDeletableBehaviorRector\SoftDeletableBehaviorRectorTest
*/
final class SoftDeletableBehaviorRector extends AbstractRector

View File

@ -13,6 +13,9 @@ use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/timestampable.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/timestampable.md
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TimestampableBehaviorRector\TimestampableBehaviorRectorTest
*/
final class TimestampableBehaviorRector extends AbstractRector

View File

@ -22,6 +22,9 @@ use Rector\RectorDefinition\RectorDefinition;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/translatable.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/translatable.md
*
* @see https://lab.axioma.lv/symfony2/pagebundle/commit/062f9f87add5740ea89072e376dd703f3188d2ce
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector\TranslationBehaviorRectorTest

View File

@ -20,6 +20,9 @@ use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/tree.md
* @see https://github.com/KnpLabs/DoctrineBehaviors/blob/4e0677379dd4adf84178f662d08454a9627781a8/docs/tree.md
*
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TreeBehaviorRector\TreeBehaviorRectorTest
*/
final class TreeBehaviorRector extends AbstractRector

View File

@ -0,0 +1,42 @@
<?php
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\LoggableBehaviorRector\Fixture;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @Gedmo\Loggable
*/
class SomeClass
{
/**
* @Gedmo\Versioned
* @ORM\Column(name="title", type="string", length=8)
*/
private $title;
}
?>
-----
<?php
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\LoggableBehaviorRector\Fixture;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SomeClass implements \Knp\DoctrineBehaviors\Contract\Entity\LoggableInterface
{
use \Knp\DoctrineBehaviors\Model\Loggable\LoggableTrait;
/**
* @ORM\Column(name="title", type="string", length=8)
*/
private $title;
}
?>

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\LoggableBehaviorRector;
use Iterator;
use Rector\DoctrineGedmoToKnplabs\Rector\Class_\LoggableBehaviorRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class LoggableBehaviorRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}
public function provideDataForTest(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return LoggableBehaviorRector::class;
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Gedmo\Mapping\Annotation;
if (class_exists('Gedmo\Mapping\Annotation\Loggable')) {
return;
}
use Doctrine\Common\Annotations\Annotation;
/**
* @Annotation
*/
class Loggable
{
/**
* @var string
*/
public $logEntryClass;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Gedmo\Mapping\Annotation;
if (class_exists('Gedmo\Mapping\Annotation\Versioned')) {
return;
}
use Doctrine\Common\Annotations\Annotation;
/**
* @Annotation
*/
class Versioned
{
}