1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace BFW\Core; |
4
|
|
|
|
5
|
|
|
use \BFW\Application; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Class used to have a personnal message/page for errors and exceptions |
9
|
|
|
*/ |
10
|
|
|
class Errors |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var \BFW\Application $app : L'instance d'Application |
14
|
|
|
*/ |
15
|
|
|
protected static $app = null; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Constructeur |
19
|
|
|
* |
20
|
|
|
* @param \BFW\Application $app : L'instance d'Application à utiliser |
21
|
|
|
*/ |
22
|
|
|
public function __construct(Application $app) |
23
|
|
|
{ |
24
|
|
|
self::$app = $app; |
25
|
|
|
|
26
|
|
|
//Find and create the handler for errors |
27
|
|
|
$this->defineErrorHandler(); |
28
|
|
|
|
29
|
|
|
//Find and create the handler for exceptions |
30
|
|
|
$this->defineExceptionHandler(); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Find and create the handler for errors |
35
|
|
|
* |
36
|
|
|
* @return void |
37
|
|
|
*/ |
38
|
|
|
protected function defineErrorHandler() |
39
|
|
|
{ |
40
|
|
|
//Find the correct class to call (return the child class if extended) |
41
|
|
|
$calledClass = get_called_class(); |
42
|
|
|
$errorRender = $calledClass::getErrorRender(); |
43
|
|
|
|
44
|
|
|
//If not render to use |
45
|
|
|
if ($errorRender === false) { |
46
|
|
|
return; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
//add the handler for errors |
50
|
|
|
set_error_handler([$this, 'errorHandler']); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Find and create the handler for exceptions |
55
|
|
|
* |
56
|
|
|
* @return type |
57
|
|
|
*/ |
58
|
|
|
protected function defineExceptionHandler() |
59
|
|
|
{ |
60
|
|
|
//Find the correct class to call (return the child class if extended) |
61
|
|
|
$calledClass = get_called_class(); |
62
|
|
|
$exceptionRender = $calledClass::getExceptionRender(); |
63
|
|
|
|
64
|
|
|
//If not render to use |
65
|
|
|
if ($exceptionRender === false) { |
66
|
|
|
return; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
//add the handler for exceptions |
70
|
|
|
set_exception_handler([$this, 'exceptionHandler']); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Get the Application instance |
75
|
|
|
* It's a method to allow override |
76
|
|
|
* |
77
|
|
|
* @return \BFW\Application |
78
|
|
|
*/ |
79
|
|
|
protected static function getApp() |
80
|
|
|
{ |
81
|
|
|
if (is_null(self::$app)) { |
82
|
|
|
self::$app = Application::getInstance(); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
return self::$app; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* get the error render from config for cli or default |
90
|
|
|
* |
91
|
|
|
* @return boolean|array Render infos |
92
|
|
|
* Boolean : false if no render to use |
93
|
|
|
* Array : Infos from config |
94
|
|
|
*/ |
95
|
|
View Code Duplication |
public static function getErrorRender() |
|
|
|
|
96
|
|
|
{ |
97
|
|
|
$calledClass = get_called_class(); |
98
|
|
|
$app = $calledClass::getApp(); |
99
|
|
|
$renderFcts = $app->getConfig('errorRenderFct'); |
100
|
|
|
|
101
|
|
|
return self::defineRenderToUse($renderFcts); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* get the exception render from config for cli or default |
106
|
|
|
* |
107
|
|
|
* @return boolean|array Render infos |
108
|
|
|
* Boolean : false if no render to use |
109
|
|
|
* Array : Infos from config |
110
|
|
|
*/ |
111
|
|
View Code Duplication |
public static function getExceptionRender() |
|
|
|
|
112
|
|
|
{ |
113
|
|
|
$calledClass = get_called_class(); |
114
|
|
|
$app = $calledClass::getApp(); |
115
|
|
|
$renderFcts = $app->getConfig('exceptionRenderFct'); |
116
|
|
|
|
117
|
|
|
return self::defineRenderToUse($renderFcts); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Find the render to use with the config |
122
|
|
|
* If cli render is not define, it's use the default render. |
123
|
|
|
* |
124
|
|
|
* @param array $renderConfig : Render infos from config |
125
|
|
|
* |
126
|
|
|
* @return boolean|array : Render to use |
127
|
|
|
* Boolean : false is no enable or no render define |
128
|
|
|
* Array : The render used |
129
|
|
|
*/ |
130
|
|
|
protected static function defineRenderToUse($renderConfig) |
131
|
|
|
{ |
132
|
|
|
//Check enabled |
133
|
|
|
if ($renderConfig['active'] === false) { |
134
|
|
|
return false; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
//The cli render if cli mode |
138
|
|
|
if (PHP_SAPI === 'cli' && isset($renderConfig['cli'])) { |
139
|
|
|
return $renderConfig['cli']; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
//The default render or cli if cli mode and no cli render configured |
143
|
|
|
if (isset($renderConfig['default'])) { |
144
|
|
|
return $renderConfig['default']; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
return false; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* The default exception handler included in BFW |
152
|
|
|
* |
153
|
|
|
* @param \Exception $exception : Exception informations |
154
|
|
|
* |
155
|
|
|
* @return void |
156
|
|
|
*/ |
157
|
|
|
public static function exceptionHandler($exception) |
158
|
|
|
{ |
159
|
|
|
//Get the current class (childs class if extended) |
160
|
|
|
$calledClass = get_called_class(); |
161
|
|
|
$errorRender = $calledClass::getExceptionRender(); |
162
|
|
|
|
163
|
|
|
//Call the "callRender" method for this class (or child class) |
164
|
|
|
$calledClass::callRender( |
165
|
|
|
$errorRender, |
166
|
|
|
'Exception Uncaught', |
167
|
|
|
$exception->getMessage(), |
168
|
|
|
$exception->getFile(), |
169
|
|
|
$exception->getLine(), |
170
|
|
|
$exception->getTrace() |
171
|
|
|
); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* The default error handler included in BFW |
176
|
|
|
* |
177
|
|
|
* @param type $errSeverity : Error severity |
178
|
|
|
* @param type $errMsg : Error message |
179
|
|
|
* @param type $errFile : File where the error is triggered |
180
|
|
|
* @param type $errLine : Line where the error is triggered |
181
|
|
|
* |
182
|
|
|
* @return void |
183
|
|
|
*/ |
184
|
|
|
public static function errorHandler( |
185
|
|
|
$errSeverity, |
186
|
|
|
$errMsg, |
187
|
|
|
$errFile, |
188
|
|
|
$errLine |
189
|
|
|
) { |
190
|
|
|
//Get the current class (childs class if extended) |
191
|
|
|
$calledClass = get_called_class(); |
192
|
|
|
$erreurType = $calledClass::getErrorType($errSeverity); |
193
|
|
|
$errorRender = $calledClass::getErrorRender(); |
194
|
|
|
|
195
|
|
|
//Call the "callRender" method for this class (or child class) |
196
|
|
|
$calledClass::callRender( |
197
|
|
|
$errorRender, |
198
|
|
|
$erreurType, |
199
|
|
|
$errMsg, |
200
|
|
|
$errFile, |
201
|
|
|
$errLine, |
202
|
|
|
debug_backtrace() |
203
|
|
|
); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Call the personnal class-method or function declared on config where |
208
|
|
|
* an exception or an error is triggered. |
209
|
|
|
* |
210
|
|
|
* @param array $renderInfos : Infos from config |
211
|
|
|
* @param type $erreurType : Error severity |
212
|
|
|
* @param type $errMsg : Error/exception message |
213
|
|
|
* @param type $errFile : File where the error/exception is triggered |
214
|
|
|
* @param type $errLine : Line where the error/exception is triggered |
215
|
|
|
* @param type $backtrace : Error/exception backtrace |
216
|
|
|
* |
217
|
|
|
* @return void |
218
|
|
|
*/ |
219
|
|
|
protected static function callRender( |
220
|
|
|
$renderInfos, |
221
|
|
|
$erreurType, |
222
|
|
|
$errMsg, |
223
|
|
|
$errFile, |
224
|
|
|
$errLine, |
225
|
|
|
$backtrace |
226
|
|
|
) { |
227
|
|
|
$calledClass = get_called_class(); |
228
|
|
|
$calledClass::saveIntoPhpLog($erreurType, $errMsg, $errFile, $errLine); |
229
|
|
|
|
230
|
|
|
$class = $renderInfos['class']; |
231
|
|
|
$method = $renderInfos['method']; |
232
|
|
|
|
233
|
|
|
//If is a class, call "$class::$method" (compatibility 5.x) |
234
|
|
|
if (!empty($class)) { |
235
|
|
|
$class::$method( |
236
|
|
|
$erreurType, |
237
|
|
|
$errMsg, |
238
|
|
|
$errFile, |
239
|
|
|
$errLine, |
240
|
|
|
$backtrace |
241
|
|
|
); |
242
|
|
|
|
243
|
|
|
return; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
//If is not a class, it's a function. |
247
|
|
|
$method( |
248
|
|
|
$erreurType, |
249
|
|
|
$errMsg, |
250
|
|
|
$errFile, |
251
|
|
|
$errLine, |
252
|
|
|
$backtrace |
253
|
|
|
); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
protected static function saveIntoPhpLog( |
257
|
|
|
$errType, |
258
|
|
|
$errMsg, |
259
|
|
|
$errFile, |
260
|
|
|
$errLine |
261
|
|
|
) { |
262
|
|
|
error_log( |
263
|
|
|
'Error detected : ' |
264
|
|
|
.$errType.' '.$errMsg |
265
|
|
|
.' at '.$errFile.':'.$errLine |
266
|
|
|
); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Map array to have a human readable severity. |
271
|
|
|
* |
272
|
|
|
* @see http://fr2.php.net/manual/fr/function.set-error-handler.php#113567 |
273
|
|
|
* |
274
|
|
|
* @param int $errSeverity : The error severity with PHP constant |
275
|
|
|
* |
276
|
|
|
* @return string |
277
|
|
|
*/ |
278
|
|
|
protected static function getErrorType($errSeverity) |
279
|
|
|
{ |
280
|
|
|
$map = [ |
281
|
|
|
E_ERROR => 'Fatal', |
282
|
|
|
E_CORE_ERROR => 'Fatal', |
283
|
|
|
E_USER_ERROR => 'Fatal', |
284
|
|
|
E_COMPILE_ERROR => 'Fatal', |
285
|
|
|
E_RECOVERABLE_ERROR => 'Fatal', |
286
|
|
|
E_WARNING => 'Warning', |
287
|
|
|
E_CORE_WARNING => 'Warning', |
288
|
|
|
E_USER_WARNING => 'Warning', |
289
|
|
|
E_COMPILE_WARNING => 'Warning', |
290
|
|
|
E_PARSE => 'Parse', |
291
|
|
|
E_NOTICE => 'Notice', |
292
|
|
|
E_USER_NOTICE => 'Notice', |
293
|
|
|
E_STRICT => 'Strict', |
294
|
|
|
E_DEPRECATED => 'Deprecated', |
295
|
|
|
E_USER_DEPRECATED => 'Deprecated' |
296
|
|
|
]; |
297
|
|
|
|
298
|
|
|
//Default value if the error is not found in the map array |
299
|
|
|
$erreurType = 'Unknown'; |
300
|
|
|
|
301
|
|
|
//Search in map array |
302
|
|
|
if (isset($map[$errSeverity])) { |
303
|
|
|
$erreurType = $map[$errSeverity]; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
return $erreurType; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* The default cli render in BFW |
311
|
|
|
* |
312
|
|
|
* @param type $erreurType : Error severity |
313
|
|
|
* @param type $errMsg : Error/exception message |
314
|
|
|
* @param type $errFile : File where the error/exception is triggered |
315
|
|
|
* @param type $errLine : Line where the error/exception is triggered |
316
|
|
|
* @param type $backtrace : Error/exception backtrace |
317
|
|
|
* |
318
|
|
|
* @return void |
319
|
|
|
*/ |
320
|
|
|
public static function defaultCliErrorRender( |
321
|
|
|
$erreurType, |
322
|
|
|
$errMsg, |
323
|
|
|
$errFile, |
324
|
|
|
$errLine, |
325
|
|
|
$backtrace |
|
|
|
|
326
|
|
|
) { |
327
|
|
|
//Create the cli message |
328
|
|
|
$msgError = $erreurType.' Error : '.$errMsg. |
329
|
|
|
' in '.$errFile.' at line '.$errLine; |
330
|
|
|
|
331
|
|
|
//Display the message with displayMsg function |
332
|
|
|
\BFW\Helpers\Cli::displayMsg( |
333
|
|
|
$msgError, |
334
|
|
|
'white', |
335
|
|
|
'red' |
336
|
|
|
); |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* The default render in BFW |
341
|
|
|
* |
342
|
|
|
* @param type $erreurType : Error severity |
343
|
|
|
* @param type $errMsg : Error/exception message |
344
|
|
|
* @param type $errFile : File where the error/exception is triggered |
345
|
|
|
* @param type $errLine : Line where the error/exception is triggered |
346
|
|
|
* @param type $backtrace : Error/exception backtrace |
347
|
|
|
* |
348
|
|
|
* @return void |
349
|
|
|
*/ |
350
|
|
|
public static function defaultErrorRender( |
351
|
|
|
$erreurType, |
352
|
|
|
$errMsg, |
353
|
|
|
$errFile, |
354
|
|
|
$errLine, |
355
|
|
|
$backtrace |
356
|
|
|
) { |
357
|
|
|
ob_clean(); |
358
|
|
|
|
359
|
|
|
echo ' |
360
|
|
|
<!doctype html> |
361
|
|
|
<html lang="fr"> |
362
|
|
|
<head> |
363
|
|
|
<title>A error is detected !</title> |
364
|
|
|
<style> |
365
|
|
|
html {padding:0; margin:0; background-color:#e3e3e3; font-family:sans-serif; font-size: 1em; word-wrap:break-word;} |
366
|
|
|
div {position:relative; margin:auto; width:950px; border: 1px solid #a6c9e2; top: 30px; margin-bottom:10px;} |
367
|
|
|
p {padding:0; margin:0;} |
368
|
|
|
p.title {font-size:1.2em; background-color:#D0DCE9; padding:10px;} |
369
|
|
|
p.info {padding:5px; margin-top:10px; margin-bottom:10px;} |
370
|
|
|
fieldset {border:none; background-color: white;} |
371
|
|
|
pre {width:910px; line-height:1.5;} |
372
|
|
|
</style> |
373
|
|
|
</head> |
374
|
|
|
<body> |
375
|
|
|
<div> |
376
|
|
|
<p class="title">Niarf, a error is detected !</p> |
377
|
|
|
<p class="info">'.$erreurType.' Error : <strong>'.$errMsg.'</strong> in '.$errFile.' at line '.$errLine.'</p> |
378
|
|
|
<fieldset><pre>'; |
379
|
|
|
foreach ($backtrace as $i => $info) { |
380
|
|
|
echo '#'.$i.' '.$info['function']; |
381
|
|
|
|
382
|
|
|
if (isset($info['args']) && count($info['args']) > 0) { |
383
|
|
|
echo '('; |
384
|
|
|
|
385
|
|
|
foreach ($info['args'] as $iArgs => $args) { |
386
|
|
|
if ($iArgs > 0) { |
387
|
|
|
echo ', '; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
if (is_array($args) || is_object($args)) { |
391
|
|
|
echo gettype($args); |
392
|
|
|
} elseif (is_null($args)) { |
393
|
|
|
echo 'null'; |
394
|
|
|
} else { |
395
|
|
|
echo htmlentities($args); |
396
|
|
|
} |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
echo ')'; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
if (isset($info['file'], $info['line'])) { |
403
|
|
|
echo ' called at ['.$info['file'].' line '.$info['line'].']'; |
404
|
|
|
} |
405
|
|
|
echo "\n\n"; |
406
|
|
|
} |
407
|
|
|
echo '</pre></fieldset> |
408
|
|
|
</div> |
409
|
|
|
<body> |
410
|
|
|
</html> |
411
|
|
|
'; |
412
|
|
|
|
413
|
|
|
ob_flush(); |
414
|
|
|
exit; |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.