Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/set/php85.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Rector\Config\RectorConfig;
use Rector\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector;
use Rector\Php85\Rector\ClassMethod\NullDebugInfoReturnRector;
use Rector\Php85\Rector\ClassMethod\SleepToSerializeRector;
use Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector;
use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector;
use Rector\Php85\Rector\FuncCall\ChrArgModuloRector;
Expand Down Expand Up @@ -37,6 +38,7 @@
ColonAfterSwitchCaseRector::class,
ArrayKeyExistsNullToEmptyStringRector::class,
ChrArgModuloRector::class,
SleepToSerializeRector::class,
]
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;

class User {
private $id;
private $name;

public function __sleep(): array {
return [];
}
}
?>
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);

namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;

class User {
private $id;
private $name;

public function __sleep() {
return null;
}
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);

namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;

class User {
private $id;
private $name;

public function __sleep() {
return ['id', 'name'];
}
}
?>
-----
<?php
declare(strict_types=1);

namespace Rector\Tests\Php85\Rector\MethodCall\NullDebugInfoReturnRector\Fixture;

class User {
private $id;
private $name;

public function __serialize(): array {
return ['id' => $this->id, 'name' => $this->name];
}
}
?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php85\Rector\MethodCall\SleepToSerializeRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class SleepToSerializeRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php85\Rector\ClassMethod\SleepToSerializeRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(SleepToSerializeRector::class);
};
131 changes: 131 additions & 0 deletions rules/Php85/Rector/ClassMethod/SleepToSerializeRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

declare(strict_types=1);

namespace Rector\Php85\Rector\ClassMethod;

use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\Rector\AbstractRector;
use Rector\TypeDeclaration\NodeAnalyzer\ReturnAnalyzer;
use Rector\ValueObject\PhpVersionFeature;
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_the_sleep_and_wakeup_magic_methods
* @see \Rector\Tests\Php85\Rector\MethodCall\SleepToSerializeRector\SleepToSerializeRectorTest
*/
final class SleepToSerializeRector extends AbstractRector implements MinPhpVersionInterface
{
public function __construct(
private BetterNodeFinder $betterNodeFinder,
private ReturnAnalyzer $returnAnalyzer
) {
}

public function provideMinPhpVersion(): int
{
return PhpVersionFeature::DEPRECATED_METHOD_SLEEP;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Change __sleep() to __serialize() with correct return values',
[
new CodeSample(
<<<'CODE_SAMPLE'
class User {
private $id;
private $name;

public function __sleep() {
return ['id', 'name'];
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class User {
private $id;
private $name;

public function __serialize(): array {
return [
'id' => $this->id,
'name' => $this->name,
];
}
}
CODE_SAMPLE
),
]
);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [ClassMethod::class];
}

/**
* @param ClassMethod $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isName($node->name, '__sleep')) {
return null;
}

if ($node->returnType instanceof Identifier && $this->isName($node->returnType, 'array')) {
return null;
}

$returns = $this->betterNodeFinder->findReturnsScoped($node);
if (! $this->returnAnalyzer->hasOnlyReturnWithExpr($node, $returns)) {
return null;
}

$hasChanged = false;
foreach ($returns as $return) {
if (! $return->expr instanceof Array_ ) {
return null;
}

if (count($return->expr->items) > 0) {
$newItems = [];
foreach ($return->expr->items as $item) {
if ($item !== null && $item->value instanceof Node\Scalar\String_) {
$propName = $item->value->value;
$newItems[] = new ArrayItem(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add $hasChanged = false init variable before loop, set $hasChanged = true after changed, verify $hasChanged before apply return, return null if no change

new PropertyFetch(new Node\Expr\Variable('this'), $propName),
$item->value
);
}
}
if (count($newItems) > 0) {
$hasChanged = true;
$return->expr->items = $newItems;
}
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check ! $hasChanged, return null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check now.

if($hasChanged){
$node->name = new Identifier('__serialize');
$node->returnType = new Identifier('array');
return $node;
}

return null;
}
}
6 changes: 6 additions & 0 deletions src/ValueObject/PhpVersionFeature.php
Original file line number Diff line number Diff line change
Expand Up @@ -804,4 +804,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_the_sleep_and_wakeup_magic_methods
* @var int
*/
public const DEPRECATED_METHOD_SLEEP = PhpVersion::PHP_85;
}
Loading