diff --git a/config/level/php/php72.yml b/config/level/php/php72.yml index 4edbae02fd5..580a42f4873 100644 --- a/config/level/php/php72.yml +++ b/config/level/php/php72.yml @@ -19,3 +19,4 @@ services: Rector\Php\Rector\FunctionLike\ReturnScalarTypehintRector: ~ Rector\Php\Rector\FuncCall\GetClassOnNullRector: ~ Rector\Php\Rector\FuncCall\IsObjectOnIncompleteClassRector: ~ + Rector\Php\Rector\FuncCall\ParseStrWithResultArgumentRector: ~ diff --git a/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php b/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php new file mode 100644 index 00000000000..8ab3a6aece7 --- /dev/null +++ b/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php @@ -0,0 +1,93 @@ +callableNodeTraverser = $callableNodeTraverser; + } + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition('Use $result argument in parse_str() function', [ + new CodeSample( + <<<'CODE_SAMPLE' +parse_str($this->query); +$data = get_defined_vars(); +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +parse_str($this->query, $result); +$data = $result; +CODE_SAMPLE + ), + ]); + } + + /** + * @return string[] + */ + public function getNodeTypes(): array + { + return [FuncCall::class]; + } + + /** + * @param FuncCall $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->isName($node, 'parse_str')) { + return null; + } + + if (isset($node->args[1])) { + return null; + } + + $resultVariable = new Variable('result'); + $node->args[1] = new Arg($resultVariable); + + /** @var Expression $expression */ + $expression = $node->getAttribute(Attribute::CURRENT_EXPRESSION); + // @todo maybe solve in generic way as attribute? + $nextExpression = $expression->getAttribute(Attribute::NEXT_NODE); + + $this->callableNodeTraverser->traverseNodesWithCallable([$nextExpression], function (Node $node) use ( + $resultVariable + ) { + if ($node instanceof FuncCall) { + if ($this->isName($node, 'get_defined_vars')) { + return $resultVariable; + } + } + + return null; + }); + + return $node; + } +} diff --git a/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/Fixture/fixture.php.inc b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..123497e6ee7 --- /dev/null +++ b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/Fixture/fixture.php.inc @@ -0,0 +1,31 @@ + +----- + diff --git a/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/ParseStrWithResultArgumentRectorTest.php b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/ParseStrWithResultArgumentRectorTest.php new file mode 100644 index 00000000000..edebbb9eff3 --- /dev/null +++ b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/ParseStrWithResultArgumentRectorTest.php @@ -0,0 +1,19 @@ +doTestFiles([__DIR__ . '/Fixture/fixture.php.inc']); + } + + protected function getRectorClass(): string + { + return ParseStrWithResultArgumentRector::class; + } +} diff --git a/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/config.yml b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/config.yml new file mode 100644 index 00000000000..d848b322e3b --- /dev/null +++ b/packages/Php/tests/Rector/FuncCall/ParseStrWithResultArgumentRector/config.yml @@ -0,0 +1,2 @@ +services: + Rector\Php\Rector\FuncCall\ParseStrWithResultArgumentRector: ~