Handler::checkFatal()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 3
eloc 4
nc 2
nop 0
1
<?php
2
/*
3
 * This file is part of Yolk - Gamer Network's PHP Framework.
4
 *
5
 * Copyright (c) 2013 Gamer Network Ltd.
6
 * 
7
 * Distributed under the MIT License, a copy of which is available in the
8
 * LICENSE file that was bundled with this package, or online at:
9
 * https://github.com/gamernetwork/yolk-core
10
 */
11
12
namespace yolk\exceptions;
13
14
use yolk\Yolk;
15
16
class Handler {
17
18
	/**
19
	 * Default error handler - convert errors to ErrorExceptions.
20
	 * @param int     $severity   the error level (http://php.net/manual/en/errorfunc.constants.php)
21
	 * @param string  $message
22
	 * @param string  $file
23
	 * @param int     $line
24
	 * @return void
25
	 */
26
	public static function error( $severity, $message, $file, $line ) {
27
28
		// Latest Twig raises a warning when accessing missing cached views - we can ignore it
29
		if( preg_match('/filemtime/', $message) )
30
			return;
31
32
		// if the error was a type hint failure then throw an InvalidArgumentException instead
33
		elseif( preg_match('/^Argument (\d+) passed to ([\w\\\\]+)::(\w+)\(\) must be an instance of ([\w\\\\]+), ([\w\\\\]+) given, called in ([\w\s\.\/_-]+) on line (\d+)/', $message, $m) )
34
			throw new \InvalidArgumentException("Argument {$m[1]} to {$m[2]}::{$m[3]}() should be an instance of {$m[4]}, {$m[5]} given", $severity, new \ErrorException($message, 0, $severity, $m[6], $m[7]));
35
36
		// convert the error to an exception
37
		throw new \ErrorException($message, 0, $severity, $file, $line);
38
39
	}
40
41
	/**
42
	 * Default exception handler
43
	 * @param \Exception $error
44
	 * @param string     $error_page   the file containing the error page to include for production web apps
45
	 * @return void
46
	 */
47
	public static function exception( \Exception $error, $error_page, $log = true ) {
48
49
		if( $log )
50
			static::logException($error);
51
52
		if( Yolk::isCLI() ) {
53
			Yolk::dump($error);
54
		}
55
		// debug web app
56
		elseif( Yolk::isDebug() ) {
57
			require __DIR__. '/error.debug.php';
58
		}
59
		// production web app
60
		else {
61
			require $error_page;
62
		}
63
64
	}
65
66
	/**
67
	 * Log an exception to the error log.
68
	 * @param \Exception $error
69
	 * @return void
70
	 */
71
	public static function logException( \Exception $error ) {
72
73
		// fatal errors will already have been error_log()'d
74
		if( !static::isFatal($error) ) {
75
			$location = $error->getFile(). ':'. $error->getLine();
76
			// type hinting error - make sure we give the correct location
77
			if( ($error instanceof \InvalidArgumentException) && ($error->getPrevious() instanceof \ErrorException) )
78
				$location = $error->getPrevious()->getFile(). ':'. $error->getPrevious()->getLine();
79
			error_log(get_class($error). ': '. $error->getMessage(). " [{$location}]");
80
		}
81
82
	}
83
84
	/**
85
	 * Shutdown function to catch fatal errors.
86
	 * @return void
87
	 */
88
	public static function checkFatal() {
89
		$error = error_get_last();
90
		if( $error && static::isFatal($error['type']) ) {
91
			Yolk::exception(new \ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']));
92
		}
93
	}
94
95
	/**
96
	 * Determine if an error code or Exception is a fatal error.
97
	 * @param  \Exception|integer  $error
98
	 * @return boolean
99
	 */
100
	protected static function isFatal( $error ) {
101
102
		if( $error instanceof \Exception )
103
			return false;
104
105
		$fatal = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR;
106
107
		if( $error instanceof \ErrorException )
108
			$error = $error->getSeverity();
109
110
		return (bool) ($error & $fatal);
111
112
	}
113
114
}
115
116
// EOF