![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/vendor/rector/rector/rules/Arguments/ |
<?php declare (strict_types=1); namespace Rector\Arguments; use PhpParser\BuilderHelpers; use PhpParser\Node\Arg; use PhpParser\Node\Expr; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Stmt\ClassMethod; use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface; use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\PhpParser\Node\NodeFactory; use Rector\PhpParser\Node\Value\ValueResolver; final class ArgumentDefaultValueReplacer { /** * @readonly * @var \Rector\PhpParser\Node\NodeFactory */ private $nodeFactory; /** * @readonly * @var \Rector\PhpParser\Node\Value\ValueResolver */ private $valueResolver; public function __construct(NodeFactory $nodeFactory, ValueResolver $valueResolver) { $this->nodeFactory = $nodeFactory; $this->valueResolver = $valueResolver; } /** * @template TCall as (MethodCall|StaticCall|ClassMethod|FuncCall|New_) * * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $node * @return TCall|null */ public function processReplaces($node, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) { if ($node instanceof ClassMethod) { if (!isset($node->params[$replaceArgumentDefaultValue->getPosition()])) { return null; } return $this->processParams($node, $replaceArgumentDefaultValue); } if (!isset($node->args[$replaceArgumentDefaultValue->getPosition()])) { return null; } return $this->processArgs($node, $replaceArgumentDefaultValue); } /** * @param mixed $value */ private function isDefaultValueMatched(?Expr $expr, $value) : bool { // allow any values before, also allow param without default value if ($value === ReplaceArgumentDefaultValue::ANY_VALUE_BEFORE) { return \true; } if (!$expr instanceof Expr) { return \false; } if ($this->valueResolver->isValue($expr, $value)) { return \true; } // ValueResolver::isValue returns false when default value is `null` return $value === null && $this->valueResolver->isNull($expr); } private function processParams(ClassMethod $classMethod, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?ClassMethod { $position = $replaceArgumentDefaultValue->getPosition(); if (!$this->isDefaultValueMatched($classMethod->params[$position]->default, $replaceArgumentDefaultValue->getValueBefore())) { return null; } $classMethod->params[$position]->default = $this->normalizeValue($replaceArgumentDefaultValue->getValueAfter()); return $classMethod; } /** * @template TCall as (MethodCall|StaticCall|FuncCall|New_) * * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $expr * @return TCall|null */ private function processArgs($expr, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?Expr { if ($expr->isFirstClassCallable()) { return null; } $position = $replaceArgumentDefaultValue->getPosition(); $particularArg = $expr->getArgs()[$position] ?? null; if (!$particularArg instanceof Arg) { return null; } $argValue = $this->valueResolver->getValue($particularArg->value); if (\is_scalar($replaceArgumentDefaultValue->getValueBefore()) && $argValue === $replaceArgumentDefaultValue->getValueBefore()) { $expr->args[$position] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter()); } elseif (\is_array($replaceArgumentDefaultValue->getValueBefore())) { $newArgs = $this->processArrayReplacement($expr->getArgs(), $replaceArgumentDefaultValue); if (\is_array($newArgs)) { $expr->args = $newArgs; } } return $expr; } /** * @param mixed $value */ private function normalizeValueToArgument($value) : Arg { return new Arg($this->normalizeValue($value)); } /** * @return \PhpParser\Node\Expr\ClassConstFetch|\PhpParser\Node\Expr * @param mixed $value */ private function normalizeValue($value) { // class constants → turn string to composite if (\is_string($value) && \strpos($value, '::') !== \false) { [$class, $constant] = \explode('::', $value); return $this->nodeFactory->createClassConstFetch($class, $constant); } return BuilderHelpers::normalizeValue($value); } /** * @param array<int, Arg> $args * @return array<int, Arg>|null */ private function processArrayReplacement(array $args, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : ?array { $argumentValues = $this->resolveArgumentValuesToBeforeRecipe($args, $replaceArgumentDefaultValue); if ($argumentValues !== $replaceArgumentDefaultValue->getValueBefore()) { return null; } if (\is_string($replaceArgumentDefaultValue->getValueAfter())) { $args[$replaceArgumentDefaultValue->getPosition()] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter()); // clear following arguments $argumentCountToClear = \count($replaceArgumentDefaultValue->getValueBefore()); for ($i = $replaceArgumentDefaultValue->getPosition() + 1; $i <= $replaceArgumentDefaultValue->getPosition() + $argumentCountToClear; ++$i) { unset($args[$i]); } } return $args; } /** * @param Arg[] $argumentNodes * @return mixed[] */ private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue) : array { $argumentValues = []; $valueBefore = $replaceArgumentDefaultValue->getValueBefore(); if (!\is_array($valueBefore)) { return []; } $beforeArgumentCount = \count($valueBefore); for ($i = 0; $i < $beforeArgumentCount; ++$i) { if (!isset($argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i])) { continue; } $nextArg = $argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i]; $argumentValues[] = $this->valueResolver->getValue($nextArg->value); } return $argumentValues; } }