17
17
use Symfony \Component \Debug \Exception \FatalErrorException ;
18
18
use Symfony \Component \Debug \Exception \FatalThrowableError ;
19
19
use Symfony \Component \Debug \Exception \OutOfMemoryException ;
20
+ use Symfony \Component \Debug \Exception \SilencedErrorContext ;
20
21
use Symfony \Component \Debug \FatalErrorHandler \UndefinedFunctionFatalErrorHandler ;
21
22
use Symfony \Component \Debug \FatalErrorHandler \UndefinedMethodFatalErrorHandler ;
22
23
use Symfony \Component \Debug \FatalErrorHandler \ClassNotFoundFatalErrorHandler ;
43
44
* can see them and weight them as more important to fix than others of the same level.
44
45
*
45
46
* @author Nicolas Grekas <p@tchwork.com>
47
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
46
48
*/
47
49
class ErrorHandler
48
50
{
@@ -88,7 +90,6 @@ class ErrorHandler
88
90
private $ screamedErrors = 0x55 ; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE
89
91
private $ loggedErrors = 0 ;
90
92
91
- private $ loggedTraces = array ();
92
93
private $ isRecursive = 0 ;
93
94
private $ isRoot = false ;
94
95
private $ exceptionHandler ;
@@ -221,7 +222,7 @@ public function setLoggers(array $loggers)
221
222
222
223
if ($ flush ) {
223
224
foreach ($ this ->bootstrappingLogger ->cleanLogs () as $ log ) {
224
- $ type = $ log [2 ]['type ' ] ;
225
+ $ type = $ log [2 ]['exception ' ]-> getSeverity () ;
225
226
if (!isset ($ flush [$ type ])) {
226
227
$ this ->bootstrappingLogger ->log ($ log [0 ], $ log [1 ], $ log [2 ]);
227
228
} elseif ($ this ->loggers [$ type ][0 ]) {
@@ -361,6 +362,8 @@ private function reRegister($prev)
361
362
*/
362
363
public function handleError ($ type , $ message , $ file , $ line , array $ context , array $ backtrace = null )
363
364
{
365
+ // Level is the current error reporting level to manage silent error.
366
+ // Strong errors are not authorized to be silenced.
364
367
$ level = error_reporting () | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED ;
365
368
$ log = $ this ->loggedErrors & $ type ;
366
369
$ throw = $ this ->thrownErrors & $ type & $ level ;
@@ -373,24 +376,28 @@ public function handleError($type, $message, $file, $line, array $context, array
373
376
if (null !== $ backtrace && $ type & E_ERROR ) {
374
377
// E_ERROR fatal errors are triggered on HHVM when
375
378
// hhvm.error_handling.call_user_handler_on_fatals=1
376
- // which is the way to get their backtrace .
379
+ // which is the way to get their backtraces .
377
380
$ this ->handleFatalError (compact ('type ' , 'message ' , 'file ' , 'line ' , 'backtrace ' ));
378
381
379
382
return true ;
380
383
}
381
384
382
- if ($ throw ) {
383
- if (null !== self ::$ toStringException ) {
384
- $ throw = self ::$ toStringException ;
385
- self ::$ toStringException = null ;
386
- } elseif (($ this ->scopedErrors & $ type ) && class_exists (ContextErrorException::class)) {
387
- $ throw = new ContextErrorException ($ this ->levels [$ type ].': ' .$ message , 0 , $ type , $ file , $ line , $ context );
388
- } else {
389
- $ throw = new \ErrorException ($ this ->levels [$ type ].': ' .$ message , 0 , $ type , $ file , $ line );
390
- }
385
+ $ logMessage = $ this ->levels [$ type ].': ' .$ message ;
386
+
387
+ if (null !== self ::$ toStringException ) {
388
+ $ errorAsException = self ::$ toStringException ;
389
+ self ::$ toStringException = null ;
390
+ } elseif (!$ throw && !($ type & $ level )) {
391
+ $ errorAsException = new SilencedErrorContext ($ type , $ file , $ line );
392
+ } elseif ($ this ->scopedErrors & $ type ) {
393
+ $ errorAsException = new ContextErrorException ($ logMessage , 0 , $ type , $ file , $ line , $ context );
394
+ } else {
395
+ $ errorAsException = new \ErrorException ($ logMessage , 0 , $ type , $ file , $ line );
396
+ }
391
397
398
+ if ($ throw ) {
392
399
if (E_USER_ERROR & $ type ) {
393
- $ backtrace = $ backtrace ?: $ throw ->getTrace ();
400
+ $ backtrace = $ backtrace ?: $ errorAsException ->getTrace ();
394
401
395
402
for ($ i = 1 ; isset ($ backtrace [$ i ]); ++$ i ) {
396
403
if (isset ($ backtrace [$ i ]['function ' ], $ backtrace [$ i ]['type ' ], $ backtrace [$ i - 1 ]['function ' ])
@@ -410,7 +417,7 @@ public function handleError($type, $message, $file, $line, array $context, array
410
417
if (($ e instanceof \Exception || $ e instanceof \Throwable) && $ e ->__toString () === $ message ) {
411
418
if (1 === $ i ) {
412
419
// On HHVM
413
- $ throw = $ e ;
420
+ $ errorAsException = $ e ;
414
421
break ;
415
422
}
416
423
self ::$ toStringException = $ e ;
@@ -421,7 +428,7 @@ public function handleError($type, $message, $file, $line, array $context, array
421
428
422
429
if (1 < $ i ) {
423
430
// On PHP (not on HHVM), display the original error message instead of the default one.
424
- $ this ->handleException ($ throw );
431
+ $ this ->handleException ($ errorAsException );
425
432
426
433
// Stop the process by giving back the error to the native handler.
427
434
return false ;
@@ -430,47 +437,23 @@ public function handleError($type, $message, $file, $line, array $context, array
430
437
}
431
438
}
432
439
433
- throw $ throw ;
434
- }
435
-
436
- // For duplicated errors, log the trace only once
437
- $ e = md5 ("{$ type }/ {$ line }/ {$ file }\x00{$ message }" , true );
438
- $ trace = true ;
439
-
440
- if (!($ this ->tracedErrors & $ type ) || isset ($ this ->loggedTraces [$ e ])) {
441
- $ trace = false ;
442
- } else {
443
- $ this ->loggedTraces [$ e ] = 1 ;
444
- }
445
-
446
- $ e = compact ('type ' , 'file ' , 'line ' , 'level ' );
447
-
448
- if ($ type & $ level ) {
449
- if ($ this ->scopedErrors & $ type ) {
450
- $ e ['scope_vars ' ] = $ context ;
451
- if ($ trace ) {
452
- $ e ['stack ' ] = $ backtrace ?: debug_backtrace (DEBUG_BACKTRACE_PROVIDE_OBJECT );
453
- }
454
- } elseif ($ trace ) {
455
- if (null === $ backtrace ) {
456
-
10000
$ e ['stack ' ] = debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS );
457
- } else {
458
- foreach ($ backtrace as &$ frame ) {
459
- unset($ frame ['args ' ], $ frame );
460
- }
461
- $ e ['stack ' ] = $ backtrace ;
462
- }
463
- }
440
+ throw $ errorAsException ;
464
441
}
465
442
466
443
if ($ this ->isRecursive ) {
467
444
$ log = 0 ;
468
445
} elseif (self ::$ stackedErrorLevels ) {
469
- self ::$ stackedErrors [] = array ($ this ->loggers [$ type ][0 ], ($ type & $ level ) ? $ this ->loggers [$ type ][1 ] : LogLevel::DEBUG , $ message , $ e );
446
+ self ::$ stackedErrors [] = array (
447
+ $ this ->loggers [$ type ][0 ],
448
+ ($ type & $ level ) ? $ this ->loggers [$ type ][1 ] : LogLevel::DEBUG ,
449
+ $ logMessage ,
450
+ array ('exception ' => $ errorAsException ),
451
+ );
470
452
} else {
471
453
try {
472
454
$ this ->isRecursive = true ;
473
- $ this ->loggers [$ type ][0 ]->log (($ type & $ level ) ? $ this ->loggers [$ type ][1 ] : LogLevel::DEBUG , $ message , $ e );
455
+ $ level = ($ type & $ level ) ? $ this ->loggers [$ type ][1 ] : LogLevel::DEBUG ;
456
+ $ this ->loggers [$ type ][0 ]->log ($ level , $ logMessage , array ('exception ' => $ errorAsException ));
474
457
} finally {
475
458
$ this ->isRecursive = false ;
476
459
}
@@ -495,20 +478,13 @@ public function handleException($exception, array $error = null)
495
478
$ type = $ exception instanceof FatalErrorException ? $ exception ->getSeverity () : E_ERROR ;
496
479
497
480
if (($ this ->loggedErrors & $ type ) || $ exception instanceof FatalThrowableError) {
498
- $ e = array (
499
- 'type ' => $ type ,
500
- 'file ' => $ exception ->getFile (),
501
- 'line ' => $ exception ->getLine (),
502
- 'level ' => error_reporting (),
503
- 'stack ' => $ exception ->getTrace (),
504
- );
505
481
if ($ exception instanceof FatalErrorException) {
506
482
if ($ exception instanceof FatalThrowableError) {
507
483
$ error = array (
508
484
'type ' => $ type ,
509
485
'message ' => $ message = $ exception ->getMessage (),
510
- 'file ' => $ e [ ' file ' ] ,
511
- 'line ' => $ e [ ' line ' ] ,
486
+ 'file ' => $ exception -> getFile () ,
487
+ 'line ' => $ exception -> getLine () ,
512
488
);
513
489
} else {
514
490
$ message = 'Fatal ' .$ exception ->getMessage ();
@@ -523,7 +499,7 @@ public function handleException($exception, array $error = null)
523
499
}
524
500
}
525
501
if ($ this ->loggedErrors & $ type ) {
526
- $ this ->loggers [$ type ][0 ]->log ($ this ->loggers [$ type ][1 ], $ message , $ e );
502
+ $ this ->loggers [$ type ][0 ]->log ($ this ->loggers [$ type ][1 ], $ message , array ( ' exception ' => $ exception ) );
527
503
}
528
504
if ($ exception instanceof FatalErrorException && !$ exception instanceof OutOfMemoryException && $ error ) {
529
505
foreach ($ this ->getFatalErrorHandlers () as $ handler ) {
@@ -629,19 +605,19 @@ public static function unstackErrors()
629
605
$ level = array_pop (self ::$ stackedErrorLevels );
630
606
631
607
if (null !== $ level ) {
632
- $ e = error_reporting ($ level );
633
- if ($ e !== ($ level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR )) {
608
+ $ errorReportingLevel = error_reporting ($ level );
609
+ if ($ errorReportingLevel !== ($ level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR )) {
634
610
// If the user changed the error level, do not overwrite it
635
- error_reporting ($ e );
611
+ error_reporting ($ errorReportingLevel );
636
612
}
637
613
}
638
614
639
615
if (empty (self ::$ stackedErrorLevels )) {
640
616
$ errors = self ::$ stackedErrors ;
641
617
self ::$ stackedErrors = array ();
642
618
643
- foreach ($ errors as $ e ) {
644
- $ e [0 ]->log ($ e [1 ], $ e [2 ], $ e [3 ]);
619
+ foreach ($ errors as $ error ) {
620
+ $ error [0 ]->log ($ error [1 ], $ error [2 ], $ error [3 ]);
645
621
}
646
622
}
647
623
}
0 commit comments