Skip to content

Commit

Permalink
Bleeding edge - report entity mapping exception
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 15, 2022
1 parent 9fa37f6 commit 00e7f8f
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
6 changes: 6 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ rules:
- PHPStan\Rules\Doctrine\ORM\RepositoryMethodCallRule
- PHPStan\Rules\Doctrine\ORM\EntityNotFinalRule

conditionalTags:
PHPStan\Rules\Doctrine\ORM\EntityMappingExceptionRule:
phpstan.rules.rule: %featureToggles.bleedingEdge%

services:
-
class: PHPStan\Rules\Doctrine\ORM\QueryBuilderDqlRule
Expand All @@ -36,6 +40,8 @@ services:
allowNullablePropertyForRequiredField: %doctrine.allowNullablePropertyForRequiredField%
tags:
- phpstan.rules.rule
-
class: PHPStan\Rules\Doctrine\ORM\EntityMappingExceptionRule
-
class: PHPStan\Rules\Doctrine\ORM\EntityNotFinalRule
-
Expand Down
62 changes: 62 additions & 0 deletions src/Rules/Doctrine/ORM/EntityMappingExceptionRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Doctrine\ORM;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassNode;
use PHPStan\Rules\Rule;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;

/**
* @implements Rule<InClassNode>
*/
class EntityMappingExceptionRule implements Rule
{

/** @var \PHPStan\Type\Doctrine\ObjectMetadataResolver */
private $objectMetadataResolver;

public function __construct(
ObjectMetadataResolver $objectMetadataResolver
)
{
$this->objectMetadataResolver = $objectMetadataResolver;
}

public function getNodeType(): string
{
return InClassNode::class;
}

public function processNode(Node $node, Scope $scope): array
{
$class = $scope->getClassReflection();
if ($class === null) {
return [];
}

$objectManager = $this->objectMetadataResolver->getObjectManager();
if ($objectManager === null) {
return [];
}

$className = $class->getName();
try {
if ($objectManager->getMetadataFactory()->isTransient($className)) {
return [];
}
} catch (\ReflectionException $e) {
return [];
}

try {
$objectManager->getClassMetadata($className);
} catch (\Doctrine\ORM\Mapping\MappingException $e) {
return [$e->getMessage()];
}

return [];
}

}
37 changes: 37 additions & 0 deletions tests/Rules/Doctrine/ORM/EntityMappingExceptionRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Doctrine\ORM;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;

/**
* @extends RuleTestCase<EntityMappingExceptionRule>
*/
class EntityMappingExceptionRuleTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new EntityMappingExceptionRule(
new ObjectMetadataResolver($this->createReflectionProvider(), __DIR__ . '/entity-manager.php', null)
);
}

public function testValidEntity(): void
{
$this->analyse([__DIR__ . '/data-attributes/enum-type.php'], []);
}

public function testInvalidEntity(): void
{
$this->analyse([__DIR__ . '/data-attributes/enum-type-without-pk.php'], [
[
'No identifier/primary key specified for Entity "PHPStan\Rules\Doctrine\ORMAttributes\FooWithoutPK". Every Entity must have an identifier/primary key.',
7,
],
]);
}

}
14 changes: 14 additions & 0 deletions tests/Rules/Doctrine/ORM/data-attributes/enum-type-without-pk.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php // lint >= 8.1

namespace PHPStan\Rules\Doctrine\ORMAttributes;

use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class FooWithoutPK
{

#[ORM\Column(type: "string", enumType: FooEnum::class)]
public FooEnum $type;

}

0 comments on commit 00e7f8f

Please sign in to comment.