Skip to content

Commit 62a871f

Browse files
committed
Updated Rector to commit 8627ee851f09406dd25c32230f00d4ae367ee4e9
rectorphp/rector-src@8627ee8 Support array_values in ArrayFirstLastRector (#7830)
1 parent 9799556 commit 62a871f

2 files changed

Lines changed: 76 additions & 9 deletions

File tree

rules/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector.php

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
use PhpParser\Node;
77
use PhpParser\Node\Expr\ArrayDimFetch;
8+
use PhpParser\Node\Expr\BinaryOp\Minus;
89
use PhpParser\Node\Expr\FuncCall;
10+
use PhpParser\Node\Scalar\Int_;
911
use Rector\NodeTypeResolver\Node\AttributeKey;
1012
use Rector\PHPStan\ScopeFetcher;
1113
use Rector\Rector\AbstractRector;
@@ -32,10 +34,14 @@ public function getRuleDefinition(): RuleDefinition
3234
return new RuleDefinition('Make use of array_first() and array_last()', [new CodeSample(<<<'CODE_SAMPLE'
3335
echo $array[array_key_first($array)];
3436
echo $array[array_key_last($array)];
37+
echo array_values($array)[0];
38+
echo array_values($array)[count($array) - 1];
3539
CODE_SAMPLE
3640
, <<<'CODE_SAMPLE'
3741
echo array_first($array);
3842
echo array_last($array);
43+
echo array_first($array);
44+
echo array_last($array);
3945
CODE_SAMPLE
4046
)]);
4147
}
@@ -50,6 +56,20 @@ public function getNodeTypes(): array
5056
* @param ArrayDimFetch $node
5157
*/
5258
public function refactor(Node $node): ?FuncCall
59+
{
60+
if ($node->dim instanceof FuncCall) {
61+
return $this->refactorArrayKeyPattern($node);
62+
}
63+
if ($node->var instanceof FuncCall && ($node->dim instanceof Int_ || $node->dim instanceof Minus)) {
64+
return $this->refactorArrayValuesPattern($node);
65+
}
66+
return null;
67+
}
68+
public function provideMinPhpVersion(): int
69+
{
70+
return PhpVersionFeature::ARRAY_FIRST_LAST;
71+
}
72+
private function refactorArrayKeyPattern(ArrayDimFetch $node): ?FuncCall
5373
{
5474
if (!$node->dim instanceof FuncCall) {
5575
return null;
@@ -66,18 +86,65 @@ public function refactor(Node $node): ?FuncCall
6686
if (!$this->nodeComparator->areNodesEqual($node->var, $node->dim->getArgs()[0]->value)) {
6787
return null;
6888
}
69-
$scope = ScopeFetcher::fetch($node->var);
70-
if ($scope->isInExpressionAssign($node)) {
71-
return null;
72-
}
73-
if ($node->getAttribute(AttributeKey::IS_UNSET_VAR)) {
89+
if ($this->shouldSkip($node, $node->var)) {
7490
return null;
7591
}
7692
$functionName = $this->isName($node->dim, self::ARRAY_KEY_FIRST) ? 'array_first' : 'array_last';
7793
return $this->nodeFactory->createFuncCall($functionName, [$node->var]);
7894
}
79-
public function provideMinPhpVersion(): int
95+
private function refactorArrayValuesPattern(ArrayDimFetch $node): ?FuncCall
8096
{
81-
return PhpVersionFeature::ARRAY_FIRST_LAST;
97+
if (!$node->var instanceof FuncCall) {
98+
return null;
99+
}
100+
if (!$this->isName($node->var, 'array_values')) {
101+
return null;
102+
}
103+
if ($node->var->isFirstClassCallable()) {
104+
return null;
105+
}
106+
if (count($node->var->getArgs()) !== 1) {
107+
return null;
108+
}
109+
if ($this->shouldSkip($node, $node)) {
110+
return null;
111+
}
112+
$arrayArg = $node->var->getArgs()[0]->value;
113+
if ($node->dim instanceof Int_ && $node->dim->value === 0) {
114+
return $this->nodeFactory->createFuncCall('array_first', [$arrayArg]);
115+
}
116+
if ($node->dim instanceof Minus) {
117+
if (!$node->dim->left instanceof FuncCall) {
118+
return null;
119+
}
120+
if (!$this->isName($node->dim->left, 'count')) {
121+
return null;
122+
}
123+
if ($node->dim->left->isFirstClassCallable()) {
124+
return null;
125+
}
126+
if (count($node->dim->left->getArgs()) !== 1) {
127+
return null;
128+
}
129+
if (!$node->dim->right instanceof Int_ || $node->dim->right->value !== 1) {
130+
return null;
131+
}
132+
if (!$this->nodeComparator->areNodesEqual($arrayArg, $node->dim->left->getArgs()[0]->value)) {
133+
return null;
134+
}
135+
return $this->nodeFactory->createFuncCall('array_last', [$arrayArg]);
136+
}
137+
return null;
138+
}
139+
private function shouldSkip(ArrayDimFetch $node, Node $scopeNode): bool
140+
{
141+
$scope = ScopeFetcher::fetch($scopeNode);
142+
if ($scope->isInExpressionAssign($node)) {
143+
return \true;
144+
}
145+
if ($node->getAttribute(AttributeKey::IS_UNSET_VAR)) {
146+
return \true;
147+
}
148+
return \false;
82149
}
83150
}

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = 'cb73a3ab268c6ee5d988568d4b424c3c51dcbef1';
22+
public const PACKAGE_VERSION = '8627ee851f09406dd25c32230f00d4ae367ee4e9';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2026-01-18 16:49:23';
27+
public const RELEASE_DATE = '2026-01-18 20:50:15';
2828
/**
2929
* @var int
3030
*/

0 commit comments

Comments
 (0)