From a9a24da4d410df0c3d5f48c7efcf2858dfd34f05 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 28 Nov 2024 16:20:54 +0100 Subject: [PATCH 1/6] Implement CallWithDeprecatedIniOptionRule --- rules.neon | 1 + .../CallWithDeprecatedIniOptionRule.php | 110 ++++++++++++++++++ .../CallWithDeprecatedIniOptionRuleTest.php | 47 ++++++++ .../data/call-with-deprecation-ini-option.php | 19 +++ 4 files changed, 177 insertions(+) create mode 100644 src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php create mode 100644 tests/Rules/Deprecations/CallWithDeprecatedIniOptionRuleTest.php create mode 100644 tests/Rules/Deprecations/data/call-with-deprecation-ini-option.php diff --git a/rules.neon b/rules.neon index 704579b7..b83fd46f 100644 --- a/rules.neon +++ b/rules.neon @@ -22,6 +22,7 @@ rules: - PHPStan\Rules\Deprecations\CallToDeprecatedFunctionRule - PHPStan\Rules\Deprecations\CallToDeprecatedMethodRule - PHPStan\Rules\Deprecations\CallToDeprecatedStaticMethodRule + - PHPStan\Rules\Deprecations\CallWithDeprecatedIniOptionRule - PHPStan\Rules\Deprecations\FetchingClassConstOfDeprecatedClassRule - PHPStan\Rules\Deprecations\FetchingDeprecatedConstRule - PHPStan\Rules\Deprecations\ImplementationOfDeprecatedInterfaceRule diff --git a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php new file mode 100644 index 00000000..8b2637fd --- /dev/null +++ b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php @@ -0,0 +1,110 @@ + + */ +class CallWithDeprecatedIniOptionRule implements Rule +{ + + private const INI_FUNCTIONS = [ + 'ini_get', + 'ini_set', + 'ini_alter', + 'ini_restore', + ]; + + private const DEPRECATED_OPTIONS = [ + 'assert.active' => 80300, + 'assert.exception' => 80300, + 'assert.bail' => 80300, + 'assert.warning' => 80300, + ]; + + private ReflectionProvider $reflectionProvider; + + private DeprecatedScopeHelper $deprecatedScopeHelper; + + private PhpVersion $phpVersion; + + public function __construct( + ReflectionProvider $reflectionProvider, + DeprecatedScopeHelper $deprecatedScopeHelper, + PhpVersion $phpVersion + ) + { + $this->reflectionProvider = $reflectionProvider; + $this->deprecatedScopeHelper = $deprecatedScopeHelper; + $this->phpVersion = $phpVersion; + } + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($this->deprecatedScopeHelper->isScopeDeprecated($scope)) { + return []; + } + + if (!($node->name instanceof Name)) { + return []; + } + + if (count($node->getArgs()) < 1) { + return []; + } + + try { + $function = $this->reflectionProvider->getFunction($node->name, $scope); + } catch (FunctionNotFoundException $e) { + // Other rules will notify if the function is not found + return []; + } + + if (!in_array(strtolower($function->getName()), self::INI_FUNCTIONS, true)) { + return []; + } + + $phpVersionId = $this->phpVersion->getVersionId(); + $iniType = $scope->getType($node->getArgs()[0]->value); + foreach ($iniType->getConstantStrings() as $string) { + if (!array_key_exists($string->getValue(), self::DEPRECATED_OPTIONS)) { + continue; + } + + if ($phpVersionId < self::DEPRECATED_OPTIONS[$string->getValue()]) { + continue; + } + + return [ + RuleErrorBuilder::message(sprintf( + "Call to function %s() with deprecated option '%s'.", + $function->getName(), + $string->getValue(), + ))->identifier('function.deprecated')->build(), + ]; + } + + return []; + } + +} diff --git a/tests/Rules/Deprecations/CallWithDeprecatedIniOptionRuleTest.php b/tests/Rules/Deprecations/CallWithDeprecatedIniOptionRuleTest.php new file mode 100644 index 00000000..66236baa --- /dev/null +++ b/tests/Rules/Deprecations/CallWithDeprecatedIniOptionRuleTest.php @@ -0,0 +1,47 @@ + + */ +class CallWithDeprecatedIniOptionRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new CallWithDeprecatedIniOptionRule( + $this->createReflectionProvider(), + new DeprecatedScopeHelper([new DefaultDeprecatedScopeResolver()]), + self::getContainer()->getByType(PhpVersion::class), + ); + } + + public function testRule(): void + { + $expectedErrors = []; + if (PHP_VERSION_ID >= 80300) { + $expectedErrors = [ + [ + "Call to function ini_set() with deprecated option 'assert.active'.", + 11, + ], + [ + "Call to function ini_get() with deprecated option 'assert.active'.", + 12, + ], + ]; + } + + $this->analyse( + [__DIR__ . '/data/call-with-deprecation-ini-option.php'], + $expectedErrors, + ); + } + +} diff --git a/tests/Rules/Deprecations/data/call-with-deprecation-ini-option.php b/tests/Rules/Deprecations/data/call-with-deprecation-ini-option.php new file mode 100644 index 00000000..7f1b4cc3 --- /dev/null +++ b/tests/Rules/Deprecations/data/call-with-deprecation-ini-option.php @@ -0,0 +1,19 @@ + Date: Thu, 28 Nov 2024 16:37:11 +0100 Subject: [PATCH 2/6] added options --- .../CallWithDeprecatedIniOptionRule.php | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php index 8b2637fd..829266bc 100644 --- a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php +++ b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php @@ -31,10 +31,34 @@ class CallWithDeprecatedIniOptionRule implements Rule ]; private const DEPRECATED_OPTIONS = [ + // deprecated since unknown version + 'mbstring.http_input' => 0, + 'mbstring.http_output' => 0, + 'mbstring.internal_encoding' => 0, + 'pdo_odbc.db2_instance_name' => 0, + 'enable_dl' => 0, + + 'mbstring.func_overload' => 70200, + 'track_errors' => 70200, + + 'iconv.input_encoding' => 50600, + 'iconv.output_encoding' => 50600, + 'iconv.internal_encoding' => 50600, + + 'allow_url_include' => 70400, + + 'assert.quiet_eval' => 80000, + + 'filter.default' => 80100, + 'oci8.old_oci_close_semantics' => 80100, + 'assert.active' => 80300, 'assert.exception' => 80300, 'assert.bail' => 80300, 'assert.warning' => 80300, + + 'session.sid_length' => 80400, + 'session.sid_bits_per_character' => 80400, ]; private ReflectionProvider $reflectionProvider; From 1097ceda36586a242ed6d6925efc28aa338188eb Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 28 Nov 2024 20:30:13 +0100 Subject: [PATCH 3/6] Support get_cfg_var() --- src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php index 829266bc..e5335aa0 100644 --- a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php +++ b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php @@ -28,6 +28,7 @@ class CallWithDeprecatedIniOptionRule implements Rule 'ini_set', 'ini_alter', 'ini_restore', + 'get_cfg_var', ]; private const DEPRECATED_OPTIONS = [ From dd78a782feb90b7387108f545516e57ccc69876c Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 28 Nov 2024 20:31:22 +0100 Subject: [PATCH 4/6] Cs --- src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php index e5335aa0..c3a16be6 100644 --- a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php +++ b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php @@ -28,7 +28,7 @@ class CallWithDeprecatedIniOptionRule implements Rule 'ini_set', 'ini_alter', 'ini_restore', - 'get_cfg_var', + 'get_cfg_var', ]; private const DEPRECATED_OPTIONS = [ From d54af339e8e190e2d0091939cad7b75ab2811b3b Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 28 Nov 2024 20:34:23 +0100 Subject: [PATCH 5/6] sort --- src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php index c3a16be6..aa809687 100644 --- a/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php +++ b/src/Rules/Deprecations/CallWithDeprecatedIniOptionRule.php @@ -39,13 +39,13 @@ class CallWithDeprecatedIniOptionRule implements Rule 'pdo_odbc.db2_instance_name' => 0, 'enable_dl' => 0, - 'mbstring.func_overload' => 70200, - 'track_errors' => 70200, - 'iconv.input_encoding' => 50600, 'iconv.output_encoding' => 50600, 'iconv.internal_encoding' => 50600, + 'mbstring.func_overload' => 70200, + 'track_errors' => 70200, + 'allow_url_include' => 70400, 'assert.quiet_eval' => 80000, From ae8fe637eadfeed98d04ec05870c2d1857bc6757 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Thu, 28 Nov 2024 22:18:56 +0100 Subject: [PATCH 6/6] bleeding edge --- rules.neon | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rules.neon b/rules.neon index b83fd46f..df499a84 100644 --- a/rules.neon +++ b/rules.neon @@ -16,13 +16,15 @@ services: tags: - phpstan.deprecations.deprecatedScopeResolver + - + class: PHPStan\Rules\Deprecations\CallWithDeprecatedIniOptionRule + rules: - PHPStan\Rules\Deprecations\AccessDeprecatedPropertyRule - PHPStan\Rules\Deprecations\AccessDeprecatedStaticPropertyRule - PHPStan\Rules\Deprecations\CallToDeprecatedFunctionRule - PHPStan\Rules\Deprecations\CallToDeprecatedMethodRule - PHPStan\Rules\Deprecations\CallToDeprecatedStaticMethodRule - - PHPStan\Rules\Deprecations\CallWithDeprecatedIniOptionRule - PHPStan\Rules\Deprecations\FetchingClassConstOfDeprecatedClassRule - PHPStan\Rules\Deprecations\FetchingDeprecatedConstRule - PHPStan\Rules\Deprecations\ImplementationOfDeprecatedInterfaceRule @@ -34,3 +36,7 @@ rules: - PHPStan\Rules\Deprecations\TypeHintDeprecatedInFunctionSignatureRule - PHPStan\Rules\Deprecations\UsageOfDeprecatedCastRule - PHPStan\Rules\Deprecations\UsageOfDeprecatedTraitRule + +conditionalTags: + PHPStan\Rules\Deprecations\CallWithDeprecatedIniOptionRule: + phpstan.rules.rule: %featureToggles.bleedingEdge%