Skip to content

Commit aa914e8

Browse files
staabmclxmstaab
andauthored
introduce Parameter object (#182)
Co-authored-by: Markus Staab <[email protected]>
1 parent 646c3a8 commit aa914e8

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

src/QueryReflection/Parameter.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace staabm\PHPStanDba\QueryReflection;
6+
7+
use PHPStan\Type\Type;
8+
9+
final class Parameter
10+
{
11+
/**
12+
* @var non-empty-string|null
13+
*/
14+
public $name;
15+
/**
16+
* @var Type
17+
*/
18+
public $type;
19+
/**
20+
* @var ?string
21+
*/
22+
public $simulatedValue;
23+
/**
24+
* @var bool
25+
*/
26+
public $isOptional;
27+
28+
/**
29+
* @param non-empty-string|null $name
30+
*/
31+
public function __construct(?string $name, Type $type, ?string $simulatedValue, bool $isOptional)
32+
{
33+
$this->type = $type;
34+
$this->simulatedValue = $simulatedValue;
35+
$this->isOptional = $isOptional;
36+
37+
if (null === $name) {
38+
return;
39+
}
40+
41+
if (!str_starts_with($name, ':')) {
42+
$name = ':'.$name;
43+
}
44+
45+
$this->name = $name;
46+
}
47+
}

src/QueryReflection/PlaceholderValidation.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
final class PlaceholderValidation
88
{
99
/**
10-
* @param array<string|int, scalar|null> $parameters
10+
* @param array<string|int, Parameter> $parameters
1111
*
1212
* @return iterable<string>
1313
*/
@@ -39,7 +39,7 @@ public function checkErrors(string $queryString, array $parameters): iterable
3939
}
4040

4141
/**
42-
* @param array<string|int, scalar|null> $parameters
42+
* @param array<string|int, Parameter> $parameters
4343
*
4444
* @return iterable<string>
4545
*/

src/QueryReflection/QueryReflection.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\Node\Expr;
88
use PhpParser\Node\Expr\BinaryOp\Concat;
99
use PHPStan\Analyser\Scope;
10+
use PHPStan\ShouldNotHappenException;
1011
use PHPStan\Type\Constant\ConstantArrayType;
1112
use PHPStan\Type\Constant\ConstantIntegerType;
1213
use PHPStan\Type\Constant\ConstantStringType;
@@ -204,7 +205,7 @@ public static function getQueryType(string $query): ?string
204205
*
205206
* @throws UnresolvableQueryException
206207
*
207-
* @return array<string|int, scalar|null>|null
208+
* @return array<string|int, Parameter>|null
208209
*/
209210
public function resolveParameters(Type $parameterTypes): ?array
210211
{
@@ -213,18 +214,35 @@ public function resolveParameters(Type $parameterTypes): ?array
213214
if ($parameterTypes instanceof ConstantArrayType) {
214215
$keyTypes = $parameterTypes->getKeyTypes();
215216
$valueTypes = $parameterTypes->getValueTypes();
217+
$optionalKeys = $parameterTypes->getOptionalKeys();
216218

217219
foreach ($keyTypes as $i => $keyType) {
220+
$isOptional = \in_array($i, $optionalKeys, true);
221+
218222
if ($keyType instanceof ConstantStringType) {
219223
$placeholderName = $keyType->getValue();
220224

221-
if (!str_starts_with($placeholderName, ':')) {
222-
$placeholderName = ':'.$placeholderName;
225+
if ('' === $placeholderName) {
226+
throw new ShouldNotHappenException('Empty placeholder name');
223227
}
224228

225-
$parameters[$placeholderName] = QuerySimulation::simulateParamValueType($valueTypes[$i], true);
229+
$param = new Parameter(
230+
$placeholderName,
231+
$valueTypes[$i],
232+
QuerySimulation::simulateParamValueType($valueTypes[$i], true),
233+
$isOptional
234+
);
235+
236+
$parameters[$param->name] = $param;
226237
} elseif ($keyType instanceof ConstantIntegerType) {
227-
$parameters[$keyType->getValue()] = QuerySimulation::simulateParamValueType($valueTypes[$i], true);
238+
$param = new Parameter(
239+
null,
240+
$valueTypes[$i],
241+
QuerySimulation::simulateParamValueType($valueTypes[$i], true),
242+
$isOptional
243+
);
244+
245+
$parameters[$keyType->getValue()] = $param;
228246
}
229247
}
230248

@@ -235,7 +253,7 @@ public function resolveParameters(Type $parameterTypes): ?array
235253
}
236254

237255
/**
238-
* @param array<string|int, scalar|null> $parameters
256+
* @param array<string|int, Parameter> $parameters
239257
*/
240258
private function replaceParameters(string $queryString, array $parameters): string
241259
{
@@ -248,7 +266,9 @@ private function replaceParameters(string $queryString, array $parameters): stri
248266
return $haystack;
249267
};
250268

251-
foreach ($parameters as $placeholderKey => $value) {
269+
foreach ($parameters as $placeholderKey => $parameter) {
270+
$value = $parameter->simulatedValue;
271+
252272
if (\is_string($value)) {
253273
// XXX escaping
254274
$value = "'".$value."'";
@@ -258,10 +278,10 @@ private function replaceParameters(string $queryString, array $parameters): stri
258278
$value = (string) $value;
259279
}
260280

261-
if (\is_int($placeholderKey)) {
262-
$queryString = $replaceFirst($queryString, '?', $value);
263-
} else {
281+
if (\is_string($placeholderKey)) {
264282
$queryString = str_replace($placeholderKey, $value, $queryString);
283+
} else {
284+
$queryString = $replaceFirst($queryString, '?', $value);
265285
}
266286
}
267287

0 commit comments

Comments
 (0)