Skip to content

Commit a08ccad

Browse files
authored
[DowngradePhp73] Handle next if with BooleanOr condition that cause possible non-array data on DowngradeArrayKeyFirstLastRector (#207)
1 parent 89c94de commit a08ccad

File tree

3 files changed

+109
-4
lines changed

3 files changed

+109
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
4+
5+
class PossibleNonArrayOrObjectArrayKeyFirst
6+
{
7+
protected mixed $value = null;
8+
9+
private function run(): bool
10+
{
11+
$v = $this->value;
12+
13+
if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) array_key_first($v)) || "\x9D" !== $k[0] || "\0" !== $k[5] || "\x5F" !== $k[9]) {
14+
return false;
15+
}
16+
17+
return true;
18+
}
19+
}
20+
21+
?>
22+
-----
23+
<?php
24+
25+
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
26+
27+
class PossibleNonArrayOrObjectArrayKeyFirst
28+
{
29+
protected mixed $value = null;
30+
31+
private function run(): bool
32+
{
33+
$v = $this->value;
34+
if (is_array($v)) {
35+
reset($v);
36+
}
37+
38+
if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) key($v)) || "\x9D" !== $k[0] || "\0" !== $k[5] || "\x5F" !== $k[9]) {
39+
return false;
40+
}
41+
42+
return true;
43+
}
44+
}
45+
46+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
4+
5+
class PossibleNonArrayOrObjectArrayKeyLast
6+
{
7+
protected mixed $value = null;
8+
9+
private function run(): bool
10+
{
11+
$v = $this->value;
12+
13+
if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) array_key_last($v)) || "\x9D" !== $k[0] || "\0" !== $k[5] || "\x5F" !== $k[9]) {
14+
return false;
15+
}
16+
17+
return true;
18+
}
19+
}
20+
21+
?>
22+
-----
23+
<?php
24+
25+
namespace Rector\Tests\DowngradePhp73\Rector\FuncCall\DowngradeArrayKeyFirstLastRector\Fixture;
26+
27+
class PossibleNonArrayOrObjectArrayKeyLast
28+
{
29+
protected mixed $value = null;
30+
31+
private function run(): bool
32+
{
33+
$v = $this->value;
34+
if (is_array($v)) {
35+
end($v);
36+
}
37+
38+
if (!\is_array($v) || 1 !== \count($v) || 10 !== \strlen($k = (string) key($v)) || "\x9D" !== $k[0] || "\0" !== $k[5] || "\x5F" !== $k[9]) {
39+
return false;
40+
}
41+
42+
return true;
43+
}
44+
}
45+
46+
?>

rules/DowngradePhp73/Rector/FuncCall/DowngradeArrayKeyFirstLastRector.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpParser\Node\Arg;
99
use PhpParser\Node\Expr;
1010
use PhpParser\Node\Expr\Assign;
11+
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
1112
use PhpParser\Node\Expr\CallLike;
1213
use PhpParser\Node\Expr\Cast\Array_;
1314
use PhpParser\Node\Expr\FuncCall;
@@ -17,8 +18,10 @@
1718
use PhpParser\Node\Expr\StaticCall;
1819
use PhpParser\Node\Expr\Variable;
1920
use PhpParser\Node\Name;
21+
use PhpParser\Node\Stmt;
2022
use PhpParser\Node\Stmt\Echo_;
2123
use PhpParser\Node\Stmt\Expression;
24+
use PhpParser\Node\Stmt\If_;
2225
use PhpParser\Node\Stmt\Return_;
2326
use PhpParser\Node\Stmt\Switch_;
2427
use PHPStan\Analyser\Scope;
@@ -161,15 +164,14 @@ private function refactorArrayKeyFirst(
161164
}
162165

163166
$resetFuncCall = $this->nodeFactory->createFuncCall('reset', [$array]);
164-
$resetFuncCallExpression = new Expression($resetFuncCall);
167+
$newStmts[] = $this->resolvePrependNewStmt($array, $resetFuncCall, $stmt);
165168

166169
$funcCall->name = new Name('key');
167170
if ($originalArray !== $array) {
168171
$firstArg = $args[0];
169172
$firstArg->value = $array;
170173
}
171174

172-
$newStmts[] = $resetFuncCallExpression;
173175
$newStmts[] = $stmt;
174176

175177
return $newStmts;
@@ -203,8 +205,7 @@ private function refactorArrayKeyLast(
203205
}
204206

205207
$endFuncCall = $this->nodeFactory->createFuncCall('end', [$array]);
206-
$endFuncCallExpression = new Expression($endFuncCall);
207-
$newStmts[] = $endFuncCallExpression;
208+
$newStmts[] = $this->resolvePrependNewStmt($array, $endFuncCall, $stmt);
208209

209210
$funcCall->name = new Name('key');
210211
if ($originalArray !== $array) {
@@ -216,6 +217,18 @@ private function refactorArrayKeyLast(
216217
return $newStmts;
217218
}
218219

220+
private function resolvePrependNewStmt(Expr|Variable $array, FuncCall $funcCall, Stmt $stmt): Expression|If_
221+
{
222+
if (! $stmt instanceof If_ || $stmt->cond instanceof FuncCall || ! $stmt->cond instanceof BooleanOr) {
223+
return new Expression($funcCall);
224+
}
225+
226+
$if = new If_($this->nodeFactory->createFuncCall('is_array', [$array]));
227+
$if->stmts[] = new Expression($funcCall);
228+
229+
return $if;
230+
}
231+
219232
private function resolveCastedArray(Expr $expr): Expr|Variable
220233
{
221234
if (! $expr instanceof Array_) {

0 commit comments

Comments
 (0)