Skip to content

Commit 64e8618

Browse files
committed
Merge pull request #30 from mekras/response_builder
ResponseBuilder class.
2 parents 5107a56 + cb742fd commit 64e8618

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

spec/Builder/ResponseBuilderSpec.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace spec\Http\Message\Builder;
4+
5+
use PhpSpec\ObjectBehavior;
6+
use Psr\Http\Message\ResponseInterface;
7+
8+
class ResponseBuilderSpec extends ObjectBehavior
9+
{
10+
function it_is_initializable(ResponseInterface $response)
11+
{
12+
$this->beConstructedWith($response);
13+
$this->shouldHaveType('Http\Message\Builder\ResponseBuilder');
14+
}
15+
16+
function it_reads_headers_from_array(ResponseInterface $response)
17+
{
18+
$response->withStatus(200, 'OK')->willReturn($response);
19+
$response->withProtocolVersion('1.1')->willReturn($response);
20+
$response->hasHeader('Content-type')->willReturn(false);
21+
$response->withHeader('Content-type', 'text/html')->willReturn($response);
22+
$this->beConstructedWith($response);
23+
$this->setHeadersFromArray(['HTTP/1.1 200 OK', 'Content-type: text/html']);
24+
}
25+
26+
function it_reads_headers_from_string(ResponseInterface $response)
27+
{
28+
$response->withStatus(200, 'OK')->willReturn($response);
29+
$response->withProtocolVersion('1.1')->willReturn($response);
30+
$response->hasHeader('Content-type')->willReturn(false);
31+
$response->withHeader('Content-type', 'text/html')->willReturn($response);
32+
$this->beConstructedWith($response);
33+
$this->setHeadersFromString("HTTP/1.1 200 OK\r\nContent-type: text/html\r\n");
34+
}
35+
}

src/Builder/ResponseBuilder.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
namespace Http\Message\Builder;
4+
5+
use Psr\Http\Message\ResponseInterface;
6+
7+
/**
8+
* Fills response object with values.
9+
*/
10+
class ResponseBuilder
11+
{
12+
/**
13+
* The response to be built.
14+
*
15+
* @var ResponseInterface
16+
*/
17+
protected $response;
18+
19+
/**
20+
* Create builder for the given response.
21+
*
22+
* @param ResponseInterface $response
23+
*/
24+
public function __construct(ResponseInterface $response)
25+
{
26+
$this->response = $response;
27+
}
28+
29+
/**
30+
* Return response.
31+
*
32+
* @return ResponseInterface
33+
*/
34+
public function getResponse()
35+
{
36+
return $this->response;
37+
}
38+
39+
/**
40+
* Add headers represented by an array of header lines.
41+
*
42+
* @param string[] $headers Response headers as array of header lines.
43+
*
44+
* @return $this
45+
*
46+
* @throws \UnexpectedValueException For invalid header values.
47+
* @throws \InvalidArgumentException For invalid status code arguments.
48+
*/
49+
public function setHeadersFromArray(array $headers)
50+
{
51+
$statusLine = trim(array_shift($headers));
52+
$parts = explode(' ', $statusLine, 3);
53+
if (count($parts) < 2 || substr(strtolower($parts[0]), 0, 5) !== 'http/') {
54+
throw new \UnexpectedValueException(
55+
sprintf('"%s" is not a valid HTTP status line', $statusLine)
56+
);
57+
}
58+
59+
$reasonPhrase = count($parts) > 2 ? $parts[2] : '';
60+
$this->response = $this->response
61+
->withStatus((int) $parts[1], $reasonPhrase)
62+
->withProtocolVersion(substr($parts[0], 5));
63+
64+
foreach ($headers as $headerLine) {
65+
$headerLine = trim($headerLine);
66+
if ('' === $headerLine) {
67+
continue;
68+
}
69+
70+
$parts = explode(':', $headerLine, 2);
71+
if (count($parts) !== 2) {
72+
throw new \UnexpectedValueException(
73+
sprintf('"%s" is not a valid HTTP header line', $headerLine)
74+
);
75+
}
76+
$name = trim(urldecode($parts[0]));
77+
$value = trim(urldecode($parts[1]));
78+
if ($this->response->hasHeader($name)) {
79+
$this->response = $this->response->withAddedHeader($name, $value);
80+
} else {
81+
$this->response = $this->response->withHeader($name, $value);
82+
}
83+
}
84+
85+
return $this;
86+
}
87+
88+
/**
89+
* Add headers represented by a single string.
90+
*
91+
* @param string $headers Response headers as single string.
92+
*
93+
* @return $this
94+
*
95+
* @throws \InvalidArgumentException if $headers is not a string on object with __toString()
96+
* @throws \UnexpectedValueException For invalid header values.
97+
*/
98+
public function setHeadersFromString($headers)
99+
{
100+
if (!(is_string($headers)
101+
|| (is_object($headers) && method_exists($headers, '__toString')))
102+
) {
103+
throw new \InvalidArgumentException(
104+
sprintf(
105+
'%s expects parameter 1 to be a string, %s given',
106+
__METHOD__,
107+
is_object($headers) ? get_class($headers) : gettype($headers)
108+
)
109+
);
110+
}
111+
112+
$this->setHeadersFromArray(explode("\r\n", $headers));
113+
114+
return $this;
115+
}
116+
}

0 commit comments

Comments
 (0)