mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-20 08:05:29 +01:00
[Gedmo to Knp] Add Translatable Behavior Rector (#2503)
[Gedmo to Knp] Add Translatable Behavior Rector
This commit is contained in:
commit
f73f38fa01
@ -3,3 +3,4 @@ services:
|
||||
Rector\DoctrineGedmoToKnplabs\Rector\Class_\TimestampableBehaviorRector: null
|
||||
Rector\DoctrineGedmoToKnplabs\Rector\Class_\SluggableBehaviorRector: null
|
||||
Rector\DoctrineGedmoToKnplabs\Rector\Class_\TreeBehaviorRector: ~
|
||||
Rector\DoctrineGedmoToKnplabs\Rector\Class_\TranslationBehaviorRector: ~
|
||||
|
@ -220,6 +220,23 @@ final class PhpDocInfo
|
||||
return null;
|
||||
}
|
||||
|
||||
public function removeByType(string $type): void
|
||||
{
|
||||
$this->ensureTypeIsTagValueNode($type, __METHOD__);
|
||||
|
||||
foreach ($this->phpDocNode->children as $key => $phpDocChildNode) {
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! is_a($phpDocChildNode->value, $type, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($this->phpDocNode->children[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
|
||||
{
|
||||
$phpDocNode = $this->getPhpDocNode();
|
||||
|
@ -19,12 +19,15 @@ final class EntityTagValueNode extends AbstractDoctrineTagValueNode
|
||||
private $repositoryClass;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var bool|null
|
||||
*/
|
||||
private $readOnly = false;
|
||||
private $readOnly;
|
||||
|
||||
public function __construct(?string $repositoryClass, bool $readOnly, ?string $originalContent)
|
||||
{
|
||||
public function __construct(
|
||||
?string $repositoryClass = null,
|
||||
?bool $readOnly = null,
|
||||
?string $originalContent = null
|
||||
) {
|
||||
$this->repositoryClass = $repositoryClass;
|
||||
$this->readOnly = $readOnly;
|
||||
|
||||
@ -39,7 +42,9 @@ final class EntityTagValueNode extends AbstractDoctrineTagValueNode
|
||||
$contentItems['repositoryClass'] = sprintf('repositoryClass="%s"', $this->repositoryClass);
|
||||
}
|
||||
|
||||
$contentItems['readOnly'] = sprintf('readOnly=%s', $this->readOnly ? 'true' : 'false');
|
||||
if ($this->readOnly !== null) {
|
||||
$contentItems['readOnly'] = sprintf('readOnly=%s', $this->readOnly ? 'true' : 'false');
|
||||
}
|
||||
|
||||
return $this->printContentItems($contentItems);
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNode\Gedmo;
|
||||
|
||||
use Gedmo\Mapping\Annotation\Locale;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
|
||||
|
||||
final class LocaleTagValueNode extends AbstractTagValueNode
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NAME = Locale::class;
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNode\Gedmo;
|
||||
|
||||
use Gedmo\Mapping\Annotation\Translatable;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
|
||||
|
||||
final class TranslatableTagValueNode extends AbstractTagValueNode
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NAME = Translatable::class;
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Gedmo;
|
||||
|
||||
use Gedmo\Mapping\Annotation\Locale;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\LocaleTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractBasicPropertyPhpDocNodeFactory;
|
||||
|
||||
final class LocalePhpDocNodeFactory extends AbstractBasicPropertyPhpDocNodeFactory
|
||||
{
|
||||
public function getClass(): string
|
||||
{
|
||||
return Locale::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LocaleTagValueNode|null
|
||||
*/
|
||||
public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator): ?PhpDocTagValueNode
|
||||
{
|
||||
return $this->createFromNode($node);
|
||||
}
|
||||
|
||||
protected function getTagValueNodeClass(): string
|
||||
{
|
||||
return LocaleTagValueNode::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Gedmo;
|
||||
|
||||
use Gedmo\Mapping\Annotation\Translatable;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\TranslatableTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractBasicPropertyPhpDocNodeFactory;
|
||||
|
||||
final class TranslatablePhpDocNodeFactory extends AbstractBasicPropertyPhpDocNodeFactory
|
||||
{
|
||||
public function getClass(): string
|
||||
{
|
||||
return Translatable::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TranslatableTagValueNode|null
|
||||
*/
|
||||
public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator): ?PhpDocTagValueNode
|
||||
{
|
||||
return $this->createFromNode($node);
|
||||
}
|
||||
|
||||
protected function getTagValueNodeClass(): string
|
||||
{
|
||||
return TranslatableTagValueNode::class;
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@ use Rector\NodeContainer\ParsedNodesByType;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
|
||||
use Rector\PhpParser\Node\Manipulator\ClassMethodManipulator;
|
||||
use Rector\PhpParser\Printer\BetterStandardPrinter;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
@ -58,21 +57,14 @@ final class RemoveUnusedParameterRector extends AbstractRector
|
||||
'__wakeup',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var BetterStandardPrinter
|
||||
*/
|
||||
private $betterStandardPrinter;
|
||||
|
||||
public function __construct(
|
||||
ClassManipulator $classManipulator,
|
||||
ClassMethodManipulator $classMethodManipulator,
|
||||
ParsedNodesByType $parsedNodesByType,
|
||||
BetterStandardPrinter $betterStandardPrinter
|
||||
ParsedNodesByType $parsedNodesByType
|
||||
) {
|
||||
$this->classManipulator = $classManipulator;
|
||||
$this->classMethodManipulator = $classMethodManipulator;
|
||||
$this->parsedNodesByType = $parsedNodesByType;
|
||||
$this->betterStandardPrinter = $betterStandardPrinter;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
@ -187,7 +179,7 @@ PHP
|
||||
$parameters1,
|
||||
$parameters2,
|
||||
function (Param $a, Param $b): int {
|
||||
return $this->betterStandardPrinter->areNodesEqual($a, $b) ? 0 : 1;
|
||||
return $this->areNodesEqual($a, $b) ? 0 : 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\GeneratedValueTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\IdTagValueNode;
|
||||
@ -49,6 +50,11 @@ final class PhpDocTagNodeFactory
|
||||
return new SpacelessPhpDocTagNode(IdTagValueNode::SHORT_NAME, new IdTagValueNode());
|
||||
}
|
||||
|
||||
public function createEntityTag(): PhpDocTagNode
|
||||
{
|
||||
return new SpacelessPhpDocTagNode(EntityTagValueNode::SHORT_NAME, new EntityTagValueNode());
|
||||
}
|
||||
|
||||
public function createIdColumnTag(): PhpDocTagNode
|
||||
{
|
||||
$columnTagValueNode = new ColumnTagValueNode(null, 'integer', null, null, null, null, null);
|
||||
|
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DoctrineGedmoToKnplabs\Rector\Class_;
|
||||
|
||||
use Nette\Utils\FileSystem;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\LocaleTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\TranslatableTagValueNode;
|
||||
use Rector\Doctrine\PhpDocParser\Ast\PhpDoc\PhpDocTagNodeFactory;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @see https://lab.axioma.lv/symfony2/pagebundle/commit/062f9f87add5740ea89072e376dd703f3188d2ce
|
||||
*
|
||||
* @see \Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector\TranslationBehaviorRectorTest
|
||||
*/
|
||||
final class TranslationBehaviorRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var ClassManipulator
|
||||
*/
|
||||
private $classManipulator;
|
||||
|
||||
/**
|
||||
* @var PhpDocTagNodeFactory
|
||||
*/
|
||||
private $phpDocTagNodeFactory;
|
||||
|
||||
public function __construct(ClassManipulator $classManipulator, PhpDocTagNodeFactory $phpDocTagNodeFactory)
|
||||
{
|
||||
$this->classManipulator = $classManipulator;
|
||||
$this->phpDocTagNodeFactory = $phpDocTagNodeFactory;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Change Translation from gedmo/doctrine-extensions to knplabs/doctrine-behaviors', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Translatable\Translatable;
|
||||
|
||||
/**
|
||||
* @ORM\Table
|
||||
*/
|
||||
class Article implements Translatable
|
||||
{
|
||||
/**
|
||||
* @Gedmo\Translatable
|
||||
* @ORM\Column(length=128)
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @Gedmo\Translatable
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @Gedmo\Locale
|
||||
* Used locale to override Translation listener`s locale
|
||||
* this is not a mapped field of entity metadata, just a simple property
|
||||
* and it is not necessary because globally locale can be set in listener
|
||||
*/
|
||||
private $locale;
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function setTranslatableLocale($locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;
|
||||
use Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface;
|
||||
|
||||
class SomeClass implements TranslatableInterface
|
||||
{
|
||||
use TranslatableTrait;
|
||||
}
|
||||
|
||||
|
||||
use Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface;
|
||||
use Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait;
|
||||
|
||||
class SomeClassTranslation implements TranslationInterface
|
||||
{
|
||||
use TranslationTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Column(length=128)
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $content;
|
||||
}
|
||||
PHP
|
||||
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->classManipulator->hasInterface($node, 'Gedmo\Translatable\Translatable')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->classManipulator->removeInterface($node, 'Gedmo\Translatable\Translatable');
|
||||
|
||||
// 1. replace trait
|
||||
$this->classManipulator->addAsFirstTrait($node, 'Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait');
|
||||
|
||||
// 2. add interface
|
||||
$node->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface');
|
||||
|
||||
$removedPropertyNameToPhpDocInfo = $this->collectAndRemoveTranslatableProperties($node);
|
||||
$removePropertyNames = array_keys($removedPropertyNameToPhpDocInfo);
|
||||
|
||||
// @todo add them as a @method annotation, so the autocomplete still works?
|
||||
$this->removeSetAndGetMethods($node, $removePropertyNames);
|
||||
|
||||
$this->dumpEntityTranslation($node, $removedPropertyNameToPhpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $removedPropertyNames
|
||||
*/
|
||||
private function removeSetAndGetMethods(Class_ $class, array $removedPropertyNames): void
|
||||
{
|
||||
foreach ($removedPropertyNames as $removedPropertyName) {
|
||||
foreach ($class->getMethods() as $method) {
|
||||
if ($this->isName($method, 'set' . ucfirst($removedPropertyName))) {
|
||||
$this->removeNode($method);
|
||||
}
|
||||
|
||||
if ($this->isName($method, 'get' . ucfirst($removedPropertyName))) {
|
||||
$this->removeNode($method);
|
||||
}
|
||||
|
||||
if ($this->isName($method, 'setTranslatableLocale')) {
|
||||
$this->removeNode($method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PhpDocInfo[]
|
||||
*/
|
||||
private function collectAndRemoveTranslatableProperties(Class_ $class): array
|
||||
{
|
||||
$removedPropertyNameToPhpDocInfo = [];
|
||||
|
||||
foreach ($class->getProperties() as $property) {
|
||||
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
|
||||
if ($propertyPhpDocInfo === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($propertyPhpDocInfo->getByType(LocaleTagValueNode::class)) {
|
||||
$this->removeNode($property);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $propertyPhpDocInfo->getByType(TranslatableTagValueNode::class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$propertyPhpDocInfo->removeByType(TranslatableTagValueNode::class);
|
||||
|
||||
$propertyName = $this->getName($property);
|
||||
$removedPropertyNameToPhpDocInfo[$propertyName] = $propertyPhpDocInfo;
|
||||
|
||||
$this->removeNode($property);
|
||||
}
|
||||
|
||||
return $removedPropertyNameToPhpDocInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocInfo[] $translatedPropertyToPhpDocInfos
|
||||
*/
|
||||
private function dumpEntityTranslation(Class_ $class, array $translatedPropertyToPhpDocInfos): void
|
||||
{
|
||||
/** @var SmartFileInfo|null $fileInfo */
|
||||
$fileInfo = $class->getAttribute(AttributeKey::FILE_INFO);
|
||||
if ($fileInfo === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$classShortName = (string) $class->name . 'Translation';
|
||||
$filePath = dirname($fileInfo->getRealPath()) . DIRECTORY_SEPARATOR . $classShortName . '.php';
|
||||
|
||||
$namespace = $class->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if (! $namespace instanceof Namespace_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$namespace = new Namespace_($namespace->name);
|
||||
|
||||
$class = new Class_($classShortName);
|
||||
$class->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface');
|
||||
$this->classManipulator->addAsFirstTrait($class, 'Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait');
|
||||
|
||||
$this->docBlockManipulator->addTag($class, $this->phpDocTagNodeFactory->createEntityTag());
|
||||
|
||||
foreach ($translatedPropertyToPhpDocInfos as $translatedPropertyName => $translatedPhpDocInfo) {
|
||||
$property = $this->nodeFactory->createPrivateProperty($translatedPropertyName);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $translatedPhpDocInfo);
|
||||
|
||||
$class->stmts[] = $property;
|
||||
}
|
||||
|
||||
$namespace->stmts[] = $class;
|
||||
|
||||
// @todo make temporary
|
||||
$content = '<?php' . PHP_EOL . $this->print($namespace) . PHP_EOL;
|
||||
|
||||
FileSystem::write($filePath, $content);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector\Fixture;
|
||||
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Translatable\Translatable;
|
||||
|
||||
/**
|
||||
* @ORM\Table
|
||||
*/
|
||||
class SomeClass implements Translatable
|
||||
{
|
||||
/**
|
||||
* @Gedmo\Translatable
|
||||
* @ORM\Column(length=128)
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @Gedmo\Translatable
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @Gedmo\Locale
|
||||
* Used locale to override Translation listener`s locale
|
||||
* this is not a mapped field of entity metadata, just a simple property
|
||||
* and it is not necessary because globally locale can be set in listener
|
||||
*/
|
||||
private $locale;
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function setTranslatableLocale($locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector\Fixture;
|
||||
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Translatable\Translatable;
|
||||
|
||||
/**
|
||||
* @ORM\Table
|
||||
*/
|
||||
class SomeClass implements \Knp\DoctrineBehaviors\Contract\Entity\TranslatableInterface
|
||||
{
|
||||
use \Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector\Fixture;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class SomeClassTranslation implements \Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface
|
||||
{
|
||||
use \Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait;
|
||||
/**
|
||||
* @ORM\Column(length=128)
|
||||
*/
|
||||
private $title;
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $content;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DoctrineGedmoToKnplabs\Tests\Rector\Class_\TranslationBehaviorRector;
|
||||
|
||||
use Nette\Utils\FileSystem;
|
||||
use Rector\DoctrineGedmoToKnplabs\Rector\Class_\TranslationBehaviorRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class TranslationBehaviorRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
// remove generated file
|
||||
FileSystem::delete(__DIR__ . '/Fixture/SomeClassTranslation.php');
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFile(__DIR__ . '/Fixture/fixture.php.inc');
|
||||
|
||||
$generatedFile = sys_get_temp_dir() . '/rector_temp_tests/SomeClassTranslation.php';
|
||||
$this->assertFileExists($generatedFile);
|
||||
|
||||
$this->assertFileEquals(__DIR__ . '/Source/ExpectedSomeClassTranslation.php', $generatedFile);
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return TranslationBehaviorRector::class;
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@ use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Rector\NetteToSymfony\Collector\CollectOnFormVariableMethodCallsCollector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpParser\Printer\BetterStandardPrinter;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
@ -54,19 +53,12 @@ final class FormControlToControllerAndFormTypeRector extends AbstractRector
|
||||
*/
|
||||
private $classNaming;
|
||||
|
||||
/**
|
||||
* @var BetterStandardPrinter
|
||||
*/
|
||||
private $betterStandardPrinter;
|
||||
|
||||
public function __construct(
|
||||
CollectOnFormVariableMethodCallsCollector $collectOnFormVariableMethodCallsCollector,
|
||||
ClassNaming $classNaming,
|
||||
BetterStandardPrinter $betterStandardPrinter
|
||||
ClassNaming $classNaming
|
||||
) {
|
||||
$this->collectOnFormVariableMethodCallsCollector = $collectOnFormVariableMethodCallsCollector;
|
||||
$this->classNaming = $classNaming;
|
||||
$this->betterStandardPrinter = $betterStandardPrinter;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
@ -269,7 +261,7 @@ PHP
|
||||
$filePath = dirname($fileInfo->getRealPath()) . DIRECTORY_SEPARATOR . 'SomeFormController.php';
|
||||
|
||||
// @todo make temporary
|
||||
$content = '<?php' . PHP_EOL . $this->betterStandardPrinter->print([$namespace]) . PHP_EOL;
|
||||
$content = '<?php' . PHP_EOL . $this->print([$namespace]) . PHP_EOL;
|
||||
FileSystem::write($filePath, $content);
|
||||
}
|
||||
|
||||
|
@ -4,18 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace Rector\NetteToSymfony\Tests\Rector\Assign\FormControlToControllerAndFormTypeRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\NetteToSymfony\Rector\Assign\FormControlToControllerAndFormTypeRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class FormControlToControllerAndFormTypeRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideDataForTest()
|
||||
*/
|
||||
public function test(string $file): void
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFile($file);
|
||||
$this->doTestFile(__DIR__ . '/Fixture/fixture.php.inc');
|
||||
|
||||
$controllerFilePath = sys_get_temp_dir() . '/rector_temp_tests/SomeFormController.php';
|
||||
$this->assertFileExists($controllerFilePath);
|
||||
@ -23,11 +19,6 @@ final class FormControlToControllerAndFormTypeRectorTest extends AbstractRectorT
|
||||
$this->assertFileEquals(__DIR__ . '/Source/SomeFormController.php', $controllerFilePath);
|
||||
}
|
||||
|
||||
public function provideDataForTest(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return FormControlToControllerAndFormTypeRector::class;
|
||||
|
@ -479,15 +479,10 @@ final class DocBlockManipulator
|
||||
PhpDocInfo $phpDocInfo,
|
||||
bool $shouldSkipEmptyLinesAbove = false
|
||||
): bool {
|
||||
// skip if has no doc comment
|
||||
if ($node->getDocComment() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$phpDoc = $this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo, $shouldSkipEmptyLinesAbove);
|
||||
if ($phpDoc !== '') {
|
||||
// no change, don't save it
|
||||
if ($node->getDocComment()->getText() === $phpDoc) {
|
||||
if ($node->getDocComment() && $node->getDocComment()->getText() === $phpDoc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -440,6 +440,30 @@ final class ClassManipulator
|
||||
return [];
|
||||
}
|
||||
|
||||
public function hasInterface(Class_ $class, string $desiredInterface): bool
|
||||
{
|
||||
foreach ($class->implements as $implement) {
|
||||
if (! $this->nameResolver->isName($implement, $desiredInterface)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function removeInterface(Class_ $class, string $desiredInterface): void
|
||||
{
|
||||
foreach ($class->implements as $implement) {
|
||||
if (! $this->nameResolver->isName($implement, $desiredInterface)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->nodeRemovingCommander->addNode($implement);
|
||||
}
|
||||
}
|
||||
|
||||
private function tryInsertBeforeFirstMethod(Class_ $classNode, Stmt $stmt): bool
|
||||
{
|
||||
foreach ($classNode->stmts as $key => $classStmt) {
|
||||
|
@ -228,10 +228,12 @@ final class NodeFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function createPrivateProperty(string $name): Property
|
||||
public function createStaticProtectedPropertyWithDefault(string $name, Node $node): Property
|
||||
{
|
||||
$propertyBuilder = $this->builderFactory->property($name);
|
||||
$propertyBuilder->makePrivate();
|
||||
$propertyBuilder->makeProtected();
|
||||
$propertyBuilder->makeStatic();
|
||||
$propertyBuilder->setDefault($node);
|
||||
|
||||
$property = $propertyBuilder->getNode();
|
||||
|
||||
@ -240,12 +242,10 @@ final class NodeFactory
|
||||
return $property;
|
||||
}
|
||||
|
||||
public function createStaticProtectedPropertyWithDefault(string $name, Node $node): Property
|
||||
public function createPrivateProperty(string $name): Property
|
||||
{
|
||||
$propertyBuilder = $this->builderFactory->property($name);
|
||||
$propertyBuilder->makeProtected();
|
||||
$propertyBuilder->makeStatic();
|
||||
$propertyBuilder->setDefault($node);
|
||||
$propertyBuilder->makePrivate();
|
||||
|
||||
$property = $propertyBuilder->getNode();
|
||||
|
||||
|
@ -22,7 +22,7 @@ trait BetterStandardPrinterTrait
|
||||
/**
|
||||
* @var BetterStandardPrinter
|
||||
*/
|
||||
private $betterStandardPrinter;
|
||||
protected $betterStandardPrinter;
|
||||
|
||||
/**
|
||||
* @required
|
||||
|
16
stubs/Gedmo/Mapping/Annotation/Locale.php
Normal file
16
stubs/Gedmo/Mapping/Annotation/Locale.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gedmo\Mapping\Annotation;
|
||||
|
||||
if (class_exists('Gedmo\Mapping\Annotation\Locale')) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*/
|
||||
class Locale
|
||||
{
|
||||
}
|
18
stubs/Gedmo/Mapping/Annotation/Translatable.php
Normal file
18
stubs/Gedmo/Mapping/Annotation/Translatable.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gedmo\Mapping\Annotation;
|
||||
|
||||
if (class_exists('Gedmo\Mapping\Annotation\Translatable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*/
|
||||
class Translatable
|
||||
{
|
||||
/** @var boolean */
|
||||
public $fallback;
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
|
||||
namespace Gedmo\Timestampable\Traits;
|
||||
|
||||
if (class_exists('Gedmo\Timestampable\Traits\TimestampableEntity')) {
|
||||
if (trait_exists('Gedmo\Timestampable\Traits\TimestampableEntity')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
12
stubs/Gedmo/Translatable/Translatable.php
Normal file
12
stubs/Gedmo/Translatable/Translatable.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Gedmo\Translatable;
|
||||
|
||||
if (interface_exists('Gedmo\Translatable\Translatable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
interface Translatable
|
||||
{
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user