Skip to content

Commit 2a59547

Browse files
authored
[symfony] Make NoListenerWithoutContractRule skip doctrine (#166)
1 parent d4ae6c8 commit 2a59547

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

src/Rules/Symfony/NoListenerWithoutContractRule.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* Subscribers have much better PHP support - IDE, PHPStan + Rector - than simple yaml files
1818
*
1919
* @implements Rule<InClassNode>
20+
*
21+
* @see \Symplify\PHPStanRules\Tests\Rules\Symfony\NoListenerWithoutContractRule\NoListenerWithoutContractRuleTest
2022
*/
2123
final class NoListenerWithoutContractRule implements Rule
2224
{
@@ -25,6 +27,25 @@ final class NoListenerWithoutContractRule implements Rule
2527
*/
2628
public const ERROR_MESSAGE = 'There should be no listeners modified in config. Use EventSubscriberInterface contract and PHP instead';
2729

30+
/**
31+
* @see https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/reference/events.html
32+
*/
33+
private const DOCTRINE_EVENT_NAMES = [
34+
'preRemove',
35+
'postRemove',
36+
'prePersist',
37+
'postPersist',
38+
'preUpdate',
39+
'postUpdate',
40+
'postLoad',
41+
'loadClassMetadata',
42+
'onClassMetadataNotFound',
43+
'preFlush',
44+
'onFlush',
45+
'postFlush',
46+
'onClear',
47+
];
48+
2849
public function getNodeType(): string
2950
{
3051
return InClassNode::class;
@@ -53,10 +74,26 @@ public function processNode(Node $node, Scope $scope): array
5374
return [];
5475
}
5576

77+
if ($this->isDoctrineListener($classLike)) {
78+
return [];
79+
}
80+
5681
$identifierRuleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
5782
->identifier(SymfonyRuleIdentifier::NO_LISTENER_WITHOUT_CONTRACT)
5883
->build();
5984

6085
return [$identifierRuleError];
6186
}
87+
88+
private function isDoctrineListener(Class_ $class): bool
89+
{
90+
// skip doctrine, as this is handling symfony only
91+
foreach ($class->getMethods() as $classMethod) {
92+
if (in_array($classMethod->name->toString(), self::DOCTRINE_EVENT_NAMES)) {
93+
return true;
94+
}
95+
}
96+
97+
return false;
98+
}
6299
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Symfony\NoListenerWithoutContractRule\Fixture;
4+
5+
final class SkipDoctrineListener
6+
{
7+
public function onFlush(\Doctrine\ODM\MongoDB\Event\OnFlushEventArgs $onFlushEventArgs)
8+
{
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Symfony\NoListenerWithoutContractRule\Fixture;
4+
5+
final class SomeBareListener
6+
{
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Symfony\NoListenerWithoutContractRule\Fixture;
4+
5+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
6+
7+
final class SomeContractedListener implements EventSubscriberInterface
8+
{
9+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Symfony\NoListenerWithoutContractRule;
4+
5+
use Iterator;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Testing\RuleTestCase;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Symplify\PHPStanRules\Rules\Symfony\NoListenerWithoutContractRule;
10+
11+
final class NoListenerWithoutContractRuleTest extends RuleTestCase
12+
{
13+
/**
14+
* @param string[] $filePaths
15+
*/
16+
#[DataProvider('provideData')]
17+
public function testRule(array $filePaths, array $expectedErrorsWithLines): void
18+
{
19+
$this->analyse($filePaths, $expectedErrorsWithLines);
20+
}
21+
22+
public static function provideData(): Iterator
23+
{
24+
yield [[__DIR__ . '/Fixture/SomeContractedListener.php'], []];
25+
yield [[__DIR__ . '/Fixture/SkipDoctrineListener.php'], []];
26+
27+
yield [[__DIR__ . '/Fixture/SomeBareListener.php'], [[
28+
NoListenerWithoutContractRule::ERROR_MESSAGE,
29+
5,
30+
]]];
31+
}
32+
33+
protected function getRule(): Rule
34+
{
35+
return new NoListenerWithoutContractRule();
36+
}
37+
}

0 commit comments

Comments
 (0)