Skip to content

Commit 8e3d37f

Browse files
Getenv
1 parent 74b909a commit 8e3d37f

File tree

7 files changed

+99
-0
lines changed

7 files changed

+99
-0
lines changed

conf/config.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,11 @@ services:
15411541
tags:
15421542
- phpstan.broker.dynamicFunctionReturnTypeExtension
15431543

1544+
-
1545+
class: PHPStan\Type\Php\GetenvFunctionReturnTypeExtension
1546+
tags:
1547+
- phpstan.broker.dynamicFunctionReturnTypeExtension
1548+
15441549
-
15451550
class: PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension
15461551
tags:

resources/functionMap_php80delta.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
'imagejpeg' => ['bool', 'im'=>'GdImage', 'filename='=>'string|resource|null', 'quality='=>'int'],
7979
'imagerotate' => ['false|object', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'],
8080
'imagescale' => ['false|object', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'],
81+
'getenv' => ['array<string, string>|string|false', 'varname'=>'string|null', 'local_only='=>'bool'],
82+
'getenv\'1' => ['array<string, string>'],
8183
'ldap_set_rebind_proc' => ['bool', 'ldap'=>'resource', 'callback'=>'?callable'],
8284
'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'],
8385
'mb_encoding_aliases' => ['list<non-falsy-string>', 'encoding'=>'string'],

src/Php/PhpVersion.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,4 +353,9 @@ public function substrReturnFalseInsteadOfEmptyString(): bool
353353
return $this->versionId < 80000;
354354
}
355355

356+
public function getenvAcceptsNull(): bool
357+
{
358+
return $this->versionId >= 80000;
359+
}
360+
356361
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Php;
4+
5+
use PhpParser\Node\Expr\FuncCall;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Php\PhpVersion;
8+
use PHPStan\Reflection\FunctionReflection;
9+
use PHPStan\Type\ArrayType;
10+
use PHPStan\Type\Constant\ConstantBooleanType;
11+
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
12+
use PHPStan\Type\StringType;
13+
use PHPStan\Type\Type;
14+
use PHPStan\Type\UnionType;
15+
16+
final class GetenvFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
17+
{
18+
public function __construct(private PhpVersion $phpVersion)
19+
{
20+
}
21+
22+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
23+
{
24+
return $functionReflection->getName() === 'getenv';
25+
}
26+
27+
public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type
28+
{
29+
if (!$this->phpVersion->getenvAcceptsNull()) {
30+
return null;
31+
}
32+
if (count($functionCall->getArgs()) < 1) {
33+
return null;
34+
}
35+
36+
$argType = $scope->getType($functionCall->getArgs()[0]->value);
37+
if ($argType->isNull()->yes()) {
38+
return new ArrayType(new StringType(), new StringType());
39+
}
40+
if ($argType->isNull()->no()) {
41+
return new UnionType([new StringType(), new ConstantBooleanType(false)]);
42+
}
43+
44+
return null;
45+
}
46+
47+
}

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ private static function findTestFiles(): iterable
5757
yield __DIR__ . '/data/explode-php80.php';
5858
}
5959

60+
if (PHP_VERSION_ID < 80000) {
61+
yield __DIR__ . '/data/getenv-php74.php';
62+
} else {
63+
yield __DIR__ . '/data/getenv-php80.php';
64+
}
65+
6066
if (PHP_VERSION_ID >= 80000) {
6167
yield __DIR__ . '/../Reflection/data/unionTypes.php';
6268
yield __DIR__ . '/../Reflection/data/mixedType.php';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace GetenvPHP74;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function test()
11+
{
12+
assertType('TODO', getenv(null));
13+
assertType('array<string, string>', getenv());
14+
assertType('string|false', getenv('foo'));
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace GetenvPHP80;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function test()
11+
{
12+
assertType('array<string, string>', getenv(null));
13+
assertType('array<string, string>', getenv());
14+
assertType('string|false', getenv('foo'));
15+
}
16+
17+
}

0 commit comments

Comments
 (0)