diff --git a/src/Console/Command/LevelsCommand.php b/src/Console/Command/LevelsCommand.php new file mode 100644 index 00000000000..37909c183bf --- /dev/null +++ b/src/Console/Command/LevelsCommand.php @@ -0,0 +1,59 @@ +consoleStyle = $consoleStyle; + + parent::__construct(); + } + + protected function configure(): void + { + $this->setName(CommandNaming::classToName(self::class)); + $this->setDescription('List available levels.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $levels = $this->getAvailbleLevels(); + + $this->consoleStyle->title(sprintf('%d available levels:', count($levels))); + $this->consoleStyle->listing($levels); + + return 0; + } + + /** + * @return string[] + */ + private function getAvailbleLevels(): array + { + $finder = Finder::create()->files() + ->in(__DIR__ . '/../../config/level'); + + $levels = []; + foreach ($finder->getIterator() as $fileInfo) { + $levels[] = $fileInfo->getBasename('.' . $fileInfo->getExtension()); + } + + sort($levels); + + return array_unique($levels); + } +} diff --git a/src/Rector/Dynamic/FunctionToMethodCallRector.php b/src/Rector/Dynamic/FunctionToMethodCallRector.php new file mode 100644 index 00000000000..7f0a466eb86 --- /dev/null +++ b/src/Rector/Dynamic/FunctionToMethodCallRector.php @@ -0,0 +1,72 @@ +render('...') + */ +final class FunctionToMethodCallRector extends AbstractRector +{ + /** + * @var string[] + */ + private $functionToMethodCall = []; + + /** + * @var MethodCallNodeFactory + */ + private $methodCallNodeFactory; + + /** + * @param string[] $functionToMethodCall e.g. ["view" => ["this", "render"]] + */ + public function __construct(array $functionToMethodCall, MethodCallNodeFactory $methodCallNodeFactory) + { + $this->functionToMethodCall = $functionToMethodCall; + $this->methodCallNodeFactory = $methodCallNodeFactory; + } + + public function isCandidate(Node $node): bool + { + if (! $node instanceof FuncCall) { + return false; + } + + if (! $node->name instanceof Name) { + return false; + } + + $functionName = $node->name->toString(); + + return isset($this->functionToMethodCall[$functionName]); + } + + /** + * @param FuncCall $funcCallNode + */ + public function refactor(Node $funcCallNode): ?Node + { + $functionName = $funcCallNode->name->toString(); + + [$variableName, $methodName] = $this->functionToMethodCall[$functionName]; + + $methodCallNode = $this->methodCallNodeFactory->createWithVariableNameAndMethodName( + $variableName, + $methodName + ); + + $methodCallNode->args = $funcCallNode->args; + + return $methodCallNode; + } +} diff --git a/src/config/level/framework-migration/laravel-to-symfony.yml b/src/config/level/framework-migration/laravel-to-symfony.yml new file mode 100644 index 00000000000..5f358da6a70 --- /dev/null +++ b/src/config/level/framework-migration/laravel-to-symfony.yml @@ -0,0 +1,11 @@ +services: + Rector\Rector\Dynamic\ClassReplacerRector: + $oldToNewClasses: + 'Illuminate\Http\Response': 'Symfony\Component\HttpFoundation\Response' + 'App\Http\Controllers\Controller': 'Symfony\Bundle\FrameworkBundle\Controller\Controller' + + + # view('...') => $this->render('...') + Rector\Rector\Dynamic\FunctionToMethodCallRector: + $functionToMethodCall: + 'view': ['this', 'render'] diff --git a/tests/Rector/FrameworkMigration/LaravelToSymfony/Correct/correct.php.inc b/tests/Rector/FrameworkMigration/LaravelToSymfony/Correct/correct.php.inc new file mode 100644 index 00000000000..963b782f28d --- /dev/null +++ b/tests/Rector/FrameworkMigration/LaravelToSymfony/Correct/correct.php.inc @@ -0,0 +1,14 @@ +render('user.profile'); + } +} diff --git a/tests/Rector/FrameworkMigration/LaravelToSymfony/LaravelToSymfonyTest.php b/tests/Rector/FrameworkMigration/LaravelToSymfony/LaravelToSymfonyTest.php new file mode 100644 index 00000000000..bfeefc28cd7 --- /dev/null +++ b/tests/Rector/FrameworkMigration/LaravelToSymfony/LaravelToSymfonyTest.php @@ -0,0 +1,31 @@ +doTestFileMatchesExpectedContent($wrong, $fixed); + } + + /** + * @return string[][] + */ + public function provideWrongToFixedFiles(): array + { + return [ + [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc'], + ]; + } + + protected function provideConfig(): string + { + return __DIR__ . '/config.yml'; + } +} diff --git a/tests/Rector/FrameworkMigration/LaravelToSymfony/Wrong/wrong.php.inc b/tests/Rector/FrameworkMigration/LaravelToSymfony/Wrong/wrong.php.inc new file mode 100644 index 00000000000..808cb29f78c --- /dev/null +++ b/tests/Rector/FrameworkMigration/LaravelToSymfony/Wrong/wrong.php.inc @@ -0,0 +1,14 @@ + $this->render('...') + Rector\Rector\Dynamic\FunctionToMethodCallRector: + $functionToMethodCall: + 'view': ['this', 'render']