diff --git a/config/set/php85.php b/config/set/php85.php index a5a49624beb..19715d7a0c2 100644 --- a/config/set/php85.php +++ b/config/set/php85.php @@ -12,6 +12,7 @@ use Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector; use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector; use Rector\Php85\Rector\FuncCall\ChrArgModuloRector; +use Rector\Php85\Rector\FuncCall\OrdSingleByteRector; use Rector\Php85\Rector\FuncCall\RemoveFinfoBufferContextArgRector; use Rector\Php85\Rector\Switch_\ColonAfterSwitchCaseRector; use Rector\Removing\Rector\FuncCall\RemoveFuncCallArgRector; @@ -37,6 +38,7 @@ ColonAfterSwitchCaseRector::class, ArrayKeyExistsNullToEmptyStringRector::class, ChrArgModuloRector::class, + OrdSingleByteRector::class, ] ); diff --git a/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_int.php.inc b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_int.php.inc new file mode 100644 index 00000000000..aaffcdbfa77 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_int.php.inc @@ -0,0 +1,9 @@ + +----- + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_str.php.inc b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_str.php.inc new file mode 100644 index 00000000000..af2fe155cb8 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/multibyte_str.php.inc @@ -0,0 +1,11 @@ + +----- + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_bool.php.inc b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_bool.php.inc new file mode 100644 index 00000000000..db18509cbdf --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_bool.php.inc @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_multibyte_int_var.php.inc b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_multibyte_int_var.php.inc new file mode 100644 index 00000000000..7cc95c53a58 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/Fixture/skip_multibyte_int_var.php.inc @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/OrdSingleByteRectorTest.php b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/OrdSingleByteRectorTest.php new file mode 100644 index 00000000000..a9db1796a52 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/OrdSingleByteRectorTest.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/OrdSingleByteRector/config/configured_rule.php b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/config/configured_rule.php new file mode 100644 index 00000000000..6989be8e1f1 --- /dev/null +++ b/rules-tests/Php85/Rector/FuncCall/OrdSingleByteRector/config/configured_rule.php @@ -0,0 +1,13 @@ +rule(OrdSingleByteRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_85); +}; diff --git a/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php b/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php new file mode 100644 index 00000000000..d1219b039b6 --- /dev/null +++ b/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php @@ -0,0 +1,110 @@ +isFirstClassCallable()) { + return null; + } + + if (! $this->isName($node, 'ord')) { + return null; + } + + $args = $node->getArgs(); + + if (! isset($node->args[0])) { + return null; + } + + $argExpr = $args[0]->value; + $type = $this->nodeTypeResolver->getNativeType($argExpr); + + if (! $type->isString()->yes() && ! $type->isInteger()->yes()) { + return null; + } + + $value = $this->valueResolver->getValue($argExpr); + $isInt = is_int($value); + + if (! $argExpr instanceof Int_) { + + if ($isInt) { + return null; + } + + $args[0]->value = new ArrayDimFetch($argExpr, new Int_(0)); + $node->args = $args; + + return $node; + } + + $value = (string) $value; + $byte = $value[0] ?? ''; + + $byteValue = $isInt ? new Int_((int) $byte) : new String_($byte); + + $args[0]->value = $byteValue; + $node->args = $args; + + return $node; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::DEPRECATE_ORD_WITH_MULTIBYTE_STRING; + } +} diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index cf0b48bd481..087d11985a2 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -810,4 +810,10 @@ final class PhpVersionFeature * @var int */ public const DEPRECATE_OUTSIDE_INTERVEL_VAL_IN_CHR_FUNCTION = PhpVersion::PHP_85; + + /** + * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_string_which_are_not_one_byte_long_to_ord + * @var int + */ + public const DEPRECATE_ORD_WITH_MULTIBYTE_STRING = PhpVersion::PHP_85; }