Completed
Push — master ( 3702d4...d8c731 )
by
unknown
03:05
created

Response::json()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
dl 0
loc 4
rs 10
c 2
b 1
f 1
cc 1
eloc 3
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 {
0 ignored issues
show
Coding Style introduced by
The property $force_dl is not named in camelCase.

This check marks property names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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     = [],
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
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
                     $sent        = false;
33
34
35
    public static function charset($charset){
36
        static::$charset = $charset;
37
    }
38
39
    public static function type($mime){
40
        static::header('Content-Type',$mime . (static::$charset ? '; charset='.static::$charset : ''));
41
    }
42
43
    /**
44
     * Force download of Response body
45
     * @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...
46
     * @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...
47
     */
48
    public static function download($filename){
49
        static::$force_dl = $filename;
50
    }
51
52
    /**
53
     * Start capturing output
54
     */
55
    public static function start(){
56
        static::$buffer = ob_start();
57
    }
58
59
    /**
60
     * Enable CORS HTTP headers.
61
     */
62
    public static function enableCORS(){
63
64
        // Allow from any origin
65
        if ($origin = filter_input(INPUT_SERVER,'HTTP_ORIGIN')) {
66
          static::header('Access-Control-Allow-Origin', $origin);
67
          static::header('Access-Control-Allow-Credentials', 'true');
68
          static::header('Access-Control-Max-Age', 86400);
69
        }
70
71
        // Access-Control headers are received during OPTIONS requests
72
        if (filter_input(INPUT_SERVER,'REQUEST_METHOD') == 'OPTIONS') {
73
            static::clean();
74
75
            if (filter_input(INPUT_SERVER,'HTTP_ACCESS_CONTROL_REQUEST_METHOD')) {
76
              static::header('Access-Control-Allow-Methods',
77
                'GET, POST, PUT, DELETE, OPTIONS, HEAD, CONNECT, PATCH, TRACE');
78
            }
79
            if ($req_h = filter_input(INPUT_SERVER,'HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) {
80
              static::header('Access-Control-Allow-Headers',$req_h);
81
            }
82
83
            static::send();
84
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method enableCORS() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
85
        }
86
    }
87
88
    public static function sent() {
89
        return static::$sent;
90
    }
91
92
    /**
93
     * Finish the output buffer capturing.
94
     * @return string The captured buffer
95
     */
96
    public static function end(){
97
        if (static::$buffer){
98
            static::$payload[] = ob_get_contents();
99
            ob_end_clean();
100
            static::$buffer = null;
101
            return end(static::$payload);
102
        }
103
    }
104
105
    /**
106
     * Check if an response output buffering is active.
107
     * @return boolean
108
     */
109
    public static function isBuffering(){
110
        return static::$buffer;
111
    }
112
113
    /**
114
     * Clear the response body
115
     */
116
    public static function clean(){
117
        static::$payload = [];
118
    }
119
120
    /**
121
     * Append a JSON object to the buffer.
122
     * @param  mixed $payload Data to append to the response buffer
123
     */
124
    public static function json($payload){
125
        static::type(static::TYPE_JSON);
126
        static::$payload[] = json_encode($payload, Options::get('core.response.json_flags',JSON_NUMERIC_CHECK));
127
    }
128
129
    /**
130
     * Append a text to the buffer.
131
     * @param  mixed $payload Text to append to the response buffer
132
     */
133
    public static function text(){
134
        static::type(static::TYPE_TEXT);
135
        static::$payload[] = implode('',func_get_args());
136
    }
137
138
    /**
139
     * Append an XML string to the buffer.
140
     * @param  mixed $payload Data to append to the response buffer
141
     */
142
    public static function xml(){
143
        static::type(static::TYPE_XML);
144
        static::$payload[] = implode('',func_get_args());
145
    }
146
147
    /**
148
     * Append a SVG string to the buffer.
149
     * @param  mixed $payload Data to append to the response buffer
150
     */
151
    public static function svg(){
152
        static::type(static::TYPE_SVG);
153
        static::$payload[] = implode('',func_get_args());
154
    }
155
156
    /**
157
     * Append an HTML string to the buffer.
158
     * @param  mixed $payload Data to append to the response buffer
159
     */
160
    public static function html(){
161
        static::type(static::TYPE_HTML);
162
        static::$payload[] = implode('',func_get_args());
163
    }
164
165
    /**
166
     * Append a raw string to the buffer.
167
     * @param  mixed $payload Data to append to the response buffer
168
     */
169
    public static function add(){
170
        static::$payload[] = implode('',func_get_args());
171
    }
172
173
    public static function status($code,$message=''){
174
        static::header('Status',$message?:$code,$code);
175
    }
176
177
    public static function header($name,$value,$code=null){
178
        static::$headers[$name] = [$value,$code];
179
    }
180
181
    public static function error($code=500,$message='Application Error'){
182
        Event::trigger('core.response.error',$code,$message);
183
        static::status($code,$message);
184
    }
185
186
    public static function body($setBody=null){
187
      if ($setBody) static::$payload = [$setBody];
188
      return Filter::with('core.response.body',is_array(static::$payload)?implode('',static::$payload):static::$payload);
189
    }
190
191
    public static function headers($setHeaders=null){
192
       if ($setHeaders) static::$headers = $setHeaders;
193
       return static::$headers;
194
    }
195
196
    /**
197
     * Save response as an object, for serialization or cache storage
198
     *
199
     * @method save
200
     *
201
     * @return array Headers and body of the response
202
     */
203
    public static function save(){
204
        return [
205
          'head' => static::$headers,
206
          'body' => static::body(),
207
        ];
208
    }
209
210
    /**
211
     * Load response from a saved state
212
     *
213
     * @method load
214
     *
215
     * @param  array $data head/body saved state
216
     */
217
    public static function load($data){
218
      $data = (object)$data;
219
      if (isset($data->head)) static::headers($data->head);
220
      if (isset($data->body)) static::body($data->body);
221
    }
222
223
    public static function send(){
224
        static::$sent = true;
225
        Event::trigger('core.response.send');
226
        if (false === headers_sent()) foreach (static::$headers as $name => $value_code) {
227
            if (is_array($value_code)) {
228
                list($value, $code) = (count($value_code) > 1) ? $value_code : [current($value_code), 200];
229
            } else {
230
                $value = $value_code;
231
                $code  = null;
232
            }
233
234
            if ($value == 'Status'){
235
              if (function_exists('http_response_code')){
236
                http_response_code($code);
237
              } else {
238
                header("Status: $code", true, $code);
239
              }
240
241
            } else {
242
                $code
243
                ? header("$name: $value", true, $code)
244
                : header("$name: $value", true);
245
            }
246
        }
247
        if (static::$force_dl) header('Content-Disposition: attachment; filename="'.static::$force_dl.'"');
248
        echo static::body();
249
    }
250
251
}
252