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

Splitting StringResponse into many smaller classes #61

Merged
merged 7 commits into from
Jun 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@
<directory>./test</directory>
</testsuite>
</testsuites>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>
38 changes: 33 additions & 5 deletions src/Response/HtmlResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Zend\Diactoros\Response;

use InvalidArgumentException;
use Psr\Http\Message\StreamInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\Stream;

Expand All @@ -29,17 +31,43 @@ class HtmlResponse extends Response
* Produces an HTML response with a Content-Type of text/html and a default
* status of 200.
*
* @param string $html HTML for the message body.
* @param string|StreamInterface $html HTML or stream for the message body.
* @param int $status Integer status code for the response; 200 by default.
* @param array $headers Array of headers to use at initialization.
* @throws InvalidArgumentException if $html is neither a string or stream.
*/
public function __construct($html, $status = 200, array $headers = [])
{
$body = new Stream('php://temp', 'wb+');
$body->write($html);
parent::__construct(
$this->createBody($html),
$status,
$this->injectContentType('text/html', $headers)
);
}

/**
* Create the message body.
*
* @param string|StreamInterface $html
* @return StreamInterface
* @throws InvalidArgumentException if $html is neither a string or stream.
*/
private function createBody($html)
{
if ($html instanceof StreamInterface) {
return $html;
}

$headers = $this->injectContentType('text/html', $headers);
if (! is_string($html)) {
throw new InvalidArgumentException(sprintf(
'Invalid content (%s) provided to %s',
(is_object($html) ? get_class($html) : gettype($html)),
__CLASS__
));
}

parent::__construct($body, $status, $headers);
$body = new Stream('php://temp', 'wb+');
$body->write($html);
return $body;
}
}
25 changes: 21 additions & 4 deletions src/Response/JsonResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Zend\Diactoros\Response;

use ArrayObject;
use InvalidArgumentException;
use Zend\Diactoros\Response;
use Zend\Diactoros\Stream;

Expand All @@ -30,13 +31,19 @@ class JsonResponse extends Response
* If the data provided is null, an empty ArrayObject is used; if the data
* is scalar, it is cast to an array prior to serialization.
*
* Default JSON encoding is performed with JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT options
* (RFC4627-compliant JSON, which may also be embedded into HTML)
* Default JSON encoding is performed with the following options, which
* produces RFC4627-compliant JSON, capable of embedding into HTML.
*
* - JSON_HEX_TAG
* - JSON_HEX_APOS
* - JSON_HEX_AMP
* - JSON_HEX_QUOT options
*
* @param string $data Data to convert to JSON.
* @param int $status Integer status code for the response; 200 by default.
* @param array $headers Array of headers to use at initialization.
* @param int $encodingOptions The JSON encoding options
* @param int $encodingOptions JSON encoding options to use.
* @throws InvalidArgumentException if unable to encode the $data to JSON.
*/
public function __construct($data, $status = 200, array $headers = [], $encodingOptions = 15)
{
Expand All @@ -54,9 +61,14 @@ public function __construct($data, $status = 200, array $headers = [], $encoding
* @param mixed $data
* @param int $encodingOptions
* @return string
* @throws InvalidArgumentException if unable to encode the $data to JSON.
*/
private function jsonEncode($data, $encodingOptions)
{
if (is_resource($data)) {
throw new InvalidArgumentException('Cannot JSON encode resources');
}

if ($data === null) {
// Use an ArrayObject to force an empty JSON object.
$data = new ArrayObject();
Expand All @@ -68,10 +80,15 @@ private function jsonEncode($data, $encodingOptions)

// Clear json_last_error()
json_encode(null);

$json = json_encode($data, $encodingOptions);

if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException(json_last_error_msg());
throw new InvalidArgumentException(sprintf(
'Unable to encode data to JSON in %s: %s',
__CLASS__,
json_last_error_msg()
));
}

return $json;
Expand Down
32 changes: 32 additions & 0 deletions test/Response/HtmlResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,36 @@ public function testConstructorAllowsPassingHeaders()
$this->assertEquals(404, $response->getStatusCode());
$this->assertSame($body, (string) $response->getBody());
}

public function testAllowsStreamsForResponseBody()
{
$stream = $this->prophesize('Psr\Http\Message\StreamInterface');
$body = $stream->reveal();
$response = new HtmlResponse($body);
$this->assertSame($body, $response->getBody());
}

public function invalidHtmlContent()
{
return [
'null' => [null],
'true' => [true],
'false' => [false],
'zero' => [0],
'int' => [1],
'zero-float' => [0.0],
'float' => [1.1],
'array' => [['php://temp']],
'object' => [(object) ['php://temp']],
];
}

/**
* @dataProvider invalidHtmlContent
* @expectedException InvalidArgumentException
*/
public function testRaisesExceptionforNonStringNonStreamBodyContent($body)
{
$response = new HtmlResponse($body);
}
}
25 changes: 22 additions & 3 deletions test/Response/JsonResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,31 @@ public function testCanProvideAlternateContentTypeViaHeadersPassedToConstructor(
}

/**
* @expectedException \InvalidArgumentException
* @expectedException InvalidArgumentException
*/
public function testJsonErrorHandling()
public function testJsonErrorHandlingOfResources()
{
// Serializing something that is not serializable.
$resource = fopen("php://memory", "r");
$resource = fopen('php://memory', 'r');
new JsonResponse($resource);
}

public function testJsonErrorHandlingOfBadEmbeddedData()
{
if (version_compare(PHP_VERSION, '5.5', 'lt')) {
$this->markTestSkipped('Skipped as PHP versions prior to 5.5 are noisy about JSON errors');
}

if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Skipped as HHVM happily serializes embedded resources');
}

// Serializing something that is not serializable.
$data = [
'stream' => fopen('php://memory', 'r'),
];

$this->setExpectedException('InvalidArgumentException', 'Unable to encode');
new JsonResponse($data);
}
}