|
22 | 22 | use Doctrine\ORM\Query\AST\SelectStatement;
|
23 | 23 | use Doctrine\ORM\Query\AST\WhereClause;
|
24 | 24 | use Doctrine\ORM\Query\TreeWalkerAdapter;
|
| 25 | +use Psr\Log\LoggerInterface; |
25 | 26 | use ShipMonk\DoctrineQueryChecker\Exception\LogicException;
|
| 27 | +use Throwable; |
| 28 | +use WeakReference; |
26 | 29 | use function array_map;
|
27 | 30 | use function class_exists;
|
28 | 31 | use function implode;
|
|
38 | 41 | class QueryCheckerTreeWalker extends TreeWalkerAdapter
|
39 | 42 | {
|
40 | 43 |
|
| 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 | + |
41 | 57 | public function walkSelectStatement(SelectStatement $selectStatement): void
|
42 | 58 | {
|
43 | 59 | if ($selectStatement->whereClause !== null) {
|
@@ -161,13 +177,15 @@ protected function verifyInputParameterType(
|
161 | 177 |
|
162 | 178 | $compatibleTypeNames = array_map(self::typeToName(...), $compatibleTypes);
|
163 | 179 |
|
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 | + ); |
171 | 189 | }
|
172 | 190 |
|
173 | 191 | private static function typeToName(string|Type|ParameterType|ArrayParameterType|null $type): string
|
@@ -274,7 +292,7 @@ protected function isEntity(object $object): bool
|
274 | 292 | $realClassName = $markerOffset === false ? $className : substr($className, $markerOffset + strlen($proxyMarker) + 2);
|
275 | 293 |
|
276 | 294 | if (!class_exists($realClassName)) {
|
277 |
| - throw new LogicException(sprintf('QueryCheckerTreeWalker: Class "%s" does not exist', $realClassName)); |
| 295 | + return false; |
278 | 296 | }
|
279 | 297 |
|
280 | 298 | return !$this->getEntityManager()->getMetadataFactory()->isTransient($realClassName);
|
@@ -312,4 +330,15 @@ protected function getEntityManager(): EntityManagerInterface
|
312 | 330 | return $this->_getQuery()->getEntityManager();
|
313 | 331 | }
|
314 | 332 |
|
| 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 | + |
315 | 344 | }
|
0 commit comments