diff --git a/.gitignore b/.gitignore index fdc19e2..792e7c5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,8 @@ /app/config/parameters.yml /build/ /phpunit.xml -.php_cs* .php-cs-fixer* -!.php_cs.dist -!.php-cs-fixer.dist +!.php-cs-fixer.dist.* /var/* !/var/cache /var/cache/* diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 2a6f2c5..7f8e872 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -6,32 +6,32 @@ ->exclude('vendor') ->exclude('mock') ->exclude('DNC') - ->exclude('tests') ->in(__DIR__); $config = new PhpCsFixer\Config(); $config->setRiskyAllowed(true) - ->setRules( + ->setRules( // @see https://mlocati.github.io/php-cs-fixer-configurator/#version:3.2 [ - '@PSR2' => true, - '@Symfony' => true, - '@PhpCsFixer' => true, - '@PhpCsFixer:risky' => true, - '@PHPUnit75Migration:risky' => true, - '@PHP73Migration' => true, - '@PHP71Migration:risky' => true, - 'php_unit_dedicate_assert' => ['target' => '5.6'], - 'array_syntax' => ['syntax' => 'short'], - 'no_superfluous_phpdoc_tags' => true, - 'native_function_invocation' => false, - 'concat_space' => ['spacing' => 'one'], - 'phpdoc_types_order' => ['null_adjustment' => 'always_first', 'sort_algorithm' => 'alpha'], - 'single_line_comment_style' => [ + '@PSR2' => true, + '@Symfony' => true, + '@PhpCsFixer' => true, + '@PhpCsFixer:risky' => true, + '@PHPUnit75Migration:risky' => true, + '@PHP73Migration' => true, + '@PHP71Migration:risky' => true, + 'php_unit_dedicate_assert' => ['target' => '5.6'], + 'array_syntax' => ['syntax' => 'short'], + 'no_superfluous_phpdoc_tags' => true, + 'native_function_invocation' => false, + 'concat_space' => ['spacing' => 'one'], + 'phpdoc_types_order' => ['null_adjustment' => 'always_first', 'sort_algorithm' => 'alpha'], + 'single_line_comment_style' => [ 'comment_types' => ['hash'], ], - 'phpdoc_summary' => false, - 'cast_spaces' => ['space' => 'none'], - 'binary_operator_spaces' => ['default' => null, 'operators' => ['=' => 'align_single_space_minimal', '=>' => 'align_single_space_minimal']], + 'phpdoc_summary' => false, + 'cast_spaces' => ['space' => 'none'], + 'binary_operator_spaces' => ['default' => null, 'operators' => ['=' => 'align_single_space_minimal', '=>' => 'align_single_space_minimal']], + 'php_unit_test_class_requires_covers' => false, ] ) ->setFinder($finder); diff --git a/CHANGELOG.md b/CHANGELOG.md index 1073cff..b928525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,22 +8,39 @@ Intended to follow [«Keep a Changelog»](https://keepachangelog.com/en/) ## [Unreleased] (meant as staging area) ### Added - -- Changelog -- composer-normalize -- Updated dev dependencies - -### Fixed -- DX: makefile, dockerfile & xdebug +- … ### TODO -- ResponseFactory -- ResponseTranscriptor + - Cookies: Write to response - Cookies: Read from request - Cookies: write and overwrite to request - Refactor `Request::withUri` to be closer to PSR-7 - Refactor `BodyStreamHook::addBodyFromResponse` using WeakMap for a PHP >=8.0 (or with [polyfill](https://github.com/BenMorel/weakmap-polyfill)) +- Remove `mock/guzzle-psr7` when `php-http/psr7-integration-tests` supports `GuzzleHttp\Psr7 ^2.0` +- Allow configurable StreamFactory instead of hardcoded used + +---- + +## [1.4.0] - 2021-10-19 + +### Added + +- PSR-17 `ResponseFactory` to enable PSR-15 +- `ResponseTranscriptor` to transcribe PSR-7 responses directly to Symfony1 one's +- Dependency to PSR-17 i.e. `psr/http-factory` +- PSR-17 GuzzleStreamFactory and a DecoyHttpFactory to support `symfony/psr-http-message-bridge` +- Started a changelog +- composer-normalize + +### Changed + +- Updated dev dependencies +- Renamed "Utillity" to `brnc\Symfony1\Message\Utility`, technically [BREAKING] yet was never supposed to be used in user land + +### Fixed + +- DX: makefile, dockerfile & xdebug ---- No changelog before October 2021, the following was only casually reconstructed diff --git a/README.md b/README.md index 8c06239..e79daab 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Partial PSR-7 Adapters for Symfony 1.5 To enable the use of future-proof PSR-15 middlewares via partial PSR-7 adapters. ## Quickstart + ```php // not fully PSR-7 compliant lazy adapters $serverRequestAdapter = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); @@ -11,18 +12,17 @@ $responseAdapter = \brnc\Symfony1\Message\Adapter\Response::fromSfWebRespon ``` ## ServerRequest + Please mind the following PSR-7 violation which is enabled by default: + ### No immutability by default + as this is just an adapter for `\sfWebRequest` which cannot easily be replaced with another instance. -This adapter – by default – also returns the very same instance when calling `with*()` methods. -For the same reason calls to methods which cannot act on and alter the underlying `\sfWebRequest` +This adapter – by default – also returns the very same instance when calling `with*()` methods. For the same reason calls to methods which cannot act on and alter the underlying `\sfWebRequest` will throw an `\brnc\Symfony1\Message\Exception\LogicException`. -This default behaviour can be changed by creating the `Request` using -the `Request::OPTION_IMMUTABLE_VIOLATION` option set to `false`. -The `Request`-adapter will then always return new instances when `with*()`-methods are called and won't throw exceptions on calls which cannot transparently act on the `\sfWebRequest`- object. - +This default behaviour can be changed by creating the `Request` using the `Request::OPTION_IMMUTABLE_VIOLATION` option set to `false`. The `Request`-adapter will then always return new instances when `with*()`-methods are called and won't throw exceptions on calls which cannot transparently act on the `\sfWebRequest`- object. ```php use brnc\Symfony1\Message\Adapter\Request; @@ -39,8 +39,8 @@ $serverRequestAdapter = Request::fromSfWebRequest( ``` ## Response -Please mind the default to mutability! +Please mind the default to mutability! ```php use brnc\Symfony1\Message\Adapter\Response; @@ -68,3 +68,64 @@ $newInstance->preSend(); $sfWebResponse->send(); ``` + +## Pass it down to a PSR-15 sub-stack + +You may use the `ResponseFactory` implementing `\Psr\Http\Message\ResponseFactoryInterface` in order to "spawn" responses within your PSR-15 sub-stack. + +```php +$request = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); +$responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse); +// (dependency) inject the ResponseFactory to your dispatcher, middlewares, and handlers +$entryPoint = new YourPSR15Dispatcher($responseFactory); +// Dispatch your sub-stack via PSR-15 +$response = $entryPoint->handler($response); +// As $response will be linked to $sfWebResponse you don't need to do anything +// if you are in the context of a Symfony1 action. Only call $response->getSfWebResponse() in dire need! +``` + +## Manually transcribe a PSR-7 Response to Symfony1 + +Assume you couldn't use other means, and you're confronted with an arbitrary PSR-7 response you can use the `ResponseTranscriptor` to copy the data from your PSR-7 response to your `\sfWebResponse`. + +Currently the `ResponseTranscriptor` doesn't support cookies, and will fail fast and hard if it encounters some. You are free to implement your own Cookie-Handler implementing `CookieTranscriptorInterface` and pass it as an optional constructor argument + +```php +// Given arbitrary PSR-7 response… +$psr7response = $psr7responseFactory(); +// …use the ResponseTranscriptor in order to– +$transcriptor = new \brnc\Symfony1\Message\Transcriptor\ResponseTranscriptor(); +// copy the response's contents. +// The returned object will be the same as in the argument! +$sfWebResponse = $transcriptor->transcribe($psr7response, $sfWebResponse); +``` + +## Pass it down to http-foundation i.e. present-day Symfony + +Combine this PSR7-Symfony1 Adapter and `symfony/psr-http-message-bridge` to connect your Symfony1 stack via PSR-7 to `symfony/http-foundation` objects and leverage using embedded (present-day) Symfony components. + +```php +// Use this chain to create a http-foundation request from a Symfony1's \sfWebRequest +$psrRequest = \brnc\Symfony1\Message\Adapter\Request::fromSfWebRequest($sfWebRequest); +$httpFoundationFactory = \Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory(); +$symfonyRequest = $httpFoundationFactory->createRequest($psrRequest); + +// Handle the request with some present day Symfony component +$symfonyResponse = $httpKernel->handle($symfonyRequest); + +// Possibly ResponseFactory is best created in the Symfony1 context +$responseFactory = new \brnc\Symfony1\Message\Factory\ResponseFactory($sfWebResponse); + +// Obtain other PSR17 factories, +// while only ResponseFactory & StreamFactory will be used (as of today) +$streamFactory = \brnc\Symfony1\Message\Factory\GuzzleStreamFactory(); +$decoyFactory = \brnc\Symfony1\Message\Factory\DecoyHttpFactory(); +// Construct the PsrHttpFactory from symfony/psr-http-message-bridge and translate… +$psrHttpFactory = Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory( + $decoyFactory, $streamFactory, $decoyFactory, $responseFactory +); +$psrResponse = $psrHttpFactory->createResponse($symfonyResponse); +// As $psrResponse will be linked to $sfWebResponse as it was created through the +// ResponseFactory you don't need to do anything if you exit via an Symfony1 action. +// Only call $psrResponse->getSfWebResponse() in dire need! +``` diff --git a/composer.json b/composer.json index 87efd0b..439814d 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "require": { "php": "^7.4 || ^8.0", "guzzlehttp/psr7": "^1.7 || ^2.0", + "psr/http-factory": "^1.0", "webmozart/assert": "^1.6" }, "require-dev": { @@ -62,7 +63,7 @@ "coverage": "XDEBUG_MODE=coverage phpunit --coverage-html coverage --coverage-text --colors=auto && chown -R 1000:1000 coverage", "quality": [ "composer normalize --dry-run", - "psalm --find-unused-psalm-suppress", + "psalm --find-unused-psalm-suppress --show-info=true", "phpstan analyse", "phpmd src,tests ansi naming # cleancode,codesize,controversial,design,unusedcode", "@style-check", diff --git a/composer.lock b/composer.lock index c1d44b7..d88ea99 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "09c45036751d4578f4144341e565a21b", + "content-hash": "735d29975654013a8a9a2e9ea4d47bf6", "packages": [ { "name": "guzzlehttp/psr7", @@ -81,6 +81,61 @@ }, "time": "2021-04-26T09:17:50+00:00" }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", diff --git a/mock/guzzle-psr7/function_include.php b/mock/guzzle-psr7/function_include.php index 4b2b638..90f5e93 100644 --- a/mock/guzzle-psr7/function_include.php +++ b/mock/guzzle-psr7/function_include.php @@ -2,13 +2,16 @@ declare(strict_types=1); -/* +/** * TODO remove this and the whole directory once php-http/psr7-integration-tests * supports GuzzleHttp\Psr7 ^2 * * Sadly needed as php-http/psr7-integration-tests @ 1.1.1 * relies on the deprecated GuzzleHttp\Psr7::stream_for instead of Utils::streamFor + * + * @internal */ +// @codeCoverageIgnoreStart if (!function_exists('GuzzleHttp\Psr7\stream_for')) { require __DIR__ . '/stream_for.php'; } diff --git a/mock/guzzle-psr7/stream_for.php b/mock/guzzle-psr7/stream_for.php index cc440e2..a454b5a 100644 --- a/mock/guzzle-psr7/stream_for.php +++ b/mock/guzzle-psr7/stream_for.php @@ -2,12 +2,15 @@ namespace GuzzleHttp\Psr7; -/* +/** * TODO remove this and the whole directory once php-http/psr7-integration-tests * supports GuzzleHttp\Psr7 ^2 * * Sadly needed as php-http/psr7-integration-tests @ 1.1.1 * relies on the deprecated GuzzleHttp\Psr7::stream_for instead of Utils::streamFor + * + * @internal + * @codeCoverageIgnore */ function stream_for($resource = '', array $options = []) { diff --git a/mock/sfEvent.php b/mock/sfEvent.php index 36ad5f1..48fdffd 100644 --- a/mock/sfEvent.php +++ b/mock/sfEvent.php @@ -2,6 +2,8 @@ /** * Minimal mock of symfony's sfEvent to enable standalone testing + * + * @internal */ class sfEvent { diff --git a/mock/sfEventDispatcher.php b/mock/sfEventDispatcher.php index 037cf0c..43a83b7 100644 --- a/mock/sfEventDispatcher.php +++ b/mock/sfEventDispatcher.php @@ -2,6 +2,8 @@ /** * Minimal mock of symfony's sfEventDispatcher to enable standalone testing + * + * @internal */ class sfEventDispatcher { diff --git a/mock/sfWebRequest.php b/mock/sfWebRequest.php index ec31407..03457a1 100644 --- a/mock/sfWebRequest.php +++ b/mock/sfWebRequest.php @@ -6,6 +6,8 @@ /** * Minimal mock of symfony's sfWebRequest to enable standalone testing + * + * @internal */ class sfWebRequest { diff --git a/mock/sfWebResponse.php b/mock/sfWebResponse.php index 376a36f..489e133 100644 --- a/mock/sfWebResponse.php +++ b/mock/sfWebResponse.php @@ -6,6 +6,8 @@ /** * Minimal mock of symfony's sfWebResponse to enable standalone testing + * + * @internal */ class sfWebResponse { diff --git a/phpstan.neon b/phpstan.neon index ee98e3c..d581c5a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,6 +3,9 @@ parameters: paths: - src - tests + excludePaths: + analyse: + - src/Factory/DecoyHttpFactory.php ignoreErrors: - message: "#^Unsafe usage of new static\\(\\)\\.$#" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 237de43..6590452 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,14 +1,14 @@ - - - ./src/Adapter - ./mock - - - - - ./tests - - + + + ./src + ./mock + + + + + ./tests + + diff --git a/src/Adapter/CommonAdapterTrait.php b/src/Adapter/CommonAdapterTrait.php index e09caa9..e4d133e 100644 --- a/src/Adapter/CommonAdapterTrait.php +++ b/src/Adapter/CommonAdapterTrait.php @@ -6,12 +6,14 @@ namespace brnc\Symfony1\Message\Adapter; -use brnc\Symfony1\Message\Utillity\Assert; +use brnc\Symfony1\Message\Utility\Assert; use GuzzleHttp\Psr7\Utils; use Psr\Http\Message\StreamInterface; /** * collects common behaviour of request and response + * + * @internal */ trait CommonAdapterTrait { diff --git a/src/Adapter/Request.php b/src/Adapter/Request.php index 4150909..7e10c9b 100644 --- a/src/Adapter/Request.php +++ b/src/Adapter/Request.php @@ -6,7 +6,7 @@ use brnc\Symfony1\Message\Exception\InvalidTypeException; use brnc\Symfony1\Message\Exception\LogicException; -use brnc\Symfony1\Message\Utillity\Assert; +use brnc\Symfony1\Message\Utility\Assert; use GuzzleHttp\Psr7\CachingStream; use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\Psr7\UploadedFile; @@ -305,6 +305,8 @@ public function getMethod(): string /** * @param string $method * + * @psalm-param mixed $method + * * @throws InvalidTypeException * * @return static diff --git a/src/Adapter/Response.php b/src/Adapter/Response.php index 4322f4c..22a8273 100644 --- a/src/Adapter/Response.php +++ b/src/Adapter/Response.php @@ -5,7 +5,7 @@ namespace brnc\Symfony1\Message\Adapter; -use brnc\Symfony1\Message\Utillity\Assert; +use brnc\Symfony1\Message\Utility\Assert; use GuzzleHttp\Psr7\Utils; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -179,12 +179,15 @@ public function getStatusCode(): int } /** + * N.b. Changes are directly applied to the adapted sfWebResponse, + * thus the returned object will return same value as the "immutable" original instance + * * @param int $code * @param string $reasonPhrase * - * @return static + * @psalm-param mixed $code * - * @deprecated Changes are directly applied to the adapted sfWebResponse, thus the returned object will return same value as the "immutable" original instance + * @return static */ public function withStatus($code, $reasonPhrase = ''): self { diff --git a/src/Exception/LogicException.php b/src/Exception/LogicException.php index 695636d..30f24d1 100644 --- a/src/Exception/LogicException.php +++ b/src/Exception/LogicException.php @@ -10,4 +10,15 @@ public static function throwAdaptingSymfony(): void { throw new self('This property cannot be altered as the underlying Symfony object does not support this.'); } + + /** @codeCoverageIgnore */ + public static function throwPsr17Decoy(): void + { + throw new self('This PSR-17 HTTP Factory is just a decoy, and is NOT implementing anything!'); + } + + public static function throwCookieTranscriptionUnsupported(): void + { + throw new self('Cookie transcription is not implemented! Rely on CookieTranscriptorInterface to build it yourself!'); + } } diff --git a/src/Factory/DecoyHttpFactory.php b/src/Factory/DecoyHttpFactory.php new file mode 100644 index 0000000..afe9d3f --- /dev/null +++ b/src/Factory/DecoyHttpFactory.php @@ -0,0 +1,80 @@ +createResponse() + * + * @codeCoverageIgnore + */ +class DecoyHttpFactory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface +{ + /** @psalm-suppress InvalidReturnType */ + public function createRequest(string $method, $uri): RequestInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createStream(string $content = ''): StreamInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createStreamFromResource($resource): StreamInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createUploadedFile(StreamInterface $stream, int $size = null, int $error = UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null): UploadedFileInterface + { + LogicException::throwPsr17Decoy(); + } + + /** @psalm-suppress InvalidReturnType */ + public function createUri(string $uri = ''): UriInterface + { + LogicException::throwPsr17Decoy(); + } +} diff --git a/src/Factory/GuzzleStreamFactory.php b/src/Factory/GuzzleStreamFactory.php new file mode 100644 index 0000000..a19e577 --- /dev/null +++ b/src/Factory/GuzzleStreamFactory.php @@ -0,0 +1,37 @@ +createResponse() + * + * While you can just use (new HttpFoundationFactory())->createRequest($psrRequest) to obtain a http-foundation request + * from this PSR-7-Symfony1 Request adapter as well as any other PSR-7 server-request. + */ +class GuzzleStreamFactory implements StreamFactoryInterface +{ + public function createStream(string $content = ''): StreamInterface + { + return Utils::streamFor($content); + } + + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface + { + return $this->createStreamFromResource(Utils::tryFopen($filename, $mode)); + } + + public function createStreamFromResource($resource): StreamInterface + { + return Utils::streamFor($resource); + } +} diff --git a/src/Factory/ResponseFactory.php b/src/Factory/ResponseFactory.php new file mode 100644 index 0000000..c92e4b1 --- /dev/null +++ b/src/Factory/ResponseFactory.php @@ -0,0 +1,40 @@ +sfWebResponse = $sfWebResponse; + } + + public static function createFactoryFromWebResponse(\sfWebResponse $sfWebResponse): self + { + return new self($sfWebResponse); + } + + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + $response = Response::fromSfWebResponse($this->sfWebResponse); + + return $response->withStatus($code, $reasonPhrase); + } +} diff --git a/src/Transcriptor/Response/CookieTranscriptorInterface.php b/src/Transcriptor/Response/CookieTranscriptorInterface.php new file mode 100644 index 0000000..371d5c7 --- /dev/null +++ b/src/Transcriptor/Response/CookieTranscriptorInterface.php @@ -0,0 +1,12 @@ +getHeader('Set-Cookie'); + if (!empty($setCookies)) { + LogicException::throwCookieTranscriptionUnsupported(); + } + } +} diff --git a/src/Transcriptor/Response/OptionsTranscriptor.php b/src/Transcriptor/Response/OptionsTranscriptor.php new file mode 100644 index 0000000..6864dcc --- /dev/null +++ b/src/Transcriptor/Response/OptionsTranscriptor.php @@ -0,0 +1,19 @@ + $options */ + public function transcribeOptions(\sfWebResponse $sfWebResponse, array $options): void + { + $options = array_merge($sfWebResponse->getOptions(), $options); + $reflexiveWebResponse = new \ReflectionObject($sfWebResponse); + $reflexOptions = $reflexiveWebResponse->getProperty('options'); + $reflexOptions->setAccessible(true); + $reflexOptions->setValue($sfWebResponse, $options); + $reflexOptions->setAccessible(false); + } +} diff --git a/src/Transcriptor/Response/OptionsTranscriptorInterface.php b/src/Transcriptor/Response/OptionsTranscriptorInterface.php new file mode 100644 index 0000000..8af189b --- /dev/null +++ b/src/Transcriptor/Response/OptionsTranscriptorInterface.php @@ -0,0 +1,17 @@ + $options */ + public function transcribeOptions(\sfWebResponse $sfWebResponse, array $options): void; +} diff --git a/src/Transcriptor/ResponseTranscriptor.php b/src/Transcriptor/ResponseTranscriptor.php new file mode 100644 index 0000000..832d0d9 --- /dev/null +++ b/src/Transcriptor/ResponseTranscriptor.php @@ -0,0 +1,61 @@ +optionsTranscriptor = $optionsTranscriptor ?? new OptionsTranscriptor(); + $this->cookieTranscriptor = $cookieTranscriptor ?? new NoCookieTranscriptor(); + } + + public function transcribe(ResponseInterface $psrResponse, \sfWebResponse $sfWebResponse): \sfWebResponse + { + $sfWebResponse->setStatusCode($psrResponse->getStatusCode(), $psrResponse->getReasonPhrase()); + $this->transcribeHeaders($psrResponse, $sfWebResponse); + $this->cookieTranscriptor->transcribeCookies($psrResponse, $sfWebResponse); + $this->transcribeProtocol($psrResponse, $sfWebResponse); + $this->transcribeBody($psrResponse, $sfWebResponse); + + return $sfWebResponse; + } + + // DOES NOT remove headers set in SF response when not set or unset in PSR-7 response + private function transcribeHeaders(ResponseInterface $psrResponse, \sfWebResponse $sfWebResponse): void + { + /** @var string $header */ + foreach (array_keys($psrResponse->getHeaders()) as $header) { + if ('set-cookie' !== strtolower($header)) { + $sfWebResponse->setHttpHeader($header, $psrResponse->getHeaderLine($header), true); + } + } + } + + private function transcribeProtocol(ResponseInterface $psrResponse, \sfWebResponse $sfWebResponse): void + { + // transcribe protocol and possibly also other options though there should be no strong need: just use a Content-Type header + $this->optionsTranscriptor->transcribeOptions($sfWebResponse, [ + 'http_protocol' => 'HTTP/' . $psrResponse->getProtocolVersion(), + ]); + } + + private function transcribeBody(ResponseInterface $psrResponse, \sfWebResponse $sfWebResponse): void + { + $body = $psrResponse->getBody(); + $sfWebResponse->setContent((string)$body); + // prevent further writes, that wouldn't make it into the transcription + $body->close(); + } +} diff --git a/src/Utillity/Assert.php b/src/Utility/Assert.php similarity index 91% rename from src/Utillity/Assert.php rename to src/Utility/Assert.php index b455ca3..0f2a1bd 100644 --- a/src/Utillity/Assert.php +++ b/src/Utility/Assert.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace brnc\Symfony1\Message\Utillity; +namespace brnc\Symfony1\Message\Utility; use brnc\Symfony1\Message\Exception\InvalidTypeException; use Webmozart\Assert\Assert as WebmozartAssert; diff --git a/tests/Adapter/RequestBasicTest.php b/tests/Adapter/RequestBasicTest.php index 839f111..f7cf028 100644 --- a/tests/Adapter/RequestBasicTest.php +++ b/tests/Adapter/RequestBasicTest.php @@ -1,11 +1,16 @@ createRequest(); - $this->assertSame('', $request->getProtocolVersion()); - $this->assertSame([], $request->getServerParams()); + static::assertSame('', $request->getProtocolVersion()); + static::assertSame([], $request->getServerParams()); $request = $request->withProtocolVersion('1.1'); - $this->assertSame('1.1', $request->getProtocolVersion()); - $this->assertSame(['SERVER_PROTOCOL' => 'HTTP/1.1'], $request->getServerParams()); + static::assertSame('1.1', $request->getProtocolVersion()); + static::assertSame(['SERVER_PROTOCOL' => 'HTTP/1.1'], $request->getServerParams()); } /** @@ -26,8 +31,8 @@ public function testProtocolVersion(): void public function testPresetProtocolVersion(): void { $request = $this->createRequest('GET', ['SERVER_PROTOCOL' => 'HTTP/1.1']); - $this->assertSame('1.1', $request->getProtocolVersion()); - $this->assertSame(['SERVER_PROTOCOL' => 'HTTP/1.1'], $request->getServerParams()); + static::assertSame('1.1', $request->getProtocolVersion()); + static::assertSame(['SERVER_PROTOCOL' => 'HTTP/1.1'], $request->getServerParams()); } /** @@ -37,38 +42,33 @@ public function testMethod(): void { $mock = $this->createSymfonyMock(); $request = Request::fromSfWebRequest($mock); - $this->assertSame('GET', $request->getMethod()); + static::assertSame('GET', $request->getMethod()); $request = $request->withMethod('PuRgE'); - $this->assertSame('PuRgE', $request->getMethod()); - $this->assertSame('PURGE', $mock->getMethod()); + static::assertSame('PuRgE', $request->getMethod()); + static::assertSame('PURGE', $mock->getMethod()); $request = $request->withMethod('GET'); - $this->assertSame('GET', $request->getMethod()); - $this->assertSame('GET', $mock->getMethod()); + static::assertSame('GET', $request->getMethod()); + static::assertSame('GET', $mock->getMethod()); } /** * @dataProvider withHeaderProvider * - * @param string $name - * @param string $value - * @param array $expectedHeaders - * @param array $expectedServerParams - * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testHeader(string $name, string $value, array $expectedHeaders, array $expectedServerParams): void { $request = $this->createRequest(); - $this->assertFalse($request->hasHeader($name)); - $this->assertSame([], $request->getHeader($name)); - $this->assertSame([], $request->getServerParams()); + static::assertFalse($request->hasHeader($name)); + static::assertSame([], $request->getHeader($name)); + static::assertSame([], $request->getServerParams()); $request = $request->withHeader($name, 'FIRST VALUE'); $request = $request->withHeader($name, $value); - $this->assertSame(true, $request->hasHeader($name)); - $this->assertSame([$value], $request->getHeader($name)); - $this->assertSame($value, $request->getHeaderLine($name)); - $this->assertSame($expectedHeaders, $request->getHeaders()); - $this->assertSame($expectedServerParams, $request->getServerParams()); + static::assertTrue($request->hasHeader($name)); + static::assertSame([$value], $request->getHeader($name)); + static::assertSame($value, $request->getHeaderLine($name)); + static::assertSame($expectedHeaders, $request->getHeaders()); + static::assertSame($expectedServerParams, $request->getServerParams()); } public function withHeaderProvider(): array @@ -77,7 +77,7 @@ public function withHeaderProvider(): array [ 'X-Foo', 'bar', - ['X-Foo' => ['bar']], + ['X-Foo' => ['bar']], ['HTTP_X_FOO' => 'bar'], ], [ @@ -90,8 +90,7 @@ public function withHeaderProvider(): array 'content-md5', 'deadbeef', [ - 'content-md5' => - ['deadbeef'], + 'content-md5' => ['deadbeef'], ], ['CONTENT_MD5' => 'deadbeef'], ], @@ -99,8 +98,7 @@ public function withHeaderProvider(): array 'CONTENT-type', 'text/plain', [ - 'CONTENT-type' => - ['text/plain'], + 'CONTENT-type' => ['text/plain'], ], ['CONTENT_TYPE' => 'text/plain'], ], @@ -113,17 +111,17 @@ public function withHeaderProvider(): array public function testWithAddedHeader(): void { $request = $this->createRequest(); - $this->assertFalse($request->hasHeader('X-Foo')); - $this->assertSame([], $request->getHeader('X-Foo')); - $this->assertSame([], $request->getServerParams()); + static::assertFalse($request->hasHeader('X-Foo')); + static::assertSame([], $request->getHeader('X-Foo')); + static::assertSame([], $request->getServerParams()); $request = $request->withAddedHeader('X-Foo', 'bar'); - $this->assertTrue($request->hasHeader('X-Foo')); + static::assertTrue($request->hasHeader('X-Foo')); $request = $request->withAddedHeader('X-Foo', 'baz'); - $this->assertTrue($request->hasHeader('X-Foo')); - $this->assertSame(['bar', 'baz'], $request->getHeader('X-Foo')); - $this->assertSame('bar,baz', $request->getHeaderLine('X-Foo')); - $this->assertSame(['X-Foo' => ['bar', 'baz']], $request->getHeaders()); - $this->assertSame(['HTTP_X_FOO' => 'bar,baz'], $request->getServerParams()); + static::assertTrue($request->hasHeader('X-Foo')); + static::assertSame(['bar', 'baz'], $request->getHeader('X-Foo')); + static::assertSame('bar,baz', $request->getHeaderLine('X-Foo')); + static::assertSame(['X-Foo' => ['bar', 'baz']], $request->getHeaders()); + static::assertSame(['HTTP_X_FOO' => 'bar,baz'], $request->getServerParams()); } /** @@ -132,17 +130,17 @@ public function testWithAddedHeader(): void public function testWithArrayAddedHeader(): void { $request = $this->createRequest(); - $this->assertFalse($request->hasHeader('X-Foo')); - $this->assertSame([], $request->getHeader('X-Foo')); - $this->assertSame([], $request->getServerParams()); + static::assertFalse($request->hasHeader('X-Foo')); + static::assertSame([], $request->getHeader('X-Foo')); + static::assertSame([], $request->getServerParams()); $request = $request->withAddedHeader('X-Foo', 'foo'); - $this->assertSame(true, $request->hasHeader('X-Foo')); + static::assertTrue($request->hasHeader('X-Foo')); $request = $request->withAddedHeader('X-Foo', ['bar', 'baz']); - $this->assertTrue($request->hasHeader('X-Foo')); - $this->assertSame(['foo', 'bar', 'baz'], $request->getHeader('X-Foo')); - $this->assertSame('foo,bar,baz', $request->getHeaderLine('X-Foo')); - $this->assertSame(['X-Foo' => ['foo', 'bar', 'baz']], $request->getHeaders()); - $this->assertSame(['HTTP_X_FOO' => 'foo,bar,baz'], $request->getServerParams()); + static::assertTrue($request->hasHeader('X-Foo')); + static::assertSame(['foo', 'bar', 'baz'], $request->getHeader('X-Foo')); + static::assertSame('foo,bar,baz', $request->getHeaderLine('X-Foo')); + static::assertSame(['X-Foo' => ['foo', 'bar', 'baz']], $request->getHeaders()); + static::assertSame(['HTTP_X_FOO' => 'foo,bar,baz'], $request->getServerParams()); } /** @@ -151,15 +149,15 @@ public function testWithArrayAddedHeader(): void public function testWithoutHeader(): void { $request = $this->createRequest('GET', ['HTTP_X_FOO' => 'bar, baz']); - $this->assertSame(true, $request->hasHeader('X-Foo')); - $this->assertSame(['bar', 'baz'], $request->getHeader('X-Foo')); - $this->assertSame('bar, baz', $request->getHeaderLine('X-Foo')); - $this->assertSame(['x-foo' => ['bar', 'baz']], $request->getHeaders()); - $this->assertSame(['HTTP_X_FOO' => 'bar, baz'], $request->getServerParams()); + static::assertTrue($request->hasHeader('X-Foo')); + static::assertSame(['bar', 'baz'], $request->getHeader('X-Foo')); + static::assertSame('bar, baz', $request->getHeaderLine('X-Foo')); + static::assertSame(['x-foo' => ['bar', 'baz']], $request->getHeaders()); + static::assertSame(['HTTP_X_FOO' => 'bar, baz'], $request->getServerParams()); $request = $request->withoutHeader('x-FoO'); - $this->assertFalse($request->hasHeader('X-Foo')); - $this->assertSame([], $request->getHeader('X-Foo')); - $this->assertSame([], $request->getServerParams()); + static::assertFalse($request->hasHeader('X-Foo')); + static::assertSame([], $request->getHeader('X-Foo')); + static::assertSame([], $request->getServerParams()); } private function createRequest( diff --git a/tests/Adapter/RequestReadingTest.php b/tests/Adapter/RequestReadingTest.php index 692f088..60326ed 100644 --- a/tests/Adapter/RequestReadingTest.php +++ b/tests/Adapter/RequestReadingTest.php @@ -1,4 +1,6 @@ prepare($request['method'], $request['server']); $readingRequestMock = Request::fromSfWebRequest($sfWebRequest); - $this->assertSame($hasHeader, $readingRequestMock->hasHeader($headerName)); + static::assertSame($hasHeader, $readingRequestMock->hasHeader($headerName)); } /** - * @param array $request * @param string $headerName * @param bool $hasHeader * @param string $getHeader @@ -40,6 +43,7 @@ public function testHasHeader(array $request, $headerName, $hasHeader, $getHeade * @param array $expectedHeaders * * @dataProvider provideHeaderTestData + * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testGetHeader(array $request, $headerName, $hasHeader, $getHeader, $getHeaderLine, $expectedHeaders): void @@ -47,11 +51,10 @@ public function testGetHeader(array $request, $headerName, $hasHeader, $getHeade $sfWebRequest = new \sfWebRequest(); $sfWebRequest->prepare($request['method'], $request['server']); $readingRequestMock = Request::fromSfWebRequest($sfWebRequest); - $this->assertSame($getHeader, $readingRequestMock->getHeader($headerName)); + static::assertSame($getHeader, $readingRequestMock->getHeader($headerName)); } /** - * @param array $request * @param string $headerName * @param bool $hasHeader * @param string $getHeader @@ -59,6 +62,7 @@ public function testGetHeader(array $request, $headerName, $hasHeader, $getHeade * @param array $expectedHeaders * * @dataProvider provideHeaderTestData + * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testGetHeaderLine( @@ -72,11 +76,10 @@ public function testGetHeaderLine( $sfWebRequest = new \sfWebRequest(); $sfWebRequest->prepare($request['method'], $request['server']); $readingRequestMock = Request::fromSfWebRequest($sfWebRequest); - $this->assertSame($getHeaderLine, $readingRequestMock->getHeaderLine($headerName)); + static::assertSame($getHeaderLine, $readingRequestMock->getHeaderLine($headerName)); } /** - * @param array $request * @param string $headerName * @param bool $hasHeader * @param string $getHeader @@ -84,6 +87,7 @@ public function testGetHeaderLine( * @param array $expectedHeaders * * @dataProvider provideHeaderTestData + * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testGetHeaders( @@ -97,14 +101,14 @@ public function testGetHeaders( $sfWebRequest = new \sfWebRequest(); $sfWebRequest->prepare($request['method'], $request['server']); $readingRequestMock = Request::fromSfWebRequest($sfWebRequest); - $this->assertSame($expectedHeaders, $readingRequestMock->getHeaders()); + static::assertSame($expectedHeaders, $readingRequestMock->getHeaders()); } public function provideHeaderTestData(): array { return [ - 'happy case' => [ - 'request' => [ + 'happy case' => [ + 'request' => [ 'method' => '', 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/1.0', @@ -119,8 +123,8 @@ public function provideHeaderTestData(): array 'x-test' => ['foo', 'bar'], ], ], - 'Content-Type set' => [ - 'request' => [ + 'Content-Type set' => [ + 'request' => [ 'method' => '', 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/1.0', @@ -137,8 +141,8 @@ public function provideHeaderTestData(): array 'x-another-header' => ['was set'], ], ], - 'Content-Type not set' => [ - 'request' => [ + 'Content-Type not set' => [ + 'request' => [ 'method' => '', 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/1.0', @@ -155,8 +159,8 @@ public function provideHeaderTestData(): array 'x-another-header' => ['was set'], ], ], - 'Content-Type Quirk I' => [ - 'request' => [ + 'Content-Type Quirk I' => [ + 'request' => [ 'method' => '', 'server' => [ 'HTTP_CONTENT_TYPE' => 'BOGUS (is overridden by following)', @@ -172,7 +176,7 @@ public function provideHeaderTestData(): array ], ], 'Content-Type Quirk II' => [ - 'request' => [ + 'request' => [ 'method' => '', 'server' => [ 'CONTENT_TYPE' => 'multipart/form-data; boundary=foobar', @@ -191,10 +195,10 @@ public function provideHeaderTestData(): array } /** - * @param array $request - * @param mixed $expectedVersion + * @phpstan-param mixed $expectedVersion * * @dataProvider provideProtocolVersionData + * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testGetProtocolVersion(array $request, $expectedVersion): void @@ -202,57 +206,52 @@ public function testGetProtocolVersion(array $request, $expectedVersion): void $sfWebRequest = new \sfWebRequest(); $sfWebRequest->prepare($request['method'], $request['server']); $readingRequestMock = Request::fromSfWebRequest($sfWebRequest); - $this->assertSame($expectedVersion, $readingRequestMock->getProtocolVersion()); + static::assertSame($expectedVersion, $readingRequestMock->getProtocolVersion()); } public function provideProtocolVersionData(): array { return [ - 'happy case' => [ - 'request' => [ + 'happy case' => [ + 'request' => [ 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/1.0', ], 'method' => '', - ], 'expected version' => '1.0', ], - 'empty string → due to symfony\'s own fallback to \'\'' => [ - 'request' => [ + 'empty string → due to symfony\'s own fallback to \'\'' => [ + 'request' => [ 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/', ], 'method' => '', - ], 'expected version' => '', ], - 'null → due to symfony\'s own fallback to \'\'' => [ - 'request' => [ + 'null → due to symfony\'s own fallback to \'\'' => [ + 'request' => [ 'server' => [], 'method' => '', - ], 'expected version' => '', ], - 'Not number dot number I → empty string: due to symfony\'s own check to \d\.\d' => [ - 'request' => [ + 'Not number dot number I → empty string: due to symfony\'s own check to \d\.\d' => [ + 'request' => [ 'method' => 'x.9', 'server' => [ 'SERVER_PROTOCOL' => 'HTTP/foo bar baz', ], - ], 'expected version' => '', ], 'Not number dot number II → empty string: due to symfony\'s own check to \d\.\d' => [ - 'request' => [ + 'request' => [ 'method' => '5.y', 'server' => [ 'SERVER_PROTOCOL' => 'foo bar baz', ], - ], 'expected version' => '', ], diff --git a/tests/Adapter/ResponseBasicTest.php b/tests/Adapter/ResponseBasicTest.php index 10d1030..6daa8ba 100644 --- a/tests/Adapter/ResponseBasicTest.php +++ b/tests/Adapter/ResponseBasicTest.php @@ -1,11 +1,16 @@ createResponse(); - $this->assertSame('', $response->getProtocolVersion()); - $this->assertSame([], $symfony->getOptions()); + static::assertSame('', $response->getProtocolVersion()); + static::assertSame([], $symfony->getOptions()); $response = $response->withProtocolVersion('1.1'); - $this->assertSame('1.1', $response->getProtocolVersion()); - $this->assertSame(['http_protocol' => 'HTTP/1.1'], $symfony->getOptions()); + static::assertSame('1.1', $response->getProtocolVersion()); + static::assertSame(['http_protocol' => 'HTTP/1.1'], $symfony->getOptions()); } /** @@ -35,10 +40,10 @@ public function testPresetProtocolVersion(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(200, null, [], [], false, ['http_protocol' => 'HTTP/1.0']); - $this->assertSame('1.0', $response->getProtocolVersion()); + static::assertSame('1.0', $response->getProtocolVersion()); $response = $response->withProtocolVersion('1.1'); - $this->assertSame('1.1', $response->getProtocolVersion()); - $this->assertSame(['http_protocol' => 'HTTP/1.1'], $symfony->getOptions()); + static::assertSame('1.1', $response->getProtocolVersion()); + static::assertSame(['http_protocol' => 'HTTP/1.1'], $symfony->getOptions()); } /** @@ -51,22 +56,22 @@ public function testStatus(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(204); - $this->assertSame(204, $response->getStatusCode()); - $this->assertSame('No reason phrase given', $response->getReasonPhrase()); - $this->assertSame(204, $symfony->getStatusCode()); - $this->assertSame('No reason phrase given', $symfony->getStatusText()); + static::assertSame(204, $response->getStatusCode()); + static::assertSame('No reason phrase given', $response->getReasonPhrase()); + static::assertSame(204, $symfony->getStatusCode()); + static::assertSame('No reason phrase given', $symfony->getStatusText()); $response = $response->withStatus(200); - $this->assertSame(200, $response->getStatusCode()); - $this->assertSame('OK', $response->getReasonPhrase()); - $this->assertSame(200, $symfony->getStatusCode()); - $this->assertSame('OK', $symfony->getStatusText()); + static::assertSame(200, $response->getStatusCode()); + static::assertSame('OK', $response->getReasonPhrase()); + static::assertSame(200, $symfony->getStatusCode()); + static::assertSame('OK', $symfony->getStatusText()); $response = $response->withStatus(400, '*** Bad Request ***'); - $this->assertSame(400, $response->getStatusCode()); - $this->assertSame('*** Bad Request ***', $response->getReasonPhrase()); - $this->assertSame(400, $symfony->getStatusCode()); - $this->assertSame('*** Bad Request ***', $symfony->getStatusText()); + static::assertSame(400, $response->getStatusCode()); + static::assertSame('*** Bad Request ***', $response->getReasonPhrase()); + static::assertSame(400, $symfony->getStatusCode()); + static::assertSame('*** Bad Request ***', $symfony->getStatusText()); } /** @@ -79,21 +84,16 @@ public function testDefaultReasonPhrase(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(204); - $response = $response->withStatus(308); - $this->assertSame(308, $response->getStatusCode()); - $this->assertSame('Permanent Redirect', $response->getReasonPhrase()); - $this->assertSame(308, $symfony->getStatusCode()); - $this->assertSame('Permanent Redirect', $symfony->getStatusText()); + $response = $response->withStatus(308); + static::assertSame(308, $response->getStatusCode()); + static::assertSame('Permanent Redirect', $response->getReasonPhrase()); + static::assertSame(308, $symfony->getStatusCode()); + static::assertSame('Permanent Redirect', $symfony->getStatusText()); } /** * @dataProvider withHeaderProvider * - * @param string $name - * @param string $value - * @param array $expectedHeaders - * @param array $expectedHttpHeaders - * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testHeader(string $name, string $value, array $expectedHeaders, array $expectedHttpHeaders): void @@ -103,16 +103,16 @@ public function testHeader(string $name, string $value, array $expectedHeaders, * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(); - $this->assertFalse($response->hasHeader($name)); - $this->assertSame([], $response->getHeader($name)); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader($name)); + static::assertSame([], $response->getHeader($name)); + static::assertSame([], $symfony->getHttpHeaders()); $response = $response->withHeader($name, 'FIRST VALUE'); $response = $response->withHeader($name, $value); - $this->assertTrue($response->hasHeader($name)); - $this->assertSame([$value], $response->getHeader($name)); - $this->assertSame($value, $response->getHeaderLine($name)); - $this->assertSame($expectedHeaders, $response->getHeaders()); - $this->assertSame($expectedHttpHeaders, $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader($name)); + static::assertSame([$value], $response->getHeader($name)); + static::assertSame($value, $response->getHeaderLine($name)); + static::assertSame($expectedHeaders, $response->getHeaders()); + static::assertSame($expectedHttpHeaders, $symfony->getHttpHeaders()); } public function withHeaderProvider(): array @@ -128,8 +128,7 @@ public function withHeaderProvider(): array 'CONTENT-type', 'text/plain', [ - 'CONTENT-type' => - ['text/plain'], + 'CONTENT-type' => ['text/plain'], ], ['Content-Type' => 'text/plain'], ], @@ -146,17 +145,17 @@ public function testwithAddedHeader(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(); - $this->assertFalse($response->hasHeader('X-Foo')); - $this->assertSame([], $response->getHeader('X-Foo')); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader('X-Foo')); + static::assertSame([], $response->getHeader('X-Foo')); + static::assertSame([], $symfony->getHttpHeaders()); $response = $response->withAddedHeader('X-Foo', 'bar'); - $this->assertTrue($response->hasHeader('X-Foo')); + static::assertTrue($response->hasHeader('X-Foo')); $response = $response->withAddedHeader('X-Foo', 'baz'); - $this->assertTrue($response->hasHeader('X-Foo')); - $this->assertSame(['bar', 'baz'], $response->getHeader('X-Foo')); - $this->assertSame('bar,baz', $response->getHeaderLine('X-Foo')); - $this->assertSame(['X-Foo' => ['bar', 'baz']], $response->getHeaders()); - $this->assertSame(['X-Foo' => 'bar,baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-Foo')); + static::assertSame(['bar', 'baz'], $response->getHeader('X-Foo')); + static::assertSame('bar,baz', $response->getHeaderLine('X-Foo')); + static::assertSame(['X-Foo' => ['bar', 'baz']], $response->getHeaders()); + static::assertSame(['X-Foo' => 'bar,baz'], $symfony->getHttpHeaders()); } /** @@ -169,17 +168,17 @@ public function testwithArrayAddedHeader(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(); - $this->assertFalse($response->hasHeader('X-Foo')); - $this->assertSame([], $response->getHeader('X-Foo')); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader('X-Foo')); + static::assertSame([], $response->getHeader('X-Foo')); + static::assertSame([], $symfony->getHttpHeaders()); $response = $response->withAddedHeader('X-Foo', 'foo'); - $this->assertTrue($response->hasHeader('X-Foo')); + static::assertTrue($response->hasHeader('X-Foo')); $response = $response->withAddedHeader('X-Foo', ['bar', 'baz']); - $this->assertTrue($response->hasHeader('X-Foo')); - $this->assertSame(['foo', 'bar', 'baz'], $response->getHeader('X-Foo')); - $this->assertSame('foo,bar,baz', $response->getHeaderLine('X-Foo')); - $this->assertSame(['X-Foo' => ['foo', 'bar', 'baz']], $response->getHeaders()); - $this->assertSame(['X-Foo' => 'foo,bar,baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-Foo')); + static::assertSame(['foo', 'bar', 'baz'], $response->getHeader('X-Foo')); + static::assertSame('foo,bar,baz', $response->getHeaderLine('X-Foo')); + static::assertSame(['X-Foo' => ['foo', 'bar', 'baz']], $response->getHeaders()); + static::assertSame(['X-Foo' => 'foo,bar,baz'], $symfony->getHttpHeaders()); } /** @@ -193,19 +192,20 @@ public function testwithoutHeader(): void */ [$response, $symfony] = $this->createResponse(204, 'No Content', ['X-Foo' => 'bar, baz']); - $this->assertTrue($response->hasHeader('X-FOO')); - $this->assertSame(['bar', 'baz'], $response->getHeader('X-Foo')); - $this->assertSame('bar, baz', $response->getHeaderLine('X-Foo')); - $this->assertSame(['X-Foo' => ['bar', 'baz']], $response->getHeaders()); - $this->assertSame(['X-Foo' => 'bar, baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-FOO')); + static::assertSame(['bar', 'baz'], $response->getHeader('X-Foo')); + static::assertSame('bar, baz', $response->getHeaderLine('X-Foo')); + static::assertSame(['X-Foo' => ['bar', 'baz']], $response->getHeaders()); + static::assertSame(['X-Foo' => 'bar, baz'], $symfony->getHttpHeaders()); $response = $response->withoutHeader('x-FoO'); - $this->assertFalse($response->hasHeader('X-Foo')); - $this->assertSame([], $response->getHeader('X-Foo')); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader('X-Foo')); + static::assertSame([], $response->getHeader('X-Foo')); + static::assertSame([], $symfony->getHttpHeaders()); } /** * @dataProvider withStatusNoContentProvider + * * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException */ public function testWithStatusNoContent(array $adapterOptions, int $initialCode, bool $initialHeaderOnly, int $setCode, bool $expectedHeadersOnly): void @@ -216,21 +216,21 @@ public function testWithStatusNoContent(array $adapterOptions, int $initialCode, */ [$response, $symfony] = $this->createResponse($initialCode, null, [], [], $initialHeaderOnly, [], $adapterOptions); - $this->assertSame($initialCode, $symfony->getStatusCode()); - $this->assertSame($initialCode, $response->getStatusCode()); - $this->assertSame($initialHeaderOnly, $symfony->isHeaderOnly()); + static::assertSame($initialCode, $symfony->getStatusCode()); + static::assertSame($initialCode, $response->getStatusCode()); + static::assertSame($initialHeaderOnly, $symfony->isHeaderOnly()); $newResponse = $response->withStatus($setCode); - $this->assertSame($setCode, $symfony->getStatusCode()); - $this->assertSame($setCode, $newResponse->getStatusCode()); - $this->assertSame($expectedHeadersOnly, $symfony->isHeaderOnly()); + static::assertSame($setCode, $symfony->getStatusCode()); + static::assertSame($setCode, $newResponse->getStatusCode()); + static::assertSame($expectedHeadersOnly, $symfony->isHeaderOnly()); } public function withStatusNoContentProvider(): array { return [ - '200 → 204 - default: set headersOnly true' => [ + '200 → 204 - default: set headersOnly true' => [ 'factory options' => [], 'initial status' => 200, 'initial headers only' => false, @@ -244,42 +244,42 @@ public function withStatusNoContentProvider(): array 'set to status' => 200, 'expect headers only' => false, ], - '200 → 201 - default : no change' => [ + '200 → 201 - default : no change' => [ 'factory options' => [], 'initial status' => 200, 'initial headers only' => false, 'set to status' => 201, 'expect headers only' => false, ], - '200 → 204 - no automagic' => [ + '200 → 204 - no automagic' => [ 'factory options' => [Response::OPTION_SEND_BODY_ON_204 => true], 'initial status' => 200, 'initial headers only' => false, 'set to status' => 204, 'expect headers only' => false, ], - '200 with setHeadersOnly(true) → 204: no change' => [ + '200 with setHeadersOnly(true) → 204: no change' => [ 'factory options' => [], 'initial status' => 200, 'initial headers only' => true, 'set to status' => 204, 'expect headers only' => true, ], - '204 with setHeadersOnly(false) → 200: no change' => [ + '204 with setHeadersOnly(false) → 200: no change' => [ 'factory options' => [], 'initial status' => 204, 'initial headers only' => false, 'set to status' => 200, 'expect headers only' => false, ], - '204 with setHeadersOnly(true) → 204: no change' => [ + '204 with setHeadersOnly(true) → 204: no change' => [ 'factory options' => [], 'initial status' => 204, 'initial headers only' => true, 'set to status' => 204, 'expect headers only' => true, ], - '204 with setHeadersOnly(false) → 204: no change' => [ + '204 with setHeadersOnly(false) → 204: no change' => [ 'factory options' => [], 'initial status' => 204, 'initial headers only' => false, @@ -290,15 +290,7 @@ public function withStatusNoContentProvider(): array } /** - * @param int $code - * @param string|null $reasonPhrase - * @param string[] $headers - * @param array $cookies - * @param bool $headerOnly - * @param array $sfOptions - * @param array $adapterOptions - * - * @return array + * @param string[] $headers */ private function createResponse( int $code = 200, diff --git a/tests/Adapter/ResponseBodyTest.php b/tests/Adapter/ResponseBodyTest.php index af48c9f..2e9b0d4 100644 --- a/tests/Adapter/ResponseBodyTest.php +++ b/tests/Adapter/ResponseBodyTest.php @@ -5,25 +5,27 @@ namespace brnc\Tests\Symfony1\Message\Adapter; use brnc\Symfony1\Message\Adapter\Response; -use PHPUnit\Framework\TestCase; use GuzzleHttp\Psr7\Utils; +use PHPUnit\Framework\TestCase; -class ResponseBodyTest extends TestCase +/** + * @internal + */ +final class ResponseBodyTest extends TestCase { - public function testWithBodyImmutable(): void { $response = $this->createResponse(false); $newStream = Utils::streamFor('Hello'); $new = $response->withBody($newStream); - $this->assertNotSame(spl_object_hash($response), spl_object_hash($new)); + static::assertNotSame(spl_object_hash($response), spl_object_hash($new)); } public function testWithBodyImmutableGetBody(): void { $response = $this->createResponse(false); - $this->assertSame('', $response->getBody()->getContents()); + static::assertSame('', $response->getBody()->getContents()); } public function testWithBodyMutable(): void @@ -32,21 +34,21 @@ public function testWithBodyMutable(): void $newStream = Utils::streamFor('Hello'); $new = $response->withBody($newStream); - $this->assertSame(spl_object_hash($response), spl_object_hash($new), 'ONLY QUIRK!'); + static::assertSame(spl_object_hash($response), spl_object_hash($new), 'ONLY QUIRK!'); } public function testWithBodyReadback(): void { $response = $this->createResponse(false); - $this->assertSame('', (string)$response->getBody()); - $this->assertSame('', $response->getSfWebResponse()->sendContent()); + static::assertSame('', (string)$response->getBody()); + static::assertSame('', $response->getSfWebResponse()->sendContent()); $newStream = Utils::streamFor('Hello'); $new = $response->withBody($newStream); - $this->assertSame('Hello', (string)$new->getBody()); - $this->assertSame('', (string)$response->getBody(), 'Original instance must not change.'); - $this->assertSame('Hello', $response->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); + static::assertSame('Hello', (string)$new->getBody()); + static::assertSame('', (string)$response->getBody(), 'Original instance must not change.'); + static::assertSame('Hello', $response->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); } public function testStreamWriting(): void @@ -55,19 +57,19 @@ public function testStreamWriting(): void $initialStream = Utils::streamFor('FOOBAR'); $initial = $original->withBody($initialStream); - $this->assertSame('FOOBAR', (string)$initial->getBody()); - $this->assertSame('FOOBAR', $initial->getSfWebResponse()->sendContent()); + static::assertSame('FOOBAR', (string)$initial->getBody()); + static::assertSame('FOOBAR', $initial->getSfWebResponse()->sendContent()); $newStream = Utils::streamFor('Hello'); $new = $initial->withBody($newStream); - $this->assertSame('Hello', (string)$new->getBody()); - $this->assertSame('Hello', $new->getSfWebResponse()->sendContent()); + static::assertSame('Hello', (string)$new->getBody()); + static::assertSame('Hello', $new->getSfWebResponse()->sendContent()); $newStream->write(' world!'); - $this->assertSame('Hello world!', (string)$new->getBody()); - $this->assertSame('Hello world!', $new->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); + static::assertSame('Hello world!', (string)$new->getBody()); + static::assertSame('Hello world!', $new->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); } public function testMultipleStreamWriting(): void @@ -77,19 +79,19 @@ public function testMultipleStreamWriting(): void $responseOne = $original->withBody($streamOne); $streamOne->write('bar'); - $this->assertSame('foobar', (string)$responseOne->getBody()); - $this->assertSame('foobar', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); + static::assertSame('foobar', (string)$responseOne->getBody()); + static::assertSame('foobar', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); $streamTwo = Utils::streamFor('Hello'); $responseTwo = $responseOne->withBody($streamTwo); $streamTwo->write(' world!'); $streamOne->write('baz'); - $this->assertSame('foobarbaz', (string)$responseOne->getBody()); - $this->assertSame('Hello world!', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); + static::assertSame('foobarbaz', (string)$responseOne->getBody()); + static::assertSame('Hello world!', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); - $this->assertSame('Hello world!', (string)$responseTwo->getBody()); - $this->assertSame('Hello world!', $responseTwo->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); + static::assertSame('Hello world!', (string)$responseTwo->getBody()); + static::assertSame('Hello world!', $responseTwo->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last withBody wins!'); } public function testDeleteStream(): void @@ -100,8 +102,8 @@ public function testDeleteStream(): void $streamOne->write('bar'); $streamOne->close(); - $this->assertSame('foo', (string)$responseOne->getBody(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); - $this->assertSame('foo', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); + static::assertSame('foo', (string)$responseOne->getBody(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); + static::assertSame('foo', $responseOne->getSfWebResponse()->sendContent(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); } public function testDeleteSecondStream(): void @@ -116,11 +118,11 @@ public function testDeleteSecondStream(): void $streamTwo->write(' world!'); $streamTwo->close(); - $this->assertSame('foobar', $responseOne->getSfWebResponse()->sendContent(), 'Fall back to earlier stream, if the later one got closed.'); - $this->assertSame('foobar', (string)$responseOne->getBody()); + static::assertSame('foobar', $responseOne->getSfWebResponse()->sendContent(), 'Fall back to earlier stream, if the later one got closed.'); + static::assertSame('foobar', (string)$responseOne->getBody()); - $this->assertSame('foobar', $responseTwo->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last readable withBody() stream wins!'); - $this->assertSame('Hello', (string)$responseTwo->getBody(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); + static::assertSame('foobar', $responseTwo->getSfWebResponse()->sendContent(), 'ONLY QUIRK! → last readable withBody() stream wins!'); + static::assertSame('Hello', (string)$responseTwo->getBody(), 'ONLY QUIRK! Preserves content of last withBody(), even when stream was closed.'); } public function testDistinguishedStream(): void @@ -136,10 +138,10 @@ public function testDistinguishedStream(): void $responseOne->preSend(); - $this->assertSame('foobarbaz', (string)$responseOne->getBody()); - $this->assertSame('foobarbaz', $responseOne->getSfWebResponse()->sendContent(), 'Distinguished body wins.'); - $this->assertSame('Hello world!', (string)$responseTwo->getBody(), 'Non-distinguished stream remains unchanged.'); - $this->assertSame('foobarbaz', $responseTwo->getSfWebResponse()->sendContent(), 'Distinguished body wins.'); + static::assertSame('foobarbaz', (string)$responseOne->getBody()); + static::assertSame('foobarbaz', $responseOne->getSfWebResponse()->sendContent(), 'Distinguished body wins.'); + static::assertSame('Hello world!', (string)$responseTwo->getBody(), 'Non-distinguished stream remains unchanged.'); + static::assertSame('foobarbaz', $responseTwo->getSfWebResponse()->sendContent(), 'Distinguished body wins.'); } private function createResponse( diff --git a/tests/Adapter/ServerRequestBasicTest.php b/tests/Adapter/ServerRequestBasicTest.php index d71e3a7..12eb81e 100644 --- a/tests/Adapter/ServerRequestBasicTest.php +++ b/tests/Adapter/ServerRequestBasicTest.php @@ -1,5 +1,7 @@ prepare('GET'); $request = Request::fromSfWebRequest($symfonyRequestMock, []); - $this->assertSame($symfonyRequestMock, $request->getSfWebRequest()); - $this->assertSame(spl_object_hash($symfonyRequestMock), spl_object_hash($request->getSfWebRequest())); + static::assertSame($symfonyRequestMock, $request->getSfWebRequest()); + static::assertSame(spl_object_hash($symfonyRequestMock), spl_object_hash($request->getSfWebRequest())); } /** @@ -31,7 +35,7 @@ public function testGetCookieParams(): void $cookies = ['cookie_1' => 'asdf', 'cookie_2' => 'qwerty']; $_COOKIE = $cookies; $request = $this->createRequest(); - $this->assertSame($cookies, $request->getCookieParams(), 'Rather a quirk: returns $_COOKIE'); + static::assertSame($cookies, $request->getCookieParams(), 'Rather a quirk: returns $_COOKIE'); $_COOKIE = $superCookies; } @@ -43,7 +47,7 @@ public function testGetQueryParams(): void $query = ['q' => 'foo+bar', 'test' => 'true']; $request = $this->createRequest('GET', [], $query); - $this->assertSame($query, $request->getQueryParams()); + static::assertSame($query, $request->getQueryParams()); } /** @@ -54,7 +58,7 @@ public function testGetParsedBody(): void $post = ['user' => 'foo', 'pass' => 'bar']; $request = $this->createRequest('POST', [], [], $post); - $this->assertSame($post, $request->getParsedBody()); + static::assertSame($post, $request->getParsedBody()); } /** @@ -63,13 +67,13 @@ public function testGetParsedBody(): void public function testWithAttribute(): void { $request = $this->createRequest(); - $this->assertSame([], $request->getAttributes()); + static::assertSame([], $request->getAttributes()); - $attribute = (object)['name' => 'foo', 'id' => 42, 'bar' => 'baz',]; + $attribute = (object)['name' => 'foo', 'id' => 42, 'bar' => 'baz']; $request = $request->withAttribute('Foo', $attribute); - $this->assertSame($attribute, $request->getAttribute('Foo')); - $this->assertSame(['Foo' => $attribute], $request->getAttributes()); + static::assertSame($attribute, $request->getAttribute('Foo')); + static::assertSame(['Foo' => $attribute], $request->getAttributes()); } /** @@ -78,15 +82,15 @@ public function testWithAttribute(): void public function testWithoutAttribute(): void { $request = $this->createRequest(); - $attribute = (object)['name' => 'foo', 'id' => 42, 'bar' => 'baz',]; + $attribute = (object)['name' => 'foo', 'id' => 42, 'bar' => 'baz']; $request = $request->withAttribute('Foo', $attribute); $request = $request->withAttribute('Bar', 'remains!'); - $this->assertSame(['Foo' => $attribute, 'Bar' => 'remains!'], $request->getAttributes()); + static::assertSame(['Foo' => $attribute, 'Bar' => 'remains!'], $request->getAttributes()); $request = $request->withoutAttribute('Foo'); - $this->assertNull($request->getAttribute('Foo')); - $this->assertSame(['Bar' => 'remains!'], $request->getAttributes()); + static::assertNull($request->getAttribute('Foo')); + static::assertSame(['Bar' => 'remains!'], $request->getAttributes()); } /** @@ -97,22 +101,11 @@ public function testGetAttribute(): void $request = $this->createRequest(); $request = $request->withAttribute('Foo', 'bar'); - $this->assertNull($request->getAttribute('Baz')); - $this->assertSame('bar', $request->getAttribute('Foo')); - $this->assertSame('baz', $request->getAttribute('Baz', 'baz')); + static::assertNull($request->getAttribute('Baz')); + static::assertSame('bar', $request->getAttribute('Foo')); + static::assertSame('baz', $request->getAttribute('Baz', 'baz')); } - /** - * @param string $method - * @param array $server - * @param array $get - * @param array $post - * @param array $cookie - * @param array $requestParameters - * @param array $options - * - * @return Request - */ private function createRequest( string $method = '', array $server = [], diff --git a/tests/Adapter/ServerRequestBodyTest.php b/tests/Adapter/ServerRequestBodyTest.php index 0a33d6e..c4253b0 100644 --- a/tests/Adapter/ServerRequestBodyTest.php +++ b/tests/Adapter/ServerRequestBodyTest.php @@ -1,38 +1,43 @@ createRequest('POST')->getBody(); - $this->assertInstanceOf(StreamInterface::class, $body); - $this->assertSame('', $body->getContents(), 'Expected empty stream.'); - $this->assertSame(true, $body->isReadable(), 'Default getBody() should be readable.'); - $this->assertSame(true, $body->isWritable(), 'Default getBody() is writable as a quirk.'); + static::assertInstanceOf(StreamInterface::class, $body); + static::assertSame('', $body->getContents(), 'Expected empty stream.'); + static::assertTrue($body->isReadable(), 'Default getBody() should be readable.'); + static::assertTrue($body->isWritable(), 'Default getBody() is writable as a quirk.'); } public function testStaticConstructionGetBodyHasContent(): void { $body = $this->createRequest('POST', [], 'dummy content')->getBody(); - $this->assertInstanceOf(StreamInterface::class, $body); - $this->assertSame('dummy content', $body->getContents(), 'Expected stream to have content.'); - $this->assertSame(true, $body->isReadable(), 'Static constructed getBody() should be readable.'); - $this->assertSame(true, $body->isWritable(), 'Static constructed getBody() is writable as a quirk.'); + static::assertInstanceOf(StreamInterface::class, $body); + static::assertSame('dummy content', $body->getContents(), 'Expected stream to have content.'); + static::assertTrue($body->isReadable(), 'Static constructed getBody() should be readable.'); + static::assertTrue($body->isWritable(), 'Static constructed getBody() is writable as a quirk.'); } public function testStaticConstructionUsingPhpInputGetBody(): void { $body = $this->createRequest('POST', [Request::OPTION_BODY_USE_STREAM => true])->getBody(); - $this->assertInstanceOf(StreamInterface::class, $body); - $this->assertSame('', $body->getContents(), 'Expected empty stream.'); - $this->assertSame(true, $body->isReadable(), 'Static constructed getBody() should be readable.'); - $this->assertSame(true, $body->isWritable(), 'Static constructed getBody() is writable as a quirk.'); + static::assertInstanceOf(StreamInterface::class, $body); + static::assertSame('', $body->getContents(), 'Expected empty stream.'); + static::assertTrue($body->isReadable(), 'Static constructed getBody() should be readable.'); + static::assertTrue($body->isWritable(), 'Static constructed getBody() is writable as a quirk.'); } public function testWithBody(): void @@ -40,7 +45,7 @@ public function testWithBody(): void $request = $this->createRequest(); $streamMock = $this->createMock(StreamInterface::class); $requestWithBody = $request->withBody($streamMock); - $this->assertSame(spl_object_hash($streamMock), spl_object_hash($requestWithBody->getBody())); + static::assertSame(spl_object_hash($streamMock), spl_object_hash($requestWithBody->getBody())); } private function createRequest( diff --git a/tests/Adapter/ServerRequestUploadTest.php b/tests/Adapter/ServerRequestUploadTest.php index abc8a4a..49b71a9 100644 --- a/tests/Adapter/ServerRequestUploadTest.php +++ b/tests/Adapter/ServerRequestUploadTest.php @@ -1,12 +1,17 @@ getUploadedFiles(); - $this->assertCount(1, $files); + static::assertCount(1, $files); $file = $files['file-one']; - $this->assertInstanceOf(UploadedFileInterface::class, $file); - $this->assertSame(1337, $file->getSize()); - $this->assertSame('that.jpg', $file->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file); + static::assertSame(1337, $file->getSize()); + static::assertSame('that.jpg', $file->getClientFilename()); } public function testFormSingleUploadedFile(): void @@ -55,11 +60,11 @@ public function testFormSingleUploadedFile(): void ); $files = $request->getUploadedFiles(); - $this->assertCount(1, $files); + static::assertCount(1, $files); $file = $files['form1']['file-one']; - $this->assertInstanceOf(UploadedFileInterface::class, $file); - $this->assertSame(1337, $file->getSize()); - $this->assertSame('that.jpg', $file->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file); + static::assertSame(1337, $file->getSize()); + static::assertSame('that.jpg', $file->getClientFilename()); } public function testFormMultipleUploadedFile(): void @@ -70,41 +75,37 @@ public function testFormMultipleUploadedFile(): void null, null, [ - 'mass_upload' => - [ - 'foo' => - [ - 'error' => 0, - 'name' => 'test.csv', - 'type' => 'text/csv', - 'tmp_name' => '/tmp/phpmYRXeG', - 'size' => 23, - ], - 'bar' => - [ - 'error' => 0, - 'name' => 'bar.sql', - 'type' => 'application/sql', - 'tmp_name' => '/tmp/phpYCTUy1', - 'size' => 7206, - ], - 'baz' => - [ - 'error' => 0, - 'name' => 'Notes.txt', - 'type' => 'text/plain', - 'tmp_name' => '/tmp/phpnhBSSm', - 'size' => 17962, - ], + 'mass_upload' => [ + 'foo' => [ + 'error' => 0, + 'name' => 'test.csv', + 'type' => 'text/csv', + 'tmp_name' => '/tmp/phpmYRXeG', + 'size' => 23, ], + 'bar' => [ + 'error' => 0, + 'name' => 'bar.sql', + 'type' => 'application/sql', + 'tmp_name' => '/tmp/phpYCTUy1', + 'size' => 7206, + ], + 'baz' => [ + 'error' => 0, + 'name' => 'Notes.txt', + 'type' => 'text/plain', + 'tmp_name' => '/tmp/phpnhBSSm', + 'size' => 17962, + ], + ], ] ); $files = $request->getUploadedFiles()['mass_upload']; - $this->assertCount(3, $files); - $this->assertInstanceOf(UploadedFileInterface::class, $files['foo']); - $this->assertInstanceOf(UploadedFileInterface::class, $files['bar']); - $this->assertInstanceOf(UploadedFileInterface::class, $files['baz']); + static::assertCount(3, $files); + static::assertInstanceOf(UploadedFileInterface::class, $files['foo']); + static::assertInstanceOf(UploadedFileInterface::class, $files['bar']); + static::assertInstanceOf(UploadedFileInterface::class, $files['baz']); } public function testDeeplyNestledUploadedFile(): void @@ -134,11 +135,11 @@ public function testDeeplyNestledUploadedFile(): void ); $files = $request->getUploadedFiles(); - $this->assertCount(1, $files); + static::assertCount(1, $files); $file = $files['form']['foo']['bar']['baz']['that-file']; - $this->assertInstanceOf(UploadedFileInterface::class, $file); - $this->assertSame(1337, $file->getSize()); - $this->assertSame('that.jpg', $file->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file); + static::assertSame(1337, $file->getSize()); + static::assertSame('that.jpg', $file->getClientFilename()); } public function testMultiFormUploadedFiles(): void @@ -149,65 +150,61 @@ public function testMultiFormUploadedFiles(): void null, null, [ - 'file-foo' => - [ - 'name' => 'test.csv', - 'type' => 'text/csv', - 'tmp_name' => '/tmp/php23', - 'error' => 0, - 'size' => 23, - ], - 'form-bar' => - [ - 'foo' => [ - 'bar' => [ - 'baz' => [ - 'file-bar' => [ - 'name' => 'that.jpg', - 'type' => 'image/jpeg', - 'tmp_name' => '/tmp/php1337', - 'error' => 0, - 'size' => 1337, - ], + 'file-foo' => [ + 'name' => 'test.csv', + 'type' => 'text/csv', + 'tmp_name' => '/tmp/php23', + 'error' => 0, + 'size' => 23, + ], + 'form-bar' => [ + 'foo' => [ + 'bar' => [ + 'baz' => [ + 'file-bar' => [ + 'name' => 'that.jpg', + 'type' => 'image/jpeg', + 'tmp_name' => '/tmp/php1337', + 'error' => 0, + 'size' => 1337, ], ], ], - 'file-baz' => - [ - 'error' => 0, - 'name' => 'text.txt', - 'type' => 'text/plain', - 'tmp_name' => '/tmp/php42', - 'size' => 42, - ], ], + 'file-baz' => [ + 'error' => 0, + 'name' => 'text.txt', + 'type' => 'text/plain', + 'tmp_name' => '/tmp/php42', + 'size' => 42, + ], + ], ] ); $files = $request->getUploadedFiles(); - $this->assertCount(2, $files); + static::assertCount(2, $files); $file1 = $files['file-foo']; - $this->assertInstanceOf(UploadedFileInterface::class, $file1); - $this->assertSame(23, $file1->getSize()); - $this->assertSame('test.csv', $file1->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file1); + static::assertSame(23, $file1->getSize()); + static::assertSame('test.csv', $file1->getClientFilename()); $file2 = $files['form-bar']['foo']['bar']['baz']['file-bar']; - $this->assertInstanceOf(UploadedFileInterface::class, $file2); - $this->assertSame(1337, $file2->getSize()); - $this->assertSame('that.jpg', $file2->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file2); + static::assertSame(1337, $file2->getSize()); + static::assertSame('that.jpg', $file2->getClientFilename()); $file3 = $files['form-bar']['file-baz']; - $this->assertInstanceOf(UploadedFileInterface::class, $file3); - $this->assertSame(42, $file3->getSize()); - $this->assertSame('text.txt', $file3->getClientFilename()); + static::assertInstanceOf(UploadedFileInterface::class, $file3); + static::assertSame(42, $file3->getSize()); + static::assertSame('text.txt', $file3->getClientFilename()); } /** * @param null|array> $files * * @throws \InvalidArgumentException - * @return Request */ private function createRequest( string $method = '', diff --git a/tests/Adapter/ServerRequestUriTargetUrlTest.php b/tests/Adapter/ServerRequestUriTargetUrlTest.php index b46f0f0..ea203a7 100644 --- a/tests/Adapter/ServerRequestUriTargetUrlTest.php +++ b/tests/Adapter/ServerRequestUriTargetUrlTest.php @@ -1,43 +1,48 @@ createRequest(null)->getUri(); - $this->assertInstanceOf(UriInterface::class, $uri); - $this->assertSame('http://localhost/', $uri->__toString()); + static::assertInstanceOf(UriInterface::class, $uri); + static::assertSame('http://localhost/', $uri->__toString()); } public function testGetUri(): void { $uri = $this->createRequest('https://example.com:1337/foo/bar?q=bar&a=42#fragment')->getUri(); - $this->assertInstanceOf(UriInterface::class, $uri); - $this->assertSame('https://example.com:1337/foo/bar?q=bar&a=42#fragment', $uri->__toString()); + static::assertInstanceOf(UriInterface::class, $uri); + static::assertSame('https://example.com:1337/foo/bar?q=bar&a=42#fragment', $uri->__toString()); } public function testGetRequestTargetDefaultMock(): void { $requestTarget = $this->createRequest(null)->getRequestTarget(); - $this->assertSame('/', $requestTarget); + static::assertSame('/', $requestTarget); } public function testGetRequestTargetDefaultEmpty(): void { $request = $this->createRequest(''); - $this->assertSame('/', $request->getRequestTarget());; + static::assertSame('/', $request->getRequestTarget()); } public function testGetRequestTarget(): void { $requestTarget = $this->createRequest('https://example.com:1337/foo/bar?q=baz&a=42#fragment')->getRequestTarget(); - $this->assertSame('/foo/bar?q=baz&a=42', $requestTarget); + static::assertSame('/foo/bar?q=baz&a=42', $requestTarget); } public function testItFailsWithUri(): void @@ -49,13 +54,6 @@ public function testItFailsWithUri(): void $request->withUri($uriMock); } - /** - * - * @param string|null $uri - * @param string $method - * - * @return Request - */ private function createRequest( ?string $uri = null, string $method = 'GET' diff --git a/tests/Factory/GuzzleStreamFactoryTest.php b/tests/Factory/GuzzleStreamFactoryTest.php new file mode 100644 index 0000000..768afc1 --- /dev/null +++ b/tests/Factory/GuzzleStreamFactoryTest.php @@ -0,0 +1,68 @@ +createStreamFromFile('php://temp', 'wb+'); + $stream->write('FOO_'); + $stream->write('BAR_'); + $stream->seek(6); + $stream->write('Z'); + + static::assertSame('_', $stream->getContents()); + $stream->rewind(); + static::assertSame('FOO_BAZ_', $stream->getContents()); + static::assertSame('', $stream->getContents()); + static::assertSame('FOO_BAZ_', (string)$stream); + } + + public function testCreateStream(): void + { + $factory = new GuzzleStreamFactory(); + $stream = $factory->createStream('Hello world…'); + static::assertInstanceOf(StreamInterface::class, $stream); + static::assertSame('Hello world…', $stream->getContents()); + } + + public function testCreateStreamFromResource(): void + { + $factory = new GuzzleStreamFactory(); + // Create resource + /** @phpstan-var resource $tmpFile */ + $tmpFile = tmpfile(); + static::assertIsResource($tmpFile); + // Write to resource before stream creation + static::assertSame(10, fwrite($tmpFile, '1234567890')); + // Try to read back + static::assertSame(0, fseek($tmpFile, 0)); + static::assertSame('1234567890', stream_get_contents($tmpFile)); + // Seek to 5th byte on resource + static::assertSame(0, fseek($tmpFile, 5)); + // Create stream + $stream = $factory->createStreamFromResource($tmpFile); + // Write to resource after stream creation + static::assertSame(12, fwrite($tmpFile, ' ABCDE FGHIJ')); + // Seek to byte 3 on resource + static::assertSame(0, fseek($tmpFile, 3)); + // Read from Stream which appears to be coupled to the resource's index + static::assertSame('45 ABCDE FGHIJ', $stream->getContents()); + // Rewind on the steam… + $stream->rewind(); + static::assertSame('12345 ABCDE FGHIJ', $stream->getContents()); + fclose($tmpFile); + } +} diff --git a/tests/Factory/ResponseFactoryTest.php b/tests/Factory/ResponseFactoryTest.php new file mode 100644 index 0000000..59cc6b3 --- /dev/null +++ b/tests/Factory/ResponseFactoryTest.php @@ -0,0 +1,34 @@ +prepare(200, 'Mkay', ['X-Test' => 'foobar'], [], false); + $factory = ResponseFactory::createFactoryFromWebResponse($symfonyResponseMock); + static::assertInstanceOf(ResponseFactory::class, $factory); + + $response = $factory->createResponse(123, 'Foo bar baZ'); + static::assertInstanceOf(ResponseFactory::class, $factory); + + static::assertInstanceOf(Response::class, $response); + /** @phpstan-var Response $responseCopy */ + $responseCopy = $response; + static::assertSame($symfonyResponseMock, $responseCopy->getSfWebResponse()); + + static::assertSame(123, $response->getStatusCode()); + static::assertSame('Foo bar baZ', $response->getReasonPhrase()); + } +} diff --git a/tests/ResponseMockTest.php b/tests/ResponseMockTest.php index 6d4a6df..972ee89 100644 --- a/tests/ResponseMockTest.php +++ b/tests/ResponseMockTest.php @@ -26,31 +26,31 @@ public function testSetHttpHeaderAppend(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(); - $this->assertFalse($response->hasHeader('X-Append-Test')); - $this->assertSame([], $response->getHeader('X-Append-Test')); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader('X-Append-Test')); + static::assertSame([], $response->getHeader('X-Append-Test')); + static::assertSame([], $symfony->getHttpHeaders()); $response = $response->withHeader('X-Append-Test', 'foo/bar'); - $this->assertTrue($response->hasHeader('X-Append-Test')); - $this->assertSame(['foo/bar'], $response->getHeader('X-Append-Test')); - $this->assertSame('foo/bar', $response->getHeaderLine('X-Append-Test')); - $this->assertSame(['X-Append-Test' => ['foo/bar']], $response->getHeaders()); - $this->assertSame(['X-Append-Test' => 'foo/bar'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-Append-Test')); + static::assertSame(['foo/bar'], $response->getHeader('X-Append-Test')); + static::assertSame('foo/bar', $response->getHeaderLine('X-Append-Test')); + static::assertSame(['X-Append-Test' => ['foo/bar']], $response->getHeaders()); + static::assertSame(['X-Append-Test' => 'foo/bar'], $symfony->getHttpHeaders()); $symfony->setHttpHeader('X-Append-Test', 'foo/baz', false); - $this->assertTrue($response->hasHeader('X-Append-Test')); - $this->assertSame(['foo/bar', 'foo/baz'], $response->getHeader('X-Append-Test')); - $this->assertSame('foo/bar, foo/baz', $response->getHeaderLine('X-Append-Test')); - $this->assertSame(['X-Append-Test' => ['foo/bar', 'foo/baz']], $response->getHeaders()); - $this->assertSame(['X-Append-Test' => 'foo/bar, foo/baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-Append-Test')); + static::assertSame(['foo/bar', 'foo/baz'], $response->getHeader('X-Append-Test')); + static::assertSame('foo/bar, foo/baz', $response->getHeaderLine('X-Append-Test')); + static::assertSame(['X-Append-Test' => ['foo/bar', 'foo/baz']], $response->getHeaders()); + static::assertSame(['X-Append-Test' => 'foo/bar, foo/baz'], $symfony->getHttpHeaders()); $symfony->setHttpHeader('X-Append-Test', 'foo/baz', true); - $this->assertTrue($response->hasHeader('X-Append-Test')); - $this->assertSame(['foo/baz'], $response->getHeader('X-Append-Test')); - $this->assertSame('foo/baz', $response->getHeaderLine('X-Append-Test')); - $this->assertSame(['X-Append-Test' => ['foo/baz']], $response->getHeaders()); - $this->assertSame(['X-Append-Test' => 'foo/baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('X-Append-Test')); + static::assertSame(['foo/baz'], $response->getHeader('X-Append-Test')); + static::assertSame('foo/baz', $response->getHeaderLine('X-Append-Test')); + static::assertSame(['X-Append-Test' => ['foo/baz']], $response->getHeaders()); + static::assertSame(['X-Append-Test' => 'foo/baz'], $symfony->getHttpHeaders()); } /** @@ -63,39 +63,39 @@ public function testSetHttpHeaderNoAppendContentType(): void * @var \sfWebResponse $symfony */ [$response, $symfony] = $this->createResponse(); - $this->assertFalse($response->hasHeader('Content-Type')); - $this->assertSame([], $response->getHeader('Content-Type')); - $this->assertSame([], $symfony->getHttpHeaders()); + static::assertFalse($response->hasHeader('Content-Type')); + static::assertSame([], $response->getHeader('Content-Type')); + static::assertSame([], $symfony->getHttpHeaders()); $response = $response->withHeader('Content-Type', 'foo/bar'); - $this->assertTrue($response->hasHeader('Content-Type')); - $this->assertSame(['foo/bar'], $response->getHeader('Content-Type')); - $this->assertSame('foo/bar', $response->getHeaderLine('Content-Type')); - $this->assertSame(['Content-Type' => ['foo/bar']], $response->getHeaders()); - $this->assertSame(['Content-Type' => 'foo/bar'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('Content-Type')); + static::assertSame(['foo/bar'], $response->getHeader('Content-Type')); + static::assertSame('foo/bar', $response->getHeaderLine('Content-Type')); + static::assertSame(['Content-Type' => ['foo/bar']], $response->getHeaders()); + static::assertSame(['Content-Type' => 'foo/bar'], $symfony->getHttpHeaders()); $symfony->setHttpHeader('Content-Type', 'foo/baz', false); - $this->assertTrue($response->hasHeader('Content-Type')); - $this->assertSame(['foo/bar'], $response->getHeader('Content-Type')); - $this->assertSame('foo/bar', $response->getHeaderLine('Content-Type')); - $this->assertSame(['Content-Type' => ['foo/bar']], $response->getHeaders()); - $this->assertSame(['Content-Type' => 'foo/bar'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('Content-Type')); + static::assertSame(['foo/bar'], $response->getHeader('Content-Type')); + static::assertSame('foo/bar', $response->getHeaderLine('Content-Type')); + static::assertSame(['Content-Type' => ['foo/bar']], $response->getHeaders()); + static::assertSame(['Content-Type' => 'foo/bar'], $symfony->getHttpHeaders()); $symfony->setHttpHeader('Content-Type', 'foo/baz', true); - $this->assertTrue($response->hasHeader('Content-Type')); - $this->assertSame(['foo/baz'], $response->getHeader('Content-Type')); - $this->assertSame('foo/baz', $response->getHeaderLine('Content-Type')); - $this->assertSame(['Content-Type' => ['foo/baz']], $response->getHeaders()); - $this->assertSame(['Content-Type' => 'foo/baz'], $symfony->getHttpHeaders()); + static::assertTrue($response->hasHeader('Content-Type')); + static::assertSame(['foo/baz'], $response->getHeader('Content-Type')); + static::assertSame('foo/baz', $response->getHeaderLine('Content-Type')); + static::assertSame(['Content-Type' => ['foo/baz']], $response->getHeaders()); + static::assertSame(['Content-Type' => 'foo/baz'], $symfony->getHttpHeaders()); } /** - * @param int $code - * @param null|string $reasonPhrase - * @param string[] $headers + * @param int $code + * @param null|string $reasonPhrase + * @param string[] $headers * @param array $cookies - * @param array $options + * @param array $options */ private function createResponse( $code = 200, diff --git a/tests/Transcriptor/ResponseTranscriptorTest.php b/tests/Transcriptor/ResponseTranscriptorTest.php new file mode 100644 index 0000000..3aead7e --- /dev/null +++ b/tests/Transcriptor/ResponseTranscriptorTest.php @@ -0,0 +1,126 @@ +expectException(LogicException::class); + $psr7Response = new Response(203); + $psr7Response = $psr7Response->withAddedHeader('Set-Cookie', 'token=1337; domain=cookie.test; path=/; expires=Sun, 12 Dec 2025 13:37:42 GMT; SameSite=Lax; secure'); + $mockResponse = $this->createSfWebResponse( + 503, + null, + ['X-Preset-Header' => 'Set sfWebResponse'], + ['sf-default' => ['name' => 'sf-default', 'value' => 'preset', 'expire' => null, 'path' => '/', 'domain' => '*', 'secure' => false, 'httpOnly' => false]] + ); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + } + + public function testTranscribeHeaders(): void + { + $psr7Response = new Response(202, ['X-PSR-7-default' => 'guzzle constructor']); + $psr7Response = $psr7Response->withAddedHeader('x-test', 'test 1'); + $psr7Response = $psr7Response->withAddedHeader('x-test', 'test 2'); + $mockResponse = $this->createSfWebResponse(); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + static::assertSame( + [ + 'X-Preset-Header' => 'sfWebResponse', + 'X-Psr-7-Default' => 'guzzle constructor', + 'X-Test' => 'test 1, test 2', + ], + $transcription->getHttpHeaders() + ); + } + + public function testTranscribeKeepSymfonyCookies(): void + { + $psr7Response = new Response(203); + $mockResponse = $this->createSfWebResponse( + 503, + null, + ['X-Preset-Header' => 'Set sfWebResponse'], + ['sf-default' => ['name' => 'sf-default', 'value' => 'preset', 'expire' => null, 'path' => '/', 'domain' => '*', 'secure' => false, 'httpOnly' => false]] + ); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + static::assertSame( + [ + 'sf-default' => ['name' => 'sf-default', 'value' => 'preset', 'expire' => null, 'path' => '/', 'domain' => '*', 'secure' => false, 'httpOnly' => false], + ], + $transcription->getCookies() + ); + } + + public function testTranscribeStatusReasonVersion(): void + { + $psr7Response = new Response(201, [], null, '1.1', 'Tested'); + $mockResponse = $this->createSfWebResponse(); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + static::assertSame($mockResponse, $transcription); + + static::assertSame(201, $transcription->getStatusCode()); + static::assertSame('Tested', $transcription->getStatusText()); + static::assertSame('', $transcription->getContent()); + static::assertFalse($transcription->isHeaderOnly()); + static::assertSame([], $transcription->getCookies()); + static::assertSame(['X-Preset-Header' => 'sfWebResponse'], $transcription->getHttpHeaders()); + static::assertSame( + [ + 'http_protocol' => 'HTTP/1.1', + 'charset' => 'utf-8', + 'content_type' => 'text/html', + 'send_http_headers' => true, + ], + $transcription->getOptions() + ); + } + + public function testTranscribeBody(): void + { + $psr7Response = new Response(200, [], 'PSR-7 Body'); + $mockResponse = $this->createSfWebResponse(); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + static::assertSame('PSR-7 Body', $transcription->getContent()); + } + + public function testTranscribeOverwriteBody(): void + { + $psr7Response = new Response(200, [], 'PSR-7 Body'); + $mockResponse = $this->createSfWebResponse(); + $mockResponse->setContent('Symfony Content'); + $transcription = (new ResponseTranscriptor(null, null))->transcribe($psr7Response, $mockResponse); + static::assertSame('PSR-7 Body', $transcription->getContent()); + } + + /** + * @param int $code + * @param null|string $reasonPhrase + * @param string[] $headers + * @param array $cookies + * @param array $options + */ + private function createSfWebResponse( + $code = 501, + $reasonPhrase = 'Default Symfony reason! [OK]', + $headers = ['X-Preset-Header' => 'sfWebResponse'], + $cookies = [], + array $options = ['http_protocol' => 'HTTP/1.0', 'charset' => 'utf-8', 'content_type' => 'text/html', 'send_http_headers' => true] + ): \sfWebResponse { + $symfonyResponseMock = new \sfWebResponse(null, $options); + $symfonyResponseMock->prepare($code, $reasonPhrase, $headers, $cookies); + + return $symfonyResponseMock; + } +} diff --git a/tests/integration/RequestTest.php b/tests/integration/RequestTest.php index 891d546..58223e5 100644 --- a/tests/integration/RequestTest.php +++ b/tests/integration/RequestTest.php @@ -7,7 +7,10 @@ use brnc\Symfony1\Message\Adapter\Request; use Http\Psr7Test\RequestIntegrationTest; -class RequestTest extends RequestIntegrationTest +/** + * @internal + */ +final class RequestTest extends RequestIntegrationTest { public function createSubject() { diff --git a/tests/integration/ResponseTest.php b/tests/integration/ResponseTest.php index 078001a..023d804 100644 --- a/tests/integration/ResponseTest.php +++ b/tests/integration/ResponseTest.php @@ -7,15 +7,16 @@ use brnc\Symfony1\Message\Adapter\Response; use Http\Psr7Test\ResponseIntegrationTest; -class ResponseTest extends ResponseIntegrationTest +/** + * @internal + */ +final class ResponseTest extends ResponseIntegrationTest { public function createSubject() { $symfonyResponseMock = new \sfWebResponse(); $symfonyResponseMock->prepare(); - $response = Response::fromSfWebResponse($symfonyResponseMock, [Response::OPTION_IMMUTABLE_VIOLATION => false]); - - return $response; + return Response::fromSfWebResponse($symfonyResponseMock, [Response::OPTION_IMMUTABLE_VIOLATION => false]); } } diff --git a/tests/integration/ServerRequestTest.php b/tests/integration/ServerRequestTest.php index f5253e0..32ca1c9 100644 --- a/tests/integration/ServerRequestTest.php +++ b/tests/integration/ServerRequestTest.php @@ -4,10 +4,13 @@ namespace brnc\Tests\Symfony1\Message\integration; -use Http\Psr7Test\ServerRequestIntegrationTest; use brnc\Symfony1\Message\Adapter\Request; +use Http\Psr7Test\ServerRequestIntegrationTest; -class ServerRequestTest extends ServerRequestIntegrationTest +/** + * @internal + */ +final class ServerRequestTest extends ServerRequestIntegrationTest { public function createSubject() {