Skip to content

Commit 9d9e32a

Browse files
authored
Merge pull request #231 from IanDelMar/wp-parse-url
Fix/update extension for wp_parse_url
2 parents 37ef209 + 2a284d8 commit 9d9e32a

File tree

2 files changed

+41
-24
lines changed

2 files changed

+41
-24
lines changed

src/WpParseUrlFunctionDynamicReturnTypeExtension.php

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use PHPStan\Type\Constant\ConstantBooleanType;
2020
use PHPStan\Type\Constant\ConstantIntegerType;
2121
use PHPStan\Type\Constant\ConstantStringType;
22-
use PHPStan\Type\IntegerType;
22+
use PHPStan\Type\IntegerRangeType;
2323
use PHPStan\Type\NullType;
2424
use PHPStan\Type\StringType;
2525
use PHPStan\Type\Type;
@@ -67,31 +67,41 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
6767
$this->cacheReturnTypes();
6868

6969
$componentType = new ConstantIntegerType(-1);
70+
7071
if (count($functionCall->getArgs()) > 1) {
7172
$componentType = $scope->getType($functionCall->getArgs()[1]->value);
7273

74+
if (! $componentType->isConstantValue()->yes()) {
75+
return $this->createAllComponentsReturnType();
76+
}
77+
78+
$componentType = $componentType->toInteger();
79+
7380
if (! $componentType instanceof ConstantIntegerType) {
7481
return $this->createAllComponentsReturnType();
7582
}
7683
}
7784

7885
$urlType = $scope->getType($functionCall->getArgs()[0]->value);
79-
if (count($urlType->getConstantStrings()) !== 0) {
80-
$returnTypes = [];
86+
if (count($urlType->getConstantStrings()) > 0) {
87+
$types = [];
8188
foreach ($urlType->getConstantStrings() as $constantString) {
8289
try {
8390
// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
8491
$result = @parse_url($constantString->getValue(), $componentType->getValue());
85-
$returnTypes[] = $scope->getTypeFromValue($result);
8692
} catch (\ValueError $e) {
87-
$returnTypes[] = new ConstantBooleanType(false);
93+
$types[] = new ConstantBooleanType(false);
94+
continue;
8895
}
96+
97+
$types[] = $scope->getTypeFromValue($result);
8998
}
90-
return TypeCombinator::union(...$returnTypes);
99+
100+
return TypeCombinator::union(...$types);
91101
}
92102

93103
if ($componentType->getValue() === -1) {
94-
return $this->createAllComponentsReturnType();
104+
return TypeCombinator::union($this->createComponentsArray(), new ConstantBooleanType(false));
95105
}
96106

97107
return $this->componentTypesPairedConstants[$componentType->getValue()] ?? new ConstantBooleanType(false);
@@ -102,24 +112,31 @@ private function createAllComponentsReturnType(): Type
102112
if ($this->allComponentsTogetherType === null) {
103113
$returnTypes = [
104114
new ConstantBooleanType(false),
115+
new NullType(),
116+
IntegerRangeType::fromInterval(0, 65535),
117+
new StringType(),
118+
$this->createComponentsArray(),
105119
];
106120

107-
$builder = ConstantArrayTypeBuilder::createEmpty();
121+
$this->allComponentsTogetherType = TypeCombinator::union(...$returnTypes);
122+
}
108123

109-
if ($this->componentTypesPairedStrings === null) {
110-
throw new \PHPStan\ShouldNotHappenException();
111-
}
124+
return $this->allComponentsTogetherType;
125+
}
112126

113-
foreach ($this->componentTypesPairedStrings as $componentName => $componentValueType) {
114-
$builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType, true);
115-
}
127+
private function createComponentsArray(): Type
128+
{
129+
$builder = ConstantArrayTypeBuilder::createEmpty();
116130

117-
$returnTypes[] = $builder->getArray();
131+
if ($this->componentTypesPairedStrings === null) {
132+
throw new \PHPStan\ShouldNotHappenException();
133+
}
118134

119-
$this->allComponentsTogetherType = TypeCombinator::union(...$returnTypes);
135+
foreach ($this->componentTypesPairedStrings as $componentName => $componentValueType) {
136+
$builder->setOffsetValueType(new ConstantStringType($componentName), $componentValueType, true);
120137
}
121138

122-
return $this->allComponentsTogetherType;
139+
return $builder->getArray();
123140
}
124141

125142
private function cacheReturnTypes(): void
@@ -129,17 +146,17 @@ private function cacheReturnTypes(): void
129146
}
130147

131148
$stringType = new StringType();
132-
$integerType = new IntegerType();
149+
$port = IntegerRangeType::fromInterval(0, 65535);
133150
$falseType = new ConstantBooleanType(false);
134151
$nullType = new NullType();
135152

136153
$stringOrFalseOrNull = TypeCombinator::union($stringType, $falseType, $nullType);
137-
$integerOrFalseOrNull = TypeCombinator::union($integerType, $falseType, $nullType);
154+
$portOrFalseOrNull = TypeCombinator::union($port, $falseType, $nullType);
138155

139156
$this->componentTypesPairedConstants = [
140157
PHP_URL_SCHEME => $stringOrFalseOrNull,
141158
PHP_URL_HOST => $stringOrFalseOrNull,
142-
PHP_URL_PORT => $integerOrFalseOrNull,
159+
PHP_URL_PORT => $portOrFalseOrNull,
143160
PHP_URL_USER => $stringOrFalseOrNull,
144161
PHP_URL_PASS => $stringOrFalseOrNull,
145162
PHP_URL_PATH => $stringOrFalseOrNull,
@@ -150,7 +167,7 @@ private function cacheReturnTypes(): void
150167
$this->componentTypesPairedStrings = [
151168
'scheme' => $stringType,
152169
'host' => $stringType,
153-
'port' => $integerType,
170+
'port' => $port,
154171
'user' => $stringType,
155172
'pass' => $stringType,
156173
'path' => $stringType,

tests/data/wp_parse_url.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
assertType("array{scheme: 'http', host: 'def.abc'}", $value);
3131

3232
$value = wp_parse_url('http://def.abc', $integer);
33-
assertType('array{scheme?: string, host?: string, port?: int, user?: string, pass?: string, path?: string, query?: string, fragment?: string}|false', $value);
33+
assertType('array{scheme?: string, host?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}|int<0, 65535>|string|false|null', $value);
3434

3535
$value = wp_parse_url('http://def.abc', PHP_URL_FRAGMENT);
3636
assertType('null', $value);
@@ -45,10 +45,10 @@
4545
assertType('false', $value);
4646

4747
$value = wp_parse_url($string, PHP_URL_PORT);
48-
assertType('int|false|null', $value);
48+
assertType('int<0, 65535>|false|null', $value);
4949

5050
$value = wp_parse_url($string);
51-
assertType('array{scheme?: string, host?: string, port?: int, user?: string, pass?: string, path?: string, query?: string, fragment?: string}|false', $value);
51+
assertType('array{scheme?: string, host?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}|false', $value);
5252

5353
/** @var 'http://def.abc'|'https://example.com' $union */
5454
$union = $union;

0 commit comments

Comments
 (0)