Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_;

use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\AbstractDoctrineTagValueNode;

final class EmbeddableTagValueNode extends AbstractDoctrineTagValueNode
{
public function __construct(string $originalContent)
{
$this->resolveOriginalContentSpacingAndOrder($originalContent);
}

public function __toString(): string
{
return $this->originalContent;
}

public function getShortName(): string
{
return '@ORM\Embeddable';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Doctrine\Class_;

use Doctrine\ORM\Mapping\Embeddable;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EmbeddableTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\AbstractPhpDocNodeFactory;
use Rector\Core\Exception\ShouldNotHappenException;

final class EmbeddablePhpDocNodeFactory extends AbstractPhpDocNodeFactory
{
public function getClass(): string
{
return Embeddable::class;
}

public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator): ?PhpDocTagValueNode
{
if (! $node instanceof Class_) {
throw new ShouldNotHappenException();
}

/** @var Embeddable|null $entity */
$entity = $this->nodeAnnotationReader->readClassAnnotation($node, $this->getClass());
if ($entity === null) {
return null;
}

$annotationContent = $this->resolveContentFromTokenIterator($tokenIterator);

return new EmbeddableTagValueNode($annotationContent);
}
}
3 changes: 1 addition & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,7 @@ parameters:
- '#Right side of && is always true#'
- '#Parameter \#(.*?) (.*?) of class PhpParser\\Node\\Expr\\BinaryOp\\(.*?) constructor expects PhpParser\\Node\\Expr, PhpParser\\Node given#'

- '#Method Rector\\BetterPhpDocParser\\PhpDocNode\\JMS\\JMSInjectParamsTagValueNode\:\:__toString\(\) should return string but returns string\|null#'
- '#Method Rector\\BetterPhpDocParser\\PhpDocNode\\JMS\\JMSServiceValueNode\:\:__toString\(\) should return string but returns string\|null#'
- '#Method Rector\\(.*?)\:\:__toString\(\) should return string but returns string\|null#'

- '#Strict comparison using \=\=\= between mixed and (.*?) will always evaluate to false#'
- '#Parameter \#1 \$c of method Rector\\Php70\\EregToPcreTransformer\:\:_ere2pcre_escape\(\) expects string, mixed given#'
59 changes: 40 additions & 19 deletions rules/doctrine/src/PhpDocParser/DoctrineDocBlockResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EmbeddableTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\IdTagValueNode;
Expand Down Expand Up @@ -37,28 +38,11 @@ public function __construct(ParsedNodeCollector $parsedNodeCollector)
public function isDoctrineEntityClass($class): bool
{
if ($class instanceof Class_) {
$phpDocInfo = $class->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return false;
}

return $phpDocInfo->hasByType(EntityTagValueNode::class);
return $this->isDoctrineEntityClassNode($class);
}

if (is_string($class)) {
if (ClassExistenceStaticHelper::doesClassLikeExist($class)) {
$classNode = $this->parsedNodeCollector->findClass($class);
if ($classNode !== null) {
return $this->isDoctrineEntityClass($classNode);
}

$reflectionClass = new ReflectionClass($class);

// dummy check of 3rd party code without running it
return Strings::contains((string) $reflectionClass->getDocComment(), '@ORM\Entity');
}

return false;
return $this->isStringClassEntity($class);
}

throw new ShouldNotHappenException();
Expand Down Expand Up @@ -137,4 +121,41 @@ public function isInDoctrineEntityClass(Node $node): bool

return $this->isDoctrineEntityClass($classNode);
}

private function isDoctrineEntityClassNode(Class_ $class): bool
{
$phpDocInfo = $class->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return false;
}

if ($phpDocInfo->hasByType(EntityTagValueNode::class)) {
return true;
}

return $phpDocInfo->hasByType(EmbeddableTagValueNode::class);
}

private function isStringClassEntity(string $class): bool
{
if (! ClassExistenceStaticHelper::doesClassLikeExist($class)) {
return false;
}

$classNode = $this->parsedNodeCollector->findClass($class);
if ($classNode !== null) {
return $this->isDoctrineEntityClass($classNode);
}

$reflectionClass = new ReflectionClass($class);

// dummy check of 3rd party code without running it
$docCommentContent = (string) $reflectionClass->getDocComment();

if (Strings::contains($docCommentContent, '@ORM\Entity')) {
return true;
}

return Strings::contains($docCommentContent, '@ORM\Embeddable');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Embeddable
*/
class SkipEmbedable
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Product
class SkipEntity
{
}
17 changes: 17 additions & 0 deletions stubs/Doctrine/ORM/Mapping/Embeddable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Doctrine\ORM\Mapping;

// mimics @see https://github.com/doctrine/orm/blob/master/lib/Doctrine/ORM/Annotation/Embeddable.php

if (class_exists('Doctrine\ORM\Mapping\Embeddable')) {
return;
}

/**
* @Annotation
* @Target("CLASS")
*/
class Embeddable implements Annotation
{
}