Passed
Push — master ( 6137c7...082ebf )
by Andy
02:06
created

Downloader::setResponseHeaders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Palmtree\Csv;
4
5
class Downloader extends Writer
6
{
7
    /**
8
     * Default headers used to tell client the response is
9
     * a downloadable, non-cacheable file.
10
     * @var array
11
     */
12
    public static $defaultResponseHeaders = [
13
        'Content-Type'              => 'application/octet-stream',
14
        'Content-Description'       => 'File Transfer',
15
        'Content-Transfer-Encoding' => 'Binary',
16
        'Content-Disposition'       => 'attachment; filename="%s"',
17
        'Expires'                   => '0',
18
        'Cache-Control'             => 'must-revalidate, post-check=0, pre-check=0',
19
        'Pragma'                    => 'public',
20
        'Content-Length'            => '%s',
21
    ];
22
23
    protected $filename;
24
    protected $responseHeaders;
25
26
    public function __construct($filename = '', $responseHeaders = [])
27
    {
28
        if (!$filename) {
29
            $filename = time() . '.csv';
30
        }
31
32
        $this->setFilename($filename);
33
        $this->setResponseHeaders($responseHeaders);
34
35
        parent::__construct('php://temp');
36
    }
37
38
    public function getResponseHeaders()
39
    {
40
        if (!$this->responseHeaders) {
41
            $this->setResponseHeaders();
42
        }
43
44
        return $this->responseHeaders;
45
    }
46
47
    public function setResponseHeaders($userHeaders = [])
48
    {
49
        $headers = static::$defaultResponseHeaders;
50
51
        $headers = array_replace($headers, $userHeaders);
52
53
        $this->responseHeaders = $headers;
54
    }
55
56
    /**
57
     * @return string
58
     */
59
    public function getFilename()
60
    {
61
        return $this->filename;
62
    }
63
64
    /**
65
     * @param string $filename
66
     *
67
     * @return Downloader
68
     */
69
    public function setFilename($filename)
70
    {
71
        $this->filename = $filename;
72
73
        return $this;
74
    }
75
76
    /**
77
     * Attempts to send the file as download to the client.
78
     *
79
     * @throws \Exception
80
     */
81
    public function download()
82
    {
83
        if (headers_sent()) {
84
            throw new \Exception('Unable to start file download. Response headers already sent.');
85
        }
86
87
        $headers = $this->getResponseHeaders();
88
        $body    = $this->getResponseBody();
89
90
        if (!empty($headers['Content-Length'])) {
91
            $headers['Content-Length'] = sprintf($headers['Content-Length'], mb_strlen($body));
92
        }
93
94
        if (isset($headers['Content-Disposition'])) {
95
            $headers['Content-Disposition'] = sprintf($headers['Content-Disposition'], $this->getFilename());
96
        }
97
98
        foreach ($headers as $key => $value) {
99
            header(sprintf('%s: %s', $key, $value));
100
        }
101
102
        print $body;
103
104
        $this->closeFileHandle();
105
    }
106
107
    protected function getResponseBody()
108
    {
109
        $this->trimTrailingLineEnding();
110
111
        rewind($this->getFileHandle());
112
113
        $body = stream_get_contents($this->getFileHandle());
114
115
        return $body;
116
    }
117
}
118