mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-02 01:10:53 +00:00
add Symfony Validator annotations
This commit is contained in:
parent
2b51b257e1
commit
04d01ffdfe
|
@ -73,7 +73,7 @@ CODE_SAMPLE
|
|||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($node);
|
||||
|
||||
$doctrineEntityTag = $phpDocInfo->getDoctrineEntityTag();
|
||||
$doctrineEntityTag = $phpDocInfo->getDoctrineEntity();
|
||||
if ($doctrineEntityTag === null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -177,49 +177,49 @@ final class PhpDocInfo
|
|||
return $this->getResolvedTypesAttribute($varTagValue);
|
||||
}
|
||||
|
||||
public function getDoctrineIdTagValueNode(): ?IdTagValueNode
|
||||
public function getDoctrineId(): ?IdTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(IdTagValueNode::class);
|
||||
return $this->getByType(IdTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineTableTagValueNode(): ?TableTagValueNode
|
||||
public function getDoctrineTable(): ?TableTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(TableTagValueNode::class);
|
||||
return $this->getByType(TableTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineManyToManyTagValueNode(): ?ManyToManyTagValueNode
|
||||
public function getDoctrineManyToMany(): ?ManyToManyTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(ManyToManyTagValueNode::class);
|
||||
return $this->getByType(ManyToManyTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineManyToOneTagValueNode(): ?ManyToOneTagValueNode
|
||||
public function getDoctrineManyToOne(): ?ManyToOneTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(ManyToOneTagValueNode::class);
|
||||
return $this->getByType(ManyToOneTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineOneToOneTagValueNode(): ?OneToOneTagValueNode
|
||||
public function getDoctrineOneToOne(): ?OneToOneTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(OneToOneTagValueNode::class);
|
||||
return $this->getByType(OneToOneTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineOneToManyTagValueNode(): ?OneToManyTagValueNode
|
||||
public function getDoctrineOneToMany(): ?OneToManyTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(OneToManyTagValueNode::class);
|
||||
return $this->getByType(OneToManyTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineEntityTag(): ?EntityTagValueNode
|
||||
public function getDoctrineEntity(): ?EntityTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(EntityTagValueNode::class);
|
||||
return $this->getByType(EntityTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineColumnTagValueNode(): ?ColumnTagValueNode
|
||||
public function getDoctrineColumn(): ?ColumnTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(ColumnTagValueNode::class);
|
||||
return $this->getByType(ColumnTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineJoinColumnTagValueNode(): ?JoinColumnTagValueNode
|
||||
{
|
||||
return $this->matchChildValueNodeOfType(JoinColumnTagValueNode::class);
|
||||
return $this->getByType(JoinColumnTagValueNode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,10 +263,10 @@ final class PhpDocInfo
|
|||
|
||||
public function getDoctrineRelationTagValueNode(): ?DoctrineRelationTagValueNodeInterface
|
||||
{
|
||||
return $this->getDoctrineManyToManyTagValueNode() ??
|
||||
$this->getDoctrineOneToManyTagValueNode() ??
|
||||
$this->getDoctrineOneToOneTagValueNode() ??
|
||||
$this->getDoctrineManyToOneTagValueNode() ?? null;
|
||||
return $this->getDoctrineManyToMany() ??
|
||||
$this->getDoctrineOneToMany() ??
|
||||
$this->getDoctrineOneToOne() ??
|
||||
$this->getDoctrineManyToOne() ?? null;
|
||||
}
|
||||
|
||||
public function removeTagValueNodeFromNode(PhpDocTagValueNode $phpDocTagValueNode): void
|
||||
|
@ -285,7 +285,7 @@ final class PhpDocInfo
|
|||
/**
|
||||
* @param string $type
|
||||
*/
|
||||
public function matchChildValueNodeOfType(string $type): ?PhpDocTagValueNode
|
||||
public function getByType(string $type): ?PhpDocTagValueNode
|
||||
{
|
||||
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
||||
if ($phpDocChildNode instanceof PhpDocTagNode) {
|
||||
|
|
|
@ -7,11 +7,17 @@ use Nette\Utils\Strings;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
||||
use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
|
||||
|
||||
abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpDocTagValueNode
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
/**
|
||||
* @var string[]|null
|
||||
*/
|
||||
protected $orderedVisibleItems;
|
||||
|
||||
/**
|
||||
* @param mixed[] $item
|
||||
*/
|
||||
|
@ -21,6 +27,51 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
|||
$json = Strings::replace($json, '#,#', ', ');
|
||||
$json = Strings::replace($json, '#\[(.*?)\]#', '{$1}');
|
||||
|
||||
// cleanup json encoded extra slashes
|
||||
$json = Strings::replace($json, '#\\\\\\\\#', '\\');
|
||||
|
||||
return sprintf('%s=%s', $key, $json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $contentItems
|
||||
*/
|
||||
protected function printContentItems(array $contentItems): string
|
||||
{
|
||||
if ($this->orderedVisibleItems !== null) {
|
||||
$contentItems = ArrayItemStaticHelper::filterAndSortVisibleItems($contentItems, $this->orderedVisibleItems);
|
||||
}
|
||||
|
||||
if ($contentItems === []) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '(' . implode(', ', $contentItems) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocTagValueNode[] $tagValueNodes
|
||||
*/
|
||||
protected function printTagValueNodesSeparatedByComma(array $tagValueNodes, string $prefix = ''): string
|
||||
{
|
||||
if ($tagValueNodes === []) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$itemsAsStrings = [];
|
||||
foreach ($tagValueNodes as $tagValueNode) {
|
||||
$itemsAsStrings[] = $prefix . (string) $tagValueNode;
|
||||
}
|
||||
|
||||
return implode(', ', $itemsAsStrings);
|
||||
}
|
||||
|
||||
protected function resolveItemsOrderFromAnnotationContent(?string $annotationContent): void
|
||||
{
|
||||
if ($annotationContent === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($annotationContent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
$tokenIterator->next();
|
||||
|
||||
// @todo somehow decouple to tag pre-processor
|
||||
if ($tag === '@ORM') {
|
||||
if (Strings::match($tag, '#@(ORM|Assert|Serializer)$#')) {
|
||||
$tag .= $tokenIterator->currentTokenValue();
|
||||
$tokenIterator->next();
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ final class DoctrineDocBlockResolver
|
|||
return false;
|
||||
}
|
||||
|
||||
return (bool) $classPhpDocInfo->getDoctrineEntityTag();
|
||||
return (bool) $classPhpDocInfo->getDoctrineEntity();
|
||||
}
|
||||
|
||||
public function getTargetEntity(Property $property): ?string
|
||||
|
@ -49,7 +49,7 @@ final class DoctrineDocBlockResolver
|
|||
return false;
|
||||
}
|
||||
|
||||
return (bool) $propertyPhpDocInfo->getDoctrineIdTagValueNode();
|
||||
return (bool) $propertyPhpDocInfo->getDoctrineId();
|
||||
}
|
||||
|
||||
public function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRelationTagValueNodeInterface
|
||||
|
@ -69,7 +69,7 @@ final class DoctrineDocBlockResolver
|
|||
return null;
|
||||
}
|
||||
|
||||
return $classPhpDocInfo->getDoctrineTableTagValueNode();
|
||||
return $classPhpDocInfo->getDoctrineTable();
|
||||
}
|
||||
|
||||
public function isDoctrineProperty(Property $property): bool
|
||||
|
@ -79,7 +79,7 @@ final class DoctrineDocBlockResolver
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($propertyPhpDocInfo->getDoctrineColumnTagValueNode()) {
|
||||
if ($propertyPhpDocInfo->getDoctrineColumn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,13 +116,13 @@ final class AddUuidToEntityWhereMissingRector extends AbstractRector
|
|||
return false;
|
||||
}
|
||||
|
||||
$idTagValueNode = $propertyPhpDocInfo->getDoctrineIdTagValueNode();
|
||||
$idTagValueNode = $propertyPhpDocInfo->getDoctrineId();
|
||||
if ($idTagValueNode === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get column!
|
||||
$columnTagValueNode = $propertyPhpDocInfo->getDoctrineColumnTagValueNode();
|
||||
$columnTagValueNode = $propertyPhpDocInfo->getDoctrineColumn();
|
||||
if ($columnTagValueNode === null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use ReflectionClass;
|
|||
use ReflectionMethod;
|
||||
use ReflectionProperty;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class NodeAnnotationReader
|
||||
{
|
||||
|
@ -46,7 +47,7 @@ final class NodeAnnotationReader
|
|||
return $this->annotationReader->getMethodAnnotation($reflectionMethod, $annotationClassName);
|
||||
}
|
||||
|
||||
public function readDoctrineClassAnnotation(Class_ $class, string $annotationClassName): Annotation
|
||||
public function readClassAnnotation(Class_ $class, string $annotationClassName): Annotation
|
||||
{
|
||||
$classReflection = $this->createClassReflectionFromNode($class);
|
||||
|
||||
|
@ -59,7 +60,10 @@ final class NodeAnnotationReader
|
|||
return $classAnnotation;
|
||||
}
|
||||
|
||||
public function readDoctrinePropertyAnnotation(Property $property, string $annotationClassName): Annotation
|
||||
/**
|
||||
* @return Annotation|Constraint|null
|
||||
*/
|
||||
public function readPropertyAnnotation(Property $property, string $annotationClassName)
|
||||
{
|
||||
$propertyReflection = $this->createPropertyReflectionFromPropertyNode($property);
|
||||
|
||||
|
|
|
@ -2,48 +2,9 @@
|
|||
|
||||
namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc\AbstractTagValueNode;
|
||||
use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
|
||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
|
||||
|
||||
abstract class AbstractDoctrineTagValueNode extends AbstractTagValueNode implements DoctrineTagNodeInterface
|
||||
{
|
||||
/**
|
||||
* @var string[]|null
|
||||
*/
|
||||
protected $orderedVisibleItems;
|
||||
|
||||
/**
|
||||
* @param string[] $contentItems
|
||||
*/
|
||||
protected function printContentItems(array $contentItems): string
|
||||
{
|
||||
if ($this->orderedVisibleItems !== null) {
|
||||
$contentItems = ArrayItemStaticHelper::filterAndSortVisibleItems($contentItems, $this->orderedVisibleItems);
|
||||
}
|
||||
|
||||
if ($contentItems === []) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '(' . implode(', ', $contentItems) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocTagValueNode[] $tagValueNodes
|
||||
*/
|
||||
protected function printTagValueNodesSeparatedByComma(array $tagValueNodes, string $prefix = ''): string
|
||||
{
|
||||
if ($tagValueNodes === []) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$itemsAsStrings = [];
|
||||
foreach ($tagValueNodes as $tagValueNode) {
|
||||
$itemsAsStrings[] = $prefix . (string) $tagValueNode;
|
||||
}
|
||||
|
||||
return implode(', ', $itemsAsStrings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,4 +133,9 @@ final class ManyToManyTagValueNode extends AbstractDoctrineTagValueNode implemen
|
|||
{
|
||||
$this->inversedBy = null;
|
||||
}
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void
|
||||
{
|
||||
$this->targetEntity = $targetEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,4 +90,9 @@ final class ManyToOneTagValueNode extends AbstractDoctrineTagValueNode implement
|
|||
{
|
||||
$this->inversedBy = null;
|
||||
}
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void
|
||||
{
|
||||
$this->targetEntity = $targetEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,4 +107,9 @@ final class OneToManyTagValueNode extends AbstractDoctrineTagValueNode implement
|
|||
{
|
||||
$this->mappedBy = null;
|
||||
}
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void
|
||||
{
|
||||
$this->targetEntity = $targetEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,4 +126,9 @@ final class OneToOneTagValueNode extends AbstractDoctrineTagValueNode implements
|
|||
{
|
||||
$this->mappedBy = null;
|
||||
}
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void
|
||||
{
|
||||
$this->targetEntity = $targetEntity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,6 @@ interface DoctrineRelationTagValueNodeInterface
|
|||
public function getTargetEntity(): ?string;
|
||||
|
||||
public function getFqnTargetEntity(): ?string;
|
||||
|
||||
public function changeTargetEntity(string $targetEntity): void;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createEntityTagValueNode(Class_ $class, string $annotationContent): EntityTagValueNode
|
||||
{
|
||||
/** @var Entity $entity */
|
||||
$entity = $this->nodeAnnotationReader->readDoctrineClassAnnotation($class, Entity::class);
|
||||
$entity = $this->nodeAnnotationReader->readClassAnnotation($class, Entity::class);
|
||||
|
||||
return new EntityTagValueNode($entity->repositoryClass, $entity->readOnly, $this->resolveAnnotationItemsOrder(
|
||||
$annotationContent
|
||||
|
@ -123,7 +123,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createTableTagValueNode(Class_ $class, string $annotationContent): TableTagValueNode
|
||||
{
|
||||
/** @var Table $table */
|
||||
$table = $this->nodeAnnotationReader->readDoctrineClassAnnotation($class, Table::class);
|
||||
$table = $this->nodeAnnotationReader->readClassAnnotation($class, Table::class);
|
||||
|
||||
return new TableTagValueNode(
|
||||
$table->name,
|
||||
|
@ -138,7 +138,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createColumnTagValueNode(Property $property, string $annotationContent): ColumnTagValueNode
|
||||
{
|
||||
/** @var Column $column */
|
||||
$column = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, Column::class);
|
||||
$column = $this->nodeAnnotationReader->readPropertyAnnotation($property, Column::class);
|
||||
|
||||
return new ColumnTagValueNode(
|
||||
$column->name,
|
||||
|
@ -157,7 +157,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createManyToManyTagValueNode(Property $property, string $annotationContent): ManyToManyTagValueNode
|
||||
{
|
||||
/** @var ManyToMany $manyToMany */
|
||||
$manyToMany = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, ManyToMany::class);
|
||||
$manyToMany = $this->nodeAnnotationReader->readPropertyAnnotation($property, ManyToMany::class);
|
||||
|
||||
return new ManyToManyTagValueNode(
|
||||
$manyToMany->targetEntity,
|
||||
|
@ -175,7 +175,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createManyToOneTagValueNode(Property $property, string $annotationContent): ManyToOneTagValueNode
|
||||
{
|
||||
/** @var ManyToOne $manyToOne */
|
||||
$manyToOne = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, ManyToOne::class);
|
||||
$manyToOne = $this->nodeAnnotationReader->readPropertyAnnotation($property, ManyToOne::class);
|
||||
|
||||
return new ManyToOneTagValueNode(
|
||||
$manyToOne->targetEntity,
|
||||
|
@ -190,7 +190,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createOneToOneTagValueNode(Property $property, string $annotationContent): OneToOneTagValueNode
|
||||
{
|
||||
/** @var OneToOne $oneToOne */
|
||||
$oneToOne = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, OneToOne::class);
|
||||
$oneToOne = $this->nodeAnnotationReader->readPropertyAnnotation($property, OneToOne::class);
|
||||
|
||||
return new OneToOneTagValueNode(
|
||||
$oneToOne->targetEntity,
|
||||
|
@ -207,7 +207,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createOneToManyTagValueNode(Property $property, string $annotationContent): OneToManyTagValueNode
|
||||
{
|
||||
/** @var OneToMany $oneToMany */
|
||||
$oneToMany = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, OneToMany::class);
|
||||
$oneToMany = $this->nodeAnnotationReader->readPropertyAnnotation($property, OneToMany::class);
|
||||
|
||||
return new OneToManyTagValueNode(
|
||||
$oneToMany->mappedBy,
|
||||
|
@ -224,7 +224,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createJoinColumnTagValueNode(Property $property, string $annotationContent): JoinColumnTagValueNode
|
||||
{
|
||||
/** @var JoinColumn $joinColumn */
|
||||
$joinColumn = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, JoinColumn::class);
|
||||
$joinColumn = $this->nodeAnnotationReader->readPropertyAnnotation($property, JoinColumn::class);
|
||||
|
||||
return $this->createJoinColumnTagValueNodeFromJoinColumnAnnotation($joinColumn, $annotationContent);
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ final class OrmTagParser extends AbstractPhpDocParser
|
|||
private function createJoinTableTagValeNode(Property $property, string $annotationContent): JoinTableTagValueNode
|
||||
{
|
||||
/** @var JoinTable $joinTable */
|
||||
$joinTable = $this->nodeAnnotationReader->readDoctrinePropertyAnnotation($property, JoinTable::class);
|
||||
$joinTable = $this->nodeAnnotationReader->readPropertyAnnotation($property, JoinTable::class);
|
||||
|
||||
$joinColumnContents = Strings::matchAll(
|
||||
$annotationContent,
|
||||
|
|
|
@ -135,7 +135,7 @@ CODE_SAMPLE
|
|||
$classMethodPhpDocInfo = $this->getPhpDocInfo($classMethod);
|
||||
|
||||
/** @var TemplateTagValueNode|null $templateTagValueNode */
|
||||
$templateTagValueNode = $classMethodPhpDocInfo->matchChildValueNodeOfType(TemplateTagValueNode::class);
|
||||
$templateTagValueNode = $classMethodPhpDocInfo->getByType(TemplateTagValueNode::class);
|
||||
if ($templateTagValueNode === null) {
|
||||
throw new ShouldNotHappenException(__METHOD__);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc\AbstractTagValueNode;
|
||||
|
||||
abstract class AbstractConstaintTagValueNode extends AbstractTagValueNode
|
||||
{
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use Symfony\Component\Validator\Constraints\Choice;
|
||||
|
||||
final class AssertChoiceTagValueNode extends AbstractConstaintTagValueNode
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const SHORT_NAME = '@Assert\Choice';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NAME = Choice::class;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
*/
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private $strict;
|
||||
|
||||
/**
|
||||
* @param mixed[]|null $callback
|
||||
*/
|
||||
public function __construct(?array $callback, ?bool $strict, string $annotationContent)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
$this->strict = $strict;
|
||||
$this->resolveItemsOrderFromAnnotationContent($annotationContent);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$contentItems = [];
|
||||
|
||||
if ($this->callback) {
|
||||
$contentItems['callback'] = $this->printArrayItem($this->callback, 'callback');
|
||||
}
|
||||
|
||||
if ($this->strict !== null) {
|
||||
$contentItems['strict'] = sprintf('strict=%s', $this->strict ? 'true' : 'false');
|
||||
}
|
||||
|
||||
return $this->printContentItems($contentItems);
|
||||
}
|
||||
|
||||
public function isCallbackClass(string $class): bool
|
||||
{
|
||||
return $class === ($this->callback[0] ?? null);
|
||||
}
|
||||
|
||||
public function changeCallbackClass(string $newClass): void
|
||||
{
|
||||
$this->callback[0] = $newClass;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use JMS\Serializer\Annotation\Type;
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc\AbstractTagValueNode;
|
||||
|
||||
final class SerializerTypeTagValueNode extends AbstractTagValueNode
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const SHORT_NAME = '@Serializer\Type';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NAME = Type::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
public function __construct(string $name, ?string $annotationContent)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->resolveItemsOrderFromAnnotationContent($annotationContent);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return sprintf('("%s")', $this->name);
|
||||
}
|
||||
|
||||
public function replaceName(string $oldName, string $newName): bool
|
||||
{
|
||||
$oldNamePattern = '#\b' . preg_quote($oldName, '#') . '\b#';
|
||||
|
||||
$newNameValue = Strings::replace($this->name, $oldNamePattern, $newName);
|
||||
if ($newNameValue !== $this->name) {
|
||||
$this->name = $newNameValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\PhpDocParser\Extension;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocParserExtensionInterface;
|
||||
use Rector\Symfony\PhpDocParser\SymfonyPhpDocTagParser;
|
||||
|
||||
final class SymfonyPhpDocParserExtension implements PhpDocParserExtensionInterface
|
||||
{
|
||||
/**
|
||||
* @var SymfonyPhpDocTagParser
|
||||
*/
|
||||
private $symfonyPhpDocTagParser;
|
||||
|
||||
public function __construct(SymfonyPhpDocTagParser $symfonyPhpDocTagParser)
|
||||
{
|
||||
$this->symfonyPhpDocTagParser = $symfonyPhpDocTagParser;
|
||||
}
|
||||
|
||||
public function matchTag(string $tag): bool
|
||||
{
|
||||
return (bool) Strings::match($tag, '#^@(Assert|Serializer)\\\\(.*?)$#');
|
||||
}
|
||||
|
||||
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
||||
{
|
||||
return $this->symfonyPhpDocTagParser->parse($tokenIterator, $tag);
|
||||
}
|
||||
}
|
61
packages/Symfony/src/PhpDocParser/SymfonyPhpDocTagParser.php
Normal file
61
packages/Symfony/src/PhpDocParser/SymfonyPhpDocTagParser.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Symfony\PhpDocParser;
|
||||
|
||||
use JMS\Serializer\Annotation\Type;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\AbstractPhpDocParser;
|
||||
use Rector\Symfony\PhpDocParser\Ast\PhpDoc\AssertChoiceTagValueNode;
|
||||
use Rector\Symfony\PhpDocParser\Ast\PhpDoc\SerializerTypeTagValueNode;
|
||||
use Symfony\Component\Validator\Constraints\Choice;
|
||||
|
||||
final class SymfonyPhpDocTagParser extends AbstractPhpDocParser
|
||||
{
|
||||
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
||||
{
|
||||
$currentPhpNode = $this->getCurrentPhpNode();
|
||||
|
||||
// this is needed to append tokens to the end of annotation, even if not used
|
||||
$annotationContent = $this->resolveAnnotationContent($tokenIterator);
|
||||
|
||||
if ($currentPhpNode instanceof Property) {
|
||||
if ($tag === AssertChoiceTagValueNode::SHORT_NAME) {
|
||||
return $this->createAssertChoiceTagValueNode($currentPhpNode, $annotationContent);
|
||||
}
|
||||
|
||||
if ($tag === SerializerTypeTagValueNode::SHORT_NAME) {
|
||||
return $this->createSerializerTypeTagValueNode($currentPhpNode, $annotationContent);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function createAssertChoiceTagValueNode(
|
||||
Property $property,
|
||||
string $annotationContent
|
||||
): AssertChoiceTagValueNode {
|
||||
/** @var Choice $choiceAnnotation */
|
||||
$choiceAnnotation = $this->nodeAnnotationReader->readPropertyAnnotation(
|
||||
$property,
|
||||
AssertChoiceTagValueNode::CLASS_NAME
|
||||
);
|
||||
|
||||
return new AssertChoiceTagValueNode($choiceAnnotation->callback, $choiceAnnotation->strict, $annotationContent);
|
||||
}
|
||||
|
||||
private function createSerializerTypeTagValueNode(
|
||||
Property $property,
|
||||
string $annotationContent
|
||||
): SerializerTypeTagValueNode {
|
||||
/** @var Type $typeAnnotation */
|
||||
$typeAnnotation = $this->nodeAnnotationReader->readPropertyAnnotation(
|
||||
$property,
|
||||
SerializerTypeTagValueNode::CLASS_NAME
|
||||
);
|
||||
|
||||
return new SerializerTypeTagValueNode($typeAnnotation->name, $annotationContent);
|
||||
}
|
||||
}
|
|
@ -68,7 +68,7 @@ final class DoctrineColumnPropertyTypeInferer implements PropertyTypeInfererInte
|
|||
}
|
||||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($property);
|
||||
$doctrineColumnTagValueNode = $phpDocInfo->getDoctrineColumnTagValueNode();
|
||||
$doctrineColumnTagValueNode = $phpDocInfo->getDoctrineColumn();
|
||||
if ($doctrineColumnTagValueNode === null) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -2,12 +2,38 @@
|
|||
|
||||
namespace Rector\PhpDoc;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Comment\Doc;
|
||||
use PhpParser\Node;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
|
||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\Symfony\PhpDocParser\Ast\PhpDoc\AssertChoiceTagValueNode;
|
||||
use Rector\Symfony\PhpDocParser\Ast\PhpDoc\SerializerTypeTagValueNode;
|
||||
|
||||
final class PhpDocClassRenamer
|
||||
{
|
||||
/**
|
||||
* @var PhpDocInfoFactory
|
||||
*/
|
||||
private $phpDocInfoFactory;
|
||||
|
||||
/**
|
||||
* @var PhpDocInfoPrinter
|
||||
*/
|
||||
private $phpDocInfoPrinter;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $shouldUpdate = false;
|
||||
|
||||
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, PhpDocInfoPrinter $phpDocInfoPrinter)
|
||||
{
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->phpDocInfoPrinter = $phpDocInfoPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Covers annotations like @ORM, @Serializer, @Assert etc
|
||||
* See https://github.com/rectorphp/rector/issues/1872
|
||||
|
@ -21,27 +47,77 @@ final class PhpDocClassRenamer
|
|||
return;
|
||||
}
|
||||
|
||||
$textDocComment = $docComment->getText();
|
||||
$this->shouldUpdate = false;
|
||||
|
||||
$oldTypes = array_keys($oldToNewClasses);
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
|
||||
$this->procesAssertChoiceTagValueNode($oldToNewClasses, $phpDocInfo);
|
||||
$this->procesDoctrineRelationTagValueNode($oldToNewClasses, $phpDocInfo);
|
||||
$this->processSerializerTypeTagValueNode($oldToNewClasses, $phpDocInfo);
|
||||
|
||||
$oldTypesPregQuoted = [];
|
||||
foreach ($oldTypes as $oldType) {
|
||||
$oldTypesPregQuoted[] = '\b' . preg_quote($oldType) . '\b';
|
||||
}
|
||||
|
||||
$oldTypesPattern = '#(?|' . implode('|', $oldTypesPregQuoted) . ')#x';
|
||||
|
||||
$match = Strings::match($textDocComment, $oldTypesPattern);
|
||||
if ($match === null) {
|
||||
if ($this->shouldUpdate === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($match as $matchedOldType) {
|
||||
$newType = $oldToNewClasses[$matchedOldType];
|
||||
$textDocComment = Strings::replace($textDocComment, '#\b' . preg_quote($matchedOldType) . '\b#', $newType);
|
||||
}
|
||||
|
||||
$textDocComment = $this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo);
|
||||
$node->setDocComment(new Doc($textDocComment));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewClasses
|
||||
*/
|
||||
private function procesAssertChoiceTagValueNode(array $oldToNewClasses, PhpDocInfo $phpDocInfo): void
|
||||
{
|
||||
$choiceTagValueNode = $phpDocInfo->getByType(AssertChoiceTagValueNode::class);
|
||||
if (! $choiceTagValueNode instanceof AssertChoiceTagValueNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
if (! $choiceTagValueNode->isCallbackClass($oldClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$choiceTagValueNode->changeCallbackClass($newClass);
|
||||
$this->shouldUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewClasses
|
||||
*/
|
||||
private function procesDoctrineRelationTagValueNode(array $oldToNewClasses, PhpDocInfo $phpDocInfo): void
|
||||
{
|
||||
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
if (! $relationTagValueNode instanceof DoctrineRelationTagValueNodeInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
if ($relationTagValueNode->getFqnTargetEntity() !== $oldClass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$relationTagValueNode->changeTargetEntity($newClass);
|
||||
$this->shouldUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewClasses
|
||||
*/
|
||||
private function processSerializerTypeTagValueNode(array $oldToNewClasses, PhpDocInfo $phpDocInfo): void
|
||||
{
|
||||
$serializerTypeTagValueNode = $phpDocInfo->getByType(SerializerTypeTagValueNode::class);
|
||||
if (! $serializerTypeTagValueNode instanceof SerializerTypeTagValueNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
if ($serializerTypeTagValueNode->replaceName($oldClass, $newClass)) {
|
||||
$this->shouldUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ final class NodeAddingCommander implements CommanderInterface
|
|||
{
|
||||
$position = $this->resolveNearestExpressionPosition($positionNode);
|
||||
|
||||
// dump($this->wrapToExpression($addedNode));
|
||||
$this->nodesToAddBefore[$position][] = $this->wrapToExpression($addedNode);
|
||||
}
|
||||
|
||||
|
|
|
@ -150,8 +150,6 @@ CODE_SAMPLE
|
|||
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($serviceType);
|
||||
|
||||
// add property via constructor
|
||||
|
||||
/** @var Class_ $classNode */
|
||||
$this->addPropertyToClass($classNode, $serviceType, $propertyName);
|
||||
|
||||
|
|
20
stubs/JMS/Serializer/Type.php
Normal file
20
stubs/JMS/Serializer/Type.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace JMS\Serializer\Annotation;
|
||||
|
||||
if (class_exists('JMS\Serializer\Annotation\Type')) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY", "METHOD","ANNOTATION"})
|
||||
*/
|
||||
final class Type
|
||||
{
|
||||
/**
|
||||
* @Required
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
}
|
42
stubs/Symfony/Validator/Choice.php
Normal file
42
stubs/Symfony/Validator/Choice.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Symfony\Component\Validator\Constraints;
|
||||
|
||||
if (class_exists('Symfony\Component\Validator\Constraints\Choice')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
|
||||
*/
|
||||
class Choice extends Constraint
|
||||
{
|
||||
const NO_SUCH_CHOICE_ERROR = '8e179f1b-97aa-4560-a02f-2a8b42e49df7';
|
||||
const TOO_FEW_ERROR = '11edd7eb-5872-4b6e-9f12-89923999fd0e';
|
||||
const TOO_MANY_ERROR = '9bd98e49-211c-433f-8630-fd1c2d0f08c3';
|
||||
protected static $errorNames = [
|
||||
self::NO_SUCH_CHOICE_ERROR => 'NO_SUCH_CHOICE_ERROR',
|
||||
self::TOO_FEW_ERROR => 'TOO_FEW_ERROR',
|
||||
self::TOO_MANY_ERROR => 'TOO_MANY_ERROR',
|
||||
];
|
||||
public $choices;
|
||||
public $callback;
|
||||
public $multiple = false;
|
||||
public $strict = true;
|
||||
public $min;
|
||||
public $max;
|
||||
public $message = 'The value you selected is not a valid choice.';
|
||||
public $multipleMessage = 'One or more of the given values is invalid.';
|
||||
public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.';
|
||||
public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultOption()
|
||||
{
|
||||
return 'choices';
|
||||
}
|
||||
}
|
262
stubs/Symfony/Validator/Constraint.php
Normal file
262
stubs/Symfony/Validator/Constraint.php
Normal file
|
@ -0,0 +1,262 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Symfony\Component\Validator;
|
||||
|
||||
if (class_exists('Symfony\Component\Validator\Constraint')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @property array $groups The groups that the constraint belongs to
|
||||
*/
|
||||
abstract class Constraint
|
||||
{
|
||||
/**
|
||||
* The name of the group given to all constraints with no explicit group.
|
||||
*/
|
||||
const DEFAULT_GROUP = 'Default';
|
||||
|
||||
/**
|
||||
* Marks a constraint that can be put onto classes.
|
||||
*/
|
||||
const CLASS_CONSTRAINT = 'class';
|
||||
|
||||
/**
|
||||
* Marks a constraint that can be put onto properties.
|
||||
*/
|
||||
const PROPERTY_CONSTRAINT = 'property';
|
||||
|
||||
/**
|
||||
* Maps error codes to the names of their constants.
|
||||
*/
|
||||
protected static $errorNames = [];
|
||||
|
||||
/**
|
||||
* Domain-specific data attached to a constraint.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $payload;
|
||||
|
||||
/**
|
||||
* Initializes the constraint with options.
|
||||
*
|
||||
* You should pass an associative array. The keys should be the names of
|
||||
* existing properties in this class. The values should be the value for these
|
||||
* properties.
|
||||
*
|
||||
* Alternatively you can override the method getDefaultOption() to return the
|
||||
* name of an existing property. If no associative array is passed, this
|
||||
* property is set instead.
|
||||
*
|
||||
* You can force that certain options are set by overriding
|
||||
* getRequiredOptions() to return the names of these options. If any
|
||||
* option is not set here, an exception is thrown.
|
||||
*
|
||||
* @param mixed $options The options (as associative array)
|
||||
* or the value for the default
|
||||
* option (any other type)
|
||||
*
|
||||
* @throws InvalidOptionsException When you pass the names of non-existing
|
||||
* options
|
||||
* @throws MissingOptionsException When you don't pass any of the options
|
||||
* returned by getRequiredOptions()
|
||||
* @throws Exception() When you don't pass an associative
|
||||
* array, but getDefaultOption() returns
|
||||
* null
|
||||
*/
|
||||
public function __construct($options = null)
|
||||
{
|
||||
$defaultOption = $this->getDefaultOption();
|
||||
$invalidOptions = [];
|
||||
$missingOptions = array_flip((array) $this->getRequiredOptions());
|
||||
$knownOptions = get_object_vars($this);
|
||||
|
||||
// The "groups" option is added to the object lazily
|
||||
$knownOptions['groups'] = true;
|
||||
|
||||
if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) {
|
||||
if (null === $defaultOption) {
|
||||
throw new Exception(sprintf('No default option is configured for constraint "%s".', \get_class($this)));
|
||||
}
|
||||
|
||||
$options[$defaultOption] = $options['value'];
|
||||
unset($options['value']);
|
||||
}
|
||||
|
||||
if (\is_array($options)) {
|
||||
reset($options);
|
||||
}
|
||||
if ($options && \is_array($options) && \is_string(key($options))) {
|
||||
foreach ($options as $option => $value) {
|
||||
if (\array_key_exists($option, $knownOptions)) {
|
||||
$this->$option = $value;
|
||||
unset($missingOptions[$option]);
|
||||
} else {
|
||||
$invalidOptions[] = $option;
|
||||
}
|
||||
}
|
||||
} elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) {
|
||||
if (null === $defaultOption) {
|
||||
throw new Exception(sprintf('No default option is configured for constraint "%s".', \get_class($this)));
|
||||
}
|
||||
|
||||
if (\array_key_exists($defaultOption, $knownOptions)) {
|
||||
$this->$defaultOption = $options;
|
||||
unset($missingOptions[$defaultOption]);
|
||||
} else {
|
||||
$invalidOptions[] = $defaultOption;
|
||||
}
|
||||
}
|
||||
|
||||
if (\count($invalidOptions) > 0) {
|
||||
throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), \get_class($this)), $invalidOptions);
|
||||
}
|
||||
|
||||
if (\count($missingOptions) > 0) {
|
||||
throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), \get_class($this)), array_keys($missingOptions));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a lazily initialized option.
|
||||
*
|
||||
* Corresponding properties are added to the object on first access. Hence
|
||||
* this method will be called at most once per constraint instance and
|
||||
* option name.
|
||||
*
|
||||
* @param string $option The option name
|
||||
* @param mixed $value The value to set
|
||||
*
|
||||
* @throws InvalidOptionsException If an invalid option name is given
|
||||
*/
|
||||
public function __set($option, $value)
|
||||
{
|
||||
if ('groups' === $option) {
|
||||
$this->groups = (array) $value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a lazily initialized option.
|
||||
*
|
||||
* Corresponding properties are added to the object on first access. Hence
|
||||
* this method will be called at most once per constraint instance and
|
||||
* option name.
|
||||
*
|
||||
* @param string $option The option name
|
||||
*
|
||||
* @return mixed The value of the option
|
||||
*
|
||||
* @throws InvalidOptionsException If an invalid option name is given
|
||||
*
|
||||
* @internal this method should not be used or overwritten in userland code
|
||||
*/
|
||||
public function __get($option)
|
||||
{
|
||||
if ('groups' === $option) {
|
||||
$this->groups = [self::DEFAULT_GROUP];
|
||||
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $option The option name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($option)
|
||||
{
|
||||
return 'groups' === $option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given group if this constraint is in the Default group.
|
||||
*
|
||||
* @param string $group
|
||||
*/
|
||||
public function addImplicitGroupName($group)
|
||||
{
|
||||
if (\in_array(self::DEFAULT_GROUP, $this->groups) && !\in_array($group, $this->groups)) {
|
||||
$this->groups[] = $group;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the default option.
|
||||
*
|
||||
* Override this method to define a default option.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @see __construct()
|
||||
*/
|
||||
public function getDefaultOption()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the required options.
|
||||
*
|
||||
* Override this method if you want to define required options.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see __construct()
|
||||
*/
|
||||
public function getRequiredOptions()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the class that validates this constraint.
|
||||
*
|
||||
* By default, this is the fully qualified name of the constraint class
|
||||
* suffixed with "Validator". You can override this method to change that
|
||||
* behavior.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function validatedBy()
|
||||
{
|
||||
return \get_class($this).'Validator';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the constraint can be put onto classes, properties or
|
||||
* both.
|
||||
*
|
||||
* This method should return one or more of the constants
|
||||
* Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
|
||||
*
|
||||
* @return string|array One or more constant values
|
||||
*/
|
||||
public function getTargets()
|
||||
{
|
||||
return self::PROPERTY_CONSTRAINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimizes the serialized value to minimize storage space.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function __sleep(): array
|
||||
{
|
||||
// Initialize "groups" option if it is not set
|
||||
$this->groups;
|
||||
|
||||
return array_keys(get_object_vars($this));
|
||||
}
|
||||
}
|
|
@ -23,12 +23,6 @@ class ClassAnnotations
|
|||
*/
|
||||
public $keepThis;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("array<Rector\Tests\Rector\Class_\RenameClassRector\Source\OldClass>")
|
||||
* @Serializer\Type("iterable<key, Rector\Tests\Rector\Class_\RenameClassRector\Source\OldClass>")
|
||||
*/
|
||||
public $flights = [];
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Rector\Tests\Rector\Class_\RenameClassRector\Source\OldClass")
|
||||
*/
|
||||
|
@ -62,12 +56,6 @@ class ClassAnnotations
|
|||
*/
|
||||
public $keepThis;
|
||||
|
||||
/**
|
||||
* @Serializer\Type("array<Rector\Tests\Rector\Class_\RenameClassRector\Source\NewClass>")
|
||||
* @Serializer\Type("iterable<key, Rector\Tests\Rector\Class_\RenameClassRector\Source\NewClass>")
|
||||
*/
|
||||
public $flights = [];
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Rector\Tests\Rector\Class_\RenameClassRector\Source\NewClass")
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Rector\Class_\RenameClassRector\Fixture;
|
||||
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
class ClassAnnotationsSerializerIterableType
|
||||
{
|
||||
/**
|
||||
* @Serializer\Type("array<Rector\Tests\Rector\Class_\RenameClassRector\Source\OldClass>")
|
||||
*/
|
||||
public $flights = [];
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Rector\Class_\RenameClassRector\Fixture;
|
||||
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
class ClassAnnotationsSerializerIterableType
|
||||
{
|
||||
/**
|
||||
* @Serializer\Type("array<Rector\Tests\Rector\Class_\RenameClassRector\Source\NewClass>")
|
||||
*/
|
||||
public $flights = [];
|
||||
}
|
||||
|
||||
?>
|
|
@ -28,24 +28,25 @@ final class RenameClassRectorTest extends AbstractRectorTestCase
|
|||
|
||||
public function provideTestFiles(): Iterator
|
||||
{
|
||||
// yield [__DIR__ . '/Fixture/class_to_new.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/class_to_interface.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/interface_to_class.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/name_insensitive.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/twig_case.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/underscore_doc.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/keep_return_tag.php.inc'];
|
||||
//
|
||||
// // Renaming class itself and its namespace
|
||||
// yield [__DIR__ . '/Fixture/rename_class_without_namespace.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/rename_class.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/rename_interface.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/rename_trait.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/rename_class_without_namespace_to_class_without_namespace.php.inc'];
|
||||
// yield [__DIR__ . '/Fixture/rename_class_to_class_without_namespace.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/class_to_new.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/class_to_interface.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/interface_to_class.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/name_insensitive.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/twig_case.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/underscore_doc.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/keep_return_tag.php.inc'];
|
||||
|
||||
// Renaming class itself and its namespace
|
||||
yield [__DIR__ . '/Fixture/rename_class_without_namespace.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/rename_class.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/rename_interface.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/rename_trait.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/rename_class_without_namespace_to_class_without_namespace.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/rename_class_to_class_without_namespace.php.inc'];
|
||||
|
||||
// Symfony/Validator + Doctrine + JMS/Serializer annotations
|
||||
yield [__DIR__ . '/Fixture/class_annotations.php.inc'];
|
||||
yield [__DIR__ . '/Fixture/class_annotations_serializer_type.php.inc'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user