rector/vendor/rector/rector-downgrade-php/docs/rector_rules_overview.md
Tomas Votruba 740fedd8a5 Updated Rector to commit 74a7c51d383b8ad5c6adb10cd67fe5f7f8ff290d
74a7c51d38 [automated] Re-Generate Nodes/Rectors Documentation (#5664)
2024-02-25 00:28:09 +00:00

38 KiB

74 Rules Overview

ArrowFunctionToAnonymousFunctionRector

Replace arrow functions with anonymous functions

 class SomeClass
 {
     public function run()
     {
         $delimiter = ",";
-        $callable = fn($matches) => $delimiter . strtolower($matches[1]);
+        $callable = function ($matches) use ($delimiter) {
+            return $delimiter . strtolower($matches[1]);
+        };
     }
 }

DowngradeAbstractPrivateMethodInTraitRector

Remove "abstract" from private methods in traits and adds an empty function body

 trait SomeTrait
 {
-    abstract private function someAbstractPrivateFunction();
+    private function someAbstractPrivateFunction() {}
 }

DowngradeArbitraryExpressionsSupportRector

Replace arbitrary expressions used with new or instanceof

 function getObjectClassName() {
     return stdClass::class;
 }

-$object = new (getObjectClassName());
+$className = getObjectClassName();
+$object = new $className();

DowngradeArrayFilterNullableCallbackRector

Unset nullable callback on array_filter

 class SomeClass
 {
     public function run($callback = null)
     {
         $data = [[]];
-        var_dump(array_filter($data, null));
+        var_dump(array_filter($data));
     }
 }

DowngradeArrayIsListRector

Replace array_is_list() function

-array_is_list([1 => 'apple', 'orange']);
+$arrayIsList = function (array $array) : bool {
+    if (function_exists('array_is_list')) {
+        return array_is_list($array);
+    }
+
+    if ($array === []) {
+        return true;
+    }
+
+    $current_key = 0;
+    foreach ($array as $key => $noop) {
+        if ($key !== $current_key) {
+            return false;
+        }
+        ++$current_key;
+    }
+
+    return true;
+};
+$arrayIsList([1 => 'apple', 'orange']);

DowngradeArrayKeyFirstLastRector

Downgrade array_key_first() and array_key_last() functions

 class SomeClass
 {
     public function run($items)
     {
-        $firstItemKey = array_key_first($items);
+        reset($items);
+        $firstItemKey = key($items);
     }
 }

DowngradeArrayMergeCallWithoutArgumentsRector

Add missing param to array_merge and array_merge_recursive

 class SomeClass
 {
     public function run()
     {
-        array_merge();
-        array_merge_recursive();
+        array_merge([]);
+        array_merge_recursive([]);
     }
 }

DowngradeArraySpreadRector

Replace array spread with array_merge function

 class SomeClass
 {
     public function run()
     {
         $parts = ['apple', 'pear'];
-        $fruits = ['banana', 'orange', ...$parts, 'watermelon'];
+        $fruits = array_merge(['banana', 'orange'], $parts, ['watermelon']);
     }

     public function runWithIterable()
     {
-        $fruits = ['banana', 'orange', ...new ArrayIterator(['durian', 'kiwi']), 'watermelon'];
+        $fruits = array_merge(
+            ['banana', 'orange'],
+            is_array(new ArrayIterator(['durian', 'kiwi'])) ?
+                new ArrayIterator(['durian', 'kiwi']) :
+                iterator_to_array(new ArrayIterator(['durian', 'kiwi'])),
+            ['watermelon']
+        );
     }
 }

DowngradeArraySpreadStringKeyRector

Replace array spread with string key to array_merge function

 $parts = ['a' => 'b'];
 $parts2 = ['c' => 'd'];

-$result = [...$parts, ...$parts2];
+$result = array_merge($parts, $parts2);

DowngradeAttributeToAnnotationRector

Refactor PHP attribute markers to annotations notation

🔧 configure it!

 use Symfony\Component\Routing\Annotation\Route;

 class SymfonyRoute
 {
-    #[Route(path: '/path', name: 'action')]
+    /**
+     * @Route("/path", name="action")
+     */
     public function action()
     {
     }
 }

DowngradeClassOnObjectToGetClassRector

Change $object::class to get_class($object)

 class SomeClass
 {
     public function run($object)
     {
-        return $object::class;
+        return get_class($object);
     }
 }

DowngradeContravariantArgumentTypeRector

Remove contravariant argument type declarations

 class ParentType {}
 class ChildType extends ParentType {}

 class A
 {
     public function contraVariantArguments(ChildType $type)
     {
     }
 }

 class B extends A
 {
-    public function contraVariantArguments(ParentType $type)
+    /**
+     * @param ParentType $type
+     */
+    public function contraVariantArguments($type)
     {
     }
 }

DowngradeCovariantReturnTypeRector

Make method return same type as parent

 class ParentType {}
 class ChildType extends ParentType {}

 class A
 {
     public function covariantReturnTypes(): ParentType
     {
     }
 }

 class B extends A
 {
-    public function covariantReturnTypes(): ChildType
+    /**
+     * @return ChildType
+     */
+    public function covariantReturnTypes(): ParentType
     {
     }
 }

DowngradeDereferenceableOperationRector

Add parentheses around non-dereferenceable expressions.

 function getFirstChar(string $str, string $suffix = '')
 {
-    return "$str$suffix"[0];
+    return ("$str$suffix")[0];
 }

DowngradeEnumToConstantListClassRector

Downgrade enum to constant list class

-enum Direction
+class Direction
 {
-    case LEFT;
+    public const LEFT = 'left';

-    case RIGHT;
+    public const RIGHT = 'right';
 }

DowngradeFinalizePublicClassConstantRector

Remove final from class constants

 class SomeClass
 {
-    final public const NAME = 'value';
+    public const NAME = 'value';
 }

DowngradeFirstClassCallableSyntaxRector

Replace variadic placeholders usage by Closure::fromCallable()

-$cb = strlen(...);
+$cb = \Closure::fromCallable('strlen');

DowngradeFlexibleHeredocSyntaxRector

Remove indentation from heredoc/nowdoc

 $query = <<<SQL
-    SELECT *
-    FROM `table`
-    WHERE `column` = true;
-    SQL;
+SELECT *
+FROM `table`
+WHERE `column` = true;
+SQL;

DowngradeFreadFwriteFalsyToNegationRector

Changes fread() or fwrite() compare to false to negation check

-fread($handle, $length) === false;
-fwrite($fp, '1') === false;
+!fread($handle, $length);
+!fwrite($fp, '1');

DowngradeHashAlgorithmXxHashRector

Downgrade hash algorithm xxh32, xxh64, xxh3 or xxh128 by default to md5. You can configure the algorithm to downgrade.

 class SomeClass
 {
     public function run()
     {
-        return hash('xxh128', 'some-data-to-hash');
+        return hash('md5', 'some-data-to-hash');
     }
 }

DowngradeIsCountableRector

Downgrade is_countable() to former version

 $items = [];
-return is_countable($items);
+return is_array($items) || $items instanceof Countable;

DowngradeIsEnumRector

Downgrades isEnum() on class reflection

 class SomeClass
 {
     public function run(ReflectionClass $reflectionClass)
     {
-        return $reflectionClass->isEnum();
+        return method_exists($reflectionClass, 'isEnum') ? $reflectionClass->isEnum() : false;
     }
 }

DowngradeJsonDecodeNullAssociativeArgRector

Downgrade json_decode() with null associative argument function

 function exactlyNull(string $json)
 {
-    $value = json_decode($json, null);
+    $value = json_decode($json, true);
 }

 function possiblyNull(string $json, ?bool $associative)
 {
-    $value = json_decode($json, $associative);
+    $value = json_decode($json, $associative === null ?: $associative);
 }

DowngradeListReferenceAssignmentRector

Convert the list reference assignment to its equivalent PHP 7.2 code

 class SomeClass
 {
     public function run($string)
     {
         $array = [1, 2, 3];
-        list($a, &$b) = $array;
+        list($a) = $array;
+        $b =& $array[1];

-        [&$c, $d, &$e] = $array;
+        [$c, $d, $e] = $array;
+        $c =& $array[0];
+        $e =& $array[2];

-        list(&$a, &$b) = $array;
+        $a =& $array[0];
+        $b =& $array[1];
     }
 }

DowngradeMatchToSwitchRector

Downgrade match() to switch()

 class SomeClass
 {
     public function run()
     {
-        $message = match ($statusCode) {
-            200, 300 => null,
-            400 => 'not found',
-            default => 'unknown status code',
-        };
+        switch ($statusCode) {
+            case 200:
+            case 300:
+                $message = null;
+                break;
+            case 400:
+                $message = 'not found';
+                break;
+            default:
+                $message = 'unknown status code';
+                break;
+        }
     }
 }

DowngradeMixedTypeDeclarationRector

Remove the "mixed" param and return type, add a @param and @return tag instead

 class SomeClass
 {
-    public function someFunction(mixed $anything): mixed
+    /**
+     * @param mixed $anything
+     * @return mixed
+     */
+    public function someFunction($anything)
     {
     }
 }

DowngradeMixedTypeTypedPropertyRector

Removes mixed type property type definition, adding @var annotations instead.

 class SomeClass
 {
-    private mixed $property;
+    /**
+     * @var mixed
+     */
+    private $property;
 }

DowngradeNamedArgumentRector

Remove named argument

 class SomeClass
 {
     public function run()
     {
-        $this->execute(b: 100);
+        $this->execute(null, 100);
     }

     private function execute($a = null, $b = null)
     {
     }
 }

DowngradeNeverTypeDeclarationRector

Remove "never" return type, add a "@return never" tag instead

-function someFunction(): never
+/**
+ * @return never
+ */
+function someFunction()
 {
 }

DowngradeNewInInitializerRector

Replace New in initializers

 class SomeClass
 {
     public function __construct(
-        private Logger $logger = new NullLogger,
+        private ?Logger $logger = null,
     ) {
+        $this->logger = $logger ?? new NullLogger;
     }
 }

DowngradeNonCapturingCatchesRector

Downgrade catch () without variable to one

 class SomeClass
 {
     public function run()
     {
         try {
             // code
-        } catch (\Exception) {
+        } catch (\Exception $exception) {
             // error
         }
     }
 }

DowngradeNullCoalescingOperatorRector

Remove null coalescing operator ??=

 $array = [];
-$array['user_id'] ??= 'value';
+$array['user_id'] = $array['user_id'] ?? 'value';

DowngradeNullsafeToTernaryOperatorRector

Change nullsafe operator to ternary operator rector

-$dateAsString = $booking->getStartDate()?->asDateTimeString();
+$dateAsString = ($bookingGetStartDate = $booking->getStartDate()) ? $bookingGetStartDate->asDateTimeString() : null;

DowngradeNumberFormatNoFourthArgRector

Downgrade number_format arg to fill 4th arg when only 3rd arg filled

 class SomeClass
 {
     public function run()
     {
-        return number_format(1000, 2, ',');
+        return number_format(1000, 2, ',', ',');
     }
 }

DowngradeNumericLiteralSeparatorRector

Remove "_" as thousands separator in numbers

 class SomeClass
 {
     public function run()
     {
-        $int = 1_000;
-        $float = 1_000_500.001;
+        $int = 1000;
+        $float = 1000500.001;
     }
 }

DowngradeObjectTypeDeclarationRector

Remove the "object" param and return type, add a @param and @return tags instead

 class SomeClass
 {
-    public function someFunction(object $someObject): object
+    /**
+     * @param object $someObject
+     * @return object
+     */
+    public function someFunction($someObject)
     {
     }
 }

DowngradeOctalNumberRector

Downgrades octal numbers to decimal ones

 class SomeClass
 {
     public function run()
     {
-        return 0o777;
+        return 0777;
     }
 }

DowngradeParameterTypeWideningRector

Change param type to match the lowest type in whole family tree

🔧 configure it!

 interface SomeInterface
 {
-    public function test(array $input);
+    /**
+     * @param mixed[] $input
+     */
+    public function test($input);
 }
 final class SomeClass implements SomeInterface
 {
     public function test($input)
     {
     }
 }

DowngradePhp72JsonConstRector

Remove Json constant that available only in php 7.2

-$inDecoder = new Decoder($connection, true, 512, \JSON_INVALID_UTF8_IGNORE);
+$inDecoder = new Decoder($connection, true, 512, 0);

-$inDecoder = new Decoder($connection, true, 512, \JSON_INVALID_UTF8_SUBSTITUTE);
+$inDecoder = new Decoder($connection, true, 512, 0);

DowngradePhp73JsonConstRector

Remove Json constant that available only in php 7.3

-json_encode($content, JSON_THROW_ON_ERROR);
+json_encode($content, 0);
+if (json_last_error() !== JSON_ERROR_NONE) {
+    throw new \Exception(json_last_error_msg());
+}

-$content = json_decode($json, null, 512, JSON_THROW_ON_ERROR);
+$content = json_decode($json, null, 512, 0);
+if (json_last_error() !== JSON_ERROR_NONE) {
+    throw new \Exception(json_last_error_msg());
+}

DowngradePhp80ResourceReturnToObjectRector

change instanceof Object to is_resource

 class SomeClass
 {
     public function run($obj)
     {
-        $obj instanceof \CurlHandle;
+        is_resource($obj) || $obj instanceof \CurlHandle;
     }
 }

DowngradePhp81ResourceReturnToObjectRector

change instanceof Object to is_resource

 class SomeClass
 {
     public function run($obj)
     {
-        $obj instanceof \finfo;
+        is_resource($obj) || $obj instanceof \finfo;
     }
 }

DowngradePhpTokenRector

"something()" will be renamed to "somethingElse()"

-$tokens = \PhpToken::tokenize($code);
+$tokens = token_get_all($code);

-foreach ($tokens as $phpToken) {
-   $name = $phpToken->getTokenName();
-   $text = $phpToken->text;
+foreach ($tokens as $token) {
+    $name = is_array($token) ? token_name($token[0]) : null;
+    $text = is_array($token) ? $token[1] : $token;
 }

DowngradePregUnmatchedAsNullConstantRector

Remove PREG_UNMATCHED_AS_NULL from preg_match and set null value on empty string matched on each match

 class SomeClass
 {
     public function run()
     {
-        preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_UNMATCHED_AS_NULL);
+        preg_match('/(a)(b)*(c)/', 'ac', $matches);
+
+        array_walk_recursive($matches, function (&$value) {
+            if ($value === '') {
+                $value = null;
+            }
+        });
     }
 }

DowngradePreviouslyImplementedInterfaceRector

Downgrade previously implemented interface

 interface ContainerExceptionInterface extends Throwable
 {
 }

-interface ExceptionInterface extends ContainerExceptionInterface, Throwable
+interface ExceptionInterface extends ContainerExceptionInterface
 {
 }

DowngradeProcOpenArrayCommandArgRector

Change array command argument on proc_open to implode spaced string

-return proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);
+return proc_open(is_array($command) ? implode(' ', array_map('escapeshellarg', $command)) : $command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]);

DowngradePropertyPromotionRector

Change constructor property promotion to property assign

 class SomeClass
 {
-    public function __construct(public float $value = 0.0)
+    public float $value;
+
+    public function __construct(float $value = 0.0)
     {
+        $this->value = $value;
     }
 }

DowngradePureIntersectionTypeRector

Remove the intersection type params and returns, add @param/@return tags instead

-function someFunction(): Foo&Bar
+/**
+ * @return Foo&Bar
+ */
+function someFunction()
 {
 }

DowngradeReadonlyClassRector

Remove "readonly" class type, decorate all properties to "readonly"

-final readonly class SomeClass
+final class SomeClass
 {
-    public string $foo;
+    public readonly string $foo;

     public function __construct()
     {
         $this->foo = 'foo';
     }
 }

DowngradeReadonlyPropertyRector

Remove "readonly" property type, add a "@readonly" tag instead

 class SomeClass
 {
-    public readonly string $foo;
+    /**
+     * @readonly
+     */
+    public string $foo;

     public function __construct()
     {
         $this->foo = 'foo';
     }
 }

DowngradeRecursiveDirectoryIteratorHasChildrenRector

Remove bool type hint on child of RecursiveDirectoryIterator hasChildren allowLinks parameter

 class RecursiveDirectoryIteratorChild extends \RecursiveDirectoryIterator
 {
-    public function hasChildren(bool $allowLinks = false): bool
+    public function hasChildren($allowLinks = false): bool
     {
         return true;
     }
 }

DowngradeReflectionClassGetConstantsFilterRector

Downgrade ReflectionClass->getConstants(ReflectionClassConstant::IS_*)

 $reflectionClass = new ReflectionClass('SomeClass');
-$constants = $reflectionClass->getConstants(ReflectionClassConstant::IS_PUBLIC));
+$reflectionClassConstants = $reflectionClass->getReflectionConstants();
+$result = [];
+array_walk($reflectionClassConstants, function ($value) use (&$result) {
+    if ($value->isPublic()) {
+       $result[$value->getName()] = $value->getValue();
+    }
+});
+$constants = $result;

DowngradeReflectionGetAttributesRector

Remove reflection getAttributes() class method code

 function run(ReflectionClass $reflectionClass)
 {
-    return $reflectionClass->getAttributes();
+    return method_exists($reflectionClass, 'getAttributes') ? $reflectionClass->getAttributes() ? [];
 }

DowngradeReflectionGetTypeRector

Downgrade reflection $reflection->getType() method call

 class SomeClass
 {
     public function run(ReflectionProperty $reflectionProperty)
     {
-        if ($reflectionProperty->getType()) {
+        if (method_exists($reflectionProperty, 'getType') ? $reflectionProperty->getType() ? null) {
             return true;
         }

         return false;
     }
 }

DowngradeReflectionPropertyGetDefaultValueRector

Downgrade ReflectionProperty->getDefaultValue()

 class SomeClass
 {
     public function run(ReflectionProperty $reflectionProperty)
     {
-        return $reflectionProperty->getDefaultValue();
+        return $reflectionProperty->getDeclaringClass()->getDefaultProperties()[$reflectionProperty->getName()] ?? null;
     }
 }

DowngradeSetAccessibleReflectionPropertyRector

Add setAccessible() on ReflectionProperty to allow reading private properties in PHP 8.0-

 class SomeClass
 {
     public function run($object)
     {
         $reflectionProperty = new ReflectionProperty($object, 'bar');
+        $reflectionProperty->setAccessible(true);

         return $reflectionProperty->getValue($object);
     }
 }

DowngradeStandaloneNullTrueFalseReturnTypeRector

Downgrade standalone return null, true, or false

 final class SomeClass
 {
-    public function run(): null
+    public function run(): mixed
     {
         return null;
     }
 }

DowngradeStaticTypeDeclarationRector

Remove "static" return and param type, add a "@param $this" and "@return $this" tag instead

 class SomeClass
 {
-    public function getStatic(): static
+    /**
+     * @return static
+     */
+    public function getStatic()
     {
         return new static();
     }
 }

DowngradeStrContainsRector

Replace str_contains() with strpos() !== false

 class SomeClass
 {
     public function run()
     {
-        return str_contains('abc', 'a');
+        return strpos('abc', 'a') !== false;
     }
 }

DowngradeStrEndsWithRector

Downgrade str_ends_with() to strncmp() version

-str_ends_with($haystack, $needle);
+"" === $needle || ("" !== $haystack && 0 === substr_compare($haystack, $needle, -\strlen($needle)));

DowngradeStrStartsWithRector

Downgrade str_starts_with() to strncmp() version

-str_starts_with($haystack, $needle);
+strncmp($haystack, $needle, strlen($needle)) === 0;

DowngradeStreamIsattyRector

Downgrade stream_isatty() function

 class SomeClass
 {
     public function run($stream)
     {
-        $isStream = stream_isatty($stream);
+        $streamIsatty = function ($stream) {
+            if (\function_exists('stream_isatty')) {
+                return stream_isatty($stream);
+            }
+
+            if (!\is_resource($stream)) {
+                trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING);
+
+                return false;
+            }
+
+            if ('\\' === \DIRECTORY_SEPARATOR) {
+                $stat = @fstat($stream);
+                // Check if formatted mode is S_IFCHR
+                return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
+            }
+
+            return \function_exists('posix_isatty') && @posix_isatty($stream);
+        };
+        $isStream = $streamIsatty($stream);
     }
 }

DowngradeStringReturnTypeOnToStringRector

Add "string" return on current __toString() method when parent method has string return on __toString() method

 abstract class ParentClass
 {
     public function __toString(): string
     {
         return 'value';
     }
 }

 class ChildClass extends ParentClass
 {
-    public function __toString()
+    public function __toString(): string
     {
         return 'value';
     }
 }

DowngradeStripTagsCallWithArrayRector

Convert 2nd argument in strip_tags() from array to string

 class SomeClass
 {
     public function run($string)
     {
         // Arrays: change to string
-        strip_tags($string, ['a', 'p']);
+        strip_tags($string, '<' . implode('><', ['a', 'p']) . '>');

         // Variables/consts/properties: if array, change to string
         $tags = ['a', 'p'];
-        strip_tags($string, $tags);
+        strip_tags($string, $tags !== null && is_array($tags) ? '<' . implode('><', $tags) . '>' : $tags);
     }
 }

DowngradeThrowExprRector

Downgrade throw expression

-echo $variable ?? throw new RuntimeException();
+if (! isset($variable)) {
+    throw new RuntimeException();
+}
+
+echo $variable;

DowngradeTrailingCommasInFunctionCallsRector

Remove trailing commas in function calls

 class SomeClass
 {
     public function __construct(string $value)
     {
         $compacted = compact(
             'posts',
-            'units',
+            'units'
         );
     }
 }

DowngradeTrailingCommasInParamUseRector

Remove trailing commas in param or use list

 class SomeClass
 {
-    public function __construct(string $value1, string $value2,)
+    public function __construct(string $value1, string $value2)
     {
-        function (string $value1, string $value2,) {
+        function (string $value1, string $value2) {
         };

-        function () use ($value1, $value2,) {
+        function () use ($value1, $value2) {
         };
     }
 }

-function inFunction(string $value1, string $value2,)
+function inFunction(string $value1, string $value2)
 {
 }

DowngradeTrailingCommasInUnsetRector

Remove trailing commas in unset

 unset(
 	$x,
-	$y,
+	$y
 );

DowngradeTypedClassConstRector

Remove typed class constant

 final class SomeClass
 {
-    public string FOO = 'test';
+    /**
+     * @var string
+     */
+    public FOO = 'test';
 }

DowngradeTypedPropertyRector

Changes property type definition from type definitions to @var annotations.

 class SomeClass
 {
-    private string $property;
+    /**
+     * @var string
+     */
+    private $property;
 }

DowngradeUnionTypeDeclarationRector

Remove the union type params and returns, add @param/@return tags instead

 class SomeClass
 {
-    public function echoInput(string|int $input): int|bool
+    /**
+     * @param string|int $input
+     * @return int|bool
+     */
+    public function echoInput($input)
     {
         echo $input;
     }
 }

DowngradeUnionTypeTypedPropertyRector

Removes union type property type definition, adding @var annotations instead.

 class SomeClass
 {
-    private string|int $property;
+    /**
+     * @var string|int
+     */
+    private $property;
 }

RemoveReturnTypeDeclarationFromCloneRector

Remove return type from __clone() method

 final class SomeClass
 {
-    public function __clone(): void
+    public function __clone()
     {
     }
 }

SetCookieOptionsArrayToArgumentsRector

Convert setcookie option array to arguments

-setcookie('name', $value, ['expires' => 360]);
+setcookie('name', $value, 360);