Skip to content

Commit

Permalink
Message: implement getBodyAsString() and getBodyAsStream() for the ca…
Browse files Browse the repository at this point in the history
…se when is a callback function
  • Loading branch information
petrkotek committed Oct 6, 2016
1 parent a849fd6 commit a95cb49
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
29 changes: 25 additions & 4 deletions lib/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,21 @@ abstract class Message implements MessageInterface {
* Note that the stream may not be rewindable, and therefore may only be
* read once.
*
* @throws \RuntimeException
* @return resource
*/
function getBodyAsStream() {

$body = $this->getBody();
if (is_callable($body)) {
$body = $this->captureCallbackOutput($body);
}
if (is_string($body) || is_null($body)) {
$stream = fopen('php://temp', 'r+');
fwrite($stream, $body);
rewind($stream);
return $stream;
}
if (is_callable($body)) {
throw new \UnexpectedValueException('Callback to stream not supported');
}
return $body;

}
Expand All @@ -66,6 +67,7 @@ function getBodyAsStream() {
* Note that because the underlying data may be based on a stream, this
* method could only work correctly the first time.
*
* @throws \RuntimeException
* @return string
*/
function getBodyAsString() {
Expand All @@ -78,7 +80,7 @@ function getBodyAsString() {
return '';
}
if (is_callable($body)) {
throw new \UnexpectedValueException('Callback to string not supported');
return $this->captureCallbackOutput($body);
}
$contentLength = $this->getHeader('Content-Length');
if (null === $contentLength) {
Expand Down Expand Up @@ -318,4 +320,23 @@ function getHttpVersion() {
return $this->httpVersion;

}

/**
* Runs given callback and captures data sent to php://output stream.
*
* @param callable $callback
* @throws \RuntimeException when ob_start() fails to start output buffer
* @return string
*/
private function captureCallbackOutput($callback)
{
$success = ob_start();
if ($success === false) {
throw new \RuntimeException('Cannot start output buffering');
}
$callback();
$content = ob_get_contents();
ob_end_clean();
return $content;
}
}
34 changes: 18 additions & 16 deletions tests/HTTP/MessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,42 +42,40 @@ function testStringBody() {

}

/**
* @expectedException \UnexpectedValueException
*/
function testCallbackBodyAsString() {

$body = $this->createCallback();
$body = $this->createCallback('foo');

$message = new MessageMock();
$message->setBody($body);

$message->getBodyAsString();
$string = $message->getBodyAsString();

$this->assertSame('foo', $string);

}

/**
* @expectedException \UnexpectedValueException
*/
function testCallbackBodyAsStream() {

$body = $this->createCallback();
$body = $this->createCallback('foo');

$message = new MessageMock();
$message->setBody($body);

$message->getBodyAsStream();
$stream = $message->getBodyAsStream();

$this->assertSame('foo', stream_get_contents($stream));

}

function testGetBodyWhenCallback() {

$body = $this->createCallback();
$callback = $this->createCallback('foo');

$message = new MessageMock();
$message->setBody($body);
$message->setBody($callback);

$this->assertEquals($body, $message->getBody());
$this->assertSame($callback, $message->getBody());

}

Expand Down Expand Up @@ -258,11 +256,15 @@ function testHasHeaders() {

}

private function createCallback()
/**
* @param string $content
* @return \Closure Returns a callback printing $content to php://output stream
*/
private function createCallback($content)
{
return function() {
return function() use ($content) {
$fd = fopen('php://output', 'r+');
fwrite($fd, 'foo');
fwrite($fd, $content);
fclose($fd);
};
}
Expand Down

0 comments on commit a95cb49

Please sign in to comment.