mirror of
https://github.com/rectorphp/rector.git
synced 2024-09-04 22:52:16 +00:00
[DowngradePhp72] Add DowngradePregUnmatchedAsNullConstantRector (#6021)
Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
parent
b2412ad62a
commit
6fe05c462c
@ -6,6 +6,7 @@ use Rector\Core\Configuration\Option;
|
||||
use Rector\Core\ValueObject\PhpVersion;
|
||||
use Rector\DowngradePhp72\Rector\ClassMethod\DowngradeParameterTypeWideningRector;
|
||||
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeObjectTypeDeclarationRector;
|
||||
use Rector\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
@ -15,4 +16,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(DowngradeObjectTypeDeclarationRector::class);
|
||||
$services->set(DowngradeParameterTypeWideningRector::class);
|
||||
$services->set(DowngradePregUnmatchedAsNullConstantRector::class);
|
||||
};
|
||||
|
@ -114,6 +114,7 @@ parameters:
|
||||
- rules/CodeQualityStrict/Rector/Variable/MoveVariableDeclarationNearReferenceRector.php
|
||||
- rules/Php80/Rector/If_/NullsafeOperatorRector.php
|
||||
- rules/Renaming/NodeManipulator/ClassRenamer.php
|
||||
- rules/DowngradePhp72/Rector/FuncCall/DowngradePregUnmatchedAsNullConstantRector.php
|
||||
|
||||
- "#^Cognitive complexity for \"Rector\\\\Php70\\\\EregToPcreTransformer\\:\\:(.*?)\" is (.*?), keep it under 9$#"
|
||||
- '#Cognitive complexity for "Rector\\CodeQuality\\Rector\\If_\\SimplifyIfIssetToNullCoalescingRector\:\:shouldSkip\(\)" is 10, keep it under 9#'
|
||||
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class DowngradePregUnmatchedAsNullConstantRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP 7.2
|
||||
* @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';
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ClassConstant
|
||||
{
|
||||
public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL;
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ClassConstant
|
||||
{
|
||||
public const PREG_UNMATCHED_AS_NULL = 512;
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if (\false === $match($regexp, $this->string, $matches, $flags, $offset)) {
|
||||
}
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if (\false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
|
||||
echo 'statement';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if (\false === $match($regexp, $this->string, $matches, $flags, $offset)) {
|
||||
echo 'statement';
|
||||
}
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if ($match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
|
||||
echo 'statement';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIf3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
|
||||
try {
|
||||
if ($match($regexp, $this->string, $matches, $flags, $offset)) {
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
echo 'statement';
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIfDirectCall
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
if (preg_match_all($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIfDirectCall
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
if (preg_match_all($regexp, $this->string, $matches, $flags, $offset)) {
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIfNegation
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
if (!preg_match_all($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) {
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class ComplexInIfNegation
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
if (!preg_match_all($regexp, $this->string, $matches, $flags, $offset)) {
|
||||
}
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class FqnConstant
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | \PREG_OFFSET_CAPTURE | \PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class FqnConstant
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | \PREG_OFFSET_CAPTURE);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class PregMatchAll
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match_all('/(a)(b)*(c)/', 'ac', $matches, PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class PregMatchAll
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match_all('/(a)(b)*(c)/', 'ac', $matches);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class SkipDifferentFlag
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_OFFSET_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class SkipNoFlag
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class SkipNotRegexFunctions
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
strlen('test');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags2
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags2
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | PREG_OFFSET_CAPTURE);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags2
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | PREG_UNMATCHED_AS_NULL | PREG_OFFSET_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags2
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, $flags | PREG_OFFSET_CAPTURE);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags3
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_OFFSET_CAPTURE);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags4
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL | $flag | $anotherFlag);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\Fixture;
|
||||
|
||||
class WithFlags4
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_OFFSET_CAPTURE | $flag | $anotherFlag);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(DowngradePregUnmatchedAsNullConstantRector::class);
|
||||
};
|
@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DowngradePhp72\Rector\FuncCall;
|
||||
|
||||
use Nette\NotImplementedException;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\BinaryOp\BitwiseOr;
|
||||
use PhpParser\Node\Expr\BinaryOp\Identical;
|
||||
use PhpParser\Node\Expr\BooleanNot;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Ternary;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\ClassConst;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
use Rector\Core\NodeManipulator\IfManipulator;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector\DowngradePregUnmatchedAsNullConstantRectorTest
|
||||
*/
|
||||
final class DowngradePregUnmatchedAsNullConstantRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private const REGEX_FUNCTION_NAMES = ['preg_match', 'preg_match_all'];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const FLAG = 'PREG_UNMATCHED_AS_NULL';
|
||||
|
||||
/**
|
||||
* @var IfManipulator
|
||||
*/
|
||||
private $ifManipulator;
|
||||
|
||||
public function __construct(IfManipulator $ifManipulator)
|
||||
{
|
||||
$this->ifManipulator = $ifManipulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [FuncCall::class, ClassConst::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FuncCall|ClassConst $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof ClassConst) {
|
||||
return $this->processsClassConst($node);
|
||||
}
|
||||
|
||||
if (! $this->isRegexFunctionNames($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$args = $node->args;
|
||||
if (! isset($args[3])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$flags = $args[3]->value;
|
||||
/** @var Variable $variable */
|
||||
$variable = $args[2]->value;
|
||||
|
||||
if ($flags instanceof BitwiseOr) {
|
||||
$this->cleanBitWiseOrFlags($node, $flags);
|
||||
return $this->handleEmptyStringToNullMatch($node, $variable);
|
||||
}
|
||||
|
||||
if (! $flags instanceof ConstFetch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isName($flags, self::FLAG)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$node = $this->handleEmptyStringToNullMatch($node, $variable);
|
||||
unset($node->args[3]);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Remove PREG_UNMATCHED_AS_NULL from preg_match and set null value on empty string matched on each match',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches, PREG_UNMATCHED_AS_NULL);
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
preg_match('/(a)(b)*(c)/', 'ac', $matches);
|
||||
array_walk_recursive($matches, function (&$value) {
|
||||
if ($value === '') {
|
||||
$value = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function processsClassConst(ClassConst $classConst): ClassConst
|
||||
{
|
||||
foreach ($classConst->consts as $key => $singleClassConst) {
|
||||
if (! $singleClassConst->value instanceof ConstFetch) {
|
||||
continue;
|
||||
}
|
||||
if (! $this->isName($singleClassConst->value, self::FLAG)) {
|
||||
continue;
|
||||
}
|
||||
$classConst->consts[$key]->value = new LNumber(512);
|
||||
return $classConst;
|
||||
}
|
||||
|
||||
return $classConst;
|
||||
}
|
||||
|
||||
private function isRegexFunctionNames(FuncCall $funcCall): bool
|
||||
{
|
||||
if ($this->isNames($funcCall, self::REGEX_FUNCTION_NAMES)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$variable = $funcCall->name;
|
||||
if (! $variable instanceof Variable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Assign|null $assignExprVariable */
|
||||
$assignExprVariable = $this->betterNodeFinder->findFirstPreviousOfNode($funcCall, function (Node $node) use (
|
||||
$variable
|
||||
): bool {
|
||||
if (! $node instanceof Assign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->nodeComparator->areNodesEqual($node->var, $variable);
|
||||
});
|
||||
|
||||
if (! $assignExprVariable instanceof Assign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$expr = $assignExprVariable->expr;
|
||||
if (! $expr instanceof Ternary) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $expr->if instanceof String_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $expr->else instanceof String_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($expr->if->value, self::REGEX_FUNCTION_NAMES, true) && in_array(
|
||||
$expr->else->value,
|
||||
self::REGEX_FUNCTION_NAMES,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private function cleanBitWiseOrFlags(FuncCall $funcCall, BitwiseOr $bitwiseOr, ?Expr $expr = null): void
|
||||
{
|
||||
if ($bitwiseOr->left instanceof BitwiseOr) {
|
||||
/** @var BitwiseOr $leftLeft */
|
||||
$leftLeft = $bitwiseOr->left;
|
||||
if ($leftLeft->left instanceof ConstFetch && $this->isName($leftLeft->left, self::FLAG)) {
|
||||
$bitwiseOr = new BitwiseOr($leftLeft->right, $bitwiseOr->right);
|
||||
}
|
||||
|
||||
/** @var BitwiseOr $leftRight */
|
||||
$leftRight = $bitwiseOr->left;
|
||||
if ($leftRight->right instanceof ConstFetch && $this->isName($leftRight->right, self::FLAG)) {
|
||||
$bitwiseOr = new BitwiseOr($leftRight->left, $bitwiseOr->right);
|
||||
}
|
||||
|
||||
if ($bitwiseOr->left instanceof BitwiseOr) {
|
||||
$this->cleanBitWiseOrFlags($funcCall, $bitwiseOr->left, $bitwiseOr->right);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expr instanceof Expr) {
|
||||
$bitwiseOr = new BitwiseOr($bitwiseOr, $expr);
|
||||
}
|
||||
|
||||
$this->assignThirdArgsValue($funcCall, $bitwiseOr);
|
||||
}
|
||||
|
||||
private function assignThirdArgsValue(FuncCall $funcCall, BitwiseOr $bitwiseOr): void
|
||||
{
|
||||
if ($bitwiseOr instanceof BitWiseOr && $bitwiseOr->right instanceof ConstFetch && $this->isName(
|
||||
$bitwiseOr->right,
|
||||
self::FLAG
|
||||
)) {
|
||||
$bitwiseOr = $bitwiseOr->left;
|
||||
}
|
||||
|
||||
if ($bitwiseOr instanceof BitWiseOr && $bitwiseOr->left instanceof ConstFetch && $this->isName(
|
||||
$bitwiseOr->left,
|
||||
self::FLAG
|
||||
)) {
|
||||
$bitwiseOr = $bitwiseOr->right;
|
||||
}
|
||||
|
||||
$funcCall->args[3]->value = $bitwiseOr;
|
||||
}
|
||||
|
||||
private function handleEmptyStringToNullMatch(FuncCall $funcCall, Variable $variable): FuncCall
|
||||
{
|
||||
$closure = new Closure();
|
||||
$variablePass = new Variable('value');
|
||||
$param = new Param($variablePass);
|
||||
$param->byRef = true;
|
||||
$closure->params = [$param];
|
||||
|
||||
$assign = new Assign($variablePass, $this->nodeFactory->createNull());
|
||||
|
||||
$if = $this->ifManipulator->createIfExpr(
|
||||
new Identical($variablePass, new String_('')),
|
||||
new Expression($assign)
|
||||
);
|
||||
|
||||
$closure->stmts[0] = $if;
|
||||
|
||||
$arguments = $this->nodeFactory->createArgs([$variable, $closure]);
|
||||
$replaceEmptystringToNull = $this->nodeFactory->createFuncCall('array_walk_recursive', $arguments);
|
||||
|
||||
return $this->processReplace($funcCall, $replaceEmptystringToNull);
|
||||
}
|
||||
|
||||
private function processReplace(FuncCall $funcCall, FuncCall $replaceEmptystringToNull): FuncCall
|
||||
{
|
||||
$parent = $funcCall->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parent instanceof Expression) {
|
||||
$this->addNodeAfterNode($replaceEmptystringToNull, $funcCall);
|
||||
return $funcCall;
|
||||
}
|
||||
|
||||
if ($parent instanceof If_ && $parent->cond === $funcCall) {
|
||||
return $this->processInIf($parent, $funcCall, $replaceEmptystringToNull);
|
||||
}
|
||||
|
||||
if (! $parent instanceof Node) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
$if = $parent->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parent instanceof BooleanNot) {
|
||||
return $this->processInIf($if, $funcCall, $replaceEmptystringToNull);
|
||||
}
|
||||
|
||||
if (! $parent instanceof Identical) {
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
if (! $if instanceof If_) {
|
||||
throw new NotImplementedYetException();
|
||||
}
|
||||
|
||||
return $this->processInIf($if, $funcCall, $replaceEmptystringToNull);
|
||||
}
|
||||
|
||||
private function processInIf(If_ $if, FuncCall $funcCall, FuncCall $replaceEmptystringToNull): FuncCall
|
||||
{
|
||||
$cond = $if->cond;
|
||||
|
||||
if (! $cond instanceof Identical && ! $cond instanceof BooleanNot) {
|
||||
$this->handleNotInIdenticalAndBooleanNot($if, $replaceEmptystringToNull);
|
||||
}
|
||||
|
||||
if ($cond instanceof Identical) {
|
||||
$valueCompare = $cond->left === $funcCall
|
||||
? $cond->right
|
||||
: $cond->left;
|
||||
if ($this->valueResolver->isFalse($valueCompare)) {
|
||||
$this->addNodeAfterNode($replaceEmptystringToNull, $if);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cond instanceof BooleanNot) {
|
||||
$this->addNodeAfterNode($replaceEmptystringToNull, $if);
|
||||
}
|
||||
|
||||
return $funcCall;
|
||||
}
|
||||
|
||||
private function handleNotInIdenticalAndBooleanNot(If_ $if, FuncCall $funcCall): void
|
||||
{
|
||||
if ($if->stmts !== []) {
|
||||
$firstStmt = $if->stmts[0];
|
||||
$this->addNodeBeforeNode($funcCall, $firstStmt);
|
||||
} else {
|
||||
$if->stmts[0] = new Expression($funcCall);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user