diff --git a/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/array_values_pattern.php.inc b/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/array_values_pattern.php.inc new file mode 100644 index 00000000000..8931a04fd8f --- /dev/null +++ b/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/array_values_pattern.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/skip_array_values_different_variable.php.inc b/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/skip_array_values_different_variable.php.inc new file mode 100644 index 00000000000..21f7abf72cb --- /dev/null +++ b/rules-tests/Php85/Rector/ArrayDimFetch/ArrayFirstLastRector/Fixture/skip_array_values_different_variable.php.inc @@ -0,0 +1,13 @@ +dim instanceof FuncCall) { + return $this->refactorArrayKeyPattern($node); + } + + if ($node->var instanceof FuncCall && ($node->dim instanceof Int_ || $node->dim instanceof Minus)) { + return $this->refactorArrayValuesPattern($node); + } + + return null; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::ARRAY_FIRST_LAST; + } + + private function refactorArrayKeyPattern(ArrayDimFetch $node): ?FuncCall { if (! $node->dim instanceof FuncCall) { return null; @@ -84,12 +108,7 @@ public function refactor(Node $node): ?FuncCall return null; } - $scope = ScopeFetcher::fetch($node->var); - if ($scope->isInExpressionAssign($node)) { - return null; - } - - if ($node->getAttribute(AttributeKey::IS_UNSET_VAR)) { + if ($this->shouldSkip($node, $node->var)) { return null; } @@ -100,8 +119,77 @@ public function refactor(Node $node): ?FuncCall return $this->nodeFactory->createFuncCall($functionName, [$node->var]); } - public function provideMinPhpVersion(): int + private function refactorArrayValuesPattern(ArrayDimFetch $node): ?FuncCall { - return PhpVersionFeature::ARRAY_FIRST_LAST; + if (! $node->var instanceof FuncCall) { + return null; + } + + if (! $this->isName($node->var, 'array_values')) { + return null; + } + + if ($node->var->isFirstClassCallable()) { + return null; + } + + if (count($node->var->getArgs()) !== 1) { + return null; + } + + if ($this->shouldSkip($node, $node)) { + return null; + } + + $arrayArg = $node->var->getArgs()[0] + ->value; + + if ($node->dim instanceof Int_ && $node->dim->value === 0) { + return $this->nodeFactory->createFuncCall('array_first', [$arrayArg]); + } + + if ($node->dim instanceof Minus) { + if (! $node->dim->left instanceof FuncCall) { + return null; + } + + if (! $this->isName($node->dim->left, 'count')) { + return null; + } + + if ($node->dim->left->isFirstClassCallable()) { + return null; + } + + if (count($node->dim->left->getArgs()) !== 1) { + return null; + } + + if (! $node->dim->right instanceof Int_ || $node->dim->right->value !== 1) { + return null; + } + + if (! $this->nodeComparator->areNodesEqual($arrayArg, $node->dim->left->getArgs()[0]->value)) { + return null; + } + + return $this->nodeFactory->createFuncCall('array_last', [$arrayArg]); + } + + return null; + } + + private function shouldSkip(ArrayDimFetch $node, Node $scopeNode): bool + { + $scope = ScopeFetcher::fetch($scopeNode); + if ($scope->isInExpressionAssign($node)) { + return true; + } + + if ($node->getAttribute(AttributeKey::IS_UNSET_VAR)) { + return true; + } + + return false; } }