1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* User: jensk |
4
|
|
|
* Date: 13-3-2017 |
5
|
|
|
* Time: 15:04 |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace library\cc; |
9
|
|
|
|
10
|
|
|
|
11
|
|
|
class AutoloadUtil |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* The decoupled autoload function for actually loading the classes |
15
|
|
|
* |
16
|
|
|
* @param $class |
17
|
|
|
* @param bool $throwException |
18
|
|
|
* |
19
|
|
|
* @return bool |
20
|
|
|
* @throws \Exception |
21
|
|
|
*/ |
22
|
|
|
public static function autoLoad($class, $throwException = true) |
23
|
|
|
{ |
24
|
|
|
if (class_exists($class, false)) { |
25
|
|
|
return true; |
26
|
|
|
} |
27
|
|
|
|
28
|
|
|
global $rootPath; |
29
|
|
|
$file = $rootPath . str_replace('\\', '/', $class) . ".php"; |
30
|
|
|
|
31
|
|
|
if (file_exists($file)) { |
32
|
|
|
return self::loadClassInExistingFile($class, $throwException, $file); |
33
|
|
|
} else { |
34
|
|
|
return self::handleUnloadableClass($class, $throwException, $rootPath, $file); |
35
|
|
|
} |
36
|
|
|
return false; |
|
|
|
|
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
private static function handleUnloadableClass($class, $throwException, $rootPath, $file) |
40
|
|
|
{ |
41
|
|
|
$debug_backtrace = debug_backtrace(); |
42
|
|
|
if (isset($debug_backtrace[2]) && isset($debug_backtrace[2]['file']) && isset($debug_backtrace[2]['line'])) { |
43
|
|
|
return self::handleUnloadableClassWithBacktrace($class, $throwException, $rootPath, $file, $debug_backtrace); |
44
|
|
|
} else { |
45
|
|
|
return self::handleUnloadableClassWithoutBacktrace($class, $throwException, $file); |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param $class |
52
|
|
|
* @param $throwException |
53
|
|
|
* @param $file |
54
|
|
|
* |
55
|
|
|
* @return bool |
56
|
|
|
* @throws \Exception |
57
|
|
|
*/ |
58
|
|
|
private static function loadClassInExistingFile($class, $throwException, $file) |
59
|
|
|
{ |
60
|
|
|
require_once($file); |
61
|
|
|
if ($throwException) { |
62
|
|
|
if (class_exists($class, false) === false && interface_exists($class, false) === false) { |
63
|
|
|
throw new \Exception('Could not load class "' . $class . '" in file ' . $file); |
64
|
|
|
} else { |
65
|
|
|
return true; |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return class_exists($class, false) || interface_exists($class, false); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @param $class |
74
|
|
|
* @param $throwException |
75
|
|
|
* @param $rootPath |
76
|
|
|
* @param $file |
77
|
|
|
* @param $debug_backtrace |
78
|
|
|
* |
79
|
|
|
* @return bool |
80
|
|
|
*/ |
81
|
|
|
private static function handleUnloadableClassWithBacktrace($class, $throwException, $rootPath, $file, $debug_backtrace) |
82
|
|
|
{ |
83
|
|
|
if ($throwException) { |
84
|
|
|
errorHandler(0, 'Could not load class \'' . $class . '\' in file ' . $rootPath . $file, $debug_backtrace[2]['file'], $debug_backtrace[2]['line']); |
85
|
|
|
} else { |
86
|
|
|
return false; |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* @param $class |
92
|
|
|
* @param $throwException |
93
|
|
|
* @param $file |
94
|
|
|
* |
95
|
|
|
* @return bool |
96
|
|
|
* @throws \Exception |
97
|
|
|
*/ |
98
|
|
|
private static function handleUnloadableClassWithoutBacktrace($class, $throwException, $file) |
99
|
|
|
{ |
100
|
|
|
if ($throwException) { |
101
|
|
|
throw new \Exception('Could not load class "' . $class . '" in file ' . $file . "\n" . 'Called from unknown origin.'); |
102
|
|
|
} else { |
103
|
|
|
return false; |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
} |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.