2021-05-17 23:17:47 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare (strict_types=1);
|
|
|
|
namespace Rector\Arguments;
|
|
|
|
|
|
|
|
use PhpParser\BuilderHelpers;
|
|
|
|
use PhpParser\Node;
|
|
|
|
use PhpParser\Node\Arg;
|
|
|
|
use PhpParser\Node\Expr\FuncCall;
|
|
|
|
use PhpParser\Node\Expr\MethodCall;
|
|
|
|
use PhpParser\Node\Expr\StaticCall;
|
|
|
|
use PhpParser\Node\Stmt\ClassMethod;
|
2021-06-10 10:46:24 +00:00
|
|
|
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
|
2021-05-17 23:17:47 +00:00
|
|
|
use Rector\Core\PhpParser\Node\NodeFactory;
|
|
|
|
use Rector\Core\PhpParser\Node\Value\ValueResolver;
|
|
|
|
final class ArgumentDefaultValueReplacer
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var \Rector\Core\PhpParser\Node\NodeFactory
|
|
|
|
*/
|
|
|
|
private $nodeFactory;
|
|
|
|
/**
|
|
|
|
* @var \Rector\Core\PhpParser\Node\Value\ValueResolver
|
|
|
|
*/
|
|
|
|
private $valueResolver;
|
|
|
|
public function __construct(\Rector\Core\PhpParser\Node\NodeFactory $nodeFactory, \Rector\Core\PhpParser\Node\Value\ValueResolver $valueResolver)
|
|
|
|
{
|
|
|
|
$this->nodeFactory = $nodeFactory;
|
|
|
|
$this->valueResolver = $valueResolver;
|
|
|
|
}
|
|
|
|
/**
|
2021-06-29 13:37:16 +00:00
|
|
|
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\FuncCall $node
|
2021-05-17 23:17:47 +00:00
|
|
|
*/
|
2021-06-29 13:37:16 +00:00
|
|
|
public function processReplaces($node, \Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?\PhpParser\Node
|
2021-05-17 23:17:47 +00:00
|
|
|
{
|
|
|
|
if ($node instanceof \PhpParser\Node\Stmt\ClassMethod) {
|
2021-06-10 10:46:24 +00:00
|
|
|
if (!isset($node->params[$replaceArgumentDefaultValue->getPosition()])) {
|
2021-05-17 23:17:47 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-06-10 10:46:24 +00:00
|
|
|
} elseif (isset($node->args[$replaceArgumentDefaultValue->getPosition()])) {
|
|
|
|
$this->processArgs($node, $replaceArgumentDefaultValue);
|
2021-05-17 23:17:47 +00:00
|
|
|
}
|
|
|
|
return $node;
|
|
|
|
}
|
|
|
|
/**
|
2021-06-29 14:24:45 +00:00
|
|
|
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall $expr
|
2021-05-17 23:17:47 +00:00
|
|
|
*/
|
2021-06-29 14:24:45 +00:00
|
|
|
private function processArgs($expr, \Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : void
|
2021-05-17 23:17:47 +00:00
|
|
|
{
|
2021-06-10 10:46:24 +00:00
|
|
|
$position = $replaceArgumentDefaultValue->getPosition();
|
2021-05-17 23:17:47 +00:00
|
|
|
$argValue = $this->valueResolver->getValue($expr->args[$position]->value);
|
2021-06-10 10:46:24 +00:00
|
|
|
if (\is_scalar($replaceArgumentDefaultValue->getValueBefore()) && $argValue === $replaceArgumentDefaultValue->getValueBefore()) {
|
|
|
|
$expr->args[$position] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter());
|
|
|
|
} elseif (\is_array($replaceArgumentDefaultValue->getValueBefore())) {
|
|
|
|
$newArgs = $this->processArrayReplacement($expr->args, $replaceArgumentDefaultValue);
|
2021-05-17 23:17:47 +00:00
|
|
|
if ($newArgs) {
|
|
|
|
$expr->args = $newArgs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param mixed $value
|
|
|
|
*/
|
|
|
|
private function normalizeValueToArgument($value) : \PhpParser\Node\Arg
|
|
|
|
{
|
|
|
|
// class constants → turn string to composite
|
2021-05-29 22:10:59 +00:00
|
|
|
if (\is_string($value) && \strpos($value, '::') !== \false) {
|
2021-05-17 23:17:47 +00:00
|
|
|
[$class, $constant] = \explode('::', $value);
|
|
|
|
$classConstFetch = $this->nodeFactory->createClassConstFetch($class, $constant);
|
|
|
|
return new \PhpParser\Node\Arg($classConstFetch);
|
|
|
|
}
|
|
|
|
return new \PhpParser\Node\Arg(\PhpParser\BuilderHelpers::normalizeValue($value));
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param Arg[] $argumentNodes
|
|
|
|
* @return Arg[]|null
|
|
|
|
*/
|
2021-06-10 10:46:24 +00:00
|
|
|
private function processArrayReplacement(array $argumentNodes, \Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?array
|
2021-05-17 23:17:47 +00:00
|
|
|
{
|
2021-06-10 10:46:24 +00:00
|
|
|
$argumentValues = $this->resolveArgumentValuesToBeforeRecipe($argumentNodes, $replaceArgumentDefaultValue);
|
|
|
|
if ($argumentValues !== $replaceArgumentDefaultValue->getValueBefore()) {
|
2021-05-17 23:17:47 +00:00
|
|
|
return null;
|
|
|
|
}
|
2021-06-10 10:46:24 +00:00
|
|
|
if (\is_string($replaceArgumentDefaultValue->getValueAfter())) {
|
|
|
|
$argumentNodes[$replaceArgumentDefaultValue->getPosition()] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter());
|
2021-05-17 23:17:47 +00:00
|
|
|
// clear following arguments
|
2021-06-10 10:46:24 +00:00
|
|
|
$argumentCountToClear = \count($replaceArgumentDefaultValue->getValueBefore());
|
|
|
|
for ($i = $replaceArgumentDefaultValue->getPosition() + 1; $i <= $replaceArgumentDefaultValue->getPosition() + $argumentCountToClear; ++$i) {
|
2021-05-17 23:17:47 +00:00
|
|
|
unset($argumentNodes[$i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $argumentNodes;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* @param Arg[] $argumentNodes
|
|
|
|
* @return mixed[]
|
|
|
|
*/
|
2021-06-10 10:46:24 +00:00
|
|
|
private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, \Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : array
|
2021-05-17 23:17:47 +00:00
|
|
|
{
|
|
|
|
$argumentValues = [];
|
|
|
|
/** @var mixed[] $valueBefore */
|
2021-06-10 10:46:24 +00:00
|
|
|
$valueBefore = $replaceArgumentDefaultValue->getValueBefore();
|
2021-05-17 23:17:47 +00:00
|
|
|
$beforeArgumentCount = \count($valueBefore);
|
|
|
|
for ($i = 0; $i < $beforeArgumentCount; ++$i) {
|
2021-06-10 10:46:24 +00:00
|
|
|
if (!isset($argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i])) {
|
2021-05-17 23:17:47 +00:00
|
|
|
continue;
|
|
|
|
}
|
2021-06-10 10:46:24 +00:00
|
|
|
$nextArg = $argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i];
|
2021-05-17 23:17:47 +00:00
|
|
|
$argumentValues[] = $this->valueResolver->getValue($nextArg->value);
|
|
|
|
}
|
|
|
|
return $argumentValues;
|
|
|
|
}
|
|
|
|
}
|