Skip to content

Commit 4cb2d85

Browse files
committed
QueryCheckerTreeWalker: support logging instead of throwing exception
1 parent d0942b7 commit 4cb2d85

File tree

4 files changed

+81
-9
lines changed

4 files changed

+81
-9
lines changed

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"require": {
88
"php": "^8.1",
99
"doctrine/dbal": "^4.2",
10-
"doctrine/orm": "^3.2"
10+
"doctrine/orm": "^3.2",
11+
"psr/log": "^1.0 || ^2.0 || ^3.0"
1112
},
1213
"require-dev": {
1314
"editorconfig-checker/editorconfig-checker": "^10.6.0",

src/QueryCheckerTreeWalker.php

+37-8
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
use Doctrine\ORM\Query\AST\SelectStatement;
2323
use Doctrine\ORM\Query\AST\WhereClause;
2424
use Doctrine\ORM\Query\TreeWalkerAdapter;
25+
use Psr\Log\LoggerInterface;
2526
use ShipMonk\DoctrineQueryChecker\Exception\LogicException;
27+
use Throwable;
28+
use WeakReference;
2629
use function array_map;
2730
use function class_exists;
2831
use function implode;
@@ -38,6 +41,19 @@
3841
class QueryCheckerTreeWalker extends TreeWalkerAdapter
3942
{
4043

44+
/**
45+
* @var WeakReference<LoggerInterface>|null
46+
*/
47+
private static ?WeakReference $logger = null;
48+
49+
/**
50+
* When logger is set, exceptions are logged instead of thrown.
51+
*/
52+
public static function setLogger(?LoggerInterface $logger): void
53+
{
54+
self::$logger = $logger !== null ? WeakReference::create($logger) : null;
55+
}
56+
4157
public function walkSelectStatement(SelectStatement $selectStatement): void
4258
{
4359
if ($selectStatement->whereClause !== null) {
@@ -161,13 +177,15 @@ protected function verifyInputParameterType(
161177

162178
$compatibleTypeNames = array_map(self::typeToName(...), $compatibleTypes);
163179

164-
throw new LogicException(sprintf(
165-
'QueryCheckerTreeWalker: Parameter "%s" is of type "%s", but expected one of: ["%s"] (because it\'s used in expression with %s)',
166-
$inputParameter->name,
167-
self::typeToName($inputParameterType),
168-
implode('", "', $compatibleTypeNames),
169-
$pathExpression->field !== null ? "{$pathExpression->identificationVariable}.{$pathExpression->field}" : $pathExpression->identificationVariable,
170-
));
180+
$this->processException(
181+
new LogicException(sprintf(
182+
'QueryCheckerTreeWalker: Parameter "%s" is of type "%s", but expected one of: ["%s"] (because it\'s used in expression with %s)',
183+
$inputParameter->name,
184+
self::typeToName($inputParameterType),
185+
implode('", "', $compatibleTypeNames),
186+
$pathExpression->field !== null ? "{$pathExpression->identificationVariable}.{$pathExpression->field}" : $pathExpression->identificationVariable,
187+
)),
188+
);
171189
}
172190

173191
private static function typeToName(string|Type|ParameterType|ArrayParameterType|null $type): string
@@ -274,7 +292,7 @@ protected function isEntity(object $object): bool
274292
$realClassName = $markerOffset === false ? $className : substr($className, $markerOffset + strlen($proxyMarker) + 2);
275293

276294
if (!class_exists($realClassName)) {
277-
throw new LogicException(sprintf('QueryCheckerTreeWalker: Class "%s" does not exist', $realClassName));
295+
return false;
278296
}
279297

280298
return !$this->getEntityManager()->getMetadataFactory()->isTransient($realClassName);
@@ -312,4 +330,15 @@ protected function getEntityManager(): EntityManagerInterface
312330
return $this->_getQuery()->getEntityManager();
313331
}
314332

333+
protected function processException(Throwable $e): void
334+
{
335+
$logger = self::$logger?->get();
336+
337+
if ($logger === null) {
338+
throw $e;
339+
}
340+
341+
$logger->error($e->getMessage(), ['exception' => $e]);
342+
}
343+
315344
}

tests/Lib/TestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ protected function setUp(): void
2626
{
2727
parent::setUp();
2828
$this->entityManager = null;
29+
QueryCheckerTreeWalker::setLogger(null);
2930
}
3031

3132
/**

tests/QueryCheckerTreeWalkerTest.php

+41
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
use Doctrine\DBAL\Types\Types;
77
use Doctrine\ORM\Query\Expr;
88
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Psr\Log\LoggerInterface;
910
use Ramsey\Uuid\Doctrine\UuidType;
1011
use ShipMonk\DoctrineQueryChecker\Exception\LogicException;
12+
use ShipMonk\DoctrineQueryChecker\QueryCheckerTreeWalker;
1113
use ShipMonkTests\DoctrineQueryChecker\Fixture\Entity\SimpleTestEntity;
1214
use ShipMonkTests\DoctrineQueryChecker\Fixture\Entity\SimpleTestEntityWithUuid;
1315
use ShipMonkTests\DoctrineQueryChecker\Fixture\Entity\TestEntityWithManyFieldTypes;
@@ -309,4 +311,43 @@ public static function provideWrongParameterTypesData(): iterable
309311
];
310312
}
311313

314+
public function testWillUseLoggerIfAvailable(): void
315+
{
316+
$logger = self::createMock(LoggerInterface::class);
317+
$logger->expects(self::once())
318+
->method('error')
319+
->with(
320+
'QueryCheckerTreeWalker: Parameter "value" is of type "float", but expected one of: ["boolean"] (because it\'s used in expression with e.booleanField)',
321+
self::arrayHasKey('exception'),
322+
);
323+
324+
QueryCheckerTreeWalker::setLogger($logger);
325+
326+
$this->getEntityManager()->createQueryBuilder()
327+
->select('e')
328+
->from(TestEntityWithManyFieldTypes::class, 'e')
329+
->andWhere('e.booleanField = :value')
330+
->setParameter('value', 123.4)
331+
->getQuery()
332+
->setQueryCache(new NullAdapter())
333+
->getResult();
334+
335+
QueryCheckerTreeWalker::setLogger(null);
336+
337+
self::assertException(
338+
LogicException::class,
339+
'QueryCheckerTreeWalker: Parameter "value" is of type "float", but expected one of: ["boolean"] (because it\'s used in expression with e.booleanField)',
340+
function (): void {
341+
$this->getEntityManager()->createQueryBuilder()
342+
->select('e')
343+
->from(TestEntityWithManyFieldTypes::class, 'e')
344+
->andWhere('e.booleanField = :value')
345+
->setParameter('value', 123.4)
346+
->getQuery()
347+
->setQueryCache(new NullAdapter())
348+
->getResult();
349+
},
350+
);
351+
}
352+
312353
}

0 commit comments

Comments
 (0)