Passed
Push — dev ( f9244b...010882 )
by 世昌
02:20
created

Response::sendFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 6
rs 10
1
<?php
2
namespace suda\framework;
3
4
use Exception;
5
use suda\application\Application;
6
use suda\framework\http\Cookie;
7
use suda\framework\http\Stream;
8
use suda\framework\http\stream\DataStream;
9
use suda\framework\response\MimeType;
10
use suda\framework\response\ContentWrapper;
11
use suda\framework\response\ResponseWrapper;
12
use suda\framework\http\Response as ResponseInterface;
13
14
class Response extends ResponseWrapper
15
{
16
    /**
17
     * 包装器
18
     *
19
     * @var ContentWrapper
20
     */
21
    protected $wrapper;
22
23
    /**
24
     * @var Application
25
     */
26
    private $application;
27
    
28
    /**
29
     * 响应数据
30
     *
31
     * @var Stream|string
32
     */
33
    protected $data;
34
35
36
    public function __construct(ResponseInterface $response, Application $application)
37
    {
38
        parent::__construct($response);
39
        $this->wrapper = new ContentWrapper;
40
        $this->application = $application;
41
    }
42
43
    /**
44
     * 设置类型
45
     *
46
     * @param string $extension
47
     * @return $this
48
     */
49
    public function setType(string $extension)
50
    {
51
        $this->header('content-type', MimeType::getMimeType($extension), true);
52
        return $this;
53
    }
54
55
    /**
56
     * 设置头部
57
     *
58
     * @param string $name
59
     * @param string $content
60
     * @param boolean $replace
61
     * @return $this
62
     */
63
    public function setHeader(string $name, string $content, bool $replace = false)
64
    {
65
        $this->header($name, $content, $replace);
66
        return $this;
67
    }
68
69
    /**
70
     * 设置请求内容
71
     *
72
     * @param mixed $content
73
     * @return $this
74
     */
75
    public function setContent($content)
76
    {
77
        if (is_string($content) || $content instanceof Stream) {
78
            $this->data = $content;
79
        } else {
80
            $wrapper = $this->wrapper->getWrapper($content);
81
            $this->data = $wrapper->getWrappedContent($this);
82
        }
83
        return $this;
84
    }
85
86
87
    /**
88
     * 发送内容数据
89
     *
90
     * @param array|string|Stream|null $data
91
     * @return $this
92
     */
93
    protected function sendContentLength($data)
94
    {
95
        if ($data === null) {
96
            $this->setHeader('content-length', 0);
97
        } elseif (is_array($data)) {
98
            $this->setHeader('content-length', $this->getDataLengthArray($data), true);
99
        } else {
100
            $this->setHeader('content-length', $this->getDataLengthItem($data), true);
101
        }
102
        return $this;
103
    }
104
105
    /**
106
     * 获取数据长度
107
     *
108
     * @param Stream[] $data
109
     * @return int
110
     */
111
    protected function getDataLengthArray(array $data):int
112
    {
113
        $length = 0;
114
        foreach ($data as $item) {
115
            $length += $this->getDataLengthItem($item);
116
        }
117
        return $length;
118
    }
119
120
    /**
121
     * 获取数据长度
122
     *
123
     * @param Stream|string $data
124
     * @return integer
125
     */
126
    protected function getDataLengthItem($data):int
127
    {
128
        if (is_string($data)) {
129
            return strlen($data);
130
        } else {
131
            return $data->length();
132
        }
133
    }
134
135
    /**
136
     * 设置 Cookie
137
     *
138
     * @param string $name
139
     * @param string $value
140
     * @param integer $expire
141
     * @return Cookie
142
     */
143
    public function setCookie(string $name, string $value, int $expire = 0):Cookie
144
    {
145
        $cookie = new Cookie($name, $value, $expire);
146
        $this->cookie($cookie);
147
        return $cookie;
148
    }
149
150
    /**
151
     * 直接发送数据
152
     *
153
     * @param mixed $content
154
     * @return void
155
     */
156
    public function sendContent($content = null)
157
    {
158
        if ($content !== null) {
159
            $this->setContent($content);
160
        }
161
        $this->sendContentLength($this->data);
162
        $this->send($this->data);
163
    }
164
165
166
    /**
167
     * 发送文件内容
168
     *
169
     * @param string $filename
170
     * @param integer $offset
171
     * @param integer $length
172
     * @return void
173
     * @throws Exception
174
     */
175
    public function sendFile(string $filename, int $offset = 0, int $length = null)
176
    {
177
        $this->triggerSendEvent();
178
        $data = new DataStream($filename, $offset, $length);
179
        $this->setHeader('content-length', $data->length());
180
        $this->response->sendFile($filename, $offset, $length);
181
    }
182
183
    /**
184
     * @param string $url
185
     * @param int $httpCode
186
     */
187
    public function redirect(string $url, int $httpCode = 302)
188
    {
189
        $this->triggerSendEvent();
190
        parent::redirect($url, $httpCode);
191
    }
192
193
    /**
194
     * 发送缓存的内容
195
     */
196
    public function end()
197
    {
198
        $this->sendContent($this->data);
199
    }
200
201
    /**
202
     * @param string|Stream $data
203
     */
204
    public function send($data)
205
    {
206
        $this->triggerSendEvent();
207
        parent::send($data);
208
    }
209
210
    /**
211
     * 出发发送内容事件
212
     */
213
    private function triggerSendEvent()
214
    {
215
        if ($this->isSend() === false) {
216
            $this->application->event()->exec('response::before-send', [$this]);
217
        }
218
    }
219
220
    /**
221
     * @return ContentWrapper
222
     */
223
    public function getWrapper(): ContentWrapper
224
    {
225
        return $this->wrapper;
226
    }
227
228
    /**
229
     * @param ContentWrapper $wrapper
230
     */
231
    public function setWrapper(ContentWrapper $wrapper)
232
    {
233
        $this->wrapper = $wrapper;
234
    }
235
}
236