Response::file()   B
last analyzed

Complexity

Conditions 7
Paths 25

Size

Total Lines 48
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 22
nc 25
nop 3
dl 0
loc 48
rs 8.6346
c 0
b 0
f 0
1
<?php
2
/**
3
 * Klein (klein.php) - A fast & flexible router for PHP
4
 *
5
 * @author      Chris O'Hara <[email protected]>
6
 * @author      Trevor Suarez (Rican7) (contributor and v2 refactorer)
7
 * @copyright   (c) Chris O'Hara
8
 * @link        https://github.com/klein/klein.php
9
 * @license     MIT
10
 */
11
12
namespace app\framework\Component\Routing;
13
14
use app\framework\Component\Routing\Exceptions\ResponseAlreadySentException;
15
use RuntimeException;
16
17
/**
18
 * Response
19
 * @package app\framework\Component\Routing
20
 */
21
class Response extends AbstractResponse
22
{
23
24
    /**
25
     * Methods
26
     */
27
28
    /**
29
     * Enable response chunking
30
     *
31
     * @link https://github.com/klein/klein.php/wiki/Response-Chunking
32
     * @link http://bit.ly/hg3gHb
33
     * @param string $str   An optional string to send as a response "chunk"
34
     * @return Response
35
     */
36
    public function chunk($str = null)
37
    {
38
        parent::chunk();
39
40
        if (null !== $str) {
41
            printf("%x\r\n", strlen($str));
42
            echo "$str\r\n";
43
            flush();
44
        }
45
46
        return $this;
47
    }
48
49
    /**
50
     * Dump a variable
51
     *
52
     * @param mixed $obj    The variable to dump
53
     * @return Response
54
     */
55
    public function dump($obj)
56
    {
57
        if (is_array($obj) || is_object($obj)) {
58
            $obj = print_r($obj, true);
59
        }
60
61
        $this->append('<pre>' .  htmlentities($obj, ENT_QUOTES) . "</pre><br />\n");
62
63
        return $this;
64
    }
65
66
    /**
67
     * Sends a file
68
     *
69
     * It should be noted that this method disables caching
70
     * of the response by default, as dynamically created
71
     * files responses are usually downloads of some type
72
     * and rarely make sense to be HTTP cached
73
     *
74
     * Also, this method removes any data/content that is
75
     * currently in the response body and replaces it with
76
     * the file's data
77
     *
78
     * @param string $path      The path of the file to send
79
     * @param string $filename  The file's name
80
     * @param string $mimetype  The MIME type of the file
81
     * @throws RuntimeException Thrown if the file could not be read
82
     * @return Response
83
     */
84
    public function file($path, $filename = null, $mimetype = null)
85
    {
86
        if ($this->sent) {
87
            throw new ResponseAlreadySentException('Response has already been sent');
88
        }
89
90
        $this->body('');
91
        $this->noCache();
92
93
        if (null === $filename) {
94
            $filename = basename($path);
95
        }
96
        if (null === $mimetype) {
97
            $mimetype = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);
98
        }
99
100
        $this->header('Content-type', $mimetype);
101
        $this->header('Content-Disposition', 'attachment; filename="'.$filename.'"');
102
103
        // If the response is to be chunked, then the content length must not be sent
104
        // see: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
105
        if (false === $this->chunked) {
106
            $this->header('Content-length', filesize($path));
107
        }
108
109
        // Send our response data
110
        $this->sendHeaders();
111
112
        $bytes_read = readfile($path);
113
114
        if (false === $bytes_read) {
115
            throw new RuntimeException('The file could not be read');
116
        }
117
118
        $this->sendBody();
119
120
        // Lock the response from further modification
121
        $this->lock();
122
123
        // Mark as sent
124
        $this->sent = true;
125
126
        // If there running FPM, tell the process manager to finish the server request/response handling
127
        if (function_exists('fastcgi_finish_request')) {
128
            fastcgi_finish_request();
129
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * Sends an object as json or jsonp by providing the padding prefix
136
     *
137
     * It should be noted that this method disables caching
138
     * of the response by default, as json responses are usually
139
     * dynamic and rarely make sense to be HTTP cached
140
     *
141
     * Also, this method removes any data/content that is
142
     * currently in the response body and replaces it with
143
     * the passed json encoded object
144
     *
145
     * @param mixed $object         The data to encode as JSON
146
     * @param string $jsonp_prefix  The name of the JSON-P function prefix
147
     * @return Response
148
     */
149
    public function json($object, $jsonp_prefix = null)
150
    {
151
        $this->body('');
152
        $this->noCache();
153
154
        $json = json_encode($object);
155
156
        if (null !== $jsonp_prefix) {
157
            // Should ideally be application/json-p once adopted
158
            $this->header('Content-Type', 'text/javascript');
159
            $this->body("$jsonp_prefix($json);");
160
        } else {
161
            $this->header('Content-Type', 'application/json');
162
            $this->body($json);
163
        }
164
165
        $this->send();
166
167
        return $this;
168
    }
169
}
170