diff --git a/Neos.Flow/Classes/Mvc/Controller/ActionToMethodDelegation.php b/Neos.Flow/Classes/Mvc/Controller/ActionToMethodDelegation.php new file mode 100644 index 0000000000..cfc326a9f0 --- /dev/null +++ b/Neos.Flow/Classes/Mvc/Controller/ActionToMethodDelegation.php @@ -0,0 +1,59 @@ +setDispatched(true); + $actionMethodName = $this->resolveActionMethodName($request); + return $this->$actionMethodName($request); + } + + /** + * Resolves and checks the current action method name + * + * @return string Method name of the current action + * @throws NoSuchActionException + */ + private function resolveActionMethodName(ActionRequest $request): string + { + $actionMethodName = $request->getControllerActionName() . 'Action'; + if (!is_callable([$this, $actionMethodName])) { + throw new NoSuchActionException(sprintf('An action "%s" does not exist in controller "%s".', $actionMethodName, get_class($this)), 1186669086); + } + + return $actionMethodName; + } +} diff --git a/Neos.Flow/Tests/Functional/Mvc/Fixtures/Controller/SimpleActionControllerTestController.php b/Neos.Flow/Tests/Functional/Mvc/Fixtures/Controller/SimpleActionControllerTestController.php new file mode 100644 index 0000000000..1904a393df --- /dev/null +++ b/Neos.Flow/Tests/Functional/Mvc/Fixtures/Controller/SimpleActionControllerTestController.php @@ -0,0 +1,48 @@ +setContent('index'); + + return $response; + } + + public function simpleReponseAction(ActionRequest $actionRequest): ActionResponse + { + $response = new ActionResponse(); + $response->setContent('Simple'); + + return $response; + } + + public function jsonResponseAction(ActionRequest $actionRequest): ActionResponse + { + $response = new ActionResponse(); + $response->setContent(json_encode(['foo' => 'bar', 'baz' => 123])); + $response->setContentType('application/json'); + + return $response; + } + + public function argumentsAction(ActionRequest $actionRequest): ActionResponse + { + $response = new ActionResponse(); + $response->setContent(strtolower($actionRequest->getArgument('testArgument'))); + if ($actionRequest->getFormat() === 'html') { + $response->setContentType('text/html'); + } + + return $response; + } +} diff --git a/Neos.Flow/Tests/Functional/Mvc/SimpleActionControllerTest.php b/Neos.Flow/Tests/Functional/Mvc/SimpleActionControllerTest.php new file mode 100644 index 0000000000..32e44cf2cc --- /dev/null +++ b/Neos.Flow/Tests/Functional/Mvc/SimpleActionControllerTest.php @@ -0,0 +1,88 @@ +registerRoute('test', 'test/mvc/simplecontrollertest(/{@action})', [ + '@package' => 'Neos.Flow', + '@subpackage' => 'Tests\Functional\Mvc\Fixtures', + '@controller' => 'SimpleActionControllerTest', + '@action' => 'index', + '@format' => 'html' + ]); + + $this->serverRequestFactory = $this->objectManager->get(ServerRequestFactoryInterface::class); + } + + /** + * Checks if a simple request is handled correctly. The route matching the + * specified URI defines a default action "index" which results in indexAction + * being called. + * + * @test + */ + public function defaultActionSpecifiedInRouteIsCalledAndResponseIsReturned() + { + $response = $this->browser->request('http://localhost/test/mvc/simplecontrollertest'); + self::assertEquals(200, $response->getStatusCode()); + self::assertEquals('index', $response->getBody()->getContents()); + } + + /** + * Checks if a simple request is handled correctly if another than the default + * action is specified. + * + * @test + */ + public function actionSpecifiedInActionRequestIsCalledAndResponseIsReturned() + { + $response = $this->browser->request('http://localhost/test/mvc/simplecontrollertest/simplereponse'); + self::assertEquals(200, $response->getStatusCode()); + self::assertEquals('Simple', $response->getBody()->getContents()); + } + + /** + * Checks if the content type and json content is correctly passed through + * + * @test + */ + public function responseContainsContentTypeAndContent() + { + $response = $this->browser->request('http://localhost/test/mvc/simplecontrollertest/jsonresponse'); + self::assertEquals(200, $response->getStatusCode()); + self::assertEquals(['application/json'], $response->getHeader('Content-Type')); + self::assertEquals(json_encode(['foo' => 'bar', 'baz' => 123]), $response->getBody()->getContents()); + } + + /** + * Checks if arguments and format are passed + * + * @test + */ + public function responseContainsArgumentContent() + { + $argument = '

Some markup

'; + $response = $this->browser->request('http://localhost/test/mvc/simplecontrollertest/arguments?testArgument=' . urlencode($argument)); + self::assertEquals(200, $response->getStatusCode()); + self::assertEquals(['text/html'], $response->getHeader('Content-Type')); + self::assertEquals(strtolower($argument), $response->getBody()->getContents()); + } +} diff --git a/Neos.Flow/Tests/Unit/Mvc/Controller/ActionToMethodDelegationTest.php b/Neos.Flow/Tests/Unit/Mvc/Controller/ActionToMethodDelegationTest.php new file mode 100644 index 0000000000..51313c3cd0 --- /dev/null +++ b/Neos.Flow/Tests/Unit/Mvc/Controller/ActionToMethodDelegationTest.php @@ -0,0 +1,73 @@ +createMock(ActionRequest::class); + $request->method('getControllerActionName')->willReturn($actionName); + + $this->expectException(NoSuchActionException::class); + + $testObject = new Fixtures\SimpleActionTestController(); + $testObject->processRequest($request); + } + + /** + * @return void + * @throws NoSuchActionException + * @throws \Neos\Flow\SignalSlot\Exception\InvalidSlotException + * @test + */ + public function responseOnlyContainsWhatActionSets() + { + $request = $this->createMock(ActionRequest::class); + $request->method('getControllerActionName')->willReturn('addTestContent'); + + $testObject = new Fixtures\SimpleActionTestController(); + $response = $testObject->processRequest($request); + self::assertInstanceOf(ActionResponse::class, $response); + self::assertEquals('Simple', $response->getContent()); + self::assertFalse($response->hasContentType()); + // default + self::assertEquals(200, $response->getStatusCode()); + } +} diff --git a/Neos.Flow/Tests/Unit/Mvc/Controller/Fixtures/SimpleActionTestController.php b/Neos.Flow/Tests/Unit/Mvc/Controller/Fixtures/SimpleActionTestController.php new file mode 100644 index 0000000000..c0dfdd5701 --- /dev/null +++ b/Neos.Flow/Tests/Unit/Mvc/Controller/Fixtures/SimpleActionTestController.php @@ -0,0 +1,19 @@ +setContent('Simple'); + return $response; + } +}