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

Commit 2f7d42f

Browse files
committed
Refactor the CsvResponse to support sending a downloadable response
This change update the CsvResponse to be able to either send a plain CSV text response, or to send the response as a downloadable file instead.
1 parent 1232e66 commit 2f7d42f

File tree

2 files changed

+253
-176
lines changed

2 files changed

+253
-176
lines changed

src/Response/CsvResponse.php

Lines changed: 105 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,105 @@
1-
<?php
2-
/**
3-
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4-
* @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (https://www.zend.com)
5-
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
6-
*/
7-
8-
declare(strict_types=1);
9-
10-
namespace Zend\Diactoros\Response;
11-
12-
use Psr\Http\Message\StreamInterface;
13-
use Zend\Diactoros\Exception;
14-
use Zend\Diactoros\Response;
15-
use Zend\Diactoros\Stream;
16-
17-
use function get_class;
18-
use function gettype;
19-
use function is_object;
20-
use function is_string;
21-
use function sprintf;
22-
23-
/**
24-
* CSV response.
25-
*
26-
* Allows creating a CSV response by passing a string to the constructor;
27-
* by default, sets a status code of 200 and sets the Content-Type header to
28-
* text/csv.
29-
*/
30-
class CsvResponse extends Response
31-
{
32-
use InjectContentTypeTrait;
33-
34-
/**
35-
* Create a CSV response.
36-
*
37-
* Produces a CSV response with a Content-Type of text/csv and a default
38-
* status of 200.
39-
*
40-
* @param string|StreamInterface $text String or stream for the message body.
41-
* @param int $status Integer status code for the response; 200 by default.
42-
* @param array $headers Array of headers to use at initialization.
43-
* @throws Exception\InvalidArgumentException if $text is neither a string or stream.
44-
*/
45-
public function __construct($text, int $status = 200, array $headers = [])
46-
{
47-
parent::__construct(
48-
$this->createBody($text),
49-
$status,
50-
$this->injectContentType('text/csv; charset=utf-8', $headers)
51-
);
52-
}
53-
54-
/**
55-
* Create the CSV message body.
56-
*
57-
* @param string|StreamInterface $text
58-
* @throws Exception\InvalidArgumentException if $text is neither a string or stream.
59-
*/
60-
private function createBody($text) : StreamInterface
61-
{
62-
if ($text instanceof StreamInterface) {
63-
return $text;
64-
}
65-
66-
if (! is_string($text)) {
67-
throw new Exception\InvalidArgumentException(sprintf(
68-
'Invalid CSV content (%s) provided to %s',
69-
(is_object($text) ? get_class($text) : gettype($text)),
70-
__CLASS__
71-
));
72-
}
73-
74-
$body = new Stream('php://temp', 'wb+');
75-
$body->write($text);
76-
$body->rewind();
77-
return $body;
78-
}
79-
}
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4+
* @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Zend\Diactoros\Response;
11+
12+
use Psr\Http\Message\StreamInterface;
13+
use Zend\Diactoros\Exception;
14+
use Zend\Diactoros\Response;
15+
use Zend\Diactoros\Stream;
16+
17+
use function get_class;
18+
use function gettype;
19+
use function is_object;
20+
use function is_string;
21+
use function sprintf;
22+
23+
/**
24+
* CSV response.
25+
*
26+
* Allows creating a CSV response by passing a string to the constructor;
27+
* by default, sets a status code of 200 and sets the Content-Type header to
28+
* text/csv.
29+
*/
30+
class CsvResponse extends Response
31+
{
32+
use DownloadResponseTrait;
33+
use InjectContentTypeTrait;
34+
35+
/**
36+
* Create a CSV response.
37+
*
38+
* Produces a CSV response with a Content-Type of text/csv and a default
39+
* status of 200.
40+
*
41+
* @param string|StreamInterface $text String or stream for the message body.
42+
* @param int $status Integer status code for the response; 200 by default.
43+
* @param string $filename
44+
* @param array $headers Array of headers to use at initialization.
45+
*/
46+
public function __construct($text, int $status = 200, string $filename = '', array $headers = [])
47+
{
48+
if (is_string($filename) && $filename !== '') {
49+
$headers = $this->prepareDownloadHeaders($filename, $headers);
50+
}
51+
52+
parent::__construct(
53+
$this->createBody($text),
54+
$status,
55+
$this->injectContentType('text/csv; charset=utf-8', $headers)
56+
);
57+
}
58+
59+
/**
60+
* Create the CSV message body.
61+
*
62+
* @param string|StreamInterface $text
63+
* @return StreamInterface
64+
* @throws Exception\InvalidArgumentException if $text is neither a string or stream.
65+
*/
66+
private function createBody($text) : StreamInterface
67+
{
68+
if ($text instanceof StreamInterface) {
69+
return $text;
70+
}
71+
72+
if (! is_string($text)) {
73+
throw new Exception\InvalidArgumentException(sprintf(
74+
'Invalid CSV content (%s) provided to %s',
75+
(is_object($text) ? get_class($text) : gettype($text)),
76+
__CLASS__
77+
));
78+
}
79+
80+
$body = new Stream('php://temp', 'wb+');
81+
$body->write($text);
82+
$body->rewind();
83+
return $body;
84+
}
85+
86+
/**
87+
* Get download headers
88+
*
89+
* @param string $filename
90+
* @return array
91+
*/
92+
private function getDownloadHeaders(string $filename): array
93+
{
94+
$headers = [];
95+
$headers['cache-control'] = ['must-revalidate'];
96+
$headers['content-description'] = ['File Transfer'];
97+
$headers['content-disposition'] = [sprintf('attachment; filename=%s', $filename)];
98+
$headers['content-transfer-encoding'] = ['Binary'];
99+
$headers['content-type'] = ['text/csv; charset=utf-8'];
100+
$headers['expires'] = ['0'];
101+
$headers['pragma'] = ['Public'];
102+
103+
return $headers;
104+
}
105+
}

0 commit comments

Comments
 (0)