From 736bf61ae3fb4b4487c1ae4d68a55e17ed75dc83 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 20 Jun 2026 12:26:44 +0200 Subject: [PATCH 1/3] [NodeAnalyzer] Detect Doctrine static function mapping (loadMetadata) entity in DoctrineEntityDetector --- src/NodeAnalyzer/DoctrineEntityDetector.php | 11 +++++-- .../DoctrineEntityDetectorTest.php | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/NodeAnalyzer/DoctrineEntityDetector/DoctrineEntityDetectorTest.php diff --git a/src/NodeAnalyzer/DoctrineEntityDetector.php b/src/NodeAnalyzer/DoctrineEntityDetector.php index 17cd9dc9..05ed978e 100644 --- a/src/NodeAnalyzer/DoctrineEntityDetector.php +++ b/src/NodeAnalyzer/DoctrineEntityDetector.php @@ -6,6 +6,7 @@ use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Reflection\ReflectionProvider; use Rector\NodeAnalyzer\DoctrineEntityAnalyzer; @@ -22,7 +23,13 @@ public function __construct( public function detect(Class_ $class): bool { - // A. check annotations + // A. check static function mapping, fields are mapped in loadMetadata() method + // @see https://www.doctrine-project.org/projects/doctrine-orm/en/3.6/reference/php-mapping.html#static-function + if ($class->getMethod('loadMetadata') instanceof ClassMethod) { + return true; + } + + // B. check annotations if ($this->doctrineEntityAnalyzer->hasClassAnnotation($class)) { return true; } @@ -33,7 +40,7 @@ public function detect(Class_ $class): bool $className = $class->namespacedName->toString(); - // B. check attributes + // C. check attributes $classReflection = $this->reflectionProvider->getClass($className); return $this->doctrineEntityAnalyzer->hasClassReflectionAttribute($classReflection); diff --git a/tests/NodeAnalyzer/DoctrineEntityDetector/DoctrineEntityDetectorTest.php b/tests/NodeAnalyzer/DoctrineEntityDetector/DoctrineEntityDetectorTest.php new file mode 100644 index 00000000..493ecb35 --- /dev/null +++ b/tests/NodeAnalyzer/DoctrineEntityDetector/DoctrineEntityDetectorTest.php @@ -0,0 +1,30 @@ +doctrineEntityDetector = $this->make(DoctrineEntityDetector::class); + } + + public function testDetectStaticFunctionMapping(): void + { + $class = new Class_('SomeEntity'); + $class->stmts[] = new ClassMethod('loadMetadata'); + + $this->assertTrue($this->doctrineEntityDetector->detect($class)); + } +} From 1c55d14378d9fa012f3e95ed6bd026d1c7a9b9a1 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 20 Jun 2026 10:27:31 +0000 Subject: [PATCH 2/3] [rector] Rector fixes --- .../Rector/MethodCall/CastDoctrineExprToStringRector.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php b/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php index 3fa370bc..c8e1d9f1 100644 --- a/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php +++ b/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php @@ -71,10 +71,6 @@ public function getNodeTypes(): array public function refactor(Node $node): ?Node { - if (! $node instanceof MethodCall) { - return null; - } - if (! $this->isObjectType($node->var, new ObjectType(DoctrineClass::QUERY_EXPR))) { return null; } From 4f8822145d2e784d94d94cc3fc5808349d54c45d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 20 Jun 2026 12:34:01 +0200 Subject: [PATCH 3/3] [PHPStan] Add @param MethodCall docblock to CastDoctrineExprToStringRector refactor() --- .../Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php b/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php index c8e1d9f1..2ce8a83e 100644 --- a/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php +++ b/rules/Orm30/Rector/MethodCall/CastDoctrineExprToStringRector.php @@ -69,6 +69,9 @@ public function getNodeTypes(): array return [MethodCall::class]; } + /** + * @param MethodCall $node + */ public function refactor(Node $node): ?Node { if (! $this->isObjectType($node->var, new ObjectType(DoctrineClass::QUERY_EXPR))) {