Skip to content

Commit

Permalink
[Php74] Add MoneyFormatToNumberFormatRector (#2727)
Browse files Browse the repository at this point in the history
Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Aug 24, 2022
1 parent d894ccc commit fadb6a4
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config/set/php74.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector;
use Rector\Php74\Rector\MethodCall\ChangeReflectionTypeToStringToGetNameRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
Expand Down Expand Up @@ -55,4 +56,6 @@
$rectorConfig->rule(RestoreDefaultNullToNullableTypePropertyRector::class);

$rectorConfig->rule(CurlyToSquareBracketArrayStringRector::class);

$rectorConfig->rule(MoneyFormatToNumberFormatRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rector\Tests\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector\Fixture;

class Fixture
{
public function run($value)
{
$value = money_format('%i', $value);
}
}

?>
-----
<?php

namespace Rector\Tests\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector\Fixture;

class Fixture
{
public function run($value)
{
$roundedValue = round($value, 2, PHP_ROUND_HALF_ODD);
$value = number_format($roundedValue, 2, '.', '');
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;

use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

final class MoneyFormatToNumberFormatRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}

/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(MoneyFormatToNumberFormatRector::class);
};
131 changes: 131 additions & 0 deletions rules/Php74/Rector/FuncCall/MoneyFormatToNumberFormatRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

declare(strict_types=1);

namespace Rector\Php74\Rector\FuncCall;

use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Analyser\Scope;
use Rector\Core\NodeAnalyzer\ArgsAnalyzer;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\Naming\Naming\VariableNaming;
use Rector\PostRector\Collector\NodesToAddCollector;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog https://www.php.net/manual/en/function.money-format.php#warning
*
* @see \Rector\Tests\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector\MoneyFormatToNumberFormatRectorTest
*/
final class MoneyFormatToNumberFormatRector extends AbstractScopeAwareRector implements MinPhpVersionInterface
{
/**
* @var string[]
*/
private const FORMATS = ['%i'];

public function __construct(
private readonly ArgsAnalyzer $argsAnalyzer,
private readonly NodesToAddCollector $nodesToAddCollector,
private readonly VariableNaming $variableNaming
) {
}

public function provideMinPhpVersion(): int
{
return PhpVersionFeature::DEPRECATE_MONEY_FORMAT;
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Change money_format() to equivalent number_format()',
[
new CodeSample(
<<<'CODE_SAMPLE'
$value = money_format('%i', $value);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$roundedValue = round($value, 2, PHP_ROUND_HALF_ODD);
$value = number_format($roundedValue, 2, '.', '');
CODE_SAMPLE
),
]
);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
}

/**
* @param FuncCall $node
*/
public function refactorWithScope(Node $node, Scope $scope): ?Node
{
if (! $this->isName($node, 'money_format')) {
return null;
}

$args = $node->getArgs();
if ($this->argsAnalyzer->hasNamedArg($args)) {
return null;
}

$formatValue = $args[0]->value;
foreach (self::FORMATS as $format) {
if ($this->valueResolver->isValue($formatValue, $format)) {
return $this->resolveNumberFormat($node, $args[1]->value, $scope);
}
}

return null;
}

private function resolveNumberFormat(FuncCall $funcCall, Expr $expr, Scope $scope): ?FuncCall
{
$currentStmt = $this->betterNodeFinder->resolveCurrentStatement($funcCall);

if (! $currentStmt instanceof Stmt) {
return null;
}

$newValue = $this->nodeFactory->createFuncCall(
'round',
[$expr, new LNumber(2), new ConstFetch(new Name('PHP_ROUND_HALF_ODD'))]
);
$variable = new Variable($this->variableNaming->createCountedValueName('roundedValue', $scope));

$this->nodesToAddCollector->addNodeBeforeNode(
new Expression(new Assign($variable, $newValue)),
$currentStmt
);

$funcCall->name = new Name('number_format');
$funcCall->args[0] = new Arg($variable);
$funcCall->args[1] = new Arg(new LNumber(2));
$funcCall->args[2] = new Arg(new String_('.'));
$funcCall->args[3] = new Arg(new String_(''));

return $funcCall;
}
}
5 changes: 5 additions & 0 deletions src/ValueObject/PhpVersionFeature.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ final class PhpVersionFeature
*/
public const DEPRECATE_REAL = PhpVersion::PHP_74;

/**
* @var int
*/
public const DEPRECATE_MONEY_FORMAT = PhpVersion::PHP_74;

/**
* @var int
*/
Expand Down

0 comments on commit fadb6a4

Please sign in to comment.