Skip to content

Commit cbcbf63

Browse files
authored
simplify mapper to prepare re-use (#272)
1 parent 020e6f1 commit cbcbf63

File tree

4 files changed

+133
-124
lines changed

4 files changed

+133
-124
lines changed

src/QueryReflection/MysqliQueryReflector.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PHPStan\Type\Type;
1515
use staabm\PHPStanDba\Error;
1616
use staabm\PHPStanDba\TypeMapping\MysqliTypeMapper;
17-
use staabm\PHPStanDba\TypeMapping\TypeMapper;
1817

1918
final class MysqliQueryReflector implements QueryReflector
2019
{
@@ -31,7 +30,7 @@ final class MysqliQueryReflector implements QueryReflector
3130
/** @var array<string, mysqli_sql_exception|list<object>|null> */
3231
private array $cache = [];
3332

34-
private TypeMapper $typeMapper;
33+
private MysqliTypeMapper $typeMapper;
3534

3635
public function __construct(mysqli $mysqli)
3736
{
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace staabm\PHPStanDba\TypeMapping;
6+
7+
use PHPStan\Type\Accessory\AccessoryNumericStringType;
8+
use PHPStan\Type\FloatType;
9+
use PHPStan\Type\IntegerType;
10+
use PHPStan\Type\IntersectionType;
11+
use PHPStan\Type\MixedType;
12+
use PHPStan\Type\StringType;
13+
use PHPStan\Type\Type;
14+
use PHPStan\Type\TypeCombinator;
15+
use PHPStan\Type\UnionType;
16+
use staabm\PHPStanDba\QueryReflection\QueryReflection;
17+
use staabm\PHPStanDba\Types\MysqlIntegerRanges;
18+
19+
final class MysqlTypeMapper
20+
{
21+
/**
22+
* @param list<string> $mysqlFlags
23+
*/
24+
public function mapToPHPStanType(?string $mysqlType, array $mysqlFlags, int $length): Type
25+
{
26+
$numeric = false;
27+
$notNull = false;
28+
$unsigned = false;
29+
$autoIncrement = false;
30+
31+
foreach ($mysqlFlags as $flag) {
32+
switch ($flag) {
33+
case 'NUM':
34+
$numeric = true;
35+
break;
36+
37+
case 'NOT_NULL':
38+
$notNull = true;
39+
break;
40+
41+
case 'AUTO_INCREMENT':
42+
$autoIncrement = true;
43+
break;
44+
45+
case 'UNSIGNED':
46+
$unsigned = true;
47+
break;
48+
49+
// ???
50+
case 'PRI_KEY':
51+
case 'PART_KEY':
52+
case 'MULTIPLE_KEY':
53+
case 'NO_DEFAULT_VALUE':
54+
}
55+
}
56+
57+
$phpstanType = null;
58+
$mysqlIntegerRanges = new MysqlIntegerRanges();
59+
60+
if ($numeric) {
61+
if ($unsigned) {
62+
$phpstanType = match ($length) {
63+
3,4 => $mysqlIntegerRanges->unsignedTinyInt(),
64+
5 => $mysqlIntegerRanges->unsignedSmallInt(),
65+
8 => $mysqlIntegerRanges->unsignedMediumInt(),
66+
10 => $mysqlIntegerRanges->unsignedInt(),
67+
20 => $mysqlIntegerRanges->unsignedBigInt(),
68+
default => null,
69+
};
70+
} else {
71+
$phpstanType = match ($length) {
72+
1, 4 => $mysqlIntegerRanges->signedTinyInt(),
73+
6 => $mysqlIntegerRanges->signedSmallInt(),
74+
9 => $mysqlIntegerRanges->signedMediumInt(),
75+
11 => $mysqlIntegerRanges->signedInt(),
76+
20, 22 => $mysqlIntegerRanges->signedBigInt(),
77+
default => null,
78+
};
79+
}
80+
}
81+
82+
if ($autoIncrement) {
83+
$phpstanType = $mysqlIntegerRanges->unsignedInt();
84+
}
85+
86+
if (null === $phpstanType) {
87+
$phpstanType = match ($mysqlType) {
88+
'DOUBLE', 'NEWDECIMAL' => new FloatType(),
89+
'LONGLONG',
90+
'LONG',
91+
'SHORT',
92+
'YEAR',
93+
'BIT',
94+
'INT24' => new IntegerType(),
95+
'BLOB',
96+
'CHAR',
97+
'STRING',
98+
'VAR_STRING',
99+
'JSON',
100+
'DATE',
101+
'TIME',
102+
'DATETIME',
103+
'TIMESTAMP' => new StringType(),
104+
default => new MixedType(),
105+
};
106+
}
107+
108+
if (QueryReflection::getRuntimeConfiguration()->isStringifyTypes()) {
109+
$numberType = new UnionType([new IntegerType(), new FloatType()]);
110+
$isNumber = $numberType->isSuperTypeOf($phpstanType)->yes();
111+
112+
if ($isNumber) {
113+
$phpstanType = new IntersectionType([
114+
new StringType(),
115+
new AccessoryNumericStringType(),
116+
]);
117+
}
118+
}
119+
120+
if (false === $notNull) {
121+
$phpstanType = TypeCombinator::addNull($phpstanType);
122+
}
123+
124+
return $phpstanType;
125+
}
126+
}

src/TypeMapping/MysqliTypeMapper.php

Lines changed: 6 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,18 @@
55
namespace staabm\PHPStanDba\TypeMapping;
66

77
use PHPStan\ShouldNotHappenException;
8-
use PHPStan\Type\Accessory\AccessoryNumericStringType;
9-
use PHPStan\Type\FloatType;
10-
use PHPStan\Type\IntegerType;
11-
use PHPStan\Type\IntersectionType;
12-
use PHPStan\Type\MixedType;
13-
use PHPStan\Type\StringType;
148
use PHPStan\Type\Type;
15-
use PHPStan\Type\TypeCombinator;
16-
use PHPStan\Type\UnionType;
17-
use staabm\PHPStanDba\QueryReflection\QueryReflection;
18-
use staabm\PHPStanDba\Types\MysqlIntegerRanges;
199

20-
final class MysqliTypeMapper implements TypeMapper
10+
final class MysqliTypeMapper
2111
{
2212
/** @var array<int, string> */
2313
private array $nativeTypes = [];
2414

2515
/** @var array<int, string> */
2616
private array $nativeFlags = [];
2717

18+
private MysqlTypeMapper $typeMapper;
19+
2820
public function __construct()
2921
{
3022
$constants = get_defined_constants(true);
@@ -47,109 +39,13 @@ public function __construct()
4739
}
4840
}
4941
}
42+
43+
$this->typeMapper = new MysqlTypeMapper();
5044
}
5145

5246
public function mapToPHPStanType(int $mysqlType, int $mysqlFlags, int $length): Type
5347
{
54-
$numeric = false;
55-
$notNull = false;
56-
$unsigned = false;
57-
$autoIncrement = false;
58-
59-
foreach ($this->flags2txt($mysqlFlags) as $flag) {
60-
switch ($flag) {
61-
case 'NUM':
62-
$numeric = true;
63-
break;
64-
65-
case 'NOT_NULL':
66-
$notNull = true;
67-
break;
68-
69-
case 'AUTO_INCREMENT':
70-
$autoIncrement = true;
71-
break;
72-
73-
case 'UNSIGNED':
74-
$unsigned = true;
75-
break;
76-
77-
// ???
78-
case 'PRI_KEY':
79-
case 'PART_KEY':
80-
case 'MULTIPLE_KEY':
81-
case 'NO_DEFAULT_VALUE':
82-
}
83-
}
84-
85-
$phpstanType = null;
86-
$mysqlIntegerRanges = new MysqlIntegerRanges();
87-
88-
if ($numeric) {
89-
if ($unsigned) {
90-
$phpstanType = match ($length) {
91-
3,4 => $mysqlIntegerRanges->unsignedTinyInt(),
92-
5 => $mysqlIntegerRanges->unsignedSmallInt(),
93-
8 => $mysqlIntegerRanges->unsignedMediumInt(),
94-
10 => $mysqlIntegerRanges->unsignedInt(),
95-
20 => $mysqlIntegerRanges->unsignedBigInt(),
96-
default => null,
97-
};
98-
} else {
99-
$phpstanType = match ($length) {
100-
1, 4 => $mysqlIntegerRanges->signedTinyInt(),
101-
6 => $mysqlIntegerRanges->signedSmallInt(),
102-
9 => $mysqlIntegerRanges->signedMediumInt(),
103-
11 => $mysqlIntegerRanges->signedInt(),
104-
20, 22 => $mysqlIntegerRanges->signedBigInt(),
105-
default => null,
106-
};
107-
}
108-
}
109-
110-
if ($autoIncrement) {
111-
$phpstanType = $mysqlIntegerRanges->unsignedInt();
112-
}
113-
114-
if (null === $phpstanType) {
115-
$phpstanType = match ($this->type2txt($mysqlType)) {
116-
'DOUBLE', 'NEWDECIMAL' => new FloatType(),
117-
'LONGLONG',
118-
'LONG',
119-
'SHORT',
120-
'YEAR',
121-
'BIT',
122-
'INT24' => new IntegerType(),
123-
'BLOB',
124-
'CHAR',
125-
'STRING',
126-
'VAR_STRING',
127-
'JSON',
128-
'DATE',
129-
'TIME',
130-
'DATETIME',
131-
'TIMESTAMP' => new StringType(),
132-
default => new MixedType(),
133-
};
134-
}
135-
136-
if (QueryReflection::getRuntimeConfiguration()->isStringifyTypes()) {
137-
$numberType = new UnionType([new IntegerType(), new FloatType()]);
138-
$isNumber = $numberType->isSuperTypeOf($phpstanType)->yes();
139-
140-
if ($isNumber) {
141-
$phpstanType = new IntersectionType([
142-
new StringType(),
143-
new AccessoryNumericStringType(),
144-
]);
145-
}
146-
}
147-
148-
if (false === $notNull) {
149-
$phpstanType = TypeCombinator::addNull($phpstanType);
150-
}
151-
152-
return $phpstanType;
48+
return $this->typeMapper->mapToPHPStanType($this->type2txt($mysqlType), $this->flags2txt($mysqlFlags), $length);
15349
}
15450

15551
private function type2txt(int $typeId): ?string

src/TypeMapping/TypeMapper.php

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)