Skip to content

Commit

Permalink
QueryBuilderDqlRule: check also other methods if enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
janedbal authored and ondrejmirtes committed Nov 15, 2023
1 parent fdca50f commit b0e0c32
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
1 change: 1 addition & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ services:
class: PHPStan\Rules\Doctrine\ORM\QueryBuilderDqlRule
arguments:
reportDynamicQueryBuilders: %doctrine.reportDynamicQueryBuilders%
searchOtherMethodsForQueryBuilderBeginning: %doctrine.searchOtherMethodsForQueryBuilderBeginning%
tags:
- phpstan.rules.rule
-
Expand Down
21 changes: 20 additions & 1 deletion src/Rules/Doctrine/ORM/QueryBuilderDqlRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Doctrine\DoctrineTypeUtils;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
use PHPStan\Type\Doctrine\QueryBuilder\OtherMethodQueryBuilderParser;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeUtils;
use Throwable;
Expand All @@ -31,13 +32,23 @@ class QueryBuilderDqlRule implements Rule
/** @var bool */
private $reportDynamicQueryBuilders;

/** @var OtherMethodQueryBuilderParser */
private $otherMethodQueryBuilderParser;

/** @var bool */
private $searchOtherMethodsForQueryBuilderBeginning;

public function __construct(
ObjectMetadataResolver $objectMetadataResolver,
bool $reportDynamicQueryBuilders
OtherMethodQueryBuilderParser $otherMethodQueryBuilderParser,
bool $reportDynamicQueryBuilders,
bool $searchOtherMethodsForQueryBuilderBeginning
)
{
$this->objectMetadataResolver = $objectMetadataResolver;
$this->otherMethodQueryBuilderParser = $otherMethodQueryBuilderParser;
$this->reportDynamicQueryBuilders = $reportDynamicQueryBuilders;
$this->searchOtherMethodsForQueryBuilderBeginning = $searchOtherMethodsForQueryBuilderBeginning;
}

public function getNodeType(): string
Expand All @@ -58,6 +69,14 @@ public function processNode(Node $node, Scope $scope): array
$calledOnType = $scope->getType($node->var);
$queryBuilderTypes = DoctrineTypeUtils::getQueryBuilderTypes($calledOnType);
if (count($queryBuilderTypes) === 0) {

if ($this->searchOtherMethodsForQueryBuilderBeginning) {
$queryBuilderTypes = $this->otherMethodQueryBuilderParser->getQueryBuilderTypes($scope, $node);
if (count($queryBuilderTypes) !== 0) {
return [];
}
}

if (
$this->reportDynamicQueryBuilders
&& (new ObjectType('Doctrine\ORM\QueryBuilder'))->isSuperTypeOf($calledOnType)->yes()
Expand Down
12 changes: 7 additions & 5 deletions tests/Rules/Doctrine/ORM/QueryBuilderDqlRuleSlowTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
use PHPStan\Type\Doctrine\QueryBuilder\OtherMethodQueryBuilderParser;

/**
* @extends RuleTestCase<QueryBuilderDqlRule>
Expand All @@ -14,7 +15,12 @@ class QueryBuilderDqlRuleSlowTest extends RuleTestCase

protected function getRule(): Rule
{
return new QueryBuilderDqlRule(new ObjectMetadataResolver(__DIR__ . '/entity-manager.php'), true);
return new QueryBuilderDqlRule(
new ObjectMetadataResolver(__DIR__ . '/entity-manager.php'),
self::getContainer()->getByType(OtherMethodQueryBuilderParser::class),
true,
true
);
}

public function testRule(): void
Expand All @@ -40,10 +46,6 @@ public function testRule(): void
'QueryBuilder: [Semantical Error] line 0, col 14 near \'Foo e\': Error: Class \'Foo\' is not defined.',
71,
],
[
'Could not analyse QueryBuilder with unknown beginning.',
89,
],
[
'Could not analyse QueryBuilder with dynamic arguments.',
99,
Expand Down
12 changes: 7 additions & 5 deletions tests/Rules/Doctrine/ORM/QueryBuilderDqlRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use PHPStan\Type\Doctrine\ObjectMetadataResolver;
use PHPStan\Type\Doctrine\QueryBuilder\OtherMethodQueryBuilderParser;

/**
* @extends RuleTestCase<QueryBuilderDqlRule>
Expand All @@ -14,7 +15,12 @@ class QueryBuilderDqlRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new QueryBuilderDqlRule(new ObjectMetadataResolver(__DIR__ . '/entity-manager.php'), true);
return new QueryBuilderDqlRule(
new ObjectMetadataResolver(__DIR__ . '/entity-manager.php'),
self::getContainer()->getByType(OtherMethodQueryBuilderParser::class),
true,
true
);
}

public function testRule(): void
Expand All @@ -40,10 +46,6 @@ public function testRule(): void
'QueryBuilder: [Semantical Error] line 0, col 14 near \'Foo e\': Error: Class \'Foo\' is not defined.',
71,
],
[
'Could not analyse QueryBuilder with unknown beginning.',
89,
],
[
'Could not analyse QueryBuilder with dynamic arguments.',
99,
Expand Down

0 comments on commit b0e0c32

Please sign in to comment.