diff --git a/src/Maker/MakeController.php b/src/Maker/MakeController.php index 546a878b0..5a92c609c 100644 --- a/src/Maker/MakeController.php +++ b/src/Maker/MakeController.php @@ -60,6 +60,7 @@ public function configureCommand(Command $command, InputConfiguration $inputConf $command ->addArgument('controller-class', InputArgument::OPTIONAL, sprintf('Choose a name for your controller class (e.g. %sController)', Str::asClassName(Str::getRandomTerm()))) ->addOption('no-template', null, InputOption::VALUE_NONE, 'Use this option to disable template generation') + ->addOption('invokable', 'i', InputOption::VALUE_NONE, 'Use this option to create an invokable controller') ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeController.txt')) ; } @@ -73,6 +74,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen ); $withTemplate = $this->isTwigInstalled() && !$input->getOption('no-template'); + $isInvokable = (bool) $input->getOption('invokable'); $useStatements = new UseStatementGenerator([ AbstractController::class, @@ -80,7 +82,9 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen Route::class, ]); - $templateName = Str::asFilePath($controllerClassNameDetails->getRelativeNameWithoutSuffix()).'/index.html.twig'; + $templateName = Str::asFilePath($controllerClassNameDetails->getRelativeNameWithoutSuffix()) + .($isInvokable ? '.html.twig' : '/index.html.twig'); + $controllerPath = $generator->generateController( $controllerClassNameDetails->getFullName(), 'controller/Controller.tpl.php', @@ -88,6 +92,7 @@ public function generate(InputInterface $input, ConsoleStyle $io, Generator $gen 'use_statements' => $useStatements, 'route_path' => Str::asRoutePath($controllerClassNameDetails->getRelativeNameWithoutSuffix()), 'route_name' => Str::asRouteName($controllerClassNameDetails->getRelativeNameWithoutSuffix()), + 'method_name' => $isInvokable ? '__invoke' : 'index', 'with_template' => $withTemplate, 'template_name' => $templateName, ] diff --git a/src/Resources/skeleton/controller/Controller.tpl.php b/src/Resources/skeleton/controller/Controller.tpl.php index 62e1e60a5..8f509e699 100644 --- a/src/Resources/skeleton/controller/Controller.tpl.php +++ b/src/Resources/skeleton/controller/Controller.tpl.php @@ -7,7 +7,7 @@ class extends AbstractController { generateRouteForControllerMethod($route_path, $route_name); ?> - public function index(): ResponseJsonResponse + public function (): ResponseJsonResponse { diff --git a/tests/Maker/MakeControllerTest.php b/tests/Maker/MakeControllerTest.php index f177b161a..42da9050d 100644 --- a/tests/Maker/MakeControllerTest.php +++ b/tests/Maker/MakeControllerTest.php @@ -116,6 +116,33 @@ public function getTestDetails(): \Generator $this->assertStringContainsString('templates/foo/bar/cool/index.html.twig', $output); }), ]; + + yield 'it_generates_a_controller_with_invoke' => [$this->createMakerTest() + ->addExtraDependencies('twig') + ->run(function (MakerTestRunner $runner) { + $output = $runner->runMaker([ + // controller class name + 'FooInvokable', + ], '--invokable'); + + $this->assertStringContainsString('src/Controller/FooInvokableController.php', $output); + $this->assertStringContainsString('templates/foo_invokable.html.twig', $output); + $this->runControllerTest($runner, 'it_generates_an_invokable_controller.php'); + }), + ]; + + yield 'it_generates_a_controller_with_invoke_in_sub_namespace' => [$this->createMakerTest() + ->addExtraDependencies('twig') + ->run(function (MakerTestRunner $runner) { + $output = $runner->runMaker([ + // controller class name + 'Admin\\FooInvokable', + ], '--invokable'); + + $this->assertStringContainsString('src/Controller/Admin/FooInvokableController.php', $output); + $this->assertStringContainsString('templates/admin/foo_invokable.html.twig', $output); + }), + ]; } private function runControllerTest(MakerTestRunner $runner, string $filename): void diff --git a/tests/fixtures/make-controller/tests/it_generates_an_invokable_controller.php b/tests/fixtures/make-controller/tests/it_generates_an_invokable_controller.php new file mode 100644 index 000000000..ed26ac147 --- /dev/null +++ b/tests/fixtures/make-controller/tests/it_generates_an_invokable_controller.php @@ -0,0 +1,26 @@ +request('GET', '/foo/invokable'); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + } + + public function testControllerInvokability() + { + $kernel = self::bootKernel(); + $controller = $kernel->getContainer()->get('App\Controller\FooInvokableController'); + $this->assertIsCallable($controller); + + $response = $controller(); + $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); + } +}