From 999be72fc9fa35be23d79361ef1eeb5dfe5bb8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 22:21:32 +0200 Subject: [PATCH 01/37] Add composer dependencies --- composer.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 700becc..5afd2e9 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "symfony/psr-http-message-bridge", "type": "symfony-bridge", "description": "PSR HTTP message bridge", - "keywords": [], + "keywords": ["http", "psr-7", "http-message"], "homepage": "http://symfony.com", "license": "MIT", "authors": [ @@ -16,16 +16,18 @@ } ], "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "psr/http-message": "~1.0" }, "require-dev": { + "zendframework/zend-diactoros": "~1.0" }, "suggest": { + "zendframework/zend-diactoros": "To use the zend-diactoros adapter" }, "autoload": { - "psr-0": { "Symfony\\Bridge\\PsrHttpMessage\\": "" } + "psr-4": { "Symfony\\Bridge\\PsrHttpMessage\\": "" } }, - "target-dir": "Symfony/Bridge/PsrHttpMessage", "minimum-stability": "dev", "extra": { "branch-alias": { From 47c656444b61fda7b070d6abc69ecfd339aa04b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 22:35:48 +0200 Subject: [PATCH 02/37] More dependencies --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5afd2e9..57eae1b 100644 --- a/composer.json +++ b/composer.json @@ -17,9 +17,11 @@ ], "require": { "php": ">=5.3.3", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "symfony/http-foundation": "~2.3" }, "require-dev": { + "symfony/phpunit-bridge": "~2.7", "zendframework/zend-diactoros": "~1.0" }, "suggest": { From 6a4ab9bc4ca47c5616a756c1ee314aa7f9475ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 22:55:41 +0200 Subject: [PATCH 03/37] Add interfaces and stubs. --- Factory/DiactorosFactory.php | 9 +++++++ Factory/HttpFoundationFactory.php | 6 +++++ HttpFoundationFactoryInterface.php | 40 ++++++++++++++++++++++++++++++ PsrHttpMessageFactoryInterface.php | 34 +++++++++++++++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 Factory/DiactorosFactory.php create mode 100644 Factory/HttpFoundationFactory.php create mode 100644 HttpFoundationFactoryInterface.php create mode 100644 PsrHttpMessageFactoryInterface.php diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php new file mode 100644 index 0000000..d6fa879 --- /dev/null +++ b/Factory/DiactorosFactory.php @@ -0,0 +1,9 @@ + + */ +class HttpFoundationFactory +{ + /** + * Creates a Symfony Request from a PSR-7 one. + * + * @param RequestInterface $psrHttpMessageRequest + * + * @return Request + */ + public function createRequest(RequestInterface $psrHttpMessageRequest) + { + // TODO + } + + /** + * Creates a Symfony Response from a PSR-7 one. + * + * @param ResponseInterface $psrHttpMessageResponse + * + * @return Response + */ + public function createResponse(ResponseInterface $psrHttpMessageResponse) + { + // TODO + } +} diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php new file mode 100644 index 0000000..16d0555 --- /dev/null +++ b/PsrHttpMessageFactoryInterface.php @@ -0,0 +1,34 @@ + + */ +interface PsrHttpMessageFactoryInterface +{ + /** + * Creates a PSR-7 Request from a Symfony one. + * + * @param Request $symfonyRequest + * + * @return RequestInterface + */ + public function createRequest(Request $symfonyRequest); + + /** + * Creates a PSR-7 Response from a Symfony one. + * + * @param Response $symfonyResponse + * + * @return ResponseInterface + */ + public function createResponse(Response $symfonyResponse); +} From 1ed3bfff834778cba36cd00bc1679d7dedbd9b92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 22:56:48 +0200 Subject: [PATCH 04/37] Add .gitignore --- .gitignore | 3 +++ Factory/DiactorosFactory.php | 31 ++++++++++++++++++++++++++--- Factory/HttpFoundationFactory.php | 32 ++++++++++++++++++++++++++++-- HttpFoundationFactoryInterface.php | 12 +++-------- 4 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index d6fa879..f580364 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -1,9 +1,34 @@ + */ +class DiactorosFactory implements PsrHttpMessageFactoryInterface +{ -class DiactorosFactory { + /** + * {@inheritdoc} + */ + public function createRequest(Request $symfonyRequest) + { + // TODO: Implement createRequest() method. + } -} \ No newline at end of file + /** + * {@inheritdoc} + */ + public function createResponse(Response $symfonyResponse) + { + // TODO: Implement createResponse() method. + } +} diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index df793b6..59e7b09 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -1,6 +1,34 @@ + */ +class HttpFoundationFactory implements HttpFoundationFactoryInterface +{ + + /** + * {@inheritdoc} + */ + public function createRequest(RequestInterface $psrHttpMessageRequest) + { + // TODO: Implement createRequest() method. + } + + /** + * {@inheritdoc} + */ + public function createResponse(ResponseInterface $psrHttpMessageResponse) + { + // TODO: Implement createResponse() method. + } +} diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index 4c0f482..5567afe 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -12,7 +12,7 @@ * * @author Kévin Dunglas */ -class HttpFoundationFactory +interface HttpFoundationFactoryInterface { /** * Creates a Symfony Request from a PSR-7 one. @@ -21,10 +21,7 @@ class HttpFoundationFactory * * @return Request */ - public function createRequest(RequestInterface $psrHttpMessageRequest) - { - // TODO - } + public function createRequest(RequestInterface $psrHttpMessageRequest); /** * Creates a Symfony Response from a PSR-7 one. @@ -33,8 +30,5 @@ public function createRequest(RequestInterface $psrHttpMessageRequest) * * @return Response */ - public function createResponse(ResponseInterface $psrHttpMessageResponse) - { - // TODO - } + public function createResponse(ResponseInterface $psrHttpMessageResponse); } From 1b81ee0176a4b0a559d92d005576b79cb812b864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 23:07:56 +0200 Subject: [PATCH 05/37] Make factory methods static. Add test infra. --- Factory/DiactorosFactory.php | 4 ++-- HttpFoundationFactoryInterface.php | 4 ++-- PsrHttpMessageFactoryInterface.php | 4 ++-- Tests/Factory/DiactorosFactoryTest.php | 19 +++++++++++++++++++ Tests/Factory/HttpFoundationFactoryTest.php | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 Tests/Factory/DiactorosFactoryTest.php create mode 100644 Tests/Factory/HttpFoundationFactoryTest.php diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index f580364..b77a01c 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -19,7 +19,7 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface /** * {@inheritdoc} */ - public function createRequest(Request $symfonyRequest) + public static function createRequest(Request $symfonyRequest) { // TODO: Implement createRequest() method. } @@ -27,7 +27,7 @@ public function createRequest(Request $symfonyRequest) /** * {@inheritdoc} */ - public function createResponse(Response $symfonyResponse) + public static function createResponse(Response $symfonyResponse) { // TODO: Implement createResponse() method. } diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index 5567afe..e251b4e 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -21,7 +21,7 @@ interface HttpFoundationFactoryInterface * * @return Request */ - public function createRequest(RequestInterface $psrHttpMessageRequest); + public static function createRequest(RequestInterface $psrHttpMessageRequest); /** * Creates a Symfony Response from a PSR-7 one. @@ -30,5 +30,5 @@ public function createRequest(RequestInterface $psrHttpMessageRequest); * * @return Response */ - public function createResponse(ResponseInterface $psrHttpMessageResponse); + public static function createResponse(ResponseInterface $psrHttpMessageResponse); } diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php index 16d0555..1767a4c 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/PsrHttpMessageFactoryInterface.php @@ -21,7 +21,7 @@ interface PsrHttpMessageFactoryInterface * * @return RequestInterface */ - public function createRequest(Request $symfonyRequest); + public static function createRequest(Request $symfonyRequest); /** * Creates a PSR-7 Response from a Symfony one. @@ -30,5 +30,5 @@ public function createRequest(Request $symfonyRequest); * * @return ResponseInterface */ - public function createResponse(Response $symfonyResponse); + public static function createResponse(Response $symfonyResponse); } diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php new file mode 100644 index 0000000..4b4322c --- /dev/null +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -0,0 +1,19 @@ + + */ +class DiactorosFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testCreateRequest() + { + + } + + public function testCreateResponse() + { + + } +} diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php new file mode 100644 index 0000000..57f810b --- /dev/null +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -0,0 +1,19 @@ + + */ +class HttpFoundationFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testCreateRequest() + { + + } + + public function testCreateResponse() + { + + } +} From 1e3307c134f17e538ab900b4c504ba835ca3d197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 23:12:03 +0200 Subject: [PATCH 06/37] Setup Travis --- .travis.yml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d350695 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,41 @@ +language: php + +sudo: false + +matrix: + include: + - php: 5.3 + - php: 5.4 + - php: 5.5 + - php: 5.6 + - php: 5.3 + env: deps=low + - php: 5.6 + env: deps=high + - php: nightly + - php: hhvm + allow_failures: + - php: nightly + - php: hhvm + fast_finish: true + +env: + global: + - deps=no + - SYMFONY_DEPRECATIONS_HELPER=weak + +before_install: + - composer self-update + - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi; + - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]] && [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi; + - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo "extension = $(pwd)/modules/symfony_debug.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini); fi; + - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then php -i; fi; + # Set the COMPOSER_ROOT_VERSION to the right version according to the branch being built + - if [ "$TRAVIS_BRANCH" = "master" ]; then export COMPOSER_ROOT_VERSION=dev-master; else export COMPOSER_ROOT_VERSION="$TRAVIS_BRANCH".x-dev; fi; + +install: + - if [ "$deps" = "no" ]; then export SYMFONY_DEPRECATIONS_HELPER=strict; fi; + - if [ "$deps" = "no" ]; then composer --prefer-source install; fi; + +script: + - phpunit From 7e7fbf66a12a6c57b4de3c6367e8b87176da4b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 23:13:38 +0200 Subject: [PATCH 07/37] Add missing static keywords --- Factory/HttpFoundationFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 59e7b09..7570f4e 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -19,7 +19,7 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface /** * {@inheritdoc} */ - public function createRequest(RequestInterface $psrHttpMessageRequest) + public static function createRequest(RequestInterface $psrHttpMessageRequest) { // TODO: Implement createRequest() method. } @@ -27,7 +27,7 @@ public function createRequest(RequestInterface $psrHttpMessageRequest) /** * {@inheritdoc} */ - public function createResponse(ResponseInterface $psrHttpMessageResponse) + public static function createResponse(ResponseInterface $psrHttpMessageResponse) { // TODO: Implement createResponse() method. } From 43d4c48ed499682f4625a4df151271f26097543b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 21 May 2015 23:31:07 +0200 Subject: [PATCH 08/37] Use ServerRequestInterface --- Factory/DiactorosFactory.php | 8 ++++++-- Factory/HttpFoundationFactory.php | 13 ++++++++----- HttpFoundationFactoryInterface.php | 6 +++--- PsrHttpMessageFactoryInterface.php | 4 ++-- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index b77a01c..e71d7f4 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -21,7 +21,9 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface */ public static function createRequest(Request $symfonyRequest) { - // TODO: Implement createRequest() method. + return new ServerRequest( + + ); } /** @@ -29,6 +31,8 @@ public static function createRequest(Request $symfonyRequest) */ public static function createResponse(Response $symfonyResponse) { - // TODO: Implement createResponse() method. + return new DiactorosResponse( + + ); } } diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 7570f4e..f3b9a1a 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -2,7 +2,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Factory; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface; use Symfony\Component\HttpFoundation\Request; @@ -15,13 +15,14 @@ */ class HttpFoundationFactory implements HttpFoundationFactoryInterface { - /** * {@inheritdoc} */ - public static function createRequest(RequestInterface $psrHttpMessageRequest) + public static function createRequest(ServerRequestInterface $psrHttpMessageRequest) { - // TODO: Implement createRequest() method. + return new Request( + + ); } /** @@ -29,6 +30,8 @@ public static function createRequest(RequestInterface $psrHttpMessageRequest) */ public static function createResponse(ResponseInterface $psrHttpMessageResponse) { - // TODO: Implement createResponse() method. + return new Response( + + ); } } diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index e251b4e..0a7db59 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -2,7 +2,7 @@ namespace Symfony\Bridge\PsrHttpMessage; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -17,11 +17,11 @@ interface HttpFoundationFactoryInterface /** * Creates a Symfony Request from a PSR-7 one. * - * @param RequestInterface $psrHttpMessageRequest + * @param ServerRequestInterface $psrHttpMessageRequest * * @return Request */ - public static function createRequest(RequestInterface $psrHttpMessageRequest); + public static function createRequest(ServerRequestInterface $psrHttpMessageRequest); /** * Creates a Symfony Response from a PSR-7 one. diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php index 1767a4c..2ad26ba 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/PsrHttpMessageFactoryInterface.php @@ -2,7 +2,7 @@ namespace Symfony\Bridge\PsrHttpMessage; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -19,7 +19,7 @@ interface PsrHttpMessageFactoryInterface * * @param Request $symfonyRequest * - * @return RequestInterface + * @return ServerRequestInterface */ public static function createRequest(Request $symfonyRequest); From bb43a07e5ac4974ac4dde930766fcfd521650df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 00:49:36 +0200 Subject: [PATCH 09/37] Basic HttpFoundationFactory::createRequest implementation --- Factory/DiactorosFactory.php | 4 +- Factory/HttpFoundationFactory.php | 19 ++- HttpFoundationFactoryInterface.php | 4 +- PsrHttpMessageFactoryInterface.php | 4 +- Tests/Factory/HttpFoundationFactoryTest.php | 40 +++++++ Tests/Fixtures/Message.php | 84 +++++++++++++ Tests/Fixtures/ServerRequest.php | 124 ++++++++++++++++++++ Tests/Fixtures/Stream.php | 86 ++++++++++++++ 8 files changed, 356 insertions(+), 9 deletions(-) create mode 100644 Tests/Fixtures/Message.php create mode 100644 Tests/Fixtures/ServerRequest.php create mode 100644 Tests/Fixtures/Stream.php diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index e71d7f4..6142a93 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -19,7 +19,7 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface /** * {@inheritdoc} */ - public static function createRequest(Request $symfonyRequest) + public function createRequest(Request $symfonyRequest) { return new ServerRequest( @@ -29,7 +29,7 @@ public static function createRequest(Request $symfonyRequest) /** * {@inheritdoc} */ - public static function createResponse(Response $symfonyResponse) + public function createResponse(Response $symfonyResponse) { return new DiactorosResponse( diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index f3b9a1a..f9fdf94 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -18,17 +18,30 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface /** * {@inheritdoc} */ - public static function createRequest(ServerRequestInterface $psrHttpMessageRequest) + public function createRequest(ServerRequestInterface $psrHttpMessageRequest) { - return new Request( + $parsedBody = $psrHttpMessageRequest->getParsedBody(); + $request = is_array($parsedBody) ? $parsedBody : []; + return new Request( + $psrHttpMessageRequest->getQueryParams(), + $request, + $psrHttpMessageRequest->getAttributes(), + $psrHttpMessageRequest->getCookieParams(), + array(), // TODO + $psrHttpMessageRequest->getServerParams(), + $psrHttpMessageRequest->getBody()->__toString() ); } + private function getFiles(array $uploadedFiles) + { + } + /** * {@inheritdoc} */ - public static function createResponse(ResponseInterface $psrHttpMessageResponse) + public function createResponse(ResponseInterface $psrHttpMessageResponse) { return new Response( diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index 0a7db59..064385c 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -21,7 +21,7 @@ interface HttpFoundationFactoryInterface * * @return Request */ - public static function createRequest(ServerRequestInterface $psrHttpMessageRequest); + public function createRequest(ServerRequestInterface $psrHttpMessageRequest); /** * Creates a Symfony Response from a PSR-7 one. @@ -30,5 +30,5 @@ public static function createRequest(ServerRequestInterface $psrHttpMessageReque * * @return Response */ - public static function createResponse(ResponseInterface $psrHttpMessageResponse); + public function createResponse(ResponseInterface $psrHttpMessageResponse); } diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php index 2ad26ba..31cb721 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/PsrHttpMessageFactoryInterface.php @@ -21,7 +21,7 @@ interface PsrHttpMessageFactoryInterface * * @return ServerRequestInterface */ - public static function createRequest(Request $symfonyRequest); + public function createRequest(Request $symfonyRequest); /** * Creates a PSR-7 Response from a Symfony one. @@ -30,5 +30,5 @@ public static function createRequest(Request $symfonyRequest); * * @return ResponseInterface */ - public static function createResponse(Response $symfonyResponse); + public function createResponse(Response $symfonyResponse); } diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 57f810b..602c254 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -1,15 +1,54 @@ */ class HttpFoundationFactoryTest extends \PHPUnit_Framework_TestCase { + private $factory; + + public function setup() + { + $this->factory = new HttpFoundationFactory(); + } + public function testCreateRequest() { + $serverRequest = new ServerRequest(); + $serverRequest->withQueryParams(array('url' => 'http://les-tilleuls.coop')); + $serverRequest->withParsedBody(array('url' => 'http://dunglas.fr')); + + $stdClass = new \stdClass(); + $serverRequest->withAttribute('custom', $stdClass); + + $serverRequest->withCookieParams(array('city' => 'Lille')); + $serverRequest->withServerParams(array('country' => 'France')); + $serverRequest->withBody(new Stream('The body')); + + $symfonyRequest = $this->factory->createRequest($serverRequest); + $this->assertEquals('http://les-tilleuls.coop', $symfonyRequest->query->get('url')); + $this->assertEquals('http://dunglas.fr', $symfonyRequest->request->get('url')); + $this->assertEquals($stdClass, $symfonyRequest->attributes->get('custom')); + $this->assertEquals('Lille', $symfonyRequest->cookies->get('city')); + $this->assertEquals('France', $symfonyRequest->server->get('country')); + $this->assertEquals('The body', $symfonyRequest->getContent()); + } + + public function testCreateRequestWithNonArrayParsedBody() + { + $serverRequest = new ServerRequest(); + + $serverRequest->withParsedBody(null); + $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); + + $serverRequest->withParsedBody(new \stdClass()); + $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); } public function testCreateResponse() @@ -17,3 +56,4 @@ public function testCreateResponse() } } + diff --git a/Tests/Fixtures/Message.php b/Tests/Fixtures/Message.php new file mode 100644 index 0000000..c14f3df --- /dev/null +++ b/Tests/Fixtures/Message.php @@ -0,0 +1,84 @@ + + */ +class Message implements MessageInterface +{ + private $version = '1.1'; + private $headers = array(); + private $body; + + public function __construct() + { + $this->body = new Stream(); + } + + public function getProtocolVersion() + { + return $this->version; + } + + public function withProtocolVersion($version) + { + $this->version = $version; + } + + public function getHeaders() + { + return $this->headers; + } + + public function hasHeader($name) + { + return isset($this->headers[$name]); + } + + public function getHeader($name) + { + return $this->hasHeader($name) ? $this->headers[$name] : array(); + } + + public function getHeaderLine($name) + { + return $this->hasHeader($name) ? join(',', $this->headers[$name]) : ''; + } + + public function withHeader($name, $value) + { + if (!is_array($value)) { + $value = array($value); + } + + $this->headers[$name] = $value; + } + + public function withAddedHeader($name, $value) + { + $this->headers[$name][] = $value; + } + + public function withoutHeader($name) + { + if ($this->hasHeader($name)) { + unset($this->headers[$name]); + } + } + + public function getBody() + { + return $this->body; + } + + public function withBody(StreamInterface $body) + { + $this->body = $body; + } +} diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php new file mode 100644 index 0000000..26ade63 --- /dev/null +++ b/Tests/Fixtures/ServerRequest.php @@ -0,0 +1,124 @@ + + */ +class ServerRequest extends Message implements ServerRequestInterface +{ + private $requestTarget = '/'; + private $method = 'GET'; + private $uri; + private $server = array(); + private $cookies = array(); + private $query = array(); + private $uploadedFiles = array(); + private $data = null; + private $attributes = array(); + + public function getRequestTarget() + { + return $this->requestTarget; + } + + public function withRequestTarget($requestTarget) + { + $this->requestTarget = $requestTarget; + } + + public function getMethod() + { + return $this->method; + } + + public function withMethod($method) + { + $this->method = $method; + } + + public function getUri() + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false) + { + $this->uri = $uri; + } + + public function getServerParams() + { + return $this->server; + } + + public function withServerParams(array $serverParams) + { + $this->server = $serverParams; + } + + public function getCookieParams() + { + return $this->cookies; + } + + public function withCookieParams(array $cookies) + { + $this->cookies = $cookies; + } + + public function getQueryParams() + { + return $this->query; + } + + public function withQueryParams(array $query) + { + $this->query = $query; + } + + public function getUploadedFiles() + { + return $this->uploadedFiles; + } + + public function withUploadedFiles(array $uploadedFiles) + { + $this->uploadedFiles = $uploadedFiles; + } + + public function getParsedBody() + { + return $this->data; + } + + public function withParsedBody($data) + { + $this->data = $data; + } + + public function getAttributes() + { + return $this->attributes; + } + + public function getAttribute($name, $default = null) + { + return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + } + + public function withAttribute($name, $value) + { + $this->attributes[$name] = $value; + } + + public function withoutAttribute($name) + { + if ($this->getAttribute($name)) { + unset($this->attributes[$name]); + } + } +} diff --git a/Tests/Fixtures/Stream.php b/Tests/Fixtures/Stream.php new file mode 100644 index 0000000..acb13e1 --- /dev/null +++ b/Tests/Fixtures/Stream.php @@ -0,0 +1,86 @@ + + */ +class Stream implements StreamInterface +{ + private $stringContent; + + public function __construct($stringContent = '') + { + $this->stringContent = $stringContent; + } + + public function __toString() + { + return $this->stringContent; + } + + public function close() + { + } + + public function detach() + { + } + + public function getSize() + { + } + + public function tell() + { + return 0; + } + + public function eof() + { + return true; + } + + public function isSeekable() + { + return false; + } + + public function seek($offset, $whence = SEEK_SET) + { + } + + public function rewind() + { + } + + public function isWritable() + { + return false; + } + + public function write($string) + { + } + + public function isReadable() + { + return true; + } + + public function read($length) + { + return $this->stringContent; + } + + public function getContents() + { + return $this->stringContent; + } + + public function getMetadata($key = null) + { + } +} From 656318bea3a322e2007f912021090c1a5a3a926a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 00:51:13 +0200 Subject: [PATCH 10/37] Remove a short array usage --- Factory/HttpFoundationFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index f9fdf94..1e544d5 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -21,7 +21,7 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface public function createRequest(ServerRequestInterface $psrHttpMessageRequest) { $parsedBody = $psrHttpMessageRequest->getParsedBody(); - $request = is_array($parsedBody) ? $parsedBody : []; + $request = is_array($parsedBody) ? $parsedBody : array(); return new Request( $psrHttpMessageRequest->getQueryParams(), From 40c297381bb9c5cd73b752e739a86a01c43749d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 08:09:32 +0200 Subject: [PATCH 11/37] Make immutable --- Tests/Factory/HttpFoundationFactoryTest.php | 3 +-- Tests/Fixtures/ServerRequest.php | 12 +++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 602c254..c99b248 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -19,7 +19,7 @@ public function setup() public function testCreateRequest() { - $serverRequest = new ServerRequest(); + $serverRequest = new ServerRequest(array('country' => 'France')); $serverRequest->withQueryParams(array('url' => 'http://les-tilleuls.coop')); $serverRequest->withParsedBody(array('url' => 'http://dunglas.fr')); @@ -27,7 +27,6 @@ public function testCreateRequest() $serverRequest->withAttribute('custom', $stdClass); $serverRequest->withCookieParams(array('city' => 'Lille')); - $serverRequest->withServerParams(array('country' => 'France')); $serverRequest->withBody(new Stream('The body')); $symfonyRequest = $this->factory->createRequest($serverRequest); diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php index 26ade63..d902495 100644 --- a/Tests/Fixtures/ServerRequest.php +++ b/Tests/Fixtures/ServerRequest.php @@ -20,6 +20,13 @@ class ServerRequest extends Message implements ServerRequestInterface private $data = null; private $attributes = array(); + public function __construct($server = array()) + { + parent::__construct(); + + $this->server = $server; + } + public function getRequestTarget() { return $this->requestTarget; @@ -55,11 +62,6 @@ public function getServerParams() return $this->server; } - public function withServerParams(array $serverParams) - { - $this->server = $serverParams; - } - public function getCookieParams() { return $this->cookies; From a246407983db77d55c07bbdb75908ff86895d70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 08:29:51 +0200 Subject: [PATCH 12/37] Enforce immutability --- Tests/Factory/HttpFoundationFactoryTest.php | 60 ++++++++++++++++----- Tests/Fixtures/Message.php | 22 ++++---- Tests/Fixtures/ServerRequest.php | 48 +++++++++-------- 3 files changed, 83 insertions(+), 47 deletions(-) diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index c99b248..2288ac0 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -19,15 +19,21 @@ public function setup() public function testCreateRequest() { - $serverRequest = new ServerRequest(array('country' => 'France')); - $serverRequest->withQueryParams(array('url' => 'http://les-tilleuls.coop')); - $serverRequest->withParsedBody(array('url' => 'http://dunglas.fr')); - $stdClass = new \stdClass(); - $serverRequest->withAttribute('custom', $stdClass); - - $serverRequest->withCookieParams(array('city' => 'Lille')); - $serverRequest->withBody(new Stream('The body')); + $serverRequest = new ServerRequest( + '1.1', + array(), + new Stream('The body'), + '/about/kevin', + 'GET', + 'http://les-tilleuls.coop/about/kevin', + array('country' => 'France'), + array('city' => 'Lille'), + array('url' => 'http://les-tilleuls.coop'), + array(), + array('url' => 'http://dunglas.fr'), + array('custom' => $stdClass) + ); $symfonyRequest = $this->factory->createRequest($serverRequest); @@ -39,14 +45,43 @@ public function testCreateRequest() $this->assertEquals('The body', $symfonyRequest->getContent()); } - public function testCreateRequestWithNonArrayParsedBody() + public function testCreateRequestWithNullParsedBody() { - $serverRequest = new ServerRequest(); + $serverRequest = new ServerRequest( + '1.1', + array(), + new Stream(), + '/', + 'GET', + null, + array(), + array(), + array(), + array(), + null, + array() + ); - $serverRequest->withParsedBody(null); $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); + } + + public function testCreateRequestWithObjectParsedBody() + { + $serverRequest = new ServerRequest( + '1.1', + array(), + new Stream(), + '/', + 'GET', + null, + array(), + array(), + array(), + array(), + new \stdClass(), + array() + ); - $serverRequest->withParsedBody(new \stdClass()); $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); } @@ -55,4 +90,3 @@ public function testCreateResponse() } } - diff --git a/Tests/Fixtures/Message.php b/Tests/Fixtures/Message.php index c14f3df..ee49172 100644 --- a/Tests/Fixtures/Message.php +++ b/Tests/Fixtures/Message.php @@ -16,9 +16,11 @@ class Message implements MessageInterface private $headers = array(); private $body; - public function __construct() + public function __construct($version = '1.1', array $headers = array(), StreamInterface $body = null) { - $this->body = new Stream(); + $this->version = $version; + $this->headers = $headers; + $this->body = null === $body ? new Stream() : $body; } public function getProtocolVersion() @@ -28,7 +30,7 @@ public function getProtocolVersion() public function withProtocolVersion($version) { - $this->version = $version; + throw \BadMethodCallException('Not implemented.'); } public function getHeaders() @@ -53,23 +55,17 @@ public function getHeaderLine($name) public function withHeader($name, $value) { - if (!is_array($value)) { - $value = array($value); - } - - $this->headers[$name] = $value; + throw \BadMethodCallException('Not implemented.'); } public function withAddedHeader($name, $value) { - $this->headers[$name][] = $value; + throw \BadMethodCallException('Not implemented.'); } public function withoutHeader($name) { - if ($this->hasHeader($name)) { - unset($this->headers[$name]); - } + throw \BadMethodCallException('Not implemented.'); } public function getBody() @@ -79,6 +75,6 @@ public function getBody() public function withBody(StreamInterface $body) { - $this->body = $body; + throw \BadMethodCallException('Not implemented.'); } } diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php index d902495..3b5ac4c 100644 --- a/Tests/Fixtures/ServerRequest.php +++ b/Tests/Fixtures/ServerRequest.php @@ -3,6 +3,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; /** @@ -10,21 +11,29 @@ */ class ServerRequest extends Message implements ServerRequestInterface { - private $requestTarget = '/'; - private $method = 'GET'; + private $requestTarget ; + private $method; private $uri; - private $server = array(); - private $cookies = array(); - private $query = array(); - private $uploadedFiles = array(); - private $data = null; - private $attributes = array(); + private $server; + private $cookies; + private $query; + private $uploadedFiles; + private $data; + private $attributes; - public function __construct($server = array()) + public function __construct($version = '1.1', array $headers = array(), StreamInterface $body = null, $requestTarget = '/', $method = 'GET', $uri = null, array $server = array(), array $cookies = array(), array $query = array(), array $uploadedFiles = array(), $data = null, array $attributes = array()) { - parent::__construct(); + parent::__construct($version, $headers, $body); + $this->requestTarget = $requestTarget; + $this->method = $method; + $this->uri = $uri; $this->server = $server; + $this->cookies = $cookies; + $this->query = $query; + $this->uploadedFiles = $uploadedFiles; + $this->data = $data; + $this->attributes = $attributes; } public function getRequestTarget() @@ -34,7 +43,7 @@ public function getRequestTarget() public function withRequestTarget($requestTarget) { - $this->requestTarget = $requestTarget; + throw \BadMethodCallException('Not implemented.'); } public function getMethod() @@ -44,7 +53,6 @@ public function getMethod() public function withMethod($method) { - $this->method = $method; } public function getUri() @@ -54,7 +62,7 @@ public function getUri() public function withUri(UriInterface $uri, $preserveHost = false) { - $this->uri = $uri; + throw \BadMethodCallException('Not implemented.'); } public function getServerParams() @@ -69,7 +77,7 @@ public function getCookieParams() public function withCookieParams(array $cookies) { - $this->cookies = $cookies; + throw \BadMethodCallException('Not implemented.'); } public function getQueryParams() @@ -79,7 +87,7 @@ public function getQueryParams() public function withQueryParams(array $query) { - $this->query = $query; + throw \BadMethodCallException('Not implemented.'); } public function getUploadedFiles() @@ -89,7 +97,7 @@ public function getUploadedFiles() public function withUploadedFiles(array $uploadedFiles) { - $this->uploadedFiles = $uploadedFiles; + throw \BadMethodCallException('Not implemented.'); } public function getParsedBody() @@ -99,7 +107,7 @@ public function getParsedBody() public function withParsedBody($data) { - $this->data = $data; + throw \BadMethodCallException('Not implemented.'); } public function getAttributes() @@ -114,13 +122,11 @@ public function getAttribute($name, $default = null) public function withAttribute($name, $value) { - $this->attributes[$name] = $value; + throw \BadMethodCallException('Not implemented.'); } public function withoutAttribute($name) { - if ($this->getAttribute($name)) { - unset($this->attributes[$name]); - } + throw \BadMethodCallException('Not implemented.'); } } From 77360d65b72bd78d127f2762b10881633747e182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 09:46:59 +0200 Subject: [PATCH 13/37] Uploaded file support --- Factory/DiactorosFactory.php | 18 ++++++- Factory/HttpFoundationFactory.php | 52 ++++++++++++++++++- HttpFoundationFactoryInterface.php | 17 ++++-- PsrHttpMessageFactoryInterface.php | 17 ++++-- Tests/Factory/HttpFoundationFactoryTest.php | 25 +++++++++ Tests/Fixtures/UploadedFile.php | 57 +++++++++++++++++++++ 6 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 Tests/Fixtures/UploadedFile.php diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 6142a93..1160a24 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -3,10 +3,12 @@ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Symfony\Bridge\PsrHttpMessage\PsrHttpMessageFactoryInterface; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Zend\Diactoros\ServerRequest; +use Zend\Diactoros\ServerRequest as DiactorosRequest; use Zend\Diactoros\Response as DiactorosResponse; +use Zend\Diactoros\UploadedFile as DiactorosUploadedFile; /** * Builds Psr\HttpMessage instances using the Zend Diactoros implementation. @@ -21,7 +23,7 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface */ public function createRequest(Request $symfonyRequest) { - return new ServerRequest( + return new DiactorosRequest( ); } @@ -35,4 +37,16 @@ public function createResponse(Response $symfonyResponse) ); } + + /** + * {@inheritdoc} + */ + public function createUploadedFile(UploadedFile $symfonyUploadedFile) + { + return new DiactorosUploadedFile( + null, + null, + null + ); + } } diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 1e544d5..dc67636 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -4,7 +4,9 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UploadedFileInterface; use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -28,14 +30,62 @@ public function createRequest(ServerRequestInterface $psrHttpMessageRequest) $request, $psrHttpMessageRequest->getAttributes(), $psrHttpMessageRequest->getCookieParams(), - array(), // TODO + $this->getFiles($psrHttpMessageRequest->getUploadedFiles()), $psrHttpMessageRequest->getServerParams(), $psrHttpMessageRequest->getBody()->__toString() ); } + /** + * Converts to the input array to $_FILES structure. + * + * @param array $uploadedFiles + * + * @return array + */ private function getFiles(array $uploadedFiles) { + $files = array(); + + foreach ($uploadedFiles as $key => $value) { + if ($value instanceof UploadedFileInterface) { + $files[$key] = $this->createUploadedFile($value); + } else { + $files[$key] = $this->getFiles($value); + } + } + + return $files; + } + + /** + * {@inheritdoc} + */ + public function createUploadedFile(UploadedFileInterface $psrUploadedFile) + { + $tempnam = $this->getTemporaryPath(); + $psrUploadedFile->moveTo($tempnam); + + $clientFileName = $psrUploadedFile->getClientFilename(); + + return new UploadedFile( + $tempnam, + null === $clientFileName ? '' : $clientFileName, + $psrUploadedFile->getClientMediaType(), + $psrUploadedFile->getSize(), + $psrUploadedFile->getError(), + true + ); + } + + /** + * Gets a temporary file path. + * + * @return string + */ + protected function getTemporaryPath() + { + return tempnam(sys_get_temp_dir(), uniqid('symfony', true)); } /** diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index 064385c..1af29a7 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -4,18 +4,20 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UploadedFileInterface; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** - * Creates Symfony Request and Response from PSR-7 ones. + * Creates Symfony Request and Response instances from PSR-7 ones. * * @author Kévin Dunglas */ interface HttpFoundationFactoryInterface { /** - * Creates a Symfony Request from a PSR-7 one. + * Creates a Symfony Request instance from a PSR-7 one. * * @param ServerRequestInterface $psrHttpMessageRequest * @@ -24,7 +26,16 @@ interface HttpFoundationFactoryInterface public function createRequest(ServerRequestInterface $psrHttpMessageRequest); /** - * Creates a Symfony Response from a PSR-7 one. + * Creates Symfony UploadedFile instance from PSR-7 ones. + * + * @param UploadedFileInterface $psrUploadedFile + * + * @return UploadedFile + */ + public function createUploadedFile(UploadedFileInterface $psrUploadedFile); + + /** + * Creates a Symfony Response instance from a PSR-7 one. * * @param ResponseInterface $psrHttpMessageResponse * diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php index 31cb721..b04bc59 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/PsrHttpMessageFactoryInterface.php @@ -4,18 +4,20 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UploadedFileInterface; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** - * Creates PSR HTTP Request and Response from Symfony ones. + * Creates PSR HTTP Request and Response instances from Symfony ones. * * @author Kévin Dunglas */ interface PsrHttpMessageFactoryInterface { /** - * Creates a PSR-7 Request from a Symfony one. + * Creates a PSR-7 Request instance from a Symfony one. * * @param Request $symfonyRequest * @@ -24,7 +26,16 @@ interface PsrHttpMessageFactoryInterface public function createRequest(Request $symfonyRequest); /** - * Creates a PSR-7 Response from a Symfony one. + * Creates a PSR-7 UploadedFile instance from a Symfony one. + * + * @param UploadedFile $symfonyUploadedFile + * + * @return UploadedFileInterface + */ + public function createUploadedFile(UploadedFile $symfonyUploadedFile); + + /** + * Creates a PSR-7 Response instance from a Symfony one. * * @param Response $symfonyResponse * diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 2288ac0..e89f61c 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -1,9 +1,11 @@ @@ -85,6 +87,29 @@ public function testCreateRequestWithObjectParsedBody() $this->assertCount(0, $this->factory->createRequest($serverRequest)->request); } + public function testCreateUploadedFile() + { + $tmpDir = sys_get_temp_dir(); + + $filePath = tempnam($tmpDir, uniqid()); + file_put_contents($filePath, 'An uploaded file.'); + + $size = filesize($filePath); + $uploadedFile = new UploadedFile($filePath, $size, UPLOAD_ERR_OK, 'myfile.txt', 'text/plain'); + + $symfonyUploadedFile = $this->factory->createUploadedFile($uploadedFile); + + $uniqid = uniqid(); + $symfonyUploadedFile->move($tmpDir, $uniqid); + + $this->assertEquals($size, $symfonyUploadedFile->getClientSize()); + $this->assertEquals(UPLOAD_ERR_OK, $symfonyUploadedFile->getError()); + $this->assertEquals('myfile.txt', $symfonyUploadedFile->getClientOriginalName()); + $this->assertEquals('txt', $symfonyUploadedFile->getClientOriginalExtension()); + $this->assertEquals('text/plain', $symfonyUploadedFile->getClientMimeType()); + $this->assertEquals('An uploaded file.', file_get_contents($tmpDir.'/'.$uniqid)); + } + public function testCreateResponse() { diff --git a/Tests/Fixtures/UploadedFile.php b/Tests/Fixtures/UploadedFile.php new file mode 100644 index 0000000..de02397 --- /dev/null +++ b/Tests/Fixtures/UploadedFile.php @@ -0,0 +1,57 @@ + + */ +class UploadedFile implements UploadedFileInterface +{ + private $filePath; + private $size; + private $error; + private $clientFileName; + private $clientMediaType; + + public function __construct($filePath, $size = null, $error = UPLOAD_ERR_OK, $clientFileName = null, $clientMediaType = null) + { + $this->filePath = $filePath; + $this->size = $size; + $this->error = $error; + $this->clientFileName = $clientFileName; + $this->clientMediaType = $clientMediaType; + } + + public function getStream() + { + throw new \RuntimeException('No stream is available.'); + } + + public function moveTo($targetPath) + { + rename($this->filePath, $targetPath); + } + + public function getSize() + { + return $this->size; + } + + public function getError() + { + return $this->error; + } + + public function getClientFilename() + { + return $this->clientFileName; + } + + public function getClientMediaType() + { + return $this->clientMediaType; + } +} From 6f5815b06e933d3008a0249c6a4183adb9e2271b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 11:02:53 +0200 Subject: [PATCH 14/37] Fix some @stof comments --- Factory/HttpFoundationFactory.php | 18 +++++++++--------- HttpFoundationFactoryInterface.php | 8 ++++---- composer.json | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index dc67636..3b1b89d 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -20,19 +20,19 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface /** * {@inheritdoc} */ - public function createRequest(ServerRequestInterface $psrHttpMessageRequest) + public function createRequest(ServerRequestInterface $psrRequest) { - $parsedBody = $psrHttpMessageRequest->getParsedBody(); + $parsedBody = $psrRequest->getParsedBody(); $request = is_array($parsedBody) ? $parsedBody : array(); return new Request( - $psrHttpMessageRequest->getQueryParams(), + $psrRequest->getQueryParams(), $request, - $psrHttpMessageRequest->getAttributes(), - $psrHttpMessageRequest->getCookieParams(), - $this->getFiles($psrHttpMessageRequest->getUploadedFiles()), - $psrHttpMessageRequest->getServerParams(), - $psrHttpMessageRequest->getBody()->__toString() + $psrRequest->getAttributes(), + $psrRequest->getCookieParams(), + $this->getFiles($psrRequest->getUploadedFiles()), + $psrRequest->getServerParams(), + $psrRequest->getBody()->__toString() ); } @@ -91,7 +91,7 @@ protected function getTemporaryPath() /** * {@inheritdoc} */ - public function createResponse(ResponseInterface $psrHttpMessageResponse) + public function createResponse(ResponseInterface $psrResponse) { return new Response( diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index 1af29a7..a066d01 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -19,11 +19,11 @@ interface HttpFoundationFactoryInterface /** * Creates a Symfony Request instance from a PSR-7 one. * - * @param ServerRequestInterface $psrHttpMessageRequest + * @param ServerRequestInterface $psrRequest * * @return Request */ - public function createRequest(ServerRequestInterface $psrHttpMessageRequest); + public function createRequest(ServerRequestInterface $psrRequest); /** * Creates Symfony UploadedFile instance from PSR-7 ones. @@ -37,9 +37,9 @@ public function createUploadedFile(UploadedFileInterface $psrUploadedFile); /** * Creates a Symfony Response instance from a PSR-7 one. * - * @param ResponseInterface $psrHttpMessageResponse + * @param ResponseInterface $psrResponse * * @return Response */ - public function createResponse(ResponseInterface $psrHttpMessageResponse); + public function createResponse(ResponseInterface $psrResponse); } diff --git a/composer.json b/composer.json index 57eae1b..43f25be 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "zendframework/zend-diactoros": "~1.0" }, "suggest": { - "zendframework/zend-diactoros": "To use the zend-diactoros adapter" + "zendframework/zend-diactoros": "To use the zend-diactoros factory" }, "autoload": { "psr-4": { "Symfony\\Bridge\\PsrHttpMessage\\": "" } From 52405397d57b5108ce647e6e30ddd35690503cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 22 May 2015 23:27:01 +0200 Subject: [PATCH 15/37] Add license headers --- Factory/DiactorosFactory.php | 9 +++++++++ Factory/HttpFoundationFactory.php | 9 +++++++++ HttpFoundationFactoryInterface.php | 9 +++++++++ PsrHttpMessageFactoryInterface.php | 9 +++++++++ Tests/Factory/DiactorosFactoryTest.php | 9 +++++++++ Tests/Factory/HttpFoundationFactoryTest.php | 9 +++++++++ Tests/Fixtures/Message.php | 9 +++++++++ Tests/Fixtures/ServerRequest.php | 9 +++++++++ Tests/Fixtures/Stream.php | 9 +++++++++ Tests/Fixtures/UploadedFile.php | 10 +++++++++- 10 files changed, 90 insertions(+), 1 deletion(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 1160a24..8a9fd4f 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Factory; use Symfony\Bridge\PsrHttpMessage\PsrHttpMessageFactoryInterface; diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 3b1b89d..fe6fac6 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Factory; use Psr\Http\Message\ServerRequestInterface; diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index a066d01..acdd44d 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage; use Psr\Http\Message\ServerRequestInterface; diff --git a/PsrHttpMessageFactoryInterface.php b/PsrHttpMessageFactoryInterface.php index b04bc59..c6b4ab9 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/PsrHttpMessageFactoryInterface.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage; use Psr\Http\Message\ServerRequestInterface; diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 4b4322c..6ff4cb4 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; /** diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index e89f61c..99d2cb2 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; diff --git a/Tests/Fixtures/Message.php b/Tests/Fixtures/Message.php index ee49172..b94e299 100644 --- a/Tests/Fixtures/Message.php +++ b/Tests/Fixtures/Message.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; use Psr\Http\Message\MessageInterface; diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php index 3b5ac4c..4622337 100644 --- a/Tests/Fixtures/ServerRequest.php +++ b/Tests/Fixtures/ServerRequest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; use Psr\Http\Message\ServerRequestInterface; diff --git a/Tests/Fixtures/Stream.php b/Tests/Fixtures/Stream.php index acb13e1..aeca3d8 100644 --- a/Tests/Fixtures/Stream.php +++ b/Tests/Fixtures/Stream.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; use Psr\Http\Message\StreamInterface; diff --git a/Tests/Fixtures/UploadedFile.php b/Tests/Fixtures/UploadedFile.php index de02397..4cfa98b 100644 --- a/Tests/Fixtures/UploadedFile.php +++ b/Tests/Fixtures/UploadedFile.php @@ -1,8 +1,16 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; -use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileInterface; /** From 8b4a07858e8fd6cb501400d35f1697854b128cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 May 2015 08:42:49 +0200 Subject: [PATCH 16/37] More unit tests for uploaded files. --- Tests/Factory/HttpFoundationFactoryTest.php | 52 ++++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 99d2cb2..6d58699 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -22,10 +22,12 @@ class HttpFoundationFactoryTest extends \PHPUnit_Framework_TestCase { private $factory; + private $tmpDir; public function setup() { $this->factory = new HttpFoundationFactory(); + $this->tmpDir = sys_get_temp_dir(); } public function testCreateRequest() @@ -41,7 +43,15 @@ public function testCreateRequest() array('country' => 'France'), array('city' => 'Lille'), array('url' => 'http://les-tilleuls.coop'), - array(), + array( + 'doc1' => $this->createUploadedFile('Doc 1', UPLOAD_ERR_OK, 'doc1.txt', 'text/plain'), + 'nested' => array( + 'docs' => array( + $this->createUploadedFile('Doc 2', UPLOAD_ERR_OK, 'doc2.txt', 'text/plain'), + $this->createUploadedFile('Doc 3', UPLOAD_ERR_OK, 'doc3.txt', 'text/plain'), + ) + ) + ), array('url' => 'http://dunglas.fr'), array('custom' => $stdClass) ); @@ -49,6 +59,9 @@ public function testCreateRequest() $symfonyRequest = $this->factory->createRequest($serverRequest); $this->assertEquals('http://les-tilleuls.coop', $symfonyRequest->query->get('url')); + $this->assertEquals('doc1.txt', $symfonyRequest->files->get('doc1')->getClientOriginalName()); + $this->assertEquals('doc2.txt', $symfonyRequest->files->get('nested[docs][0]', null, true)->getClientOriginalName()); + $this->assertEquals('doc3.txt', $symfonyRequest->files->get('nested[docs][1]', null, true)->getClientOriginalName()); $this->assertEquals('http://dunglas.fr', $symfonyRequest->request->get('url')); $this->assertEquals($stdClass, $symfonyRequest->attributes->get('custom')); $this->assertEquals('Lille', $symfonyRequest->cookies->get('city')); @@ -98,25 +111,40 @@ public function testCreateRequestWithObjectParsedBody() public function testCreateUploadedFile() { - $tmpDir = sys_get_temp_dir(); - - $filePath = tempnam($tmpDir, uniqid()); - file_put_contents($filePath, 'An uploaded file.'); - - $size = filesize($filePath); - $uploadedFile = new UploadedFile($filePath, $size, UPLOAD_ERR_OK, 'myfile.txt', 'text/plain'); - + $uploadedFile = $this->createUploadedFile('An uploaded file.', UPLOAD_ERR_OK, 'myfile.txt', 'text/plain'); $symfonyUploadedFile = $this->factory->createUploadedFile($uploadedFile); $uniqid = uniqid(); - $symfonyUploadedFile->move($tmpDir, $uniqid); + $symfonyUploadedFile->move($this->tmpDir, $uniqid); - $this->assertEquals($size, $symfonyUploadedFile->getClientSize()); + $this->assertEquals($uploadedFile->getSize(), $symfonyUploadedFile->getClientSize()); $this->assertEquals(UPLOAD_ERR_OK, $symfonyUploadedFile->getError()); $this->assertEquals('myfile.txt', $symfonyUploadedFile->getClientOriginalName()); $this->assertEquals('txt', $symfonyUploadedFile->getClientOriginalExtension()); $this->assertEquals('text/plain', $symfonyUploadedFile->getClientMimeType()); - $this->assertEquals('An uploaded file.', file_get_contents($tmpDir.'/'.$uniqid)); + $this->assertEquals('An uploaded file.', file_get_contents($this->tmpDir.'/'.$uniqid)); + } + + /** + * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileException + * @expectedExceptionMessage The file "e" could not be written on disk. + */ + public function testCreateUploadedFileWithError() + { + $uploadedFile = $this->createUploadedFile('Error.', UPLOAD_ERR_CANT_WRITE, 'e', 'text/plain'); + $symfonyUploadedFile = $this->factory->createUploadedFile($uploadedFile); + + $this->assertEquals(UPLOAD_ERR_CANT_WRITE, $symfonyUploadedFile->getError()); + + $symfonyUploadedFile->move($this->tmpDir, 'shouldFail.txt'); + } + + private function createUploadedFile($content, $error, $clientFileName, $clientMediaType) + { + $filePath = tempnam($this->tmpDir, uniqid()); + file_put_contents($filePath, $content); + + return new UploadedFile($filePath, filesize($filePath), $error, $clientFileName, $clientMediaType); } public function testCreateResponse() From 14dac4e4e980190d31c639035d889264147bc530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 May 2015 09:14:12 +0200 Subject: [PATCH 17/37] HttpFoundation Response factory and tests --- Factory/HttpFoundationFactory.php | 9 ++++- Tests/Factory/HttpFoundationFactoryTest.php | 15 +++++++ Tests/Fixtures/Response.php | 45 +++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 Tests/Fixtures/Response.php diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index fe6fac6..2b3ee8e 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -102,8 +102,13 @@ protected function getTemporaryPath() */ public function createResponse(ResponseInterface $psrResponse) { - return new Response( - + $response = new Response( + $psrResponse->getBody()->__toString(), + $psrResponse->getStatusCode(), + $psrResponse->getHeaders() ); + $response->setProtocolVersion($psrResponse->getProtocolVersion()); + + return $response; } } diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 6d58699..d0843ea 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; +use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response; use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\ServerRequest; use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Stream; use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\UploadedFile; @@ -149,6 +150,20 @@ private function createUploadedFile($content, $error, $clientFileName, $clientMe public function testCreateResponse() { + $response = new Response( + '1.0', + array( + 'X-Symfony' => '2.8' + ), + new Stream('The response body'), + 200 + ); + + $symfonyResponse = $this->factory->createResponse($response); + $this->assertEquals('1.0', $symfonyResponse->getProtocolVersion()); + $this->assertEquals('2.8', $symfonyResponse->headers->get('X-Symfony')); + $this->assertEquals('The response body', $symfonyResponse->getContent()); + $this->assertEquals(200, $symfonyResponse->getStatusCode()); } } diff --git a/Tests/Fixtures/Response.php b/Tests/Fixtures/Response.php new file mode 100644 index 0000000..204cc8e --- /dev/null +++ b/Tests/Fixtures/Response.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PsrHttpMessage\Tests\Fixtures; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; + +/** + * @author Kévin Dunglas + */ +class Response extends Message implements ResponseInterface +{ + private $statusCode; + + public function __construct($version = '1.1', array $headers = array(), StreamInterface $body = null, $statusCode) + { + parent::__construct($version, $headers, $body); + + $this->statusCode = $statusCode; + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function withStatus($code, $reasonPhrase = '') + { + throw \BadMethodCallException('Not implemented.'); + } + + public function getReasonPhrase() + { + throw \BadMethodCallException('Not implemented.'); + } +} From 8c3c90e06b29e4730b3647762b8089f10b69b44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 May 2015 09:14:34 +0200 Subject: [PATCH 18/37] Fix CS --- Factory/DiactorosFactory.php | 1 - Tests/Factory/DiactorosFactoryTest.php | 2 -- Tests/Factory/HttpFoundationFactoryTest.php | 6 +++--- Tests/Fixtures/Message.php | 2 +- Tests/Fixtures/ServerRequest.php | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 8a9fd4f..cd82d24 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -26,7 +26,6 @@ */ class DiactorosFactory implements PsrHttpMessageFactoryInterface { - /** * {@inheritdoc} */ diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 6ff4cb4..cea5108 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -18,11 +18,9 @@ class DiactorosFactoryTest extends \PHPUnit_Framework_TestCase { public function testCreateRequest() { - } public function testCreateResponse() { - } } diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index d0843ea..8a7192e 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -50,8 +50,8 @@ public function testCreateRequest() 'docs' => array( $this->createUploadedFile('Doc 2', UPLOAD_ERR_OK, 'doc2.txt', 'text/plain'), $this->createUploadedFile('Doc 3', UPLOAD_ERR_OK, 'doc3.txt', 'text/plain'), - ) - ) + ), + ), ), array('url' => 'http://dunglas.fr'), array('custom' => $stdClass) @@ -153,7 +153,7 @@ public function testCreateResponse() $response = new Response( '1.0', array( - 'X-Symfony' => '2.8' + 'X-Symfony' => '2.8', ), new Stream('The response body'), 200 diff --git a/Tests/Fixtures/Message.php b/Tests/Fixtures/Message.php index b94e299..cb30ec2 100644 --- a/Tests/Fixtures/Message.php +++ b/Tests/Fixtures/Message.php @@ -59,7 +59,7 @@ public function getHeader($name) public function getHeaderLine($name) { - return $this->hasHeader($name) ? join(',', $this->headers[$name]) : ''; + return $this->hasHeader($name) ? implode(',', $this->headers[$name]) : ''; } public function withHeader($name, $value) diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php index 4622337..593e940 100644 --- a/Tests/Fixtures/ServerRequest.php +++ b/Tests/Fixtures/ServerRequest.php @@ -20,7 +20,7 @@ */ class ServerRequest extends Message implements ServerRequestInterface { - private $requestTarget ; + private $requestTarget; private $method; private $uri; private $server; From 65261eef193db91ada7f574aa1e26cd67e642186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 May 2015 23:39:43 +0200 Subject: [PATCH 19/37] Diactoros factory draft implementation --- Factory/DiactorosFactory.php | 41 ++++++++++++++++++++++---- Factory/HttpFoundationFactory.php | 6 ++-- Tests/Factory/DiactorosFactoryTest.php | 1 + 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index cd82d24..4f93a35 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -32,17 +32,46 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface public function createRequest(Request $symfonyRequest) { return new DiactorosRequest( - + $symfonyRequest->server->all(), + array(), + $symfonyRequest->getUri(), + $symfonyRequest->getMethod(), + $symfonyRequest->getContent(), + $symfonyRequest->server->getHeaders() ); } + /** + * Converts Symfony uploaded files array to the PSR one. + * + * @param array $uploadedFiles + * + * @return array + */ + private function getFiles(array $uploadedFiles) + { + $files = array(); + + foreach ($uploadedFiles as $key => $value) { + if ($value instanceof UploadedFile) { + $files[$key] = $this->createUploadedFile($value); + } else { + $files[$key] = $this->getFiles($value); + } + } + + return $files; + } + /** * {@inheritdoc} */ public function createResponse(Response $symfonyResponse) { return new DiactorosResponse( - + $symfonyResponse->getContent(), + $symfonyResponse->getStatusCode(), + $symfonyResponse->headers->all() ); } @@ -52,9 +81,11 @@ public function createResponse(Response $symfonyResponse) public function createUploadedFile(UploadedFile $symfonyUploadedFile) { return new DiactorosUploadedFile( - null, - null, - null + $symfonyUploadedFile->getRealPath(), + $symfonyUploadedFile->getSize(), + $symfonyUploadedFile->getError(), + $symfonyUploadedFile->getClientOriginalName(), + $symfonyUploadedFile->getClientMimeType() ); } } diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 2b3ee8e..8a1b981 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -72,13 +72,13 @@ private function getFiles(array $uploadedFiles) */ public function createUploadedFile(UploadedFileInterface $psrUploadedFile) { - $tempnam = $this->getTemporaryPath(); - $psrUploadedFile->moveTo($tempnam); + $temporaryPath = $this->getTemporaryPath(); + $psrUploadedFile->moveTo($temporaryPath); $clientFileName = $psrUploadedFile->getClientFilename(); return new UploadedFile( - $tempnam, + $temporaryPath, null === $clientFileName ? '' : $clientFileName, $psrUploadedFile->getClientMediaType(), $psrUploadedFile->getSize(), diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index cea5108..ce92002 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -10,6 +10,7 @@ */ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; +use Symfony\Component\HttpFoundation\Request; /** * @author Kévin Dunglas From 7e44bc24eab6cacdd14c3be97282cedcadf2c154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 10:49:36 +0200 Subject: [PATCH 20/37] New version of DiactorosFactory::createRequest(). Tests. --- Factory/DiactorosFactory.php | 43 +++++++------ Tests/Factory/DiactorosFactoryTest.php | 87 ++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 19 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 4f93a35..640de8a 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -15,8 +15,8 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Zend\Diactoros\ServerRequest as DiactorosRequest; use Zend\Diactoros\Response as DiactorosResponse; +use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory; use Zend\Diactoros\UploadedFile as DiactorosUploadedFile; /** @@ -31,14 +31,19 @@ class DiactorosFactory implements PsrHttpMessageFactoryInterface */ public function createRequest(Request $symfonyRequest) { - return new DiactorosRequest( + $request = DiactorosRequestFactory::fromGlobals( $symfonyRequest->server->all(), - array(), - $symfonyRequest->getUri(), - $symfonyRequest->getMethod(), - $symfonyRequest->getContent(), - $symfonyRequest->server->getHeaders() + $symfonyRequest->query->all(), + $symfonyRequest->request->all(), + $symfonyRequest->cookies->all(), + $this->getFiles($symfonyRequest->files->all()) ); + + foreach ($symfonyRequest->attributes->all() as $key => $value) { + $request = $request->withAttribute($key, $value); + } + + return $request; } /** @@ -63,18 +68,6 @@ private function getFiles(array $uploadedFiles) return $files; } - /** - * {@inheritdoc} - */ - public function createResponse(Response $symfonyResponse) - { - return new DiactorosResponse( - $symfonyResponse->getContent(), - $symfonyResponse->getStatusCode(), - $symfonyResponse->headers->all() - ); - } - /** * {@inheritdoc} */ @@ -88,4 +81,16 @@ public function createUploadedFile(UploadedFile $symfonyUploadedFile) $symfonyUploadedFile->getClientMimeType() ); } + + /** + * {@inheritdoc} + */ + public function createResponse(Response $symfonyResponse) + { + return new DiactorosResponse( + $symfonyResponse->getContent(), + $symfonyResponse->getStatusCode(), + $symfonyResponse->headers->all() + ); + } } diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index ce92002..967c43f 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -10,6 +10,9 @@ */ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; + +use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; /** @@ -17,8 +20,92 @@ */ class DiactorosFactoryTest extends \PHPUnit_Framework_TestCase { + private $factory; + private $tmpDir; + + public function setup() + { + $this->factory = new DiactorosFactory(); + $this->tmpDir = sys_get_temp_dir(); + } + public function testCreateRequest() { + $stdClass = new \stdClass(); + $request = new Request( + array( + 'foo' => '1', + 'bar' => array('baz' => '42'), + ), + array( + 'twitter' => array( + '@dunglas' => 'Kévin Dunglas', + '@coopTilleuls' => 'Les-Tilleuls.coop', + ), + 'baz' => '2', + ), + array( + 'a1' => $stdClass, + 'a2' => array('foo' => 'bar'), + ), + array( + 'c1' => 'foo', + 'c2' => array('c3' => 'bar'), + ), + array( + 'f1' => $this->createUploadedFile('F1', 'f1.txt', 'text/plain', UPLOAD_ERR_OK), + 'foo' => array('f2' => $this->createUploadedFile('F2', 'f2.txt', 'text/plain', UPLOAD_ERR_OK)), + ), + array( + 'REQUEST_METHOD' => 'POST', + 'HTTP_X_SYMFONY' => '2.8', + ), + 'Content' + ); + + $psrRequest = $this->factory->createRequest($request); + + $queryParams = $psrRequest->getQueryParams(); + $this->assertEquals('1', $queryParams['foo']); + $this->assertEquals('42', $queryParams['bar']['baz']); + + $parsedBody = $psrRequest->getParsedBody(); + $this->assertEquals('Kévin Dunglas', $parsedBody['twitter']['@dunglas']); + $this->assertEquals('Les-Tilleuls.coop', $parsedBody['twitter']['@coopTilleuls']); + $this->assertEquals('2', $parsedBody['baz']); + + $attributes = $psrRequest->getAttributes(); + $this->assertEquals($stdClass, $attributes['a1']); + $this->assertEquals('bar', $attributes['a2']['foo']); + + $cookies = $psrRequest->getCookieParams(); + $this->assertEquals('foo', $cookies['c1']); + $this->assertEquals('bar', $cookies['c2']['c3']); + + $uploadedFiles = $psrRequest->getUploadedFiles(); + $this->assertEquals('F1', $uploadedFiles['f1']->getStream()->__toString()); + $this->assertEquals('f1.txt', $uploadedFiles['f1']->getClientFilename()); + $this->assertEquals('text/plain', $uploadedFiles['f1']->getClientMediaType()); + $this->assertEquals(UPLOAD_ERR_OK, $uploadedFiles['f1']->getError()); + + $this->assertEquals('F2', $uploadedFiles['foo']['f2']->getStream()->__toString()); + $this->assertEquals('f2.txt', $uploadedFiles['foo']['f2']->getClientFilename()); + $this->assertEquals('text/plain', $uploadedFiles['foo']['f2']->getClientMediaType()); + $this->assertEquals(UPLOAD_ERR_OK, $uploadedFiles['foo']['f2']->getError()); + + $serverParams = $psrRequest->getServerParams(); + $this->assertEquals('POST', $serverParams['REQUEST_METHOD']); + $this->assertEquals('2.8', $serverParams['HTTP_X_SYMFONY']); + $this->assertEquals('POST', $psrRequest->getMethod()); + $this->assertEquals(array('2.8'), $psrRequest->getHeader('X-Symfony')); + } + + private function createUploadedFile($content, $originalName, $mimeType, $error) + { + $path = tempnam($this->tmpDir, uniqid()); + file_put_contents($path, $content); + + return new UploadedFile($path, $originalName, $mimeType, filesize($path), $error, true); } public function testCreateResponse() From 1e480a9321f07926f34b499876e85b0a743e6bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 11:02:49 +0200 Subject: [PATCH 21/37] Rename HttpMessageFactoryInterface --- Factory/DiactorosFactory.php | 4 ++-- ...ageFactoryInterface.php => HttpMessageFactoryInterface.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename PsrHttpMessageFactoryInterface.php => HttpMessageFactoryInterface.php (97%) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 640de8a..d859a30 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -11,7 +11,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Factory; -use Symfony\Bridge\PsrHttpMessage\PsrHttpMessageFactoryInterface; +use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -24,7 +24,7 @@ * * @author Kévin Dunglas */ -class DiactorosFactory implements PsrHttpMessageFactoryInterface +class DiactorosFactory implements HttpMessageFactoryInterface { /** * {@inheritdoc} diff --git a/PsrHttpMessageFactoryInterface.php b/HttpMessageFactoryInterface.php similarity index 97% rename from PsrHttpMessageFactoryInterface.php rename to HttpMessageFactoryInterface.php index c6b4ab9..ac0b497 100644 --- a/PsrHttpMessageFactoryInterface.php +++ b/HttpMessageFactoryInterface.php @@ -23,7 +23,7 @@ * * @author Kévin Dunglas */ -interface PsrHttpMessageFactoryInterface +interface HttpMessageFactoryInterface { /** * Creates a PSR-7 Request instance from a Symfony one. From 9127c843e8beb002f659b2a548aacfdd9d19112e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 11:04:01 +0200 Subject: [PATCH 22/37] Update LICENSE copyright year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0b3292c..43028bc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2014 Fabien Potencier +Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From b3600681217e29e3a57d2e67c6ec337de5a33a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 18:59:23 +0200 Subject: [PATCH 23/37] Better stream handling in DiactorosFactory::createRequest --- Factory/DiactorosFactory.php | 10 ++++++++++ Tests/Factory/DiactorosFactoryTest.php | 2 ++ 2 files changed, 12 insertions(+) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index d859a30..eaa611c 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Response; use Zend\Diactoros\Response as DiactorosResponse; use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory; +use Zend\Diactoros\Stream as DiactorosStream; use Zend\Diactoros\UploadedFile as DiactorosUploadedFile; /** @@ -31,6 +32,13 @@ class DiactorosFactory implements HttpMessageFactoryInterface */ public function createRequest(Request $symfonyRequest) { + try { + $stream = new DiactorosStream($symfonyRequest->getContent(true)); + } catch (\LogicException $e) { + $stream = new DiactorosStream('php://temp', 'wb+'); + $stream->write($symfonyRequest->getContent()); + } + $request = DiactorosRequestFactory::fromGlobals( $symfonyRequest->server->all(), $symfonyRequest->query->all(), @@ -39,6 +47,8 @@ public function createRequest(Request $symfonyRequest) $this->getFiles($symfonyRequest->files->all()) ); + $request = $request->withBody($stream); + foreach ($symfonyRequest->attributes->all() as $key => $value) { $request = $request->withAttribute($key, $value); } diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 967c43f..abc8b60 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -65,6 +65,8 @@ public function testCreateRequest() $psrRequest = $this->factory->createRequest($request); + $this->assertEquals('Content', $psrRequest->getBody()->__toString()); + $queryParams = $psrRequest->getQueryParams(); $this->assertEquals('1', $queryParams['foo']); $this->assertEquals('42', $queryParams['bar']['baz']); From 4d11665791617a9d91f49bfb2601fd6f1c973b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 19:22:18 +0200 Subject: [PATCH 24/37] New DiactorosFactory::createResponse implementation. Tests. --- Factory/DiactorosFactory.php | 28 +++++++++++++++++--------- Tests/Factory/DiactorosFactoryTest.php | 11 ++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index eaa611c..9d0b86b 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -32,13 +32,6 @@ class DiactorosFactory implements HttpMessageFactoryInterface */ public function createRequest(Request $symfonyRequest) { - try { - $stream = new DiactorosStream($symfonyRequest->getContent(true)); - } catch (\LogicException $e) { - $stream = new DiactorosStream('php://temp', 'wb+'); - $stream->write($symfonyRequest->getContent()); - } - $request = DiactorosRequestFactory::fromGlobals( $symfonyRequest->server->all(), $symfonyRequest->query->all(), @@ -47,6 +40,13 @@ public function createRequest(Request $symfonyRequest) $this->getFiles($symfonyRequest->files->all()) ); + try { + $stream = new DiactorosStream($symfonyRequest->getContent(true)); + } catch (\LogicException $e) { + $stream = new DiactorosStream('php://temp', 'wb+'); + $stream->write($symfonyRequest->getContent()); + } + $request = $request->withBody($stream); foreach ($symfonyRequest->attributes->all() as $key => $value) { @@ -97,10 +97,20 @@ public function createUploadedFile(UploadedFile $symfonyUploadedFile) */ public function createResponse(Response $symfonyResponse) { - return new DiactorosResponse( - $symfonyResponse->getContent(), + $stream = new DiactorosStream('php://temp', 'wb+'); + $stream->write($symfonyResponse->getContent()); + + $response = new DiactorosResponse( + $stream, $symfonyResponse->getStatusCode(), $symfonyResponse->headers->all() ); + + $protocolVersion = $symfonyResponse->getProtocolVersion(); + if ('1.1' !== $protocolVersion) { + $response = $response->withProtocolVersion($protocolVersion); + } + + return $response; } } diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index abc8b60..85f40bd 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -14,6 +14,7 @@ use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; /** * @author Kévin Dunglas @@ -112,5 +113,15 @@ private function createUploadedFile($content, $originalName, $mimeType, $error) public function testCreateResponse() { + $response = new Response( + 'Response content.', + 202, + array('X-Symfony' => array('2.8')) + ); + + $psrResponse = $this->factory->createResponse($response); + $this->assertEquals('Response content.', $psrResponse->getBody()->__toString()); + $this->assertEquals(202, $psrResponse->getStatusCode()); + $this->assertEquals(array('2.8'), $psrResponse->getHeader('X-Symfony')); } } From e129154703ce0bbc03b803bbeec02958fa29433e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 24 May 2015 22:04:04 +0200 Subject: [PATCH 25/37] StreamedResponse support --- Factory/DiactorosFactory.php | 13 ++++++++++++- Tests/Factory/DiactorosFactoryTest.php | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 9d0b86b..4732463 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; use Zend\Diactoros\Response as DiactorosResponse; use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory; use Zend\Diactoros\Stream as DiactorosStream; @@ -98,7 +99,17 @@ public function createUploadedFile(UploadedFile $symfonyUploadedFile) public function createResponse(Response $symfonyResponse) { $stream = new DiactorosStream('php://temp', 'wb+'); - $stream->write($symfonyResponse->getContent()); + if ($symfonyResponse instanceof StreamedResponse) { + ob_start(function ($buffer) use ($stream) { + $stream->write($buffer); + + return false; + }); + $symfonyResponse->sendContent(); + ob_end_clean(); + } else { + $stream->write($symfonyResponse->getContent()); + } $response = new DiactorosResponse( $stream, diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 85f40bd..2fd9659 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; /** * @author Kévin Dunglas @@ -124,4 +125,19 @@ public function testCreateResponse() $this->assertEquals(202, $psrResponse->getStatusCode()); $this->assertEquals(array('2.8'), $psrResponse->getHeader('X-Symfony')); } + + public function testCreateResponseFromStreamed() + { + $response = new StreamedResponse(function () { + echo "Line 1\n"; + flush(); + + echo "Line 2\n"; + flush(); + }); + + $psrResponse = $this->factory->createResponse($response); + + $this->assertEquals("Line 1\nLine 2\n", $psrResponse->getBody()->__toString()); + } } From 91a13dc66909b64758a7fb62426888c0b38ec0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 25 May 2015 09:15:51 +0200 Subject: [PATCH 26/37] Fix BadMethodCallException --- Tests/Fixtures/Message.php | 10 +++++----- Tests/Fixtures/Response.php | 4 ++-- Tests/Fixtures/ServerRequest.php | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Tests/Fixtures/Message.php b/Tests/Fixtures/Message.php index cb30ec2..5cd0999 100644 --- a/Tests/Fixtures/Message.php +++ b/Tests/Fixtures/Message.php @@ -39,7 +39,7 @@ public function getProtocolVersion() public function withProtocolVersion($version) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getHeaders() @@ -64,17 +64,17 @@ public function getHeaderLine($name) public function withHeader($name, $value) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function withAddedHeader($name, $value) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function withoutHeader($name) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getBody() @@ -84,6 +84,6 @@ public function getBody() public function withBody(StreamInterface $body) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } } diff --git a/Tests/Fixtures/Response.php b/Tests/Fixtures/Response.php index 204cc8e..70717d5 100644 --- a/Tests/Fixtures/Response.php +++ b/Tests/Fixtures/Response.php @@ -35,11 +35,11 @@ public function getStatusCode() public function withStatus($code, $reasonPhrase = '') { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getReasonPhrase() { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } } diff --git a/Tests/Fixtures/ServerRequest.php b/Tests/Fixtures/ServerRequest.php index 593e940..63b8c06 100644 --- a/Tests/Fixtures/ServerRequest.php +++ b/Tests/Fixtures/ServerRequest.php @@ -52,7 +52,7 @@ public function getRequestTarget() public function withRequestTarget($requestTarget) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getMethod() @@ -71,7 +71,7 @@ public function getUri() public function withUri(UriInterface $uri, $preserveHost = false) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getServerParams() @@ -86,7 +86,7 @@ public function getCookieParams() public function withCookieParams(array $cookies) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getQueryParams() @@ -96,7 +96,7 @@ public function getQueryParams() public function withQueryParams(array $query) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getUploadedFiles() @@ -106,7 +106,7 @@ public function getUploadedFiles() public function withUploadedFiles(array $uploadedFiles) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getParsedBody() @@ -116,7 +116,7 @@ public function getParsedBody() public function withParsedBody($data) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function getAttributes() @@ -131,11 +131,11 @@ public function getAttribute($name, $default = null) public function withAttribute($name, $value) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } public function withoutAttribute($name) { - throw \BadMethodCallException('Not implemented.'); + throw new \BadMethodCallException('Not implemented.'); } } From ef384ae537a3418b97fb197528a4134c6459d91b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 26 May 2015 00:05:39 +0200 Subject: [PATCH 27/37] Throw an exception if Zend Diactoros isn't installed. --- Factory/DiactorosFactory.php | 8 ++++++++ Tests/Fixtures/Response.php | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 4732463..d931d7f 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -28,6 +28,13 @@ */ class DiactorosFactory implements HttpMessageFactoryInterface { + public function __construct() + { + if (!class_exists('Zend\Diactoros\ServerRequestFactory')) { + throw new \RuntimeException('Zend Diactoros must be installed ot use the DiactorosFactory.'); + } + } + /** * {@inheritdoc} */ @@ -105,6 +112,7 @@ public function createResponse(Response $symfonyResponse) return false; }); + $symfonyResponse->sendContent(); ob_end_clean(); } else { diff --git a/Tests/Fixtures/Response.php b/Tests/Fixtures/Response.php index 70717d5..0fd85c2 100644 --- a/Tests/Fixtures/Response.php +++ b/Tests/Fixtures/Response.php @@ -21,7 +21,7 @@ class Response extends Message implements ResponseInterface { private $statusCode; - public function __construct($version = '1.1', array $headers = array(), StreamInterface $body = null, $statusCode) + public function __construct($version = '1.1', array $headers = array(), StreamInterface $body = null, $statusCode = 200) { parent::__construct($version, $headers, $body); From bcfa6982f3a3b2d8dda20a430528ada644e4fbf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 26 May 2015 08:13:45 +0200 Subject: [PATCH 28/37] Fix Travis --- .travis.yml | 7 +++---- Factory/DiactorosFactory.php | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index d350695..010a995 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,9 @@ sudo: false matrix: include: - - php: 5.3 - - php: 5.4 - php: 5.5 - php: 5.6 - - php: 5.3 + - php: 5.5 env: deps=low - php: 5.6 env: deps=high @@ -28,7 +26,6 @@ before_install: - composer self-update - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi; - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]] && [ $(php -r "echo PHP_MINOR_VERSION;") -le 4 ]; then echo "extension = apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi; - - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo "extension = $(pwd)/modules/symfony_debug.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini); fi; - if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then php -i; fi; # Set the COMPOSER_ROOT_VERSION to the right version according to the branch being built - if [ "$TRAVIS_BRANCH" = "master" ]; then export COMPOSER_ROOT_VERSION=dev-master; else export COMPOSER_ROOT_VERSION="$TRAVIS_BRANCH".x-dev; fi; @@ -36,6 +33,8 @@ before_install: install: - if [ "$deps" = "no" ]; then export SYMFONY_DEPRECATIONS_HELPER=strict; fi; - if [ "$deps" = "no" ]; then composer --prefer-source install; fi; + - if [ "$deps" = "high" ]; then composer --prefer-source update; fi; + - if [ "$deps" = "low" ]; then composer --prefer-source --prefer-lowest --prefer-stable update; fi; script: - phpunit diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index d931d7f..810d095 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -31,7 +31,7 @@ class DiactorosFactory implements HttpMessageFactoryInterface public function __construct() { if (!class_exists('Zend\Diactoros\ServerRequestFactory')) { - throw new \RuntimeException('Zend Diactoros must be installed ot use the DiactorosFactory.'); + throw new \RuntimeException('Zend Diactoros must be installed to use the DiactorosFactory.'); } } From 8a2bd7bca314eb5c899f10392bf48802faaffc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 11:01:20 +0200 Subject: [PATCH 29/37] Remove dev dependency to Zend Diactoros --- .travis.yml | 5 ++++- Tests/Factory/DiactorosFactoryTest.php | 4 ++++ composer.json | 3 +-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 010a995..39e7eb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,11 @@ sudo: false matrix: include: + - php: 5.3 + - php: 5.4 - php: 5.5 - php: 5.6 - - php: 5.5 + - php: 5.3 env: deps=low - php: 5.6 env: deps=high @@ -31,6 +33,7 @@ before_install: - if [ "$TRAVIS_BRANCH" = "master" ]; then export COMPOSER_ROOT_VERSION=dev-master; else export COMPOSER_ROOT_VERSION="$TRAVIS_BRANCH".x-dev; fi; install: + - if [[ "$TRAVIS_PHP_VERSION" != "5.3" ]] && [[ "$TRAVIS_PHP_VERSION" != "5.4" ]]; then composer require --no-update zendframework/zend-diactoros; fi; - if [ "$deps" = "no" ]; then export SYMFONY_DEPRECATIONS_HELPER=strict; fi; - if [ "$deps" = "no" ]; then composer --prefer-source install; fi; - if [ "$deps" = "high" ]; then composer --prefer-source update; fi; diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 2fd9659..4fc6e4e 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -27,6 +27,10 @@ class DiactorosFactoryTest extends \PHPUnit_Framework_TestCase public function setup() { + if (!class_exists('Zend\Diactoros\ServerRequestFactory')) { + $this->markTestSkipped('Zend Diactoros is not installed.'); + } + $this->factory = new DiactorosFactory(); $this->tmpDir = sys_get_temp_dir(); } diff --git a/composer.json b/composer.json index 43f25be..ae75a1e 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,7 @@ "symfony/http-foundation": "~2.3" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7", - "zendframework/zend-diactoros": "~1.0" + "symfony/phpunit-bridge": "~2.7" }, "suggest": { "zendframework/zend-diactoros": "To use the zend-diactoros factory" From f41f3e4d3b5dc372f1f5e7ae2e287106d0d45db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 11:39:37 +0200 Subject: [PATCH 30/37] New DiactorosFactory implementation --- Factory/DiactorosFactory.php | 39 ++++++++++++++------- Factory/HttpFoundationFactory.php | 8 +++-- HttpFoundationFactoryInterface.php | 11 ------ HttpMessageFactoryInterface.php | 11 ------ Tests/Factory/HttpFoundationFactoryTest.php | 14 ++++++-- composer.json | 2 +- 6 files changed, 45 insertions(+), 40 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 810d095..f6831ad 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Zend\Diactoros\Response as DiactorosResponse; +use Zend\Diactoros\ServerRequest; use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory; use Zend\Diactoros\Stream as DiactorosStream; use Zend\Diactoros\UploadedFile as DiactorosUploadedFile; @@ -40,22 +41,30 @@ public function __construct() */ public function createRequest(Request $symfonyRequest) { - $request = DiactorosRequestFactory::fromGlobals( - $symfonyRequest->server->all(), - $symfonyRequest->query->all(), - $symfonyRequest->request->all(), - $symfonyRequest->cookies->all(), - $this->getFiles($symfonyRequest->files->all()) - ); + $server = DiactorosRequestFactory::normalizeServer($symfonyRequest->server->all()); + $headers = $symfonyRequest->headers->all(); try { - $stream = new DiactorosStream($symfonyRequest->getContent(true)); + $body = new DiactorosStream($symfonyRequest->getContent(true)); } catch (\LogicException $e) { - $stream = new DiactorosStream('php://temp', 'wb+'); - $stream->write($symfonyRequest->getContent()); + $body = new DiactorosStream('php://temp', 'wb+'); + $body->write($symfonyRequest->getContent()); } - $request = $request->withBody($stream); + $request = new ServerRequest( + $server, + DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())), + DiactorosRequestFactory::marshalUriFromServer($server, $headers), + $symfonyRequest->getMethod(), + $body, + $headers + ); + + $request = $request + ->withCookieParams($symfonyRequest->cookies->all()) + ->withQueryParams($symfonyRequest->query->all()) + ->withParsedBody($symfonyRequest->request->all()) + ; foreach ($symfonyRequest->attributes->all() as $key => $value) { $request = $request->withAttribute($key, $value); @@ -87,9 +96,13 @@ private function getFiles(array $uploadedFiles) } /** - * {@inheritdoc} + * Creates a PSR-7 UploadedFile instance from a Symfony one. + * + * @param UploadedFile $symfonyUploadedFile + * + * @return UploadedFileInterface */ - public function createUploadedFile(UploadedFile $symfonyUploadedFile) + private function createUploadedFile(UploadedFile $symfonyUploadedFile) { return new DiactorosUploadedFile( $symfonyUploadedFile->getRealPath(), diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 8a1b981..8fa9c42 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -68,9 +68,13 @@ private function getFiles(array $uploadedFiles) } /** - * {@inheritdoc} + * Creates Symfony UploadedFile instance from PSR-7 ones. + * + * @param UploadedFileInterface $psrUploadedFile + * + * @return UploadedFile */ - public function createUploadedFile(UploadedFileInterface $psrUploadedFile) + private function createUploadedFile(UploadedFileInterface $psrUploadedFile) { $temporaryPath = $this->getTemporaryPath(); $psrUploadedFile->moveTo($temporaryPath); diff --git a/HttpFoundationFactoryInterface.php b/HttpFoundationFactoryInterface.php index acdd44d..32ec456 100644 --- a/HttpFoundationFactoryInterface.php +++ b/HttpFoundationFactoryInterface.php @@ -13,8 +13,6 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UploadedFileInterface; -use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -34,15 +32,6 @@ interface HttpFoundationFactoryInterface */ public function createRequest(ServerRequestInterface $psrRequest); - /** - * Creates Symfony UploadedFile instance from PSR-7 ones. - * - * @param UploadedFileInterface $psrUploadedFile - * - * @return UploadedFile - */ - public function createUploadedFile(UploadedFileInterface $psrUploadedFile); - /** * Creates a Symfony Response instance from a PSR-7 one. * diff --git a/HttpMessageFactoryInterface.php b/HttpMessageFactoryInterface.php index ac0b497..1367c8c 100644 --- a/HttpMessageFactoryInterface.php +++ b/HttpMessageFactoryInterface.php @@ -13,8 +13,6 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\UploadedFileInterface; -use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -34,15 +32,6 @@ interface HttpMessageFactoryInterface */ public function createRequest(Request $symfonyRequest); - /** - * Creates a PSR-7 UploadedFile instance from a Symfony one. - * - * @param UploadedFile $symfonyUploadedFile - * - * @return UploadedFileInterface - */ - public function createUploadedFile(UploadedFile $symfonyUploadedFile); - /** * Creates a PSR-7 Response instance from a Symfony one. * diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 8a7192e..9e611e3 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; +use Psr\Http\Message\UploadedFileInterface; use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response; use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\ServerRequest; @@ -113,7 +114,7 @@ public function testCreateRequestWithObjectParsedBody() public function testCreateUploadedFile() { $uploadedFile = $this->createUploadedFile('An uploaded file.', UPLOAD_ERR_OK, 'myfile.txt', 'text/plain'); - $symfonyUploadedFile = $this->factory->createUploadedFile($uploadedFile); + $symfonyUploadedFile = $this->callCreateUploadedFile($uploadedFile); $uniqid = uniqid(); $symfonyUploadedFile->move($this->tmpDir, $uniqid); @@ -133,7 +134,7 @@ public function testCreateUploadedFile() public function testCreateUploadedFileWithError() { $uploadedFile = $this->createUploadedFile('Error.', UPLOAD_ERR_CANT_WRITE, 'e', 'text/plain'); - $symfonyUploadedFile = $this->factory->createUploadedFile($uploadedFile); + $symfonyUploadedFile = $this->callCreateUploadedFile($uploadedFile); $this->assertEquals(UPLOAD_ERR_CANT_WRITE, $symfonyUploadedFile->getError()); @@ -148,6 +149,15 @@ private function createUploadedFile($content, $error, $clientFileName, $clientMe return new UploadedFile($filePath, filesize($filePath), $error, $clientFileName, $clientMediaType); } + private function callCreateUploadedFile(UploadedFileInterface $uploadedFile) + { + $reflection = new \ReflectionClass($this->factory); + $createUploadedFile = $reflection->getMethod('createUploadedFile'); + $createUploadedFile->setAccessible(true); + + return $createUploadedFile->invokeArgs($this->factory, array($uploadedFile)); + } + public function testCreateResponse() { $response = new Response( diff --git a/composer.json b/composer.json index ae75a1e..6f87655 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "symfony/phpunit-bridge": "~2.7" }, "suggest": { - "zendframework/zend-diactoros": "To use the zend-diactoros factory" + "zendframework/zend-diactoros": "To use the Zend Diactoros factory" }, "autoload": { "psr-4": { "Symfony\\Bridge\\PsrHttpMessage\\": "" } From 9c6f18095e9624018f6c77167ee56201b6b19c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 14:50:07 +0200 Subject: [PATCH 31/37] Added cookies support --- Factory/DiactorosFactory.php | 13 +++- Factory/HttpFoundationFactory.php | 78 +++++++++++++++++++++ Tests/Factory/DiactorosFactoryTest.php | 4 ++ Tests/Factory/HttpFoundationFactoryTest.php | 29 +++++++- 4 files changed, 122 insertions(+), 2 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index f6831ad..0ef7126 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -132,10 +132,21 @@ public function createResponse(Response $symfonyResponse) $stream->write($symfonyResponse->getContent()); } + $headers = $symfonyResponse->headers->all(); + + $cookies = $symfonyResponse->headers->getCookies(); + if (!empty($cookies)) { + $headers['Set-Cookie'] = array(); + + foreach ($cookies as $coookie) { + $headers['Set-Cookie'][] = $coookie->__toString(); + } + } + $response = new DiactorosResponse( $stream, $symfonyResponse->getStatusCode(), - $symfonyResponse->headers->all() + $headers ); $protocolVersion = $symfonyResponse->getProtocolVersion(); diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 8fa9c42..42537af 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -15,6 +15,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UploadedFileInterface; use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -113,6 +114,83 @@ public function createResponse(ResponseInterface $psrResponse) ); $response->setProtocolVersion($psrResponse->getProtocolVersion()); + foreach ($psrResponse->getHeader('Set-Cookie') as $cookie) { + $response->headers->setCookie($this->createCookie($cookie)); + } + return $response; } + + /** + * Creates a Cookie instance from a cookie string. + * + * Some snippets have been taken from the Guzzle project: https://github.com/guzzle/guzzle/blob/5.3/src/Cookie/SetCookie.php#L34 + * + * @param string $cookie + * + * @return Cookie + * + * @BadMethodCallException + */ + private function createCookie($cookie) + { + foreach (explode(';', $cookie) as $part) { + $part = trim($part); + + $data = explode('=', $part, 2); + $name = $data[0]; + $value = isset($data[1]) ? trim($data[1], " \n\r\t\0\x0B\"") : null; + + if (!isset($cookieName)) { + $cookieName = $name; + $cookieValue = $value; + + continue; + } + + if ('expires' === strtolower($name) && null !== $value) { + $cookieExpire = new \DateTime($value); + + continue; + } + + if ('path' === strtolower($name) && null !== $value) { + $cookiePath = $value; + + continue; + } + + if ('domain' === strtolower($name) && null !== $value) { + $cookieDomain = $value; + + continue; + } + + if ('secure' === strtolower($name)) { + $cookieSecure = true; + + continue; + } + + if ('httponly' === strtolower($name)) { + $cookieHttpOnly = true; + + continue; + } + } + + if (!isset($cookieName)) { + throw new \BadMethodCallException('The value of the Set-Cookie header is malformed.'); + } + + return new Cookie( + $cookieName, + $cookieValue, + isset($cookieExpire) ? $cookieExpire : 0, + isset($cookiePath) ? $cookiePath : '/', + isset($cookieDomain) ? $cookieDomain : null, + isset($cookieSecure), + isset($cookieHttpOnly) + ); + } } diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index 4fc6e4e..e5f2149 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -123,11 +124,14 @@ public function testCreateResponse() 202, array('X-Symfony' => array('2.8')) ); + $response->headers->setCookie(new Cookie('city', 'Lille', new \DateTime('Wed, 13 Jan 2021 22:23:01 GMT'))); $psrResponse = $this->factory->createResponse($response); $this->assertEquals('Response content.', $psrResponse->getBody()->__toString()); $this->assertEquals(202, $psrResponse->getStatusCode()); $this->assertEquals(array('2.8'), $psrResponse->getHeader('X-Symfony')); + var_dump($psrResponse->getHeader('Set-Cookie')[0]); + $this->assertEquals(array('city=Lille; expires=Wed, 13-Jan-2021 22:23:01 GMT; path=/; httponly'), $psrResponse->getHeader('Set-Cookie')); } public function testCreateResponseFromStreamed() diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 9e611e3..f24cea6 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -163,7 +163,13 @@ public function testCreateResponse() $response = new Response( '1.0', array( - 'X-Symfony' => '2.8', + 'X-Symfony' => array('2.8'), + 'Set-Cookie' => array( + 'theme=light', + 'test', + 'ABC=AeD; Domain=dunglas.fr; Path=/kevin; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly', + + ), ), new Stream('The response body'), 200 @@ -173,6 +179,27 @@ public function testCreateResponse() $this->assertEquals('1.0', $symfonyResponse->getProtocolVersion()); $this->assertEquals('2.8', $symfonyResponse->headers->get('X-Symfony')); + + $cookies = $symfonyResponse->headers->getCookies(); + $this->assertEquals('theme', $cookies[0]->getName()); + $this->assertEquals('light', $cookies[0]->getValue()); + $this->assertEquals(0, $cookies[0]->getExpiresTime()); + $this->assertEquals(null, $cookies[0]->getDomain()); + $this->assertEquals('/', $cookies[0]->getPath()); + $this->assertEquals(false, $cookies[0]->isSecure()); + $this->assertEquals(false, $cookies[0]->isHttpOnly()); + + $this->assertEquals('test', $cookies[1]->getName()); + $this->assertEquals(null, $cookies[1]->getValue()); + + $this->assertEquals('ABC', $cookies[2]->getName()); + $this->assertEquals('AeD', $cookies[2]->getValue()); + $this->assertEquals(strtotime('Wed, 13 Jan 2021 22:23:01 GMT'), $cookies[2]->getExpiresTime()); + $this->assertEquals('dunglas.fr', $cookies[2]->getDomain()); + $this->assertEquals('/kevin', $cookies[2]->getPath()); + $this->assertEquals(true, $cookies[2]->isSecure()); + $this->assertEquals(true, $cookies[2]->isHttpOnly()); + $this->assertEquals('The response body', $symfonyResponse->getContent()); $this->assertEquals(200, $symfonyResponse->getStatusCode()); } From 7d8bdc875e1e9f682ef60bbd3ce6dd0058443e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 14:51:27 +0200 Subject: [PATCH 32/37] PHPUnit optimizations --- Tests/Factory/HttpFoundationFactoryTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index f24cea6..3fe3095 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -184,21 +184,21 @@ public function testCreateResponse() $this->assertEquals('theme', $cookies[0]->getName()); $this->assertEquals('light', $cookies[0]->getValue()); $this->assertEquals(0, $cookies[0]->getExpiresTime()); - $this->assertEquals(null, $cookies[0]->getDomain()); + $this->assertNull($cookies[0]->getDomain()); $this->assertEquals('/', $cookies[0]->getPath()); - $this->assertEquals(false, $cookies[0]->isSecure()); - $this->assertEquals(false, $cookies[0]->isHttpOnly()); + $this->assertFalse($cookies[0]->isSecure()); + $this->assertFalse($cookies[0]->isHttpOnly()); $this->assertEquals('test', $cookies[1]->getName()); - $this->assertEquals(null, $cookies[1]->getValue()); + $this->assertNull($cookies[1]->getValue()); $this->assertEquals('ABC', $cookies[2]->getName()); $this->assertEquals('AeD', $cookies[2]->getValue()); $this->assertEquals(strtotime('Wed, 13 Jan 2021 22:23:01 GMT'), $cookies[2]->getExpiresTime()); $this->assertEquals('dunglas.fr', $cookies[2]->getDomain()); $this->assertEquals('/kevin', $cookies[2]->getPath()); - $this->assertEquals(true, $cookies[2]->isSecure()); - $this->assertEquals(true, $cookies[2]->isHttpOnly()); + $this->assertTrue($cookies[2]->isSecure()); + $this->assertTrue($cookies[2]->isHttpOnly()); $this->assertEquals('The response body', $symfonyResponse->getContent()); $this->assertEquals(200, $symfonyResponse->getStatusCode()); From eacce8fb754437e2eadd57a1048ab0194fc35109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 14:53:25 +0200 Subject: [PATCH 33/37] Remove crap. --- Factory/HttpFoundationFactory.php | 4 ++-- Tests/Factory/DiactorosFactoryTest.php | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 42537af..6062b5d 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -33,11 +33,11 @@ class HttpFoundationFactory implements HttpFoundationFactoryInterface public function createRequest(ServerRequestInterface $psrRequest) { $parsedBody = $psrRequest->getParsedBody(); - $request = is_array($parsedBody) ? $parsedBody : array(); + $parsedBody = is_array($parsedBody) ? $parsedBody : array(); return new Request( $psrRequest->getQueryParams(), - $request, + $parsedBody, $psrRequest->getAttributes(), $psrRequest->getCookieParams(), $this->getFiles($psrRequest->getUploadedFiles()), diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index e5f2149..cffab52 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -130,7 +130,6 @@ public function testCreateResponse() $this->assertEquals('Response content.', $psrResponse->getBody()->__toString()); $this->assertEquals(202, $psrResponse->getStatusCode()); $this->assertEquals(array('2.8'), $psrResponse->getHeader('X-Symfony')); - var_dump($psrResponse->getHeader('Set-Cookie')[0]); $this->assertEquals(array('city=Lille; expires=Wed, 13-Jan-2021 22:23:01 GMT; path=/; httponly'), $psrResponse->getHeader('Set-Cookie')); } From 7012db5c596703171477c690c9b369a8f0370a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 15:04:01 +0200 Subject: [PATCH 34/37] Enhanced headers support --- Factory/HttpFoundationFactory.php | 5 ++++- Tests/Factory/HttpFoundationFactoryTest.php | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 6062b5d..9926fd0 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -35,7 +35,7 @@ public function createRequest(ServerRequestInterface $psrRequest) $parsedBody = $psrRequest->getParsedBody(); $parsedBody = is_array($parsedBody) ? $parsedBody : array(); - return new Request( + $request = new Request( $psrRequest->getQueryParams(), $parsedBody, $psrRequest->getAttributes(), @@ -44,6 +44,9 @@ public function createRequest(ServerRequestInterface $psrRequest) $psrRequest->getServerParams(), $psrRequest->getBody()->__toString() ); + $request->headers->replace($psrRequest->getHeaders()); + + return $request; } /** diff --git a/Tests/Factory/HttpFoundationFactoryTest.php b/Tests/Factory/HttpFoundationFactoryTest.php index 3fe3095..412e287 100644 --- a/Tests/Factory/HttpFoundationFactoryTest.php +++ b/Tests/Factory/HttpFoundationFactoryTest.php @@ -37,7 +37,10 @@ public function testCreateRequest() $stdClass = new \stdClass(); $serverRequest = new ServerRequest( '1.1', - array(), + array( + 'X-Dunglas-API-Platform' => '1.0', + 'X-data' => array('a', 'b'), + ), new Stream('The body'), '/about/kevin', 'GET', @@ -69,6 +72,8 @@ public function testCreateRequest() $this->assertEquals('Lille', $symfonyRequest->cookies->get('city')); $this->assertEquals('France', $symfonyRequest->server->get('country')); $this->assertEquals('The body', $symfonyRequest->getContent()); + $this->assertEquals('1.0', $symfonyRequest->headers->get('X-Dunglas-API-Platform')); + $this->assertEquals(array('a', 'b'), $symfonyRequest->headers->get('X-data', null, false)); } public function testCreateRequestWithNullParsedBody() From b887c36e349fdb827c56dd822e3cee09d037b419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 16:08:15 +0200 Subject: [PATCH 35/37] CS fixes --- Factory/DiactorosFactory.php | 4 ++-- Factory/HttpFoundationFactory.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 0ef7126..1f4fbae 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -138,8 +138,8 @@ public function createResponse(Response $symfonyResponse) if (!empty($cookies)) { $headers['Set-Cookie'] = array(); - foreach ($cookies as $coookie) { - $headers['Set-Cookie'][] = $coookie->__toString(); + foreach ($cookies as $cookie) { + $headers['Set-Cookie'][] = $cookie->__toString(); } } diff --git a/Factory/HttpFoundationFactory.php b/Factory/HttpFoundationFactory.php index 9926fd0..2c356fd 100644 --- a/Factory/HttpFoundationFactory.php +++ b/Factory/HttpFoundationFactory.php @@ -133,7 +133,7 @@ public function createResponse(ResponseInterface $psrResponse) * * @return Cookie * - * @BadMethodCallException + * @throws \InvalidArgumentException */ private function createCookie($cookie) { @@ -183,7 +183,7 @@ private function createCookie($cookie) } if (!isset($cookieName)) { - throw new \BadMethodCallException('The value of the Set-Cookie header is malformed.'); + throw new \InvalidArgumentException('The value of the Set-Cookie header is malformed.'); } return new Cookie( From ca2ea3bfb02a979dc50c78bd66e5fe8dcb8c039d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 27 May 2015 23:53:51 +0200 Subject: [PATCH 36/37] BinaryFileResponse support --- Factory/DiactorosFactory.php | 27 +++++++++++++++----------- Tests/Factory/DiactorosFactoryTest.php | 14 +++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Factory/DiactorosFactory.php b/Factory/DiactorosFactory.php index 1f4fbae..31726f1 100644 --- a/Factory/DiactorosFactory.php +++ b/Factory/DiactorosFactory.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -54,7 +55,7 @@ public function createRequest(Request $symfonyRequest) $request = new ServerRequest( $server, DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())), - DiactorosRequestFactory::marshalUriFromServer($server, $headers), + $symfonyRequest->getUri(), $symfonyRequest->getMethod(), $body, $headers @@ -118,18 +119,22 @@ private function createUploadedFile(UploadedFile $symfonyUploadedFile) */ public function createResponse(Response $symfonyResponse) { - $stream = new DiactorosStream('php://temp', 'wb+'); - if ($symfonyResponse instanceof StreamedResponse) { - ob_start(function ($buffer) use ($stream) { - $stream->write($buffer); + if ($symfonyResponse instanceof BinaryFileResponse) { + $stream = new DiactorosStream($symfonyResponse->getFile()->getPathname(), 'r'); + } else { + $stream = new DiactorosStream('php://temp', 'wb+'); + if ($symfonyResponse instanceof StreamedResponse) { + ob_start(function ($buffer) use ($stream) { + $stream->write($buffer); - return false; - }); + return false; + }); - $symfonyResponse->sendContent(); - ob_end_clean(); - } else { - $stream->write($symfonyResponse->getContent()); + $symfonyResponse->sendContent(); + ob_end_clean(); + } else { + $stream->write($symfonyResponse->getContent()); + } } $headers = $symfonyResponse->headers->all(); diff --git a/Tests/Factory/DiactorosFactoryTest.php b/Tests/Factory/DiactorosFactoryTest.php index cffab52..a4c32bd 100644 --- a/Tests/Factory/DiactorosFactoryTest.php +++ b/Tests/Factory/DiactorosFactoryTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\PsrHttpMessage\Tests\Factory; use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; @@ -65,6 +66,7 @@ public function testCreateRequest() ), array( 'REQUEST_METHOD' => 'POST', + 'HTTP_HOST' => 'dunglas.fr', 'HTTP_X_SYMFONY' => '2.8', ), 'Content' @@ -147,4 +149,16 @@ public function testCreateResponseFromStreamed() $this->assertEquals("Line 1\nLine 2\n", $psrResponse->getBody()->__toString()); } + + public function testCreateResponseFromBinaryFile() + { + $path = tempnam($this->tmpDir, uniqid()); + file_put_contents($path, 'Binary'); + + $response = new BinaryFileResponse($path); + + $psrResponse = $this->factory->createResponse($response); + + $this->assertEquals('Binary', $psrResponse->getBody()->__toString()); + } } From 577e6330860082a1d9393e8938c049bf48a4fe0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 28 May 2015 12:24:48 +0200 Subject: [PATCH 37/37] Support Symfony 3.0 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 6f87655..2086398 100644 --- a/composer.json +++ b/composer.json @@ -18,10 +18,10 @@ "require": { "php": ">=5.3.3", "psr/http-message": "~1.0", - "symfony/http-foundation": "~2.3" + "symfony/http-foundation": "~2.3|~3.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "symfony/phpunit-bridge": "~2.7|~3.0" }, "suggest": { "zendframework/zend-diactoros": "To use the Zend Diactoros factory"