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

Commit

Permalink
Add functionality to create CSV response from array and traversable
Browse files Browse the repository at this point in the history
In addition to the refactor to create the CSV response from a string,
this change adds the ability to create the CSV response from a plain old
PHP array as well as a Traversable. I'm not altogether happy with the
naming of some of the functions and variables, but will address that,
just as soon as I can think of better names.
  • Loading branch information
settermjd committed Oct 29, 2019
1 parent 6295730 commit 1bd3919
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/Response/CsvResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Zend\Diactoros\Response;

use Psr\Http\Message\StreamInterface;
use Traversable;
use Zend\Diactoros\Exception;
use Zend\Diactoros\Response;
use Zend\Diactoros\Stream;
Expand All @@ -31,6 +32,7 @@ class CsvResponse extends DownloadResponse
{
use InjectContentTypeTrait;

const DEFAULT_LINE_ENDING = "\n";
const DEFAULT_SEPARATOR = ',';

/**
Expand Down Expand Up @@ -83,6 +85,10 @@ private function createBody($text) : StreamInterface
$body = $text;
}

if (is_array($text) | $text instanceof Traversable) {
$body = $this->createBodyFromIterable($text);
}

return $body;
}

Expand All @@ -109,6 +115,25 @@ private function createBodyFromString(string $text) : StreamInterface
return $body;
}

/**
* Create the CSV response body from the contents of an array
* @param array|Traversable $text
* @return StreamInterface
*/
public function createBodyFromIterable($text) : StreamInterface
{
$body = new Stream('php://temp', 'wb+');
$last = end($text);
reset($text);

foreach ($text as $row) {
$body->write($this->getRecord($row, $last));
}
$body->rewind();

return $body;
}

/**
* Get a fully rendered CSV record
* @param array $row
Expand Down
95 changes: 95 additions & 0 deletions test/Response/CsvResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,101 @@ public function testConstructorAcceptsBodyAsString()
$this->assertSame(200, $response->getStatusCode());
}

/**
* @dataProvider arrayToBodyDataProvider
* @param array $input
* @param string $output
* @param array $options
*/
public function testConstructorAcceptsArrayAsBody($input, string $output, array $options)
{
$response = new CsvResponse($input, $options);
$this->assertSame($output, (string) $response->getBody());
$this->assertSame(200, $response->getStatusCode());
}

public function arrayToBodyDataProvider()
{
$bodyWithCommaAsFieldSeparatorOutput = <<<EOF
first,last,email,dob
john,citizen,john.citizen@afakeemailaddress.com,01/01/1970
EOF;

$bodyWithTabAsFieldSeparatorOutput = <<<EOF
first last email dob
john citizen john.citizen@afakeemailaddress.com 01/01/1970
EOF;

$bodyWithSemicolonAsFieldSeparatorOutput = <<<EOF
first;last;email;dob
john;citizen;john.citizen@afakeemailaddress.com;01/01/1970
EOF;

$bodyWithSemicolonAsFieldSeparatorAndCarriageReturnNewlineAsLineEndingOutput = <<<EOF
first;last;email;dob\r
john;citizen;john.citizen@afakeemailaddress.com;01/01/1970
EOF;

$iterator = new \ArrayIterator(
[
["first","last","email","dob"],
["john","citizen","john.citizen@afakeemailaddress.com","01/01/1970"],
]
);

return [
[
[
["first","last","email","dob"],
["john","citizen","john.citizen@afakeemailaddress.com","01/01/1970"],
],
$bodyWithCommaAsFieldSeparatorOutput,
[
"field_separator" => ',',
],
],
[
[
["first","last","email","dob"],
["john","citizen","john.citizen@afakeemailaddress.com","01/01/1970"],
],
$bodyWithTabAsFieldSeparatorOutput,
[
"field_separator" => "\t",
],
],
[
[
["first","last","email","dob"],
["john","citizen","john.citizen@afakeemailaddress.com","01/01/1970"],
],
$bodyWithSemicolonAsFieldSeparatorOutput,
[
"field_separator" => ";",
],
],
[
[
["first","last","email","dob"],
["john","citizen","john.citizen@afakeemailaddress.com","01/01/1970"],
],
$bodyWithSemicolonAsFieldSeparatorAndCarriageReturnNewlineAsLineEndingOutput,
[
"field_separator" => ";",
"line_ending" => "\r\n",
],
],
[
$iterator,
$bodyWithSemicolonAsFieldSeparatorAndCarriageReturnNewlineAsLineEndingOutput,
[
"field_separator" => ";",
"line_ending" => "\r\n",
],
],
];
}

public function testConstructorAllowsPassingStatus()
{
$status = 404;
Expand Down

0 comments on commit 1bd3919

Please sign in to comment.