From b94211c46ad7adec3819fefaf23b9650b926dcd7 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 21 Oct 2025 11:18:50 +0200 Subject: [PATCH] SQLFilter: replace internal array shape with class --- phpstan-baseline.neon | 8 +------- phpstan.neon | 4 ++++ src/Query/Filter/Parameter.php | 20 +++++++++++++++++++ src/Query/Filter/SQLFilter.php | 31 ++++++++++++++++++------------ src/Query/ParameterTypeInferer.php | 6 +++--- 5 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 src/Query/Filter/Parameter.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fecf7487974..a9c9b994c15 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2563,7 +2563,7 @@ parameters: path: src/Query/Exec/MultiTableUpdateExecutor.php - - message: '#^Parameter \#3 \$types of method Doctrine\\DBAL\\Connection\:\:executeStatement\(\) expects array\\|string, Doctrine\\DBAL\\ArrayParameterType\|Doctrine\\DBAL\\ParameterType\|Doctrine\\DBAL\\Types\\Type\|string\>, list\ given\.$#' + message: '#^Parameter \#3 \$types of method Doctrine\\DBAL\\Connection\:\:executeStatement\(\) expects array\\|string, Doctrine\\DBAL\\ArrayParameterType\|Doctrine\\DBAL\\ParameterType\|Doctrine\\DBAL\\Types\\Type\|string\>, list\ given\.$#' identifier: argument.type count: 1 path: src/Query/Exec/MultiTableUpdateExecutor.php @@ -2610,12 +2610,6 @@ parameters: count: 1 path: src/Query/Expr/Select.php - - - message: '#^Property Doctrine\\ORM\\Query\\Filter\\SQLFilter\:\:\$parameters \(array\\) does not accept non\-empty\-array\\.$#' - identifier: assign.propertyType - count: 1 - path: src/Query/Filter/SQLFilter.php - - message: '#^Method Doctrine\\ORM\\Query\\ParameterTypeInferer\:\:inferType\(\) never returns int so it can be removed from the return type\.$#' identifier: return.unusedType diff --git a/phpstan.neon b/phpstan.neon index 40f6f50c815..107b826cd90 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -12,6 +12,10 @@ parameters: message: '~^Match expression does not handle remaining values:~' path: src/Utility/PersisterHelper.php + # The return type is already narrow enough. + - '~^Method Doctrine\\ORM\\Query\\ParameterTypeInferer\:\:inferType\(\) never returns ''[a-z_]+'' so it can be removed from the return type\.$~' + - '~^Method Doctrine\\ORM\\Query\\ParameterTypeInferer\:\:inferType\(\) never returns Doctrine\\DBAL\\(?:Array)?ParameterType\:\:[A-Z_]+ so it can be removed from the return type\.$~' + # DBAL 4 compatibility - message: '~^Method Doctrine\\ORM\\Query\\AST\\Functions\\TrimFunction::getTrimMode\(\) never returns .* so it can be removed from the return type\.$~' diff --git a/src/Query/Filter/Parameter.php b/src/Query/Filter/Parameter.php new file mode 100644 index 00000000000..249d4a8ea84 --- /dev/null +++ b/src/Query/Filter/Parameter.php @@ -0,0 +1,20 @@ + + * @phpstan-var array */ private array $parameters = []; @@ -49,7 +49,7 @@ final public function __construct( */ final public function setParameterList(string $name, array $values, string $type = Types::STRING): static { - $this->parameters[$name] = ['value' => $values, 'type' => $type, 'is_list' => true]; + $this->parameters[$name] = new Parameter(value: $values, type: $type, isList: true); // Keep the parameters sorted for the hash ksort($this->parameters); @@ -71,11 +71,11 @@ final public function setParameterList(string $name, array $values, string $type */ final public function setParameter(string $name, mixed $value, string|null $type = null): static { - if ($type === null) { - $type = ParameterTypeInferer::inferType($value); - } - - $this->parameters[$name] = ['value' => $value, 'type' => $type, 'is_list' => false]; + $this->parameters[$name] = new Parameter( + value: $value, + type: $type ?? ParameterTypeInferer::inferType($value), + isList: false, + ); // Keep the parameters sorted for the hash ksort($this->parameters); @@ -102,11 +102,11 @@ final public function getParameter(string $name): string throw new InvalidArgumentException("Parameter '" . $name . "' does not exist."); } - if ($this->parameters[$name]['is_list']) { + if ($this->parameters[$name]->isList) { throw FilterException::cannotConvertListParameterIntoSingleValue($name); } - return $this->em->getConnection()->quote((string) $this->parameters[$name]['value']); + return $this->em->getConnection()->quote((string) $this->parameters[$name]->value); } /** @@ -124,7 +124,7 @@ final public function getParameterList(string $name): string throw new InvalidArgumentException("Parameter '" . $name . "' does not exist."); } - if ($this->parameters[$name]['is_list'] === false) { + if (! $this->parameters[$name]->isList) { throw FilterException::cannotConvertSingleParameterIntoListValue($name); } @@ -133,7 +133,7 @@ final public function getParameterList(string $name): string $quoted = array_map( static fn (mixed $value): string => $connection->quote((string) $value), - $param['value'], + $param->value, ); return implode(',', $quoted); @@ -152,7 +152,14 @@ final public function hasParameter(string $name): bool */ final public function __toString(): string { - return serialize($this->parameters); + return serialize(array_map( + static fn (Parameter $value): array => [ + 'value' => $value->value, + 'type' => $value->type, + 'is_list' => $value->isList, + ], + $this->parameters, + )); } /** diff --git a/src/Query/ParameterTypeInferer.php b/src/Query/ParameterTypeInferer.php index dae28faee18..1c9b8627e20 100644 --- a/src/Query/ParameterTypeInferer.php +++ b/src/Query/ParameterTypeInferer.php @@ -25,9 +25,9 @@ final class ParameterTypeInferer { /** - * Infers type of a given value, returning a compatible constant: - * - Type (\Doctrine\DBAL\Types\Type::*) - * - Connection (\Doctrine\DBAL\Connection::PARAM_*) + * Infers the type of a given value + * + * @return ParameterType::*|ArrayParameterType::*|Types::* */ public static function inferType(mixed $value): ParameterType|ArrayParameterType|int|string {