PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.8.0
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.8.0
3.8.0 3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 All 112 releases
templately / includes / Utils / Exception / TemplatelyException.php

TemplatelyException.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! 3.8.0, at includes/Utils/Exception/TemplatelyException.php

174 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Utils\Exception;
4
5 use Templately\Utils\Response\ErrorCode;
6 use Templately\Utils\Response\TemplatelyError;
7 use Throwable;
8
9 /**
10 * The exception base that carries the response contract (spec 043 / PRD PHP-3).
11 *
12 * A plain `\Exception` carries a message and nothing else, so every catch site had
13 * to re-derive the two things that actually matter — is this worth retrying, and
14 * how bad is it — usually by matching on the exception's CLASS, and sometimes on
15 * its message text. That is why the same failure could be retryable in one runner
16 * and terminal in another.
17 *
18 * This carries the registry code instead, and `severity`/`retryable` follow from
19 * it, so a thrown error and a returned `TemplatelyError` describe a failure the
20 * same way.
21 *
22 * The user-facing message is deliberately separate from the internal one. The
23 * internal text goes to the log; only `get_user_message()` is safe to show, which
24 * is what keeps a framework message or a file path from reaching the browser
25 * (FR-008).
26 */
27 class TemplatelyException extends \Exception {
28
29 /**
30 * @var string An `ErrorCode` registry value.
31 */
32 protected $error_code;
33
34 /**
35 * @var string|null Shown to the user; falls back to the registry's wording.
36 */
37 protected $user_message;
38
39 /**
40 * @var array Structured params (retry_after, upgrade_url, …).
41 */
42 protected $context;
43
44 /**
45 * @param string $error_code An `ErrorCode` value.
46 * @param string $message INTERNAL message — logged, never shown.
47 * @param string|null $user_message Safe, user-facing text.
48 * @param array $context Structured params.
49 * @param Throwable|null $previous
50 */
51 public function __construct(
52 $error_code = ErrorCode::SERVER_ERROR,
53 $message = '',
54 $user_message = null,
55 $context = [],
56 $previous = null
57 ) {
58 $this->error_code = ErrorCode::exists( $error_code ) ? $error_code : ErrorCode::SERVER_ERROR;
59 $this->user_message = $user_message;
60 $this->context = is_array( $context ) ? $context : [];
61
62 parent::__construct( $message, 0, $previous );
63 }
64
65 /**
66 * @return string
67 */
68 public function get_error_code() {
69 return $this->error_code;
70 }
71
72 /**
73 * @return bool
74 */
75 public function is_retryable() {
76 return ErrorCode::retryable( $this->error_code );
77 }
78
79 /**
80 * @return string fatal|error|warning|info
81 */
82 public function get_severity() {
83 return ErrorCode::severity( $this->error_code );
84 }
85
86 /**
87 * @return array
88 */
89 public function get_context() {
90 return $this->context;
91 }
92
93 /**
94 * The text that may be shown. Never the internal message.
95 *
96 * @return string
97 */
98 public function get_user_message() {
99 if ( ! empty( $this->user_message ) ) {
100 return $this->user_message;
101 }
102
103 return ErrorCode::default_message( $this->error_code );
104 }
105
106 /**
107 * Convert to the same value object the normalizer produces, so a thrown error
108 * and a returned one are indistinguishable downstream.
109 *
110 * @return TemplatelyError
111 */
112 public function to_error() {
113 return new TemplatelyError( $this->error_code, $this->get_user_message(), [
114 'context' => $this->context,
115 ] );
116 }
117
118 /**
119 * Give any throwable a registry code.
120 *
121 * The bare `\Exception` throws scattered through the import pipeline carry no
122 * classification at all, so this is what lets a catch site ask "retryable?"
123 * without caring whether the thing it caught was typed.
124 *
125 * The original message becomes the INTERNAL one; the user gets the registry's
126 * wording, because an arbitrary throwable's message may contain a file path,
127 * a SQL fragment, or a framework internal.
128 *
129 * @param Throwable $throwable
130 * @param string|null $fallback_code Used when the type suggests nothing better.
131 * @return TemplatelyException
132 */
133 public static function classify( $throwable, $fallback_code = null ) {
134 if ( $throwable instanceof self ) {
135 return $throwable;
136 }
137
138 $code = $fallback_code && ErrorCode::exists( $fallback_code )
139 ? $fallback_code
140 : self::code_for_throwable( $throwable );
141
142 return new self(
143 $code,
144 $throwable instanceof Throwable ? $throwable->getMessage() : (string) $throwable,
145 null,
146 [],
147 $throwable instanceof Throwable ? $throwable : null
148 );
149 }
150
151 /**
152 * Map a throwable's TYPE to a registry code.
153 *
154 * Type only — never the message. Message text is prose: it is translated, it
155 * changes, and branching on it is the habit this contract exists to end (INV-4).
156 *
157 * @param Throwable $throwable
158 * @return string
159 */
160 private static function code_for_throwable( $throwable ) {
161 // A PHP Error (TypeError, ValueError, a call to an undefined method) is a
162 // bug in this plugin, not a condition the user can resolve or retry.
163 if ( $throwable instanceof \Error ) {
164 return ErrorCode::SERVER_ERROR;
165 }
166
167 if ( $throwable instanceof \JsonException ) {
168 return ErrorCode::MALFORMED_JSON;
169 }
170
171 return ErrorCode::SERVER_ERROR;
172 }
173 }
174