Skip to content

Commit 004fb4b

Browse files
committed
Implement CallWithDeprecatedIniOptionRule
1 parent 81833b5 commit 004fb4b

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

rules.neon

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rules:
2222
- PHPStan\Rules\Deprecations\CallToDeprecatedFunctionRule
2323
- PHPStan\Rules\Deprecations\CallToDeprecatedMethodRule
2424
- PHPStan\Rules\Deprecations\CallToDeprecatedStaticMethodRule
25+
- PHPStan\Rules\Deprecations\CallWithDeprecatedIniOptionRule
2526
- PHPStan\Rules\Deprecations\FetchingClassConstOfDeprecatedClassRule
2627
- PHPStan\Rules\Deprecations\FetchingDeprecatedConstRule
2728
- PHPStan\Rules\Deprecations\ImplementationOfDeprecatedInterfaceRule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Deprecations;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\FuncCall;
7+
use PhpParser\Node\Name;
8+
use PHPStan\Analyser\Scope;
9+
use PHPStan\Broker\FunctionNotFoundException;
10+
use PHPStan\Php\PhpVersion;
11+
use PHPStan\Reflection\ReflectionProvider;
12+
use PHPStan\Rules\Rule;
13+
use PHPStan\Rules\RuleErrorBuilder;
14+
use function count;
15+
use function in_array;
16+
use function sprintf;
17+
use function strtolower;
18+
19+
/**
20+
* @implements Rule<FuncCall>
21+
*/
22+
class CallWithDeprecatedIniOptionRule implements Rule
23+
{
24+
25+
private const INI_FUNCTIONS = [
26+
'ini_get',
27+
'ini_set',
28+
'ini_alter',
29+
'ini_restore',
30+
];
31+
32+
private const DEPRECATED_OPTIONS = [
33+
'assert.active' => 80300,
34+
'assert.exception' => 80300,
35+
'assert.bail' => 80300,
36+
'assert.warning' => 80300,
37+
];
38+
39+
private ReflectionProvider $reflectionProvider;
40+
41+
private DeprecatedScopeHelper $deprecatedScopeHelper;
42+
43+
private PhpVersion $phpVersion;
44+
45+
public function __construct(
46+
ReflectionProvider $reflectionProvider,
47+
DeprecatedScopeHelper $deprecatedScopeHelper,
48+
PhpVersion $phpVersion
49+
)
50+
{
51+
$this->reflectionProvider = $reflectionProvider;
52+
$this->deprecatedScopeHelper = $deprecatedScopeHelper;
53+
$this->phpVersion = $phpVersion;
54+
}
55+
56+
public function getNodeType(): string
57+
{
58+
return FuncCall::class;
59+
}
60+
61+
public function processNode(Node $node, Scope $scope): array
62+
{
63+
if ($this->deprecatedScopeHelper->isScopeDeprecated($scope)) {
64+
return [];
65+
}
66+
67+
if (!($node->name instanceof Name)) {
68+
return [];
69+
}
70+
71+
if (count($node->getArgs()) < 1) {
72+
return [];
73+
}
74+
75+
try {
76+
$function = $this->reflectionProvider->getFunction($node->name, $scope);
77+
} catch (FunctionNotFoundException $e) {
78+
// Other rules will notify if the function is not found
79+
return [];
80+
}
81+
82+
if (!in_array(strtolower($function->getName()), self::INI_FUNCTIONS, true)) {
83+
return [];
84+
}
85+
86+
$phpVersionId = $this->phpVersion->getVersionId();
87+
$iniType = $scope->getType($node->getArgs()[0]->value);
88+
foreach ($iniType->getConstantStrings() as $string) {
89+
if (!array_key_exists($string->getValue(), self::DEPRECATED_OPTIONS)) {
90+
continue;
91+
}
92+
93+
if ($phpVersionId < self::DEPRECATED_OPTIONS[$string->getValue()]) {
94+
continue;
95+
}
96+
97+
return [
98+
RuleErrorBuilder::message(sprintf(
99+
"Call to function %s() with deprecated option '%s'.",
100+
$function->getName(),
101+
$string->getValue(),
102+
))->identifier('function.deprecated')->build(),
103+
];
104+
}
105+
106+
return [];
107+
}
108+
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Deprecations;
4+
5+
use PHPStan\Php\PhpVersion;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Testing\RuleTestCase;
8+
use const PHP_VERSION_ID;
9+
10+
/**
11+
* @extends RuleTestCase<CallWithDeprecatedIniOptionRule>
12+
*/
13+
class CallWithDeprecatedIniOptionRuleTest extends RuleTestCase
14+
{
15+
16+
protected function getRule(): Rule
17+
{
18+
return new CallWithDeprecatedIniOptionRule(
19+
$this->createReflectionProvider(),
20+
new DeprecatedScopeHelper([new DefaultDeprecatedScopeResolver()]),
21+
self::getContainer()->getByType(PhpVersion::class),
22+
);
23+
}
24+
25+
public function testRule(): void
26+
{
27+
$expectedErrors = [];
28+
if (PHP_VERSION_ID >= 80300) {
29+
$expectedErrors = [
30+
[
31+
"Call to function ini_set() with deprecated option 'assert.active'.",
32+
11,
33+
],
34+
[
35+
"Call to function ini_get() with deprecated option 'assert.active'.",
36+
12,
37+
],
38+
];
39+
}
40+
41+
$this->analyse(
42+
[__DIR__ . '/data/call-with-deprecation-ini-option.php'],
43+
$expectedErrors,
44+
);
45+
}
46+
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace CallWithDeprecatedIniOption;
4+
5+
function doFooBar(): void {
6+
var_dump(ini_set('memory_limit', '2048M'));
7+
var_dump(ini_get('memory_limit'));
8+
}
9+
10+
function doFoo(): void {
11+
var_dump(ini_set('assert.active', false));
12+
var_dump(ini_get('assert.active'));
13+
}
14+
15+
/** @deprecated */
16+
function inDeprecatedFunction(): void {
17+
var_dump(ini_set('assert.active', false));
18+
var_dump(ini_get('assert.active'));
19+
}

0 commit comments

Comments
 (0)