Skip to content

Commit 3f8977e

Browse files
committed
feature #1 Initial support (dunglas)
This PR was squashed before being merged into the 2.8-dev branch (closes #1). Discussion ---------- Initial support | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | symfony/symfony-docs#5331 - [x] Composer dependencies - [x] Interfaces - [x] Stub - [x] HttpFoundationFactory implementation - [x] DiactorosFactory implementation - [x] StreamedResponse Commits ------- ca41146 Initial support
2 parents 01b110b + ca41146 commit 3f8977e

15 files changed

+1313
-5
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml

.travis.yml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
language: php
2+
3+
sudo: false
4+
5+
matrix:
6+
include:
7+
- php: 5.3
8+
- php: 5.4
9+
- php: 5.5
10+
- php: 5.6
11+
- php: 5.3
12+
env: deps=low
13+
- php: 5.6
14+
env: deps=high
15+
- php: nightly
16+
- php: hhvm
17+
allow_failures:
18+
- php: nightly
19+
- php: hhvm
20+
fast_finish: true
21+
22+
env:
23+
global:
24+
- deps=no
25+
- SYMFONY_DEPRECATIONS_HELPER=weak
26+
27+
before_install:
28+
- composer self-update
29+
- if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi;
30+
- 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;
31+
- if [[ "$TRAVIS_PHP_VERSION" != "nightly" ]] && [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then php -i; fi;
32+
# Set the COMPOSER_ROOT_VERSION to the right version according to the branch being built
33+
- if [ "$TRAVIS_BRANCH" = "master" ]; then export COMPOSER_ROOT_VERSION=dev-master; else export COMPOSER_ROOT_VERSION="$TRAVIS_BRANCH".x-dev; fi;
34+
35+
install:
36+
- if [[ "$TRAVIS_PHP_VERSION" != "5.3" ]] && [[ "$TRAVIS_PHP_VERSION" != "5.4" ]]; then composer require --no-update zendframework/zend-diactoros; fi;
37+
- if [ "$deps" = "no" ]; then export SYMFONY_DEPRECATIONS_HELPER=strict; fi;
38+
- if [ "$deps" = "no" ]; then composer --prefer-source install; fi;
39+
- if [ "$deps" = "high" ]; then composer --prefer-source update; fi;
40+
- if [ "$deps" = "low" ]; then composer --prefer-source --prefer-lowest --prefer-stable update; fi;
41+
42+
script:
43+
- phpunit

Factory/DiactorosFactory.php

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PsrHttpMessage\Factory;
13+
14+
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
15+
use Symfony\Component\HttpFoundation\BinaryFileResponse;
16+
use Symfony\Component\HttpFoundation\File\UploadedFile;
17+
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpFoundation\Response;
19+
use Symfony\Component\HttpFoundation\StreamedResponse;
20+
use Zend\Diactoros\Response as DiactorosResponse;
21+
use Zend\Diactoros\ServerRequest;
22+
use Zend\Diactoros\ServerRequestFactory as DiactorosRequestFactory;
23+
use Zend\Diactoros\Stream as DiactorosStream;
24+
use Zend\Diactoros\UploadedFile as DiactorosUploadedFile;
25+
26+
/**
27+
* Builds Psr\HttpMessage instances using the Zend Diactoros implementation.
28+
*
29+
* @author Kévin Dunglas <dunglas@gmail.com>
30+
*/
31+
class DiactorosFactory implements HttpMessageFactoryInterface
32+
{
33+
public function __construct()
34+
{
35+
if (!class_exists('Zend\Diactoros\ServerRequestFactory')) {
36+
throw new \RuntimeException('Zend Diactoros must be installed to use the DiactorosFactory.');
37+
}
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function createRequest(Request $symfonyRequest)
44+
{
45+
$server = DiactorosRequestFactory::normalizeServer($symfonyRequest->server->all());
46+
$headers = $symfonyRequest->headers->all();
47+
48+
try {
49+
$body = new DiactorosStream($symfonyRequest->getContent(true));
50+
} catch (\LogicException $e) {
51+
$body = new DiactorosStream('php://temp', 'wb+');
52+
$body->write($symfonyRequest->getContent());
53+
}
54+
55+
$request = new ServerRequest(
56+
$server,
57+
DiactorosRequestFactory::normalizeFiles($this->getFiles($symfonyRequest->files->all())),
58+
$symfonyRequest->getUri(),
59+
$symfonyRequest->getMethod(),
60+
$body,
61+
$headers
62+
);
63+
64+
$request = $request
65+
->withCookieParams($symfonyRequest->cookies->all())
66+
->withQueryParams($symfonyRequest->query->all())
67+
->withParsedBody($symfonyRequest->request->all())
68+
;
69+
70+
foreach ($symfonyRequest->attributes->all() as $key => $value) {
71+
$request = $request->withAttribute($key, $value);
72+
}
73+
74+
return $request;
75+
}
76+
77+
/**
78+
* Converts Symfony uploaded files array to the PSR one.
79+
*
80+
* @param array $uploadedFiles
81+
*
82+
* @return array
83+
*/
84+
private function getFiles(array $uploadedFiles)
85+
{
86+
$files = array();
87+
88+
foreach ($uploadedFiles as $key => $value) {
89+
if ($value instanceof UploadedFile) {
90+
$files[$key] = $this->createUploadedFile($value);
91+
} else {
92+
$files[$key] = $this->getFiles($value);
93+
}
94+
}
95+
96+
return $files;
97+
}
98+
99+
/**
100+
* Creates a PSR-7 UploadedFile instance from a Symfony one.
101+
*
102+
* @param UploadedFile $symfonyUploadedFile
103+
*
104+
* @return UploadedFileInterface
105+
*/
106+
private function createUploadedFile(UploadedFile $symfonyUploadedFile)
107+
{
108+
return new DiactorosUploadedFile(
109+
$symfonyUploadedFile->getRealPath(),
110+
$symfonyUploadedFile->getSize(),
111+
$symfonyUploadedFile->getError(),
112+
$symfonyUploadedFile->getClientOriginalName(),
113+
$symfonyUploadedFile->getClientMimeType()
114+
);
115+
}
116+
117+
/**
118+
* {@inheritdoc}
119+
*/
120+
public function createResponse(Response $symfonyResponse)
121+
{
122+
if ($symfonyResponse instanceof BinaryFileResponse) {
123+
$stream = new DiactorosStream($symfonyResponse->getFile()->getPathname(), 'r');
124+
} else {
125+
$stream = new DiactorosStream('php://temp', 'wb+');
126+
if ($symfonyResponse instanceof StreamedResponse) {
127+
ob_start(function ($buffer) use ($stream) {
128+
$stream->write($buffer);
129+
130+
return false;
131+
});
132+
133+
$symfonyResponse->sendContent();
134+
ob_end_clean();
135+
} else {
136+
$stream->write($symfonyResponse->getContent());
137+
}
138+
}
139+
140+
$headers = $symfonyResponse->headers->all();
141+
142+
$cookies = $symfonyResponse->headers->getCookies();
143+
if (!empty($cookies)) {
144+
$headers['Set-Cookie'] = array();
145+
146+
foreach ($cookies as $cookie) {
147+
$headers['Set-Cookie'][] = $cookie->__toString();
148+
}
149+
}
150+
151+
$response = new DiactorosResponse(
152+
$stream,
153+
$symfonyResponse->getStatusCode(),
154+
$headers
155+
);
156+
157+
$protocolVersion = $symfonyResponse->getProtocolVersion();
158+
if ('1.1' !== $protocolVersion) {
159+
$response = $response->withProtocolVersion($protocolVersion);
160+
}
161+
162+
return $response;
163+
}
164+
}

0 commit comments

Comments
 (0)