Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 1829cb1

Browse files
committed
Merge branch 'develop'
Merging develop to master in preparation for 1.2.0 release.
2 parents 90f5cf9 + e745d9a commit 1829cb1

File tree

11 files changed

+598
-4
lines changed

11 files changed

+598
-4
lines changed

CHANGELOG.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,38 @@
22

33
All notable changes to this project will be documented in this file, in reverse chronological order by release.
44

5+
## 1.2.0 - TBD
6+
7+
### Added
8+
9+
- [#88](https://github.com/zendframework/zend-diactoros/pull/88) updates the
10+
`SapiEmitter` to emit a `Content-Length` header with the content length as
11+
reported by the response body stream, assuming that
12+
`StreamInterface::getSize()` returns an integer.
13+
- [#77](https://github.com/zendframework/zend-diactoros/pull/77) adds a new
14+
response type, `Zend\Diactoros\Response\TextResponse`, for returning plain
15+
text responses. By default, it sets the content type to `text/plain;
16+
charset=utf-8`; per the other response types, the signature is `new
17+
TextResponse($text, $status = 200, array $headers = []`.
18+
- [#90](https://github.com/zendframework/zend-diactoros/pull/90) adds a new
19+
`Zend\Diactoros\CallbackStream`, allowing you to back a stream with a PHP
20+
callable (such as a generator) to generate the message content. Its
21+
constructor accepts the callable: `$stream = new CallbackStream($callable);`
22+
23+
### Deprecated
24+
25+
- Nothing.
26+
27+
### Removed
28+
29+
- Nothing.
30+
31+
### Fixed
32+
33+
- [#77](https://github.com/zendframework/zend-diactoros/pull/77) updates the
34+
`HtmlResponse` to set the charset to utf-8 by default (if no content type
35+
header is provided at instantiation).
36+
537
## 1.1.5 - TBD
638

739
### Added
@@ -49,7 +81,8 @@ All notable changes to this project will be documented in this file, in reverse
4981

5082
### Added
5183

52-
- Nothing.
84+
- [#73](https://github.com/zendframework/zend-diactoros/pull/73) adds caching of
85+
the vendor directory to the Travis-CI configuration, to speed up builds.
5386

5487
### Deprecated
5588

doc/book/custom-responses.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ Some standard use cases, however, make this un-wieldy:
2323
Starting with version 1.1, Diactoros offers several custom response types for simplifying these
2424
common tasks.
2525

26+
## Text Responses
27+
28+
`Zend\Diactoros\Response\TextResponse` creates a plain text response. It sets the
29+
`Content-Type` header to `text/plain` by default:
30+
31+
```php
32+
$response = new TextResponse('Hello world!');
33+
```
34+
35+
The constructor accepts two additional arguments: a status code and an array of headers.
36+
37+
```php
38+
$response = new TextResponse($text, 200, ['Content-Type' => ['text/csv']]);
39+
```
40+
2641
## HTML Responses
2742

2843
`Zend\Diactoros\Response\HtmlResponse` allows specifying HTML as a payload, and sets the

src/CallbackStream.php

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @see http://github.com/zendframework/zend-diactoros for the canonical source repository
6+
* @copyright Copyright (c) 2015 Oscar Otero (http://oscarotero.com) / Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8+
*/
9+
10+
namespace Zend\Diactoros;
11+
12+
use InvalidArgumentException;
13+
use RuntimeException;
14+
use Psr\Http\Message\StreamInterface;
15+
16+
/**
17+
* Implementation of PSR HTTP streams
18+
*/
19+
class CallbackStream implements StreamInterface
20+
{
21+
/**
22+
* @var callable|null
23+
*/
24+
protected $callback;
25+
26+
/**
27+
* @param callable $callback
28+
* @throws InvalidArgumentException
29+
*/
30+
public function __construct(callable $callback)
31+
{
32+
$this->attach($callback);
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function __toString()
39+
{
40+
return $this->getContents();
41+
}
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
public function close()
47+
{
48+
$this->callback = null;
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
public function detach()
55+
{
56+
$callback = $this->callback;
57+
$this->callback = null;
58+
return $callback;
59+
}
60+
61+
/**
62+
* Attach a new callback to the instance.
63+
*
64+
* @param callable $callback
65+
* @throws InvalidArgumentException for callable callback
66+
*/
67+
public function attach(callable $callback)
68+
{
69+
$this->callback = $callback;
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function getSize()
76+
{
77+
}
78+
79+
/**
80+
* {@inheritdoc}
81+
*/
82+
public function tell()
83+
{
84+
throw new RuntimeException('Callback streams cannot tell position');
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
public function eof()
91+
{
92+
return empty($this->callback);
93+
}
94+
95+
/**
96+
* {@inheritdoc}
97+
*/
98+
public function isSeekable()
99+
{
100+
return false;
101+
}
102+
103+
/**
104+
* {@inheritdoc}
105+
*/
106+
public function seek($offset, $whence = SEEK_SET)
107+
{
108+
throw new RuntimeException('Callback streams cannot seek position');
109+
}
110+
111+
/**
112+
* {@inheritdoc}
113+
*/
114+
public function rewind()
115+
{
116+
throw new RuntimeException('Callback streams cannot rewind position');
117+
}
118+
119+
/**
120+
* {@inheritdoc}
121+
*/
122+
public function isWritable()
123+
{
124+
return false;
125+
}
126+
127+
/**
128+
* {@inheritdoc}
129+
*/
130+
public function write($string)
131+
{
132+
throw new RuntimeException('Callback streams cannot write');
133+
}
134+
135+
/**
136+
* {@inheritdoc}
137+
*/
138+
public function isReadable()
139+
{
140+
return false;
141+
}
142+
143+
/**
144+
* {@inheritdoc}
145+
*/
146+
public function read($length)
147+
{
148+
throw new RuntimeException('Callback streams cannot read');
149+
}
150+
151+
/**
152+
* {@inheritdoc}
153+
*/
154+
public function getContents()
155+
{
156+
$callback = $this->detach();
157+
158+
return $callback ? $callback() : '';
159+
}
160+
161+
/**
162+
* {@inheritdoc}
163+
*/
164+
public function getMetadata($key = null)
165+
{
166+
$metadata = [
167+
'eof' => $this->eof(),
168+
'stream_type' => 'callback',
169+
'seekable' => false
170+
];
171+
172+
if (null === $key) {
173+
return $metadata;
174+
}
175+
176+
if (! array_key_exists($key, $metadata)) {
177+
return null;
178+
}
179+
180+
return $metadata[$key];
181+
}
182+
}

src/Response/HtmlResponse.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function __construct($html, $status = 200, array $headers = [])
4141
parent::__construct(
4242
$this->createBody($html),
4343
$status,
44-
$this->injectContentType('text/html', $headers)
44+
$this->injectContentType('text/html; charset=utf-8', $headers)
4545
);
4646
}
4747

src/Response/SapiEmitter.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public function emit(ResponseInterface $response, $maxBufferLevel = null)
2929
throw new RuntimeException('Unable to emit response; headers already sent');
3030
}
3131

32+
if (! $response->hasHeader('Content-Length')) {
33+
// PSR-7 indicates int OR null for the stream size; for null values,
34+
// we will not auto-inject the Content-Length.
35+
if (null !== $response->getBody()->getSize()) {
36+
$response = $response->withHeader('Content-Length', (string) $response->getBody()->getSize());
37+
}
38+
}
39+
3240
$this->emitStatusLine($response);
3341
$this->emitHeaders($response);
3442
$this->emitBody($response, $maxBufferLevel);

src/Response/TextResponse.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @see http://github.com/zendframework/zend-diactoros for the canonical source repository
6+
* @copyright Copyright (c) 2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8+
*/
9+
10+
namespace Zend\Diactoros\Response;
11+
12+
use InvalidArgumentException;
13+
use Psr\Http\Message\StreamInterface;
14+
use Zend\Diactoros\Response;
15+
use Zend\Diactoros\Stream;
16+
17+
/**
18+
* Plain text response.
19+
*
20+
* Allows creating a response by passing a string to the constructor;
21+
* by default, sets a status code of 200 and sets the Content-Type header to
22+
* text/plain.
23+
*/
24+
class TextResponse extends Response
25+
{
26+
use InjectContentTypeTrait;
27+
28+
/**
29+
* Create a plain text response.
30+
*
31+
* Produces a text response with a Content-Type of text/plain and a default
32+
* status of 200.
33+
*
34+
* @param string|StreamInterface $text String or stream for the message body.
35+
* @param int $status Integer status code for the response; 200 by default.
36+
* @param array $headers Array of headers to use at initialization.
37+
* @throws InvalidArgumentException if $text is neither a string or stream.
38+
*/
39+
public function __construct($text, $status = 200, array $headers = [])
40+
{
41+
parent::__construct(
42+
$this->createBody($text),
43+
$status,
44+
$this->injectContentType('text/plain; charset=utf-8', $headers)
45+
);
46+
}
47+
48+
/**
49+
* Create the message body.
50+
*
51+
* @param string|StreamInterface $text
52+
* @return StreamInterface
53+
* @throws InvalidArgumentException if $html is neither a string or stream.
54+
*/
55+
private function createBody($text)
56+
{
57+
if ($text instanceof StreamInterface) {
58+
return $text;
59+
}
60+
61+
if (! is_string($text)) {
62+
throw new InvalidArgumentException(sprintf(
63+
'Invalid content (%s) provided to %s',
64+
(is_object($text) ? get_class($text) : gettype($text)),
65+
__CLASS__
66+
));
67+
}
68+
69+
$body = new Stream('php://temp', 'wb+');
70+
$body->write($text);
71+
return $body;
72+
}
73+
}

0 commit comments

Comments
 (0)