diff --git a/typo3/sysext/core/Classes/Http/JsonResponse.php b/typo3/sysext/core/Classes/Http/JsonResponse.php index 1d63d1dfb6f11bca29f7206fe64fc79f85b964d2..fc397bf39d77c30be3e9b40154cf5c9b827f7476 100644 --- a/typo3/sysext/core/Classes/Http/JsonResponse.php +++ b/typo3/sysext/core/Classes/Http/JsonResponse.php @@ -20,7 +20,7 @@ namespace TYPO3\CMS\Core\Http; * * Highly inspired by ZF zend-diactoros * - * @internal Note that this is not public API yet. + * @internal Note that this is not public API, use PSR-17 interfaces instead */ class JsonResponse extends Response { @@ -32,7 +32,6 @@ class JsonResponse extends Response * </code> * * @var int - * @internal use {@see \TYPO3\CMS\Core\Http\ResponseFactory::JSON_FLAGS_RFC4627} instead */ const DEFAULT_JSON_FLAGS = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES; @@ -52,7 +51,6 @@ class JsonResponse extends Response * @param int $status Integer status code for the response; 200 by default. * @param array $headers Array of headers to use at initialization. * @param int $encodingOptions JSON encoding options to use. - * @internal use {@see \TYPO3\CMS\Core\Http\ResponseFactory::createJsonResponseFromData} instead */ public function __construct( $data = [], @@ -80,7 +78,6 @@ class JsonResponse extends Response * @param array $data * @param int $encodingOptions * @return $this - * @internal use {@see \TYPO3\CMS\Core\Http\ResponseFactory::createJsonResponseFromData} instead */ public function setPayload(array $data = [], $encodingOptions = self::DEFAULT_JSON_FLAGS): JsonResponse { diff --git a/typo3/sysext/core/Classes/Http/Response.php b/typo3/sysext/core/Classes/Http/Response.php index 84a41870ecd2e4a948d81684a2aed0cd1d8ce1f4..d3ebb69e83be6a4dcc46d55dc096202286abe3f8 100644 --- a/typo3/sysext/core/Classes/Http/Response.php +++ b/typo3/sysext/core/Classes/Http/Response.php @@ -23,6 +23,8 @@ use TYPO3\CMS\Core\Utility\MathUtility; * Default implementation for the ResponseInterface of the PSR-7 standard. * * Highly inspired by https://github.com/phly/http/ + * + * @internal Note that this is not public API, use PSR-17 interfaces instead */ class Response extends Message implements ResponseInterface { diff --git a/typo3/sysext/core/Classes/Http/ResponseFactory.php b/typo3/sysext/core/Classes/Http/ResponseFactory.php index 9f5179e161aee6e39726efb0d713ba50e7c1ca7c..f7766617a85f955cb7e6acfab265447cdebea901 100644 --- a/typo3/sysext/core/Classes/Http/ResponseFactory.php +++ b/typo3/sysext/core/Classes/Http/ResponseFactory.php @@ -17,22 +17,14 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Http; +use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; +/** + * @internal Note that this is not public API, use PSR-17 interfaces instead. + */ class ResponseFactory implements ResponseFactoryInterface { - /** - * Default flags for json_encode; value of: - * - * <code> - * JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES - * </code> - * - * @var int - */ - public const JSON_FLAGS_RFC4627 = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES; - /** * Create a new response. * @@ -44,53 +36,4 @@ class ResponseFactory implements ResponseFactoryInterface { return new Response(null, $code, [], $reasonPhrase); } - - public function createHtmlResponse(string $html): ResponseInterface - { - $response = $this->createResponse(); - $response->withAddedHeader('Content-Type', 'text/html; charset=utf-8'); - - $stream = new Stream('php://temp', 'wb+'); - $stream->write($html); - $stream->rewind(); - return $response->withBody($stream); - } - - public function createJsonResponse(string $json): ResponseInterface - { - $response = $this->createResponse(); - $response->withAddedHeader('Content-Type', 'application/json; charset=utf-8'); - - $stream = new Stream('php://temp', 'wb+'); - $stream->write($json); - $stream->rewind(); - return $response->withBody($stream); - } - - /** - * Create a JSON response with the given data. - * - * Default JSON encoding is performed with the following options, which - * produces RFC4627-compliant JSON, capable of embedding into HTML. - * - * - {@see JSON_HEX_TAG} - * - {@see JSON_HEX_APOS} - * - {@see JSON_HEX_AMP} - * - {@see JSON_HEX_QUOT} - * - {@see JSON_UNESCAPED_SLASHES} - * - * @param mixed $data - * @param int $encodingOptions - * @return ResponseInterface - * @throws \JsonException - */ - public function createJsonResponseFromData($data, int $encodingOptions = self::JSON_FLAGS_RFC4627): ResponseInterface - { - return $this->createJsonResponse((string)json_encode($data, $encodingOptions | JSON_THROW_ON_ERROR)); - } - - public function createRedirectResponse(UriInterface $uri, int $code = 303): ResponseInterface - { - return $this->createResponse($code)->withAddedHeader('location', (string)$uri); - } } diff --git a/typo3/sysext/core/Classes/Http/ResponseFactoryInterface.php b/typo3/sysext/core/Classes/Http/ResponseFactoryInterface.php deleted file mode 100644 index b29127263ab5241e339441aa537428aa0ed18247..0000000000000000000000000000000000000000 --- a/typo3/sysext/core/Classes/Http/ResponseFactoryInterface.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -namespace TYPO3\CMS\Core\Http; - -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UriInterface; - -interface ResponseFactoryInterface extends \Psr\Http\Message\ResponseFactoryInterface -{ - public function createHtmlResponse(string $html): ResponseInterface; - public function createJsonResponse(string $json): ResponseInterface; - public function createRedirectResponse(UriInterface $uri, int $code = 303): ResponseInterface; -} diff --git a/typo3/sysext/core/Configuration/Services.yaml b/typo3/sysext/core/Configuration/Services.yaml index 77ecacb4ac54d140e4511b7fdc5c104295735b77..dec0119453f76a92d4f43d6222fb0a63dbef5dc4 100644 --- a/typo3/sysext/core/Configuration/Services.yaml +++ b/typo3/sysext/core/Configuration/Services.yaml @@ -200,9 +200,6 @@ services: Psr\Http\Message\ResponseFactoryInterface: alias: TYPO3\CMS\Core\Http\ResponseFactory public: true - TYPO3\CMS\Core\Http\ResponseFactoryInterface: - alias: TYPO3\CMS\Core\Http\ResponseFactory - public: true Psr\Http\Message\ServerRequestFactoryInterface: alias: TYPO3\CMS\Core\Http\ServerRequestFactory public: true diff --git a/typo3/sysext/core/Documentation/Changelog/11.0/Deprecation-92784-ExtbaseControllerActionsMustReturnResponseInterface.rst b/typo3/sysext/core/Documentation/Changelog/11.0/Deprecation-92784-ExtbaseControllerActionsMustReturnResponseInterface.rst index f3eecaae76383edbb8a2d0bef355a1baf4d26260..49f383e208b1d1cef116cc9571502a7166b5f9ab 100644 --- a/typo3/sysext/core/Documentation/Changelog/11.0/Deprecation-92784-ExtbaseControllerActionsMustReturnResponseInterface.rst +++ b/typo3/sysext/core/Documentation/Changelog/11.0/Deprecation-92784-ExtbaseControllerActionsMustReturnResponseInterface.rst @@ -29,8 +29,9 @@ All installations that use Extbase controller actions which don't return an inst Migration ========= -Since the core follows not only PSR-7 (https://www.php-fig.org/psr/psr-7/) but also PSR-17 (https://www.php-fig.org/psr/psr-17/), -which defines how response factories should look like, the core provides a factory to create various different response types. +Since the core follows not only PSR-7 (https://www.php-fig.org/psr/psr-7/) +but also PSR-17 (https://www.php-fig.org/psr/psr-17/), +the PSR-17 response factory should be used. The response factory is available in all extbase controllers and can be used as a shorthand function to create responses for html and json, the two most used content types. The factory can also be used to create a blank response object whose content and headers can be set freely. @@ -43,7 +44,10 @@ Example: $items = $this->itemRepository->findAll(); $this->view->assign('items', $items); - return $this->responseFactory->createHtmlResponse($this->view->render()); + $response = $this->responseFactory->createResponse() + ->withAddedHeader('Content-Type', 'text/html; charset=utf-8'); + $response->getBody()->write($this->view->render()); + return $response; } This example only shows the most common use case. It causes html with a :html:`Content-Type: text/html` header and @@ -77,11 +81,13 @@ Example: $items = $this->itemRepository->findAll(); $this->view->assign('items', $items); - return $this->responseFactory - ->createHtmlResponse($this->view->render()) + $response = $this->responseFactory + ->createResponse() ->withHeader('Cache-Control', 'must-revalidate') - ->withStatus(200, 'Super ok!') - ; + ->withHeader('Content-Type', 'text/html; charset=utf-8') + ->withStatus(200, 'Super ok!'); + $response->getBody()->write($this->view->render()); + return $response; } .. tip:: diff --git a/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php b/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php index b0e7ab1f9861d844da2ed98560abf4db29923451..d23877d91466aeb499172a67f2dbde7052c75a3f 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php +++ b/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php @@ -16,10 +16,10 @@ namespace TYPO3\CMS\Extbase\Mvc\Controller; use Psr\EventDispatcher\EventDispatcherInterface; +use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\Response; -use TYPO3\CMS\Core\Http\ResponseFactoryInterface; use TYPO3\CMS\Core\Http\Stream; use TYPO3\CMS\Core\Messaging\AbstractMessage; use TYPO3\CMS\Core\Messaging\FlashMessage; @@ -1141,8 +1141,9 @@ abstract class ActionController implements ControllerInterface */ protected function htmlResponse(string $html = null): ResponseInterface { - return $this->responseFactory->createHtmlResponse( - $html ?? $this->view->render() - ); + $response = $this->responseFactory->createResponse() + ->withHeader('Content-Type', 'text/html; charset=utf-8'); + $response->getBody()->write($html ?? $this->view->render()); + return $response; } } diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php index 5e6caa9f100c8007e0ba9aa4028cffb9bbcbfca6..65a614d0f3e1448b79dfc41c676f29cd19cf3ee4 100644 --- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php +++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php @@ -77,7 +77,10 @@ class ContentController extends ActionController ]]); $this->view->assign('value', $value); - return $this->responseFactory->createJsonResponse($this->view->render()); + $response = $this->responseFactory->createResponse() + ->withAddedHeader('Content-Type', 'application/json; charset=utf-8'); + $response->getBody()->write($this->view->render()); + return $response; } /** diff --git a/typo3/sysext/extbase/Tests/Functional/Mvc/Controller/ControllerArgumentsMappingTest.php b/typo3/sysext/extbase/Tests/Functional/Mvc/Controller/ControllerArgumentsMappingTest.php index 420d9e16fcfd68681e88dc8b979ea3e2109c64ca..9991b99f6757165d13d5768badeb7a25bf90e617 100644 --- a/typo3/sysext/extbase/Tests/Functional/Mvc/Controller/ControllerArgumentsMappingTest.php +++ b/typo3/sysext/extbase/Tests/Functional/Mvc/Controller/ControllerArgumentsMappingTest.php @@ -115,6 +115,7 @@ class ControllerArgumentsMappingTest extends FunctionalTestCase $response = $this->controller->processRequest($this->request); + $response->getBody()->rewind(); self::assertEquals($expectedTitle, $response->getBody()->getContents()); } } diff --git a/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php b/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php index 27cb7b8a59be017e2e547e25c5e2536a44cf1621..0b4fea45a613a19607ca38d170e675b80d776a6a 100644 --- a/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php +++ b/typo3/sysext/extbase/Tests/Functional/Mvc/Validation/ActionControllerValidationTest.php @@ -113,6 +113,7 @@ class ActionControllerValidationTest extends FunctionalTestCase foreach ($titleErrors as $titleError) { self::assertContains($titleError->getCode(), $expectedErrorCodes); } + $response->getBody()->rewind(); self::assertEquals('testFormAction', $response->getBody()->getContents()); } @@ -178,6 +179,7 @@ class ActionControllerValidationTest extends FunctionalTestCase } } + $response->getBody()->rewind(); self::assertEquals('testFormAction', $response->getBody()->getContents()); }