Skip to content

Commit cd475eb

Browse files
ArshidArshid
authored andcommitted
Add rector to migrate __sleep() to __serialize()
1 parent fb5d1cf commit cd475eb

5 files changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;
5+
6+
class User {
7+
private $id;
8+
private $name;
9+
10+
public function __sleep() {
11+
return ['id', 'name'];
12+
}
13+
}
14+
?>
15+
-----
16+
<?php
17+
declare(strict_types=1);
18+
19+
namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;
20+
21+
class User {
22+
private $id;
23+
private $name;
24+
25+
public function __serialize(): array {
26+
return ['id' => $this->id, 'name' => $this->name];
27+
}
28+
}
29+
?>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Php85\Rector\MethodCall\SleepToSerializeRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class SleepToSerializeRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\Php85\Rector\ClassMethod\SleepToSerializeRector;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rule(SleepToSerializeRector::class);
10+
};
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Php85\Rector\ClassMethod;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\Array_;
9+
use PhpParser\Node\Expr\ArrayItem;
10+
use PhpParser\Node\Expr\PropertyFetch;
11+
use PhpParser\Node\Identifier;
12+
use PhpParser\Node\Name;
13+
use PhpParser\Node\Stmt\ClassMethod;
14+
use Rector\Rector\AbstractRector;
15+
use Rector\ValueObject\PhpVersionFeature;
16+
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
17+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
18+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
19+
20+
/**
21+
* @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_sleep_and_wakeup_magic_methods
22+
* @see \Rector\Tests\Php85\Rector\MethodCall\SleepToSerializeRector\SleepToSerializeRectorTest
23+
*/
24+
final class SleepToSerializeRector extends AbstractRector implements MinPhpVersionInterface
25+
{
26+
public function provideMinPhpVersion(): int
27+
{
28+
return PhpVersionFeature::DEPRECATED_METHOD_SLEEP;
29+
}
30+
31+
public function getRuleDefinition(): RuleDefinition
32+
{
33+
return new RuleDefinition(
34+
'Change __sleep() to __serialize() with correct return values',
35+
[
36+
new CodeSample(
37+
<<<'CODE_SAMPLE'
38+
class User {
39+
private $id;
40+
private $name;
41+
42+
public function __sleep() {
43+
return ['id', 'name'];
44+
}
45+
}
46+
CODE_SAMPLE
47+
,
48+
<<<'CODE_SAMPLE'
49+
class User {
50+
private $id;
51+
private $name;
52+
53+
public function __serialize(): array {
54+
return [
55+
'id' => $this->id,
56+
'name' => $this->name,
57+
];
58+
}
59+
}
60+
CODE_SAMPLE
61+
)
62+
]
63+
);
64+
}
65+
66+
/**
67+
* @return array<class-string<Node>>
68+
*/
69+
public function getNodeTypes(): array
70+
{
71+
return [ClassMethod::class];
72+
}
73+
74+
/**
75+
* @param ClassMethod $node
76+
*/
77+
public function refactor(Node $node): ?Node
78+
{
79+
if (! $this->isName($node->name, '__sleep')) {
80+
return null;
81+
}
82+
83+
$node->name = new Identifier('__serialize');
84+
$node->returnType = new Identifier('array');
85+
86+
if(!is_array($node->stmts)){
87+
return null;
88+
}
89+
90+
foreach ($node->stmts as $stmt) {
91+
if ($stmt instanceof Node\Stmt\Return_ && $stmt->expr instanceof Array_) {
92+
$newItems = [];
93+
foreach ($stmt->expr->items as $item) {
94+
if ($item !== null && $item->value instanceof Node\Scalar\String_) {
95+
$propName = $item->value->value;
96+
$newItems[] = new ArrayItem(
97+
new PropertyFetch(new Node\Expr\Variable('this'), $propName),
98+
$item->value
99+
);
100+
}
101+
}
102+
$stmt->expr->items = $newItems;
103+
}
104+
}
105+
106+
return $node;
107+
}
108+
}

src/ValueObject/PhpVersionFeature.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,4 +804,10 @@ final class PhpVersionFeature
804804
* @var int
805805
*/
806806
public const DEPRECATE_OUTSIDE_INTERVEL_VAL_IN_CHR_FUNCTION = PhpVersion::PHP_85;
807+
808+
/**
809+
* @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_sleep_and_wakeup_magic_methods
810+
* @var int
811+
*/
812+
public const DEPRECATED_METHOD_SLEEP = PhpVersion::PHP_85;
807813
}

0 commit comments

Comments
 (0)