From cb55c60fd794c49fbe3f4ea5cb6a6b1e833b7a7b Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 11 Sep 2025 14:58:06 +0530 Subject: [PATCH 1/6] WakeupToUnserializeRector --- config/set/php85.php | 2 + .../Fixture/wakeup.php.inc | 29 +++++++ .../WakeupToUnserializeRectorTest.php | 28 +++++++ .../config/configured_rule.php | 10 +++ .../Class_/WakeupToUnserializeRector.php | 81 +++++++++++++++++++ src/ValueObject/PhpVersionFeature.php | 6 ++ 6 files changed, 156 insertions(+) create mode 100644 rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc create mode 100644 rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/WakeupToUnserializeRectorTest.php create mode 100644 rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/config/configured_rule.php create mode 100644 rules/Php85/Rector/Class_/WakeupToUnserializeRector.php diff --git a/config/set/php85.php b/config/set/php85.php index cee158fa245..ba507b6a40c 100644 --- a/config/set/php85.php +++ b/config/set/php85.php @@ -10,6 +10,7 @@ use Rector\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector; use Rector\Php85\Rector\ClassMethod\NullDebugInfoReturnRector; use Rector\Php85\Rector\Class_\SleepToSerializeRector; +use Rector\Php85\Rector\Class_\WakeupToUnserializeRector; use Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector; use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector; use Rector\Php85\Rector\FuncCall\ChrArgModuloRector; @@ -41,6 +42,7 @@ ChrArgModuloRector::class, SleepToSerializeRector::class, OrdSingleByteRector::class, + WakeupToUnserializeRector::class ] ); diff --git a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc new file mode 100644 index 00000000000..62f088af0e7 --- /dev/null +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc @@ -0,0 +1,29 @@ +id = 1; + } +} +?> +----- +id = 1; + } +} +?> diff --git a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/WakeupToUnserializeRectorTest.php b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/WakeupToUnserializeRectorTest.php new file mode 100644 index 00000000000..e242647f5d3 --- /dev/null +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/WakeupToUnserializeRectorTest.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/Class_/WakeupToUnserializeRector/config/configured_rule.php b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/config/configured_rule.php new file mode 100644 index 00000000000..659c7717a7c --- /dev/null +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(WakeupToUnserializeRector::class); +}; diff --git a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php new file mode 100644 index 00000000000..ff2a641b395 --- /dev/null +++ b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php @@ -0,0 +1,81 @@ +> + */ + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * @param Class_ $node + */ + public function refactor(Node $node): ?Node + { + if ($node->getMethod('__unserialize') instanceof ClassMethod) { + return null; + } + + $classMethod = $node->getMethod('__wakeup'); + if (! $classMethod instanceof ClassMethod) { + return null; + } + + if ($classMethod->returnType instanceof Identifier && $this->isName($classMethod->returnType, 'array')) { + return null; + } + + $classMethod->name = new Identifier('__unserialize'); + return $node; + } +} diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 78a946ee218..9670d115bf0 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -816,6 +816,12 @@ final class PhpVersionFeature * @var int */ public const DEPRECATED_METHOD_SLEEP = PhpVersion::PHP_85; + + /** + * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_sleep_and_wakeup_magic_methods + * @var int + */ + public const DEPRECATED_METHOD_WAKEUP = PhpVersion::PHP_85; /** * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_passing_string_which_are_not_one_byte_long_to_ord From 0b0163ed6dd74fde673bd3e16969e015055ce409 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 11 Sep 2025 15:19:21 +0530 Subject: [PATCH 2/6] WakeupToUnserializeRector --- .../Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc | 2 +- rules/Php85/Rector/Class_/WakeupToUnserializeRector.php | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc index 62f088af0e7..9061bcf3758 100644 --- a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc @@ -7,7 +7,7 @@ class User { private $id; private $name; - public function __wakeup(): void{ + public function __wakeup(){ $this->id = 1; } } diff --git a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php index ff2a641b395..e0733f988ad 100644 --- a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php +++ b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php @@ -70,12 +70,9 @@ public function refactor(Node $node): ?Node if (! $classMethod instanceof ClassMethod) { return null; } - - if ($classMethod->returnType instanceof Identifier && $this->isName($classMethod->returnType, 'array')) { - return null; - } $classMethod->name = new Identifier('__unserialize'); + $classMethod->returnType = new Identifier('void'); return $node; } } From 65ad3589507eef6aed5cb7d9df4ee610bcaf6048 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 11 Sep 2025 19:23:49 +0530 Subject: [PATCH 3/6] WakeupToUnserializeRector --- .../WakeupToUnserializeRector/Fixture/wakeup.php.inc | 2 +- .../Php85/Rector/Class_/WakeupToUnserializeRector.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc index 9061bcf3758..b82710abe1b 100644 --- a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc @@ -22,7 +22,7 @@ class User { private $id; private $name; - public function __unserialize(): void{ + public function __unserialize(array $data): void{ $this->id = 1; } } diff --git a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php index e0733f988ad..10ae1f8a840 100644 --- a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php +++ b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php @@ -5,7 +5,9 @@ namespace Rector\Php85\Rector\Class_; use PhpParser\Node; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; +use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use Rector\Rector\AbstractRector; @@ -15,6 +17,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** + * @see https://3v4l.org/NS419 + * @see https://3v4l.org/nMOpl * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_sleep_and_wakeup_magic_methods * @see \Rector\Tests\Php85\Rector\Class_\WakeupToUnserializeRector\WakeupToUnserializeRectorTest */ @@ -73,6 +77,12 @@ public function refactor(Node $node): ?Node $classMethod->name = new Identifier('__unserialize'); $classMethod->returnType = new Identifier('void'); + $param = new Param( + var: new Variable('data'), + type: new Identifier('array') + ); + + $classMethod->params[] = $param; return $node; } } From c57a51697cbbb56075f7ab94ecba6565b956ebde Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 11 Sep 2025 20:48:24 +0530 Subject: [PATCH 4/6] WakeupToUnserializeRector - auto assign --- rector.php | 0 .../Fixture/wakeup.php.inc | 6 ++- .../Class_/WakeupToUnserializeRector.php | 38 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) mode change 100644 => 100755 rector.php diff --git a/rector.php b/rector.php old mode 100644 new mode 100755 diff --git a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc index b82710abe1b..c8abafca716 100644 --- a/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc +++ b/rules-tests/Php85/Rector/Class_/WakeupToUnserializeRector/Fixture/wakeup.php.inc @@ -23,7 +23,11 @@ class User { private $name; public function __unserialize(array $data): void{ - $this->id = 1; + foreach ($data as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } } } ?> diff --git a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php index 10ae1f8a840..c6bea12bbaf 100644 --- a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php +++ b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php @@ -5,11 +5,18 @@ namespace Rector\Php85\Rector\Class_; use PhpParser\Node; +use PhpParser\Node\Expr\Assign; +use PhpParser\Node\Expr\FuncCall; +use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PhpParser\Node\Param; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Expression; +use PhpParser\Node\Stmt\Foreach_; +use PhpParser\Node\Stmt\If_; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; @@ -83,6 +90,37 @@ public function refactor(Node $node): ?Node ); $classMethod->params[] = $param; + + $classMethod->stmts = [$this->assignProperties()]; + return $node; } + + protected function assignProperties(): Foreach_{ + $assign = new Assign( + new PropertyFetch(new Variable('this'), new Variable('property')), + new Variable('value') + ); + + $if = new If_( + new FuncCall(new Name('property_exists'), [ + new Node\Arg(new Variable('this')), + new Node\Arg(new Variable('property')), + ]), + [ + 'stmts' => [new Expression($assign)], + ] + ); + + $foreach = new Foreach_( + new Variable('data'), + new Variable('value'), + [ + 'keyVar' => new Variable('property'), + 'stmts' => [$if], + ] + ); + + return $foreach; + } } From f773812adc25a1b9c73c04b0fa328307994840c1 Mon Sep 17 00:00:00 2001 From: Arshid Date: Thu, 11 Sep 2025 21:01:06 +0530 Subject: [PATCH 5/6] WakeupToUnserializeRector - auto assign --- rector.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 rector.php diff --git a/rector.php b/rector.php old mode 100755 new mode 100644 From a57b9ecf7f4f0930b23aec0e7c4162b79b78c55f Mon Sep 17 00:00:00 2001 From: Arshid Date: Fri, 12 Sep 2025 07:58:04 +0530 Subject: [PATCH 6/6] WakeupToUnserializeRector - auto assign --- rules/Php85/Rector/Class_/WakeupToUnserializeRector.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php index c6bea12bbaf..87b7dd8256b 100644 --- a/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php +++ b/rules/Php85/Rector/Class_/WakeupToUnserializeRector.php @@ -51,7 +51,12 @@ public function __wakeup() { , <<<'CODE_SAMPLE' class User { - public function __unserialize(){ + public function __unserialize(array $data): void{ + foreach ($data as $property => $value) { + if (property_exists($this, $property)) { + $this->{$property} = $value; + } + } } } CODE_SAMPLE