From 3bbaeb444fb61d4b4600b54a02f7736be7952c84 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:13:55 +0530 Subject: [PATCH 01/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- config/set/php85.php | 2 + .../ChrArgModuloRectorTest.php | 28 +++++++ .../ChrArgModuloRector/Fixture/chr.php.inc | 7 ++ .../Fixture/chr_var.php.inc | 9 +++ .../config/configured_rule.php | 13 ++++ .../Rector/FuncCall/ChrArgModuloRector.php | 73 +++++++++++++++++++ 6 files changed, 132 insertions(+) create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/ChrArgModuloRectorTest.php create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/config/configured_rule.php create mode 100644 rules/Php85/Rector/FuncCall/ChrArgModuloRector.php diff --git a/config/set/php85.php b/config/set/php85.php index 074c18b2af9..be4cad3a560 100644 --- a/config/set/php85.php +++ b/config/set/php85.php @@ -11,6 +11,7 @@ use Rector\Php85\Rector\ClassMethod\NullDebugInfoReturnRector; use Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector; use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector; +use Rector\Php85\Rector\FuncCall\ChrArgModuloRector; use Rector\Php85\Rector\FuncCall\RemoveFinfoBufferContextArgRector; use Rector\Php85\Rector\Switch_\ColonAfterSwitchCaseRector; use Rector\Removing\Rector\FuncCall\RemoveFuncCallArgRector; @@ -34,6 +35,7 @@ DeprecatedAnnotationToDeprecatedAttributeRector::class, ColonAfterSwitchCaseRector::class, ArrayKeyExistsNullToEmptyStringRector::class, + ChrArgModuloRector::class, ] ); diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/ChrArgModuloRectorTest.php b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/ChrArgModuloRectorTest.php new file mode 100644 index 00000000000..093a907ccf2 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/ChrArgModuloRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc new file mode 100644 index 00000000000..27d447721f9 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc @@ -0,0 +1,7 @@ + +----- + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc new file mode 100644 index 00000000000..25eb6fb3a61 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc @@ -0,0 +1,9 @@ + +----- + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/config/configured_rule.php b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/config/configured_rule.php new file mode 100644 index 00000000000..15d2a0b412f --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/config/configured_rule.php @@ -0,0 +1,13 @@ +rule(ChrArgModuloRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_85); +}; diff --git a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php new file mode 100644 index 00000000000..0664c75f2f3 --- /dev/null +++ b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php @@ -0,0 +1,73 @@ +isName($node, 'chr')) { + return null; + } + + $args = $node->getArgs(); + + if (! isset($node->args[0])) { + return null; + } + + $argExpr = $args[0]->value; + + if ($argExpr instanceof Mod) { + return null; + } + + $args[0]->value = new Mod($argExpr, new LNumber(256)); + $node->args = $args; + + return $node; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::DEPRECATE_OUTSIDE_INTERVEL_VAL_IN_CHR_FUNCTION; + } +} From 856b65eb88fcec5de2eed253f54a03a1cf2fa174 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:14:58 +0530 Subject: [PATCH 02/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- rules/Php85/Rector/FuncCall/ChrArgModuloRector.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php index 0664c75f2f3..769a7abc784 100644 --- a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php +++ b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php @@ -13,7 +13,10 @@ use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; - +/** + * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_integers_outside_the_interval_0_255_to_chr + * @see \Rector\Tests\Php85\Rector\FuncCall\ChrArgModuloRector\ChrArgModuloRectorTest + */ final class ChrArgModuloRector extends AbstractRector implements MinPhpVersionInterface { public function getRuleDefinition(): RuleDefinition From cf5a5083c05ff0818a17e883206e38a738ef96e9 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:34:04 +0530 Subject: [PATCH 03/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- src/ValueObject/PhpVersionFeature.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 1c72c63d39b..b76487f4a62 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -798,4 +798,10 @@ final class PhpVersionFeature * @var int */ public const DEPRECATE_NULL_ARG_IN_ARRAY_KEY_EXISTS_FUNCTION = PhpVersion::PHP_85; + + /** + * @see https://wiki.php.net/rfc/deprecations_php_8_5#eprecate_passing_integers_outside_the_interval_0_255_to_chr + * @var int + */ + public const DEPRECATE_OUTSIDE_INTERVEL_VAL_IN_CHR_FUNCTION = PhpVersion::PHP_85; } From 57126280650dbf0a30bd69d22c7d3236ef5af09b Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:39:15 +0530 Subject: [PATCH 04/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../ChrArgModuloRector/Fixture/chr_var.php.inc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc index 25eb6fb3a61..2e9bae1ede9 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc @@ -1,9 +1,13 @@ ----- \ No newline at end of file From 46fa79533fd5d7d0325d34cbde062935675074d9 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:47:40 +0530 Subject: [PATCH 05/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../FuncCall/ChrArgModuloRector/Fixture/chr.php.inc | 8 ++++++-- .../ChrArgModuloRector/Fixture/chr_inbond.php.inc | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc index 27d447721f9..320ac129c3a 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc @@ -1,7 +1,11 @@ ----- \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc new file mode 100644 index 00000000000..863fb0a3af8 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc @@ -0,0 +1,11 @@ + +----- + \ No newline at end of file From 878bf554394637efe93968c491d65c3317ef0166 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:49:59 +0530 Subject: [PATCH 06/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../ChrArgModuloRector/Fixture/chr_inbond.php.inc | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc deleted file mode 100644 index 863fb0a3af8..00000000000 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_inbond.php.inc +++ /dev/null @@ -1,11 +0,0 @@ - ------ - \ No newline at end of file From 45e67881c06e2979d7b526fafb4ac3465feb4c68 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 28 Aug 2025 22:50:57 +0530 Subject: [PATCH 07/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../ChrArgModuloRector/Fixture/skip_chr_inbond.inc | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc new file mode 100644 index 00000000000..5945d1b0b8b --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc @@ -0,0 +1,7 @@ + \ No newline at end of file From dd6b58db56c216240b6113f7753fde81b360c1cb Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 29 Aug 2025 07:45:26 +0530 Subject: [PATCH 08/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../ChrArgModuloRector/Fixture/chr.php.inc | 2 +- .../Fixture/chr_var.php.inc | 2 +- ...chr_inbond.inc => skip_chr_inbond.php.inc} | 2 -- .../Rector/FuncCall/ChrArgModuloRector.php | 24 ++++++++++++++++++- 4 files changed, 25 insertions(+), 5 deletions(-) rename rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/{skip_chr_inbond.inc => skip_chr_inbond.php.inc} (88%) diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc index 320ac129c3a..be18fad6675 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc @@ -7,5 +7,5 @@ echo chr(300); \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc index 2e9bae1ede9..090330dadd8 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc @@ -9,5 +9,5 @@ echo chr($n); namespace Rector\Tests\Php85\Rector\FuncCall\ChrArgModuloRector\Fixture; $n = 400; -echo chr($n % 256); +echo chr(144); ?> \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.php.inc similarity index 88% rename from rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc rename to rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.php.inc index 5945d1b0b8b..c303cdffff7 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/skip_chr_inbond.php.inc @@ -1,6 +1,4 @@ isFirstClassCallable()) { + return null; + } + if (! $this->isName($node, 'chr')) { return null; } @@ -63,7 +76,16 @@ public function refactor(Node $node): ?Node return null; } - $args[0]->value = new Mod($argExpr, new LNumber(256)); + $value = $this->valueResolver->getValue($argExpr); + if (! is_int($value)) { + return null; + } + + $modValue = $value % 256; + + $modValue = new \PhpParser\Node\Scalar\Int_($modValue); + + $args[0]->value = $modValue; $node->args = $args; return $node; From dc4ae1dee61066bc7a81d90b75daa809d6810a20 Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 29 Aug 2025 14:22:15 +0530 Subject: [PATCH 09/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- .../FuncCall/ChrArgModuloRector/Fixture/chr.php.inc | 2 +- .../ChrArgModuloRector/Fixture/chr_var.php.inc | 2 +- rules/Php85/Rector/FuncCall/ChrArgModuloRector.php | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc index be18fad6675..320ac129c3a 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr.php.inc @@ -7,5 +7,5 @@ echo chr(300); \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc index 090330dadd8..2e9bae1ede9 100644 --- a/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc +++ b/rules-tests/Php85/Rector/FuncCall/ChrArgModuloRector/Fixture/chr_var.php.inc @@ -9,5 +9,5 @@ echo chr($n); namespace Rector\Tests\Php85\Rector\FuncCall\ChrArgModuloRector\Fixture; $n = 400; -echo chr(144); +echo chr($n % 256); ?> \ No newline at end of file diff --git a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php index 82743538f69..11869c2b00f 100644 --- a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php +++ b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php @@ -81,11 +81,15 @@ public function refactor(Node $node): ?Node return null; } - $modValue = $value % 256; + if ($argExpr instanceof Mod) { + return null; + } - $modValue = new \PhpParser\Node\Scalar\Int_($modValue); + if ( $value >= 0 && $value <= 255) { + return null; + } - $args[0]->value = $modValue; + $args[0]->value = new Mod($argExpr, new LNumber(256)); $node->args = $args; return $node; From 12ac237a7f47a27029e46e1fe25f04820f4605e0 Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 29 Aug 2025 14:27:29 +0530 Subject: [PATCH 10/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- rules/Php85/Rector/FuncCall/ChrArgModuloRector.php | 1 - 1 file changed, 1 deletion(-) diff --git a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php index 11869c2b00f..6c2d3afc88b 100644 --- a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php +++ b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php @@ -6,7 +6,6 @@ use PhpParser\Node; use PhpParser\Node\Expr\BinaryOp\Mod; -use PhpParser\Node\Expr\Cast\Int_; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Scalar\LNumber; use Rector\PhpParser\Node\Value\ValueResolver; From e0290a489e63b918b97e97a9db5f58880ee9258f Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 29 Aug 2025 14:28:58 +0530 Subject: [PATCH 11/11] Wrap chr() argument with % 256 to avoid deprecated out-of-range integers --- rules/Php85/Rector/FuncCall/ChrArgModuloRector.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php index 6c2d3afc88b..8a36f3085c7 100644 --- a/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php +++ b/rules/Php85/Rector/FuncCall/ChrArgModuloRector.php @@ -80,10 +80,6 @@ public function refactor(Node $node): ?Node return null; } - if ($argExpr instanceof Mod) { - return null; - } - if ( $value >= 0 && $value <= 255) { return null; }