1: | <?php declare(strict_types=1); |
2: | |
3: | namespace Salient\Utility\Exception; |
4: | |
5: | |
6: | |
7: | |
8: | class PcreErrorException extends AbstractUtilityException |
9: | { |
10: | private const ERROR_MESSAGE_MAP = [ |
11: | \PREG_NO_ERROR => 'No error', |
12: | \PREG_INTERNAL_ERROR => 'Internal error', |
13: | \PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 characters, possibly incorrectly encoded', |
14: | \PREG_BAD_UTF8_OFFSET_ERROR => 'The offset did not correspond to the beginning of a valid UTF-8 code point', |
15: | \PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit exhausted', |
16: | \PREG_RECURSION_LIMIT_ERROR => 'Recursion limit exhausted', |
17: | \PREG_JIT_STACKLIMIT_ERROR => 'JIT stack limit exhausted', |
18: | ]; |
19: | |
20: | protected int $PcreError; |
21: | protected string $PcreErrorMessage; |
22: | protected string $Function; |
23: | |
24: | protected $Pattern; |
25: | |
26: | protected $Subject; |
27: | |
28: | private static array $ErrorNameMap; |
29: | |
30: | |
31: | |
32: | |
33: | |
34: | public function __construct(?int $error, string $function, $pattern, $subject) |
35: | { |
36: | $error ??= preg_last_error(); |
37: | $message = \PHP_VERSION_ID < 80000 |
38: | ? self::ERROR_MESSAGE_MAP[$error] ?? 'Unknown error' |
39: | : preg_last_error_msg(); |
40: | |
41: | $this->PcreError = $error; |
42: | $this->PcreErrorMessage = $message; |
43: | $this->Function = $function; |
44: | $this->Pattern = $pattern; |
45: | $this->Subject = $subject; |
46: | |
47: | parent::__construct(sprintf( |
48: | 'Call to %s() failed with %s (%s)', |
49: | $function, |
50: | (self::$ErrorNameMap ??= $this->getErrorNameMap())[$error], |
51: | $message, |
52: | )); |
53: | } |
54: | |
55: | |
56: | |
57: | |
58: | public function getPcreError(): int |
59: | { |
60: | return $this->PcreError; |
61: | } |
62: | |
63: | |
64: | |
65: | |
66: | public function getPcreErrorName(): string |
67: | { |
68: | return self::$ErrorNameMap[$this->PcreError]; |
69: | } |
70: | |
71: | |
72: | |
73: | |
74: | public function getPcreErrorMessage(): string |
75: | { |
76: | return $this->PcreErrorMessage; |
77: | } |
78: | |
79: | |
80: | |
81: | |
82: | public function getFunction(): string |
83: | { |
84: | return $this->Function; |
85: | } |
86: | |
87: | |
88: | |
89: | |
90: | |
91: | |
92: | public function getPattern() |
93: | { |
94: | return $this->Pattern; |
95: | } |
96: | |
97: | |
98: | |
99: | |
100: | |
101: | |
102: | public function getSubject() |
103: | { |
104: | return $this->Subject; |
105: | } |
106: | |
107: | |
108: | |
109: | |
110: | private function getErrorNameMap(): array |
111: | { |
112: | |
113: | $constants = get_defined_constants(true)['pcre']; |
114: | foreach ($constants as $name => $value) { |
115: | if (substr($name, -6) !== '_ERROR') { |
116: | continue; |
117: | } |
118: | |
119: | $errors[$value] = $name; |
120: | } |
121: | |
122: | return $errors ?? []; |
123: | } |
124: | } |
125: | |