Skip to content

Commit

Permalink
[Php55] Handle crash on concat variable single quote on PregReplaceEM…
Browse files Browse the repository at this point in the history
…odifierRector (#2483)

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Jun 13, 2022
1 parent 28ed5cf commit 6f164da
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Rector\Tests\Php55\Rector\FuncCall\PregReplaceEModifierRector\Fixture;

class ConcatVariable
{
public function run()
{
$test = 'become : ';
$string ='string';
echo preg_replace("#([a-z]*)#e", "'".$test."' . strtoupper('\\1')", $string);
}
}

?>
-----
<?php

namespace Rector\Tests\Php55\Rector\FuncCall\PregReplaceEModifierRector\Fixture;

class ConcatVariable
{
public function run()
{
$test = 'become : ';
$string ='string';
echo preg_replace_callback('#([a-z]*)#', function ($matches) use ($test) {
return $test . strtoupper($matches[1]);
}, $string);
}
}

?>
4 changes: 1 addition & 3 deletions rules/Php55/Rector/FuncCall/PregReplaceEModifierRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,7 @@ public function refactor(Node $node): ?Node
/** @var Arg $secondArgument */
$secondArgument = $node->args[1];
$secondArgumentValue = $secondArgument->value;
$anonymousFunction = $this->anonymousFunctionFactory->createAnonymousFunctionFromString(
$secondArgumentValue
);
$anonymousFunction = $this->anonymousFunctionFactory->createAnonymousFunctionFromExpr($secondArgumentValue);
if (! $anonymousFunction instanceof Closure) {
return null;
}
Expand Down
23 changes: 15 additions & 8 deletions rules/Php72/NodeFactory/AnonymousFunctionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
use PHPStan\Type\Type;
use PHPStan\Type\VoidType;
use Rector\Core\Contract\PhpParser\NodePrinterInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\PhpParser\Parser\InlineCodeParser;
use Rector\Core\PhpParser\Parser\SimplePhpParser;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand Down Expand Up @@ -71,7 +71,8 @@ public function __construct(
private readonly NodeComparator $nodeComparator,
private readonly AstResolver $astResolver,
private readonly NodePrinterInterface $nodePrinter,
private readonly PrivatesAccessor $privatesAccessor
private readonly PrivatesAccessor $privatesAccessor,
private readonly InlineCodeParser $inlineCodeParser
) {
}

Expand Down Expand Up @@ -142,14 +143,11 @@ public function createFromPhpMethodReflection(PhpMethodReflection $phpMethodRefl
return $anonymousFunction;
}

public function createAnonymousFunctionFromString(Expr $expr): ?Closure
public function createAnonymousFunctionFromExpr(Expr $expr): ?Closure
{
if (! $expr instanceof String_) {
// not supported yet
throw new ShouldNotHappenException();
}
$stringValue = $this->inlineCodeParser->stringify($expr);

$phpCode = '<?php ' . $expr->value . ';';
$phpCode = '<?php ' . $stringValue . ';';
$contentStmts = $this->simplePhpParser->parseString($phpCode);

$anonymousFunction = new Closure();
Expand Down Expand Up @@ -179,6 +177,15 @@ public function createAnonymousFunctionFromString(Expr $expr): ?Closure
$anonymousFunction->stmts[] = new Return_($stmt);
$anonymousFunction->params[] = new Param(new Variable('matches'));

$variables = $expr instanceof Variable
? []
: $this->betterNodeFinder->findInstanceOf($expr, Variable::class);

$anonymousFunction->uses = array_map(
fn (Variable $variable): ClosureUse => new ClosureUse($variable),
$variables
);

return $anonymousFunction;
}

Expand Down
13 changes: 12 additions & 1 deletion src/PhpParser/Parser/InlineCodeParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ final class InlineCodeParser
*/
private const ENDING_SEMI_COLON_REGEX = '#;(\s+)?$#';

/**
* @var string
* @see https://regex101.com/r/8fDjnR/1
*/
private const VARIABLE_IN_SINGLE_QUOTED_REGEX = '#\'(?<variable>\$.*)\'#U';

public function __construct(
private readonly NodePrinterInterface $nodePrinter,
private readonly NodeScopeAndMetadataDecorator $nodeScopeAndMetadataDecorator,
Expand Down Expand Up @@ -83,7 +89,12 @@ public function stringify(Expr $expr): string
}

if ($expr instanceof Concat) {
return $this->stringify($expr->left) . $this->stringify($expr->right);
$string = $this->stringify($expr->left) . $this->stringify($expr->right);
return Strings::replace(
$string,
self::VARIABLE_IN_SINGLE_QUOTED_REGEX,
fn (array $match) => $match['variable']
);
}

return $this->nodePrinter->print($expr);
Expand Down

0 comments on commit 6f164da

Please sign in to comment.