Merge pull request #2406 from jeroensmit/AddPregQuoteDelimiterRectorDelimiterCheck

Added check for correct delimiter to use in preg_quote
This commit is contained in:
Tomáš Votruba 2019-12-07 15:58:23 +01:00 committed by GitHub
commit 936918c393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 29 deletions

View File

@ -306,14 +306,8 @@ Changes settype() to (type) where possible
Add preg_quote delimiter when missing
```diff
class SomeClass
{
public function test()
{
- return preg_quote('name');
+ return preg_quote('name', '#');
}
}
-'#' . preg_quote('name') . '#';
+'#' . preg_quote('name', '#') . '#';
```
<br>
@ -5923,8 +5917,7 @@ services:
- return SomeStaticClass::go();
+ return $this->someStaticClass->go();
}
-}
+}
}
```
<br>

View File

@ -6,8 +6,10 @@ namespace Rector\CodeQuality\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\BinaryOp\Concat;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Scalar\String_;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -17,28 +19,21 @@ use Rector\RectorDefinition\RectorDefinition;
*/
final class AddPregQuoteDelimiterRector extends AbstractRector
{
/**
* @see https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
*/
private const ALL_MODIFIERS = 'imsxeADSUXJu';
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add preg_quote delimiter when missing', [
new CodeSample(
<<<'PHP'
class SomeClass
{
public function test()
{
return preg_quote('name');
}
}
'#' . preg_quote('name') . '#';
PHP
,
<<<'PHP'
class SomeClass
{
public function test()
{
return preg_quote('name', '#');
}
}
'#' . preg_quote('name', '#') . '#';
PHP
),
@ -67,8 +62,54 @@ PHP
return null;
}
$node->args[1] = new Arg(new String_('#'));
$delimiter = $this->determineDelimiter($node);
if ($delimiter === null) {
return null;
}
$node->args[1] = new Arg(new String_($delimiter));
return $node;
}
private function determineDelimiter(FuncCall $funcCall)
{
$parent = $this->getUppermostConcat($funcCall);
if ($parent === null) {
return null;
}
$leftMostConcatNode = $parent->left;
while ($leftMostConcatNode instanceof Concat) {
$leftMostConcatNode = $leftMostConcatNode->left;
}
$rightMostConcatNode = $parent->right;
while ($rightMostConcatNode instanceof Concat) {
$rightMostConcatNode = $rightMostConcatNode->right;
}
if (! $leftMostConcatNode instanceof String_) {
return null;
}
$possibleLeftDelimiter = substr($leftMostConcatNode->value, 0, 1);
if (! $rightMostConcatNode instanceof String_) {
return null;
}
$possibleRightDelimiter = substr(rtrim($rightMostConcatNode->value, self::ALL_MODIFIERS), -1, 1);
if ($possibleLeftDelimiter === $possibleRightDelimiter) {
return $possibleLeftDelimiter;
}
return null;
}
private function getUppermostConcat(FuncCall $funcCall): ?Concat
{
$upperMostConcat = null;
$parent = $funcCall->getAttribute(AttributeKey::PARENT_NODE);
while ($parent instanceof Concat) {
$upperMostConcat = $parent;
$parent = $parent->getAttribute(AttributeKey::PARENT_NODE);
}
return $upperMostConcat;
}
}

View File

@ -4,9 +4,11 @@ namespace Rector\CodeQuality\Tests\Rector\FuncCall\AddPregQuoteDelimiterRector\F
class SomeClass
{
public function test()
public function test($input)
{
return preg_quote('name');
$patttern1 = '/' . preg_quote('name'). '/';
$patttern2 = '#' . preg_quote('name'). '#';
$patttern3 = '#\d' . preg_quote('name'). '\d#';
}
}
@ -18,9 +20,11 @@ namespace Rector\CodeQuality\Tests\Rector\FuncCall\AddPregQuoteDelimiterRector\F
class SomeClass
{
public function test()
public function test($input)
{
return preg_quote('name', '#');
$patttern1 = '/' . preg_quote('name', '/'). '/';
$patttern2 = '#' . preg_quote('name', '#'). '#';
$patttern3 = '#\d' . preg_quote('name', '#'). '\d#';
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Rector\CodeQuality\Tests\Rector\FuncCall\AddPregQuoteDelimiterRector\Fixture;
class SomeClass
{
public function test()
{
$pattern1 = preg_quote('name');
$pattern2 = '/' . preg_quote('name');
$pattern3 = preg_quote('name') . '/';
$pattern4 = '#' . preg_quote('name') . '/';
}
}
?>

View File

@ -0,0 +1,29 @@
<?php
namespace Rector\CodeQuality\Tests\Rector\FuncCall\AddPregQuoteDelimiterRector\WithModifiers;
class SomeClass
{
public function test($input)
{
$patttern1 = '/' . preg_quote('name'). '/imsxeA';
$patttern2 = '#' . preg_quote('name'). '#DSUXJu';
}
}
?>
-----
<?php
namespace Rector\CodeQuality\Tests\Rector\FuncCall\AddPregQuoteDelimiterRector\WithModifiers;
class SomeClass
{
public function test($input)
{
$patttern1 = '/' . preg_quote('name', '/'). '/imsxeA';
$patttern2 = '#' . preg_quote('name', '#'). '#DSUXJu';
}
}
?>