From a4376201c1c116355977af4e543b1203fb70b2de Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 5 Oct 2026 09:57:34 +1100 Subject: [PATCH 1/2] Name literal arguments and replace isset, empty and elvis in Sql isset() checks become explicit null comparisons or ??=, so the behaviour for null entries is unchanged. Sql's factory methods switch from ?: to ??, which is equivalent because every constructor already treats a falsy table as no table. Signed-off-by: Simon Mundy --- analyzer-baseline.toml | 38 +--- lint-baseline.toml | 192 ------------------ src/Sql/AbstractSql.php | 29 ++- src/Sql/Argument/Identifiers.php | 2 +- src/Sql/Argument/Values.php | 2 +- src/Sql/Combine.php | 4 +- src/Sql/Ddl/AlterTable.php | 2 +- src/Sql/Ddl/Column/AbstractLengthColumn.php | 2 +- .../Ddl/Column/AbstractTimestampColumn.php | 2 +- src/Sql/Ddl/Column/Integer.php | 2 +- src/Sql/Ddl/Constraint/AbstractConstraint.php | 2 +- src/Sql/Ddl/Constraint/ForeignKey.php | 2 +- src/Sql/Ddl/CreateTable.php | 2 +- src/Sql/Ddl/Index/Index.php | 2 +- src/Sql/Expression.php | 6 +- src/Sql/Join.php | 3 +- src/Sql/Literal.php | 2 +- src/Sql/Platform/Platform.php | 16 +- src/Sql/Select.php | 13 +- src/Sql/Sql.php | 8 +- 20 files changed, 52 insertions(+), 279 deletions(-) diff --git a/analyzer-baseline.toml b/analyzer-baseline.toml index 6a0f82f4..da461359 100644 --- a/analyzer-baseline.toml +++ b/analyzer-baseline.toml @@ -1936,7 +1936,7 @@ count = 1 file = "src/Sql/AbstractSql.php" code = "mixed-argument" message = "Invalid argument type for argument #1 of `vsprintf`: expected `string`, but found `mixed`." -count = 2 +count = 1 [[issues]] file = "src/Sql/AbstractSql.php" @@ -2058,12 +2058,6 @@ code = "possibly-undefined-string-array-index" message = "Possibly undefined array key `string('column')` accessed on `array`." count = 1 -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "possibly-undefined-variable" -message = "Variable `$paramSpecs` might not have been defined on all execution paths leading to this point." -count = 1 - [[issues]] file = "src/Sql/AbstractSql.php" code = "string-member-selector" @@ -3576,36 +3570,12 @@ code = "class-must-be-final" message = 'Class `PhpDb\Sql\Platform\Platform` should be declared `final`.' count = 1 -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "invalid-iterator" -message = "The expression provided to `foreach` is not iterable. It resolved to type `nonnull`, which is not iterable." -count = 1 - -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "mixed-argument" -message = "Invalid argument type for argument #2 of `is_a`: expected `class-string`, but found `mixed`." -count = 1 - [[issues]] file = "src/Sql/Platform/Platform.php" code = "mixed-array-assignment" message = "Unsafe array assignment on type `mixed`." count = 1 -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "mixed-assignment" -message = "Assigning `mixed` type to a variable may lead to unexpected behavior." -count = 2 - -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "mixed-method-access" -message = "Attempting to access a method on a non-object type (`mixed`)." -count = 1 - [[issues]] file = "src/Sql/Platform/Platform.php" code = "mixed-return-statement" @@ -3618,12 +3588,6 @@ code = "mixed-return-statement" message = 'Could not infer a precise return type for function `PhpDb\Sql\Platform\Platform::getSqlString`. Saw type `mixed`.' count = 1 -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "mixed-return-statement" -message = 'Could not infer a precise return type for function `PhpDb\Sql\Platform\Platform::getTypeDecorator`. Saw type `mixed`.' -count = 1 - [[issues]] file = "src/Sql/Platform/Platform.php" code = "non-existent-method" diff --git a/lint-baseline.toml b/lint-baseline.toml index 82306798..e342477e 100644 --- a/lint-baseline.toml +++ b/lint-baseline.toml @@ -372,24 +372,6 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "literal-named-argument" -message = 'Literal argument `"\n ,"` should be passed as a named argument for clarity.' -count = 1 - -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "literal-named-argument" -message = "Literal argument `'%'` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "literal-named-argument" -message = "Literal argument `'__'` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/AbstractSql.php" code = "no-else-clause" @@ -402,36 +384,12 @@ code = "no-else-clause" message = "Avoid `elseif` clauses." count = 5 -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 5 - -[[issues]] -file = "src/Sql/AbstractSql.php" -code = "no-shorthand-ternary" -message = "Use of the shorthand ternary operator." -count = 1 - [[issues]] file = "src/Sql/AbstractSql.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Argument/Identifiers.php" -code = "literal-named-argument" -message = "Literal argument `'%s'` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Argument/Values.php" -code = "literal-named-argument" -message = "Literal argument `'%s'` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Combine.php" code = "cyclomatic-complexity" @@ -444,24 +402,12 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/Combine.php" -code = "literal-named-argument" -message = "Literal argument `' '` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Combine.php" code = "no-array-accumulation-in-loop" message = "Array spread in reassignment inside a loop causes O(n²) array copying." count = 1 -[[issues]] -file = "src/Sql/Combine.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - [[issues]] file = "src/Sql/Ddl/AlterTable.php" code = "kan-defect" @@ -480,30 +426,12 @@ code = "no-else-clause" message = "Avoid `elseif` clauses." count = 2 -[[issues]] -file = "src/Sql/Ddl/AlterTable.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - [[issues]] file = "src/Sql/Ddl/AlterTable.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Ddl/Column/AbstractLengthColumn.php" -code = "literal-named-argument" -message = "Literal argument `0` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/Column/AbstractLengthColumn.php" -code = "literal-named-argument" -message = "Literal argument `2` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Ddl/Column/AbstractPrecisionColumn.php" code = "excessive-parameter-list" @@ -516,12 +444,6 @@ code = "halstead" message = "Method has a high halstead difficulty" count = 1 -[[issues]] -file = "src/Sql/Ddl/Column/AbstractTimestampColumn.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - [[issues]] file = "src/Sql/Ddl/Column/Column.php" code = "no-else-clause" @@ -534,30 +456,12 @@ code = "no-else-clause" message = "Avoid `elseif` clauses." count = 1 -[[issues]] -file = "src/Sql/Ddl/Column/Integer.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - -[[issues]] -file = "src/Sql/Ddl/Constraint/AbstractConstraint.php" -code = "literal-named-argument" -message = "Literal argument `'%s'` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Ddl/Constraint/ForeignKey.php" code = "excessive-parameter-list" message = "Parameter list is too long." count = 1 -[[issues]] -file = "src/Sql/Ddl/Constraint/ForeignKey.php" -code = "literal-named-argument" -message = "Literal argument `'%s'` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Ddl/CreateTable.php" code = "cyclomatic-complexity" @@ -576,24 +480,12 @@ code = "no-else-clause" message = "Avoid `elseif` clauses." count = 2 -[[issues]] -file = "src/Sql/Ddl/CreateTable.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - [[issues]] file = "src/Sql/Ddl/CreateTable.php" code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Ddl/Index/Index.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - [[issues]] file = "src/Sql/Delete.php" code = "no-else-clause" @@ -606,24 +498,6 @@ code = "halstead" message = "Method has a high halstead difficulty" count = 1 -[[issues]] -file = "src/Sql/Expression.php" -code = "literal-named-argument" -message = "Literal argument `'%%'` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Expression.php" -code = "literal-named-argument" -message = "Literal argument `'%s'` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Expression.php" -code = "literal-named-argument" -message = "Literal argument `1` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Expression.php" code = "no-else-clause" @@ -648,36 +522,6 @@ code = "too-many-methods" message = "Class has too many methods." count = 1 -[[issues]] -file = "src/Sql/Join.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 1 - -[[issues]] -file = "src/Sql/Literal.php" -code = "literal-named-argument" -message = "Literal argument `'%%'` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "literal-named-argument" -message = "Literal argument `''` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "literal-named-argument" -message = "Literal argument `true` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Platform/Platform.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 2 - [[issues]] file = "src/Sql/Predicate/In.php" code = "halstead" @@ -780,18 +624,6 @@ code = "kan-defect" message = "Class has a high kan defect score." count = 1 -[[issues]] -file = "src/Sql/Select.php" -code = "literal-named-argument" -message = "Literal argument `' as '` should be passed as a named argument for clarity." -count = 1 - -[[issues]] -file = "src/Sql/Select.php" -code = "literal-named-argument" -message = "Literal argument `2` should be passed as a named argument for clarity." -count = 1 - [[issues]] file = "src/Sql/Select.php" code = "no-else-clause" @@ -804,24 +636,6 @@ code = "no-else-clause" message = "Avoid `elseif` clauses." count = 3 -[[issues]] -file = "src/Sql/Select.php" -code = "no-empty" -message = "Use of the `empty` construct." -count = 1 - -[[issues]] -file = "src/Sql/Select.php" -code = "no-isset" -message = "Use of the `isset` construct." -count = 2 - -[[issues]] -file = "src/Sql/Select.php" -code = "no-negated-ternary" -message = "Negated ternary condition." -count = 1 - [[issues]] file = "src/Sql/Select.php" code = "too-many-methods" @@ -834,12 +648,6 @@ code = "too-many-properties" message = "Class has too many properties." count = 1 -[[issues]] -file = "src/Sql/Sql.php" -code = "no-shorthand-ternary" -message = "Use of the shorthand ternary operator." -count = 4 - [[issues]] file = "src/Sql/Update.php" code = "cyclomatic-complexity" diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSql.php index b5e818d8..b2bd0de9 100644 --- a/src/Sql/AbstractSql.php +++ b/src/Sql/AbstractSql.php @@ -55,7 +55,7 @@ abstract class AbstractSql implements SqlInterface #[Override] public function getSqlString(?PlatformInterface $adapterPlatform = null): string { - $adapterPlatform = $adapterPlatform ?: new DefaultAdapterPlatform(); + $adapterPlatform ??= new DefaultAdapterPlatform(); return $this->buildSqlString($adapterPlatform); } @@ -83,7 +83,7 @@ protected function buildSqlString( } } - return rtrim(implode(' ', $sqls), "\n ,"); + return rtrim(implode(' ', $sqls), characters: "\n ,"); } /** @@ -95,23 +95,24 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi return vsprintf($specifications, $parameters); } - $parametersCount = count($parameters); + $parametersCount = count($parameters); + $specificationString = null; + $paramSpecs = []; - foreach ($specifications as $specificationString => $paramSpecs) { + foreach ($specifications as $candidateString => $paramSpecs) { if (count($paramSpecs) === $parametersCount) { + $specificationString = (string) $candidateString; break; } - - unset($specificationString, $paramSpecs); } - if (! isset($specificationString)) { + if (null === $specificationString) { throw Exception\RuntimeException::forUnsupportedParameterCount(); } $topParameters = []; foreach ($parameters as $position => $paramsForPosition) { - if (isset($paramSpecs[$position]['combinedby'])) { + if (null !== ($paramSpecs[$position]['combinedby'] ?? null)) { $multiParamValues = []; foreach ($paramsForPosition as $multiParamsForPosition) { if (is_array($multiParamsForPosition)) { @@ -121,7 +122,7 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi $multiParamsForPosition = [$multiParamsForPosition]; } - if (! isset($paramSpecs[$position][$ppCount])) { + if (null === ($paramSpecs[$position][$ppCount] ?? null)) { throw Exception\RuntimeException::forUnsupportedParameterCountOf($ppCount); } @@ -131,7 +132,7 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi $topParameters[] = implode($paramSpecs[$position]['combinedby'], $multiParamValues); } elseif (null !== $paramSpecs[$position]) { $ppCount = count($paramsForPosition); - if (! isset($paramSpecs[$position][$ppCount])) { + if (null === ($paramSpecs[$position][$ppCount] ?? null)) { throw Exception\RuntimeException::forUnsupportedParameterCountOf($ppCount); } @@ -208,7 +209,7 @@ protected function processExpression( $expressionValues = $expressionData['values']; if ([] === $expressionValues) { - return str_replace('%%', '%', $specification); + return str_replace('%%', replace: '%', subject: $specification); } if (null === $namedParameterPrefix || '' === $namedParameterPrefix) { @@ -218,12 +219,10 @@ protected function processExpression( } else { $namedParameterPrefix = $this->processInfo['paramPrefix'] - . str_replace([' ', "\t", "\n", "\r"], '__', $namedParameterPrefix); + . str_replace([' ', "\t", "\n", "\r"], replace: '__', subject: $namedParameterPrefix); } - if (! isset($this->instanceParameterIndex[$namedParameterPrefix])) { - $this->instanceParameterIndex[$namedParameterPrefix] = 1; - } + $this->instanceParameterIndex[$namedParameterPrefix] ??= 1; $expressionParamIndex = &$this->instanceParameterIndex[$namedParameterPrefix]; $expressionValues = $this->flattenExpressionValues($expressionValues); diff --git a/src/Sql/Argument/Identifiers.php b/src/Sql/Argument/Identifiers.php index 2e27955e..03ff6c88 100644 --- a/src/Sql/Argument/Identifiers.php +++ b/src/Sql/Argument/Identifiers.php @@ -37,7 +37,7 @@ public function getSpecification(): string { $count = count($this->identifiers); return $count > 0 - ? '(' . implode(', ', array_fill(0, $count, '%s')) . ')' + ? '(' . implode(', ', array_fill(0, count: $count, value: '%s')) . ')' : '(NULL)'; } diff --git a/src/Sql/Argument/Values.php b/src/Sql/Argument/Values.php index 23e869db..45751c97 100644 --- a/src/Sql/Argument/Values.php +++ b/src/Sql/Argument/Values.php @@ -37,7 +37,7 @@ public function getSpecification(): string { $count = count($this->values); return $count > 0 - ? '(' . implode(', ', array_fill(0, $count, '%s')) . ')' + ? '(' . implode(', ', array_fill(0, count: $count, value: '%s')) . ')' : '(NULL)'; } diff --git a/src/Sql/Combine.php b/src/Sql/Combine.php index ceb269ca..c9c2de0a 100644 --- a/src/Sql/Combine.php +++ b/src/Sql/Combine.php @@ -126,7 +126,7 @@ public function getRawState(?string $key = null): mixed ? $this->combine[0]['select']->getRawState(self::COLUMNS) : [], ]; - return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; + return null !== $key && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; } /** @@ -175,6 +175,6 @@ protected function buildSqlString( ); } - return trim($sql, ' '); + return trim($sql, characters: ' '); } } diff --git a/src/Sql/Ddl/AlterTable.php b/src/Sql/Ddl/AlterTable.php index b824cade..e8f2a4f0 100644 --- a/src/Sql/Ddl/AlterTable.php +++ b/src/Sql/Ddl/AlterTable.php @@ -160,7 +160,7 @@ public function getRawState(?string $key = null): array|string self::TABLE_OPTIONS => $this->options, ]; - return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; + return null !== $key && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; } public function setOption(string $name, Literal|bool|int|string $value): static diff --git a/src/Sql/Ddl/Column/AbstractLengthColumn.php b/src/Sql/Ddl/Column/AbstractLengthColumn.php index abc4e19a..c4bf3556 100644 --- a/src/Sql/Ddl/Column/AbstractLengthColumn.php +++ b/src/Sql/Ddl/Column/AbstractLengthColumn.php @@ -59,7 +59,7 @@ public function getExpressionData(): array $attributes = substr($expressionData['spec'], strlen($this->specification)); $expressionData['spec'] = "{$this->specification}(%s){$attributes}"; - array_splice($expressionData['values'], 2, 0, [new Literal($lengthExpression)]); + array_splice($expressionData['values'], offset: 2, length: 0, replacement: [new Literal($lengthExpression)]); return $expressionData; } diff --git a/src/Sql/Ddl/Column/AbstractTimestampColumn.php b/src/Sql/Ddl/Column/AbstractTimestampColumn.php index 4709509b..e34b25fd 100644 --- a/src/Sql/Ddl/Column/AbstractTimestampColumn.php +++ b/src/Sql/Ddl/Column/AbstractTimestampColumn.php @@ -19,7 +19,7 @@ public function getExpressionData(): array $expressionData = parent::getExpressionData(); $options = $this->getOptions(); - if (isset($options['on_update'])) { + if (null !== ($options['on_update'] ?? null)) { $expressionData['spec'] .= ' %s'; $expressionData['values'][] = new Literal('ON UPDATE CURRENT_TIMESTAMP'); } diff --git a/src/Sql/Ddl/Column/Integer.php b/src/Sql/Ddl/Column/Integer.php index 9a8d50e9..e2328019 100644 --- a/src/Sql/Ddl/Column/Integer.php +++ b/src/Sql/Ddl/Column/Integer.php @@ -30,7 +30,7 @@ public function getExpressionData(): array $expressionData = parent::getExpressionData(); $options = $this->getOptions(); - if (! isset($options['length'])) { + if (null === ($options['length'] ?? null)) { return $expressionData; } diff --git a/src/Sql/Ddl/Constraint/AbstractConstraint.php b/src/Sql/Ddl/Constraint/AbstractConstraint.php index 946d149d..ffecc368 100644 --- a/src/Sql/Ddl/Constraint/AbstractConstraint.php +++ b/src/Sql/Ddl/Constraint/AbstractConstraint.php @@ -65,7 +65,7 @@ public function getExpressionData(): array $columnCount = count($this->columns); if (0 !== $columnCount) { - $columnSpec = array_fill(0, $columnCount, '%s'); + $columnSpec = array_fill(0, count: $columnCount, value: '%s'); $specParts[] = str_replace('%s', implode(', ', $columnSpec), $this->columnSpecification); for ($i = 0; $i < $columnCount; $i++) { $values[] = new Identifier($this->columns[$i]); diff --git a/src/Sql/Ddl/Constraint/ForeignKey.php b/src/Sql/Ddl/Constraint/ForeignKey.php index 9a28096f..e7d7a690 100644 --- a/src/Sql/Ddl/Constraint/ForeignKey.php +++ b/src/Sql/Ddl/Constraint/ForeignKey.php @@ -70,7 +70,7 @@ public function getExpressionData(): array $expressionData['values'][] = new Identifier($this->referenceTable); if (0 !== $colCount) { - $expressionData['spec'] .= ' (' . implode(', ', array_fill(0, $colCount, '%s')) . ')'; + $expressionData['spec'] .= ' (' . implode(', ', array_fill(0, count: $colCount, value: '%s')) . ')'; foreach ($this->referenceColumn as $column) { $expressionData['values'][] = new Identifier($column); } diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index 70596816..ff1aff99 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -98,7 +98,7 @@ public function getRawState(?string $key = null): array|string self::TABLE_OPTIONS => $this->options, ]; - return isset($key) && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; + return null !== $key && array_key_exists($key, $rawState) ? $rawState[$key] : $rawState; } public function ifNotExists(bool $ifNotExists = true): static diff --git a/src/Sql/Ddl/Index/Index.php b/src/Sql/Ddl/Index/Index.php index 38526ef5..1d314528 100644 --- a/src/Sql/Ddl/Index/Index.php +++ b/src/Sql/Ddl/Index/Index.php @@ -39,7 +39,7 @@ public function getExpressionData(): array $specPart = '%s'; $values[] = new Identifier($this->columns[$i]); - if (isset($this->lengths[$i])) { + if (null !== ($this->lengths[$i] ?? null)) { $specPart .= "({$this->lengths[$i]})"; } diff --git a/src/Sql/Expression.php b/src/Sql/Expression.php index f89e3c79..c4771771 100644 --- a/src/Sql/Expression.php +++ b/src/Sql/Expression.php @@ -47,7 +47,7 @@ public function __construct( * * @todo Make notes in documentation */ - $parameters = array_slice(func_get_args(), 1); + $parameters = array_slice(func_get_args(), offset: 1); } $this->setParameters($parameters); @@ -67,7 +67,7 @@ public function getExpressionData(): array { $parameters = $this->parameters; $parametersCount = count($parameters); - $specification = str_replace('%', '%%', $this->expression); + $specification = str_replace('%', replace: '%%', subject: $this->expression); if (0 === $parametersCount) { return [ @@ -77,7 +77,7 @@ public function getExpressionData(): array } // assign locally, escaping % signs - $specification = str_replace(self::PLACEHOLDER, '%s', $specification, $count); + $specification = str_replace(self::PLACEHOLDER, replace: '%s', subject: $specification, count: $count); // test number of replacements without considering same variable begin used many times first, which is // faster, if the test fails then resort to regex which are slow and used rarely diff --git a/src/Sql/Join.php b/src/Sql/Join.php index c4bba6d3..303ec695 100644 --- a/src/Sql/Join.php +++ b/src/Sql/Join.php @@ -9,6 +9,7 @@ use Override; use ReturnTypeWillChange; +use function array_key_exists; use function array_shift; use function count; use function is_array; @@ -157,6 +158,6 @@ public function rewind(): void #[ReturnTypeWillChange] public function valid(): bool { - return isset($this->joins[$this->position]); + return array_key_exists($this->position, $this->joins); } } diff --git a/src/Sql/Literal.php b/src/Sql/Literal.php index cd0d5c7d..d27974be 100644 --- a/src/Sql/Literal.php +++ b/src/Sql/Literal.php @@ -21,7 +21,7 @@ public function __construct( public function getExpressionData(): array { return [ - 'spec' => str_replace('%', '%%', $this->literal), + 'spec' => str_replace('%', replace: '%%', subject: $this->literal), 'values' => [], ]; } diff --git a/src/Sql/Platform/Platform.php b/src/Sql/Platform/Platform.php index abadd243..b36ce003 100644 --- a/src/Sql/Platform/Platform.php +++ b/src/Sql/Platform/Platform.php @@ -77,20 +77,20 @@ public function getTypeDecorator( ): PlatformDecoratorInterface|PreparableSqlInterface|SqlInterface { $platformName = $this->resolvePlatformName($adapterOrPlatform); - if (! isset($this->decorators[$platformName])) { + /** @var array|null $decorators */ + $decorators = $this->decorators[$platformName] ?? null; + if (null === $decorators) { return $subject; } - $subjectClass = $subject::class; - if (isset($this->decorators[$platformName][$subjectClass])) { - $decorator = $this->decorators[$platformName][$subjectClass]; + $decorator = $decorators[$subject::class] ?? null; + if (null !== $decorator) { $decorator->setSubject($subject); return $decorator; } - /** @var PlatformDecoratorInterface $decorator */ - foreach ($this->decorators[$platformName] as $type => $decorator) { - if (! ($subject instanceof $type && is_a($decorator, $type, true))) { + foreach ($decorators as $type => $decorator) { + if (! ($subject instanceof $type && is_a($decorator, $type, allow_string: true))) { continue; } @@ -161,7 +161,7 @@ protected function resolvePlatformName(PlatformInterface|AdapterInterface|null $ } $platformName = $this->resolvePlatform($adapterOrPlatform)->getName(); - $normalized = str_replace([' ', '_'], '', strtolower($platformName)); + $normalized = str_replace([' ', '_'], replace: '', subject: strtolower($platformName)); if (null === $adapterOrPlatform) { $this->cachedPlatformName = $normalized; diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 9aa88fe3..051284b9 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -545,7 +545,7 @@ protected function processOrder( ?DriverInterface $driver = null, ?ParameterContainer $parameterContainer = null, ): ?array { - if (empty($this->order)) { + if ([] === $this->order) { return null; } @@ -560,7 +560,7 @@ protected function processOrder( if (is_int($k)) { if (str_contains($v, ' ')) { - [$k, $v] = explode(' ', $v, 2); + [$k, $v] = explode(' ', $v, limit: 2); } else { $k = $v; $v = self::ORDER_ASCENDING; @@ -609,11 +609,11 @@ protected function processSelect( $columnAs = null; if (is_string($columnIndexOrAs)) { $columnAs = $platform->quoteIdentifier($columnIndexOrAs); - } elseif (stripos($columnName, ' as ') === false) { + } elseif (stripos($columnName, needle: ' as ') === false) { $columnAs = is_string($column) ? $platform->quoteIdentifier($column) : 'Expression' . $expr++; } - $columns[] = null !== $columnAs ? [$columnName, $columnAs] : [$columnName]; + $columns[] = null === $columnAs ? [$columnName] : [$columnName, $columnAs]; } foreach ($this->getJoins()->getJoins() as $join) { @@ -646,17 +646,18 @@ protected function processSelect( } } + $quantifier = null; if ($this->quantifier) { $quantifier = $this->quantifier instanceof ExpressionInterface ? $this->processExpression($this->quantifier, $platform, $driver, $parameterContainer, 'quantifier') : $this->quantifier; } - if (! isset($table)) { + if (null === $table) { return [$columns]; } - if (isset($quantifier)) { + if (null !== $quantifier) { return [$quantifier, $columns, $table]; } diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index dbff8df9..aa2c14d7 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -46,7 +46,7 @@ public function delete(string|TableIdentifier|null $table = null): Delete throw Exception\InvalidArgumentException::forForeignTable($this->table); } - return new Delete($table ?: $this->table); + return new Delete($table ?? $this->table); } public function getAdapter(): ?AdapterInterface @@ -75,7 +75,7 @@ public function insert(string|TableIdentifier|null $table = null): Insert throw Exception\InvalidArgumentException::forForeignTable($this->table); } - return new Insert($table ?: $this->table); + return new Insert($table ?? $this->table); } public function prepareStatementForSqlObject( @@ -102,7 +102,7 @@ public function select(string|TableIdentifier|null $table = null): Select throw Exception\InvalidArgumentException::forForeignTable($this->table); } - return new Select($table ?: $this->table); + return new Select($table ?? $this->table); } /** @@ -121,6 +121,6 @@ public function update(string|TableIdentifier|null $table = null): Update throw Exception\InvalidArgumentException::forForeignTable($this->table); } - return new Update($table ?: $this->table); + return new Update($table ?? $this->table); } } From e182bd37d9a9b61fe6f023b70e3360bd93155e5a Mon Sep 17 00:00:00 2001 From: Simon Mundy Date: Mon, 5 Oct 2026 10:10:22 +1100 Subject: [PATCH 2/2] Exit the specification loop early in createSqlFromSpecificationAndParameters() Clears the prefer-early-continue lint hint raised by the rewritten loop. Signed-off-by: Simon Mundy --- src/Sql/AbstractSql.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSql.php index b2bd0de9..6043537e 100644 --- a/src/Sql/AbstractSql.php +++ b/src/Sql/AbstractSql.php @@ -100,10 +100,12 @@ protected function createSqlFromSpecificationAndParameters(array|string $specifi $paramSpecs = []; foreach ($specifications as $candidateString => $paramSpecs) { - if (count($paramSpecs) === $parametersCount) { - $specificationString = (string) $candidateString; - break; + if (count($paramSpecs) !== $parametersCount) { + continue; } + + $specificationString = (string) $candidateString; + break; } if (null === $specificationString) {