Completed
Push — master ( 035d24...d62e14 )
by Kanto
15s queued 12s
created

Controller::handleShutdown()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
nc 3
nop 0
dl 0
loc 11
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * Kore : Simple And Minimal Framework
4
 *
5
 */
6
7
namespace Kore;
8
9
use Kore\Log;
10
use Exception;
11
12
/**
13
 * Controller class
14
 *
15
 */
16
abstract class Controller
17
{
18
    /**
19
     * controller namespace
20
     *
21
     * @var string
22
     */
23
    protected $controller;
24
    /**
25
     * path arguments
26
     *
27
     * @var array<string>
28
     */
29
    protected $args = array();
30
    /**
31
     * request body
32
     *
33
     * @var string
34
     */
35
    protected $body;
36
37
    /**
38
     * Action
39
     *
40
     * The action is implemented in subclasses.
41
     * @return void
42
     */
43
    abstract protected function action();
44
45
    /**
46
     * Main Processing
47
     *
48
     * @param string $controller controller namespace
49
     * @param array<string> $args path arguments
50
     * @return void
51
     */
52
    public function main($controller, $args)
53
    {
54
        $this->controller = $controller;
55
        $this->args = $args;
56
        Log::init($this->moduleName(), $this->logLevel());
57
58
        Log::debug(sprintf('[START]%s', $this->controller));
59
        try {
60
            $this->preaction();
61
            $this->action();
62
        } catch (Exception $e) {
63
            $this->handleError($e);
64
        }
65
        Log::debug(sprintf('[END]%s', $this->controller));
66
    }
67
68
    /**
69
     * Get the module name
70
     *
71
     * The default is 'app'.
72
     * If you need to customize, please override it with subclasses.
73
     * @return string module name
74
     */
75
    protected function moduleName()
76
    {
77
        return 'app';
78
    }
79
80
    /**
81
     * Get the log level
82
     *
83
     * The default is Log::LEVEL_DEBUG.
84
     * If you need to customize, please override it with subclasses.
85
     * @return int log level
86
     * @see \Kore\Log
87
     */
88
    protected function logLevel()
89
    {
90
        return Log::LEVEL_DEBUG;
91
    }
92
93
    /**
94
     * Preprocessing of the action
95
     *
96
     * If you need to customize, please override it with subclasses.
97
     * @return void
98
     */
99
    protected function preaction()
100
    {
101
        // Override if necessary
102
    }
103
104
    /**
105
     * Handling Errors
106
     *
107
     * If you need to customize the handling of errors, please override it with subclasses.
108
     * @param Exception $e errors
109
     * @return void
110
     * @throws Exception
111
     */
112
    protected function handleError($e)
113
    {
114
        Log::error($e);
115
        throw $e;
116
    }
117
118
    /**
119
     * Handling Shutdown
120
     *
121
     * If you need to customize the handling of shutdown, please override it with subclasses.
122
     * @return void
123
     * @codeCoverageIgnore
124
     */
125
    public function handleShutdown()
126
    {
127
        $error = error_get_last();
128
        if ($error) {
129
            $errorFile = $error['file'];
130
            $errorLine = $error['line'];
131
            $errorMessage = $error['message'];
132
            $errorType = $error['type'];
133
134
            if ($errorType === E_ERROR) {
135
                $this->handleError(new Exception("$errorMessage $errorFile:$errorLine"));
136
            }
137
        }
138
    }
139
140
    /**
141
     * Get the http method
142
     *
143
     * @return mixed http method
144
     */
145
    protected function getMethod()
146
    {
147
        return $this->getServer('REQUEST_METHOD');
148
    }
149
150
    /**
151
     * Get the User Agent
152
     *
153
     * @return mixed User Agent
154
     */
155
    protected function getUserAgent()
156
    {
157
        return $this->getServer('HTTP_USER_AGENT');
158
    }
159
160
    /**
161
     * Get the http header
162
     *
163
     * @param string $key header key
164
     * @param mixed $default default value if there is no value specified in the key
165
     * @return mixed http header
166
     */
167
    protected function getHeader($key, $default = null)
168
    {
169
        $headerName = 'HTTP_' . str_replace('-', '_', strtoupper($key));
170
        return $this->getServer($headerName, $default);
171
    }
172
173
    /**
174
     * Get the query parameters
175
     *
176
     * If no key is specified, all query parameters are returned.
177
     * @param string|null $key query parameter key
178
     * @param mixed $default default value if there is no value specified in the key
179
     * @return mixed query parameters
180
     */
181
    protected function getQuery($key = null, $default = null)
182
    {
183
        return $this->getFromArray($_GET, $key, $default);
184
    }
185
186
    /**
187
     * Get the post parameters
188
     *
189
     * If no key is specified, all post parameters are returned.
190
     * @param string|null $key post parameter key
191
     * @param mixed $default default value if there is no value specified in the key
192
     * @return mixed post parameters
193
     */
194
    protected function getPost($key = null, $default = null)
195
    {
196
        return $this->getFromArray($_POST, $key, $default);
197
    }
198
199
    /**
200
     * Get the body data
201
     *
202
     * @return string body data
203
     */
204
    protected function getBody()
205
    {
206
        if (!isset($this->body)) {
207
            $body = file_get_contents('php://input');
208
            $this->body = $body !== false ? $body : '';
209
        }
210
        return $this->body;
211
    }
212
213
    /**
214
     * Get the body data in json format
215
     *
216
     * @return array<mixed> body data
217
     */
218
    protected function getJsonBody()
219
    {
220
        return json_decode($this->getBody(), true);
221
    }
222
223
    /**
224
     * Get the cookie parameters
225
     *
226
     * If no key is specified, all cookie parameters are returned.
227
     * @param string|null $key cookie parameter key
228
     * @param mixed $default default value if there is no value specified in the key
229
     * @return mixed cookie parameters
230
     */
231
    protected function getCookie($key = null, $default = null)
232
    {
233
        return $this->getFromArray($_COOKIE, $key, $default);
234
    }
235
236
    /**
237
     * Get the server parameters
238
     *
239
     * If no key is specified, all server parameters are returned.
240
     * @param string|null $key server parameter key
241
     * @param mixed $default default value if there is no value specified in the key
242
     * @return mixed server parameters
243
     */
244
    protected function getServer($key = null, $default = null)
245
    {
246
        return $this->getFromArray($_SERVER, $key, $default);
247
    }
248
 
249
    /**
250
     * Get the path arguments
251
     *
252
     * If no key is specified, all path arguments are returned.
253
     * @param string|null $key path argument key
254
     * @param mixed $default default value if there is no value specified in the key
255
     * @return mixed path arguments
256
     */
257
    protected function getArg($key = null, $default = null)
258
    {
259
        return $this->getFromArray($this->args, $key, $default);
260
    }
261
262
    /**
263
     * Get from array
264
     *
265
     * If no key is specified, array is returned.
266
     * @param array<mixed> $array array
267
     * @param string|null $key path key
268
     * @param mixed $default default value if there is no value specified in the key
269
     * @return mixed value
270
     */
271
    protected function getFromArray($array, $key = null, $default = null)
272
    {
273
        if ($key === null) {
274
            return $array;
275
        }
276
        if (!isset($array[$key])) {
277
            return $default;
278
        }
279
        return $array[$key];
280
    }
281
282
    /**
283
     * Respond in view format
284
     *
285
     * @param string $path view file path
286
     * @param array<mixed> $data response data
287
     * @param int $responseCode http status code, the default is 200
288
     * @return void
289
     */
290
    protected function respondView($path, $data=array(), $responseCode = 200)
291
    {
292
        http_response_code($responseCode);
293
        require(VIEWS_DIR.'/'.$path.'.php');
294
    }
295
296
    /**
297
     * Extract the view
298
     *
299
     * @param string $path view file path
300
     * @param array<mixed> $data response data
301
     * @return string|false view
302
     */
303
    protected function extractView($path, $data=array())
304
    {
305
        ob_start();
306
        $this->respondView($path, $data);
307
        $buffer = ob_get_contents();
308
        ob_end_clean();
309
        return $buffer;
310
    }
311
312
    /**
313
     * Respond in json format
314
     *
315
     * @param array<mixed> $data response data
316
     * @param int $responseCode http status code, the default is 200
317
     * @return void
318
     */
319
    protected function respondJson($data=array(), $responseCode = 200)
320
    {
321
        $json = json_encode($data);
322
        http_response_code($responseCode);
323
        header('Content-Type: application/json');
324
        echo $json;
325
    }
326
327
    /**
328
     * Redirect
329
     *
330
     * @param string $url redirect url
331
     * @param int $responseCode http status code, the default is 302
332
     * @return void
333
     */
334
    protected function redirect($url, $responseCode = 302)
335
    {
336
        header("Location: $url", true, $responseCode);
337
    }
338
}
339