Skip to content

Commit

Permalink
[DowngradePhp73] Handle (array) cast on DowngradeArrayKeyFirstLastRec…
Browse files Browse the repository at this point in the history
…tor (#1478)

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Dec 13, 2021
1 parent 41caea7 commit 4214801
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class CastArrayKeyFirstValue
{
public function run(ClassMethod $classMethod)
{
$firstItemKey = array_key_first((array) $classMethod->stmts);
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class CastArrayKeyFirstValue
{
public function run(ClassMethod $classMethod)
{
$stmts = (array) $classMethod->stmts;
reset($stmts);
$firstItemKey = key($stmts);
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class CastArrayKeyLastValue
{
public function run(ClassMethod $classMethod)
{
$lastItemKey = array_key_last((array) $classMethod->stmts);
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class CastArrayKeyLastValue
{
public function run(ClassMethod $classMethod)
{
$stmts = (array) $classMethod->stmts;
end($stmts);
$lastItemKey = key($stmts);
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class DoubleCast
{
public function run(ClassMethod $classMethod)
{
$lastItemKey = array_key_last((array)(array) $classMethod->stmts);
}
}

?>
-----
<?php

namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;

use PhpParser\Node\Stmt\ClassMethod;

class DoubleCast
{
public function run(ClassMethod $classMethod)
{
$stmts = (array)(array) $classMethod->stmts;
end($stmts);
$lastItemKey = key($stmts);
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@

use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Cast\Array_;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Rector\AbstractRector;
use Rector\Naming\Naming\VariableNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

Expand All @@ -19,6 +26,11 @@
*/
final class DowngradeArrayKeyFirstLastRector extends AbstractRector
{
public function __construct(
private readonly VariableNaming $variableNaming
) {
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Downgrade array_key_first() and array_key_last() functions', [
Expand Down Expand Up @@ -82,12 +94,20 @@ private function refactorArrayKeyFirst(FuncCall $funcCall): ?FuncCall
return null;
}

$array = $funcCall->args[0]->value;
$originalArray = $funcCall->args[0]->value;
$array = $this->resolveCastedArray($originalArray);

if ($originalArray !== $array) {
$this->addAssignNewVariable($funcCall, $originalArray, $array);
}

$resetFuncCall = $this->nodeFactory->createFuncCall('reset', [$array]);
$this->nodesToAddCollector->addNodeBeforeNode($resetFuncCall, $funcCall);

$funcCall->name = new Name('key');
if ($originalArray !== $array) {
$funcCall->args[0]->value = $array;
}

return $funcCall;
}
Expand All @@ -102,12 +122,45 @@ private function refactorArrayKeyLast(FuncCall $funcCall): ?FuncCall
return null;
}

$array = $funcCall->args[0]->value;
$originalArray = $funcCall->args[0]->value;
$array = $this->resolveCastedArray($originalArray);

if ($originalArray !== $array) {
$this->addAssignNewVariable($funcCall, $originalArray, $array);
}

$resetFuncCall = $this->nodeFactory->createFuncCall('end', [$array]);
$this->nodesToAddCollector->addNodeBeforeNode($resetFuncCall, $funcCall);

$funcCall->name = new Name('key');
if ($originalArray !== $array) {
$funcCall->args[0]->value = $array;
}

return $funcCall;
}

private function addAssignNewVariable(FuncCall $funcCall, Expr $expr, Expr|Variable $variable): void
{
$this->addNodeBeforeNode(new Expression(new Assign($variable, $expr)), $funcCall);
}

private function resolveCastedArray(Expr $expr): Expr|Variable
{
if (! $expr instanceof Array_) {
return $expr;
}

if ($expr->expr instanceof Array_) {
return $this->resolveCastedArray($expr->expr);
}

$scope = $expr->getAttribute(AttributeKey::SCOPE);
$variableName = $this->variableNaming->createCountedValueName(
(string) $this->nodeNameResolver->getName($expr->expr),
$scope
);

return new Variable($variableName);
}
}

0 comments on commit 4214801

Please sign in to comment.