Completed
Push — master ( 57f4b6...27e8c7 )
by Stefano
02:19
created

Response::download()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/**
4
 * Response
5
 *
6
 * Handles the HTTP Response for the current execution.
7
 *
8
 * @package core
9
 * @author [email protected]
10
 * @copyright Caffeina srl - 2015 - http://caffeina.it
11
 */
12
13
class Response {
14
    use Module;
15
16
    const TYPE_JSON               = 'application/json',
17
          TYPE_HTML               = 'text/html',
18
          TYPE_TEXT               = 'text/plain',
19
          TYPE_CSS                = 'text/css',
20
          TYPE_XML                = 'text/xml',
21
          TYPE_SVG                = 'image/svg+xml',
22
          TYPE_JS                 = 'application/javascript',
23
          TYPE_BIN                = 'application/octet-stream';
24
25
    protected static $payload     = [],
26
                     $status      = 200,
27
                     $charset     = "utf-8",
28
                     $headers     = ['Content-Type' => ['text/html; charset=utf-8']],
29
                     $buffer      = null,
30
                     $force_dl    = false,
31
                     $link        = null;
32
33
34
    public static function charset($charset){
35
        static::$charset = $charset;
36
    }
37
38
    public static function type($mime){
39
        static::header('Content-Type',$mime . (static::$charset ? '; charset='.static::$charset : ''));
40
    }
41
42
    /**
43
     * Force download of Response body
44
     * @param  string/bool $filename Pass a falsy value to disable download or pass a filename for exporting content
0 ignored issues
show
Documentation introduced by
The doc-type string/bool could not be parsed: Unknown type name "string/bool" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
45
     * @return [type]        [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
46
     */
47
    public static function download($filename){
48
        static::$force_dl = $filename;
49
    }
50
51
    /**
52
     * Start capturing output
53
     */
54
    public static function start(){
55
        static::$buffer = ob_start();
56
    }
57
58
    /**
59
     * Enable CORS HTTP headers.
60
     */
61
    public static function enableCORS(){
62
63
        // Allow from any origin
64
        if ($origin = filter_input(INPUT_SERVER,'HTTP_ORIGIN')) {
65
          static::header('Access-Control-Allow-Origin', $origin);
66
          static::header('Access-Control-Allow-Credentials', 'true');
67
          static::header('Access-Control-Max-Age', 86400);
68
        }
69
70
        // Access-Control headers are received during OPTIONS requests
71
        if (filter_input(INPUT_SERVER,'REQUEST_METHOD') == 'OPTIONS') {
72
            static::clean();
73
74
            if (filter_input(INPUT_SERVER,'HTTP_ACCESS_CONTROL_REQUEST_METHOD')) {
75
              static::header('Access-Control-Allow-Methods',
76
                'GET, POST, PUT, DELETE, OPTIONS, HEAD, CONNECT, PATCH, TRACE');
77
            }
78
            if ($req_h = filter_input(INPUT_SERVER,'HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) {
79
              static::header('Access-Control-Allow-Headers',$req_h);
80
            }
81
82
            static::send();
83
            exit;
84
        }
85
    }
86
87
    /**
88
     * Finish the output buffer capturing.
89
     * @return string The captured buffer
90
     */
91
    public static function end(){
92
        if (static::$buffer){
93
            static::$payload[] = ob_get_contents();
94
            ob_end_clean();
95
            static::$buffer = null;
96
            return end(static::$payload);
97
        }
98
    }
99
100
    /**
101
     * Check if an response output buffering is active.
102
     * @return boolean
103
     */
104
    public static function isBuffering(){
105
        return static::$buffer;
106
    }
107
108
    /**
109
     * Clear the response body
110
     */
111
    public static function clean(){
112
        static::$payload = [];
113
    }
114
115
    /**
116
     * Append a JSON object to the buffer.
117
     * @param  mixed $payload Data to append to the response buffer
118
     */
119
    public static function json($payload){
120
        static::type(static::TYPE_JSON);
121
        static::$payload[] = json_encode($payload, Options::get('core.response.json_flags',JSON_NUMERIC_CHECK));
122
    }
123
124
    /**
125
     * Append a text to the buffer.
126
     * @param  mixed $payload Text to append to the response buffer
127
     */
128
    public static function text(){
129
        static::type(static::TYPE_TEXT);
130
        static::$payload[] = implode('',func_get_args());
131
    }
132
133
    /**
134
     * Append an XML string to the buffer.
135
     * @param  mixed $payload Data to append to the response buffer
136
     */
137
    public static function xml(){
138
        static::type(static::TYPE_XML);
139
        static::$payload[] = implode('',func_get_args());
140
    }
141
142
    /**
143
     * Append a SVG string to the buffer.
144
     * @param  mixed $payload Data to append to the response buffer
145
     */
146
    public static function svg(){
147
        static::type(static::TYPE_SVG);
148
        static::$payload[] = implode('',func_get_args());
149
    }
150
151
    /**
152
     * Append an HTML string to the buffer.
153
     * @param  mixed $payload Data to append to the response buffer
154
     */
155
    public static function html(){
156
        static::type(static::TYPE_HTML);
157
        static::$payload[] = implode('',func_get_args());
158
    }
159
160
    /**
161
     * Append a raw string to the buffer.
162
     * @param  mixed $payload Data to append to the response buffer
163
     */
164
    public static function add(){
165
        static::$payload[] = implode('',func_get_args());
166
    }
167
168
    public static function status($code,$message=''){
169
        static::header('Status',$message?:$code,$code);
170
    }
171
172
    public static function header($name,$value,$code=null){
173
        static::$headers[$name] = [$value,$code];
174
    }
175
176
    public static function error($code=500,$message='Application Error'){
177
        Event::trigger('core.response.error',$code,$message);
178
        static::status($code,$message);
179
    }
180
181
    public static function body($setBody=null){
182
      if ($setBody) static::$payload = [$setBody];
183
      return Filter::with('core.response.body',is_array(static::$payload)?implode('',static::$payload):static::$payload);
184
    }
185
186
    public static function headers($setHeaders=null){
187
       if ($setHeaders) static::$headers = $setHeaders;
188
       return static::$headers;
189
    }
190
191
    /**
192
     * Save response as an object, for serialization or cache storage
193
     *
194
     * @method save
195
     *
196
     * @return array Headers and body of the response
197
     */
198
    public static function save(){
199
        return [
200
          'head' => static::$headers,
201
          'body' => static::body(),
202
        ];
203
    }
204
205
    /**
206
     * Load response from a saved state
207
     *
208
     * @method load
209
     *
210
     * @param  array $data head/body saved state
211
     */
212
    public static function load($data){
213
      $data = (object)$data;
214
      if (isset($data->head)) static::headers($data->head);
215
      if (isset($data->body)) static::body($data->body);
216
    }
217
218
    public static function send(){
219
        Event::trigger('core.response.send');
220
        if (false === headers_sent()) foreach (static::$headers as $name => $value_code) {
221
            if (is_array($value_code)) {
222
                list($value, $code) = (count($value_code) > 1) ? $value_code : [current($value_code), 200];
223
            } else {
224
                $value = $value_code;
225
                $code  = null;
226
            }
227
228
            if ($value == 'Status'){
229
              if (function_exists('http_response_code')){
230
                http_response_code($code);
231
              } else {
232
                header("Status: $code", true, $code);
233
              }
234
235
            } else {
236
                $code
237
                ? header("$name: $value", true, $code)
238
                : header("$name: $value", true);
239
            }
240
        }
241
        if (!static::$force_dl) header('Content-Disposition: attachment; filename="'.static::$force_dl.'"');
242
        echo static::body();
243
    }
244
245
}
246