1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
<?php /** * An exception thrown while trying to build or resolve a binding in the container. * * @package lucatume\DI52 */
namespace lucatume\DI52;
use Exception; use Psr\Container\ContainerExceptionInterface; use ReflectionClass; use Throwable;
/** * Class ContainerException * * @package lucatume\DI52 */ class ContainerException extends Exception implements ContainerExceptionInterface { /** * Extracts a property from an object. * * @param object $object The object to extract the property from. * @param string $property The property to extract. * * @return mixed The property value if found, `null` otherwise. */ private static function getPropertyValue($object, $property) { $reflectionClass = new ReflectionClass($object);
do { if ($reflectionClass->hasProperty($property)) { $traceProperty = $reflectionClass->getProperty($property); $traceProperty->setAccessible(true); return $traceProperty->getValue($object); }
$reflectionClass = $reflectionClass->getParentClass(); } while ($reflectionClass instanceof ReflectionClass);
return null; }
/** * Sets a private or protected property on an object. * * @param object $object The object to set the property on. * @param string $property The property to set. * @param mixed $value The value to set. * * @return bool Whether the property was set or not. */ private static function setPropertyValue($object, $property, $value) { $reflectionClass = new ReflectionClass($object);
do { if ($reflectionClass->hasProperty($property)) { $traceProperty = $reflectionClass->getProperty($property); $traceProperty->setAccessible(true); $traceProperty->setValue($object, $value); return true; }
$reflectionClass = $reflectionClass->getParentClass(); } while ($reflectionClass instanceof ReflectionClass);
return false; }
/** * Formats an error message to provide a useful debug message. * * @param string|object $id The id of what is actually being built or the object that is being built. * @param Exception|Throwable $thrown The original exception thrown while trying to make the target. * @param array<string> $buildLine A set of consecutive items the resolver is currently trying to build. * * @return string The formatted make error message. */ private static function makeBuildLineErrorMessage($id, $thrown, array $buildLine) { $idString = is_string($id) ? $id : gettype($id); if ($thrown instanceof NestedParseError) { $last = $thrown->getType() . ' $' . $thrown->getName(); } else { $last = array_pop($buildLine) ?: $idString; } $lastEntry = "Error while making {$last}: " . lcfirst( rtrim( str_replace('"', '', $thrown->getMessage()), '.' ) ) . '.'; $frags = array_merge($buildLine, [$lastEntry]);
return implode("\n\t=> ", $frags); }
/** * Builds a container exception from a throwable. * * @param string|object $id The id of what is actually being built or the object that is being built. * @param Exception|Throwable $thrown The throwable to build the exception from. * @param int $maskThrowables The bitmask of throwable properties to mask. * @param array<string> $buildLine A set of consecutive items the resolver is currently trying to build. * * @return ContainerException The built Container exception. */ public static function fromThrowable($id, $thrown, $maskThrowables, array $buildLine) { $message = ($maskThrowables & Container::EXCEPTION_MASK_MESSAGE) ? self::makeBuildLineErrorMessage($id, $thrown, $buildLine) : $thrown->getMessage();
$exceptionClass = $thrown instanceof self ? get_class($thrown) : self::class;
$built = new $exceptionClass($message, $thrown->getCode(), $thrown);
if (($maskThrowables & Container::EXCEPTION_MASK_FILE_LINE) && ($thrownFile = self::getPropertyValue($thrown, 'file')) && ($thrownLine = self::getPropertyValue($thrown, 'line')) ) { self::setPropertyValue($built, 'file', $thrownFile); self::setPropertyValue($built, 'line', $thrownLine); }
return $built; } }
|