PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 2.2.0
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v2.2.0
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / classes / exceptions / store-engine-exception.php

store-engine-exception.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 2.2.0, at includes/classes/exceptions/store-engine-exception.php

224 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine\Classes\Exceptions;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 die();
7 }
8
9 use Exception;
10 use Throwable;
11 use WP_Error;
12
13 /**
14 * WP_Error compatible exception.
15 */
16 class StoreEngineException extends Exception {
17
18 protected string $wp_code = '';
19
20 protected $data = [];
21
22 /**
23 * @var Throwable|StoreEngineException|null
24 */
25 protected ?Throwable $previous = null;
26
27 /**
28 * @param string $message
29 * @param string $wp_code
30 * @param mixed $data
31 * @param int $code
32 * @param ?Throwable $previous
33 */
34 public function __construct( string $message, string $wp_code = '', $data = null, int $code = 0, ?Throwable $previous = null ) {
35 parent::__construct( $message, $code, $previous );
36
37 $this->wp_code = $wp_code ?: sanitize_title( $this->get_class_code() );
38 $this->previous = $previous;
39
40 if ( is_numeric( $data ) && $data > 0 && ! $code ) {
41 $code = $data;
42 $data = [ 'status' => $data ];
43 }
44
45 if ( ! $data ) {
46 $data = [];
47 }
48
49 if ( empty( $data['status'] ) ) {
50 $data['status'] = $code ? $code : 500;
51 }
52
53 $this->data = $data;
54 }
55
56 /**
57 * @throws self
58 */
59 public static function throw( string $message, $data = null, int $code = 0, ?Throwable $previous = null ) {
60 throw new self( wp_kses_post( $message ), '', $data, $code, $previous ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
61 }
62
63 protected function get_class_code(): string {
64 $code = str_replace( [ __NAMESPACE__ . '\\', 'StoreEngine', 'Exception' ], '', get_called_class() );
65 if ( $code ) {
66 preg_match_all( '/([A-Z][a-z]+|[A-Z]+(?![a-z]))/', $code, $matches );
67
68 if ( ! empty( $matches[0] ) ) {
69 return strtolower( implode( '-', $matches[0] ) );
70 }
71 }
72
73 return $code ?: 'unknown-error';
74 }
75
76 public function get_wp_error_code(): string {
77 return $this->wp_code;
78 }
79
80 public function get_data( ?string $key = null ) {
81 if ( $key ) {
82 if ( isset( $this->data[ $key ] ) ) {
83 return $this->data[ $key ];
84 }
85
86 return null;
87 }
88
89 return $this->data;
90 }
91
92 public function set_data( array $data ) {
93 $this->data = $data;
94 }
95
96 public function set_message( string $message ) {
97 if ( $this->message ) {
98 // Keep a track of old messages.
99 if ( ! isset( $this->data['old_message'] ) ) {
100 $this->data['old_message'] = [];
101 }
102
103 $this->data['old_message'][] = $this->message;
104 }
105
106 $this->message = $message;
107 }
108
109 public function add_data( string $key, $value ) {
110 $this->data[ $key ] = $value;
111 }
112
113 public function get_wp_error(): WP_Error {
114 return new WP_Error( $this->wp_code, $this->getMessage(), $this->data );
115 }
116
117 /**
118 * @alias get_wp_error()
119 * @return WP_Error
120 */
121 public function toWpError(): WP_Error {
122 return $this->get_wp_error();
123 }
124
125 public function get_previous_data(): ?array {
126 if ( ! $this->previous ) {
127 return null;
128 }
129
130 if ( is_a( $this->previous, self::class ) && method_exists( $this->previous, 'get_data' ) ) {
131 return $this->previous->get_data();
132 }
133
134 return null;
135 }
136
137 const WITH_MESSAGE = 1;
138 const WITH_PREVIOUS = 2;
139 const WITH_TRACE = 4;
140 const WITH_WP_TRACE = 8;
141
142 public function to_array( $options = null ): array {
143 $data = [
144 'wp_code' => $this->wp_code,
145 'type' => str_replace( 'StoreEngine\Classes\Exceptions\\', '', get_class( $this ) ),
146 'data' => $this->get_data(),
147 'code' => $this->getCode(),
148 'file' => $this->getFile(),
149 'line' => $this->getLine(),
150 ];
151
152 if ( $options & self::WITH_MESSAGE ) {
153 $data['message'] = $this->getMessage();
154 }
155
156 if ( $options & self::WITH_PREVIOUS ) {
157 $data['previous'] = $this->previous && method_exists( $this->previous, 'to_array' ) ? $this->previous->to_array() : null;
158 }
159
160 if ( $options & self::WITH_TRACE ) {
161 $data['backtrace'] = $this->getTrace();
162 }
163
164 if ( $options & self::WITH_WP_TRACE ) {
165 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_wp_debug_backtrace_summary -- Serializing the WP call trace into the exception payload for structured error reporting.
166 $data['backtrace'] = wp_debug_backtrace_summary( null, 0, false );
167 }
168
169 return $data;
170 }
171
172 public function __toJsonString( $flags = 0, $depth = 512 ): string {
173 return wp_json_encode( $this->to_array(), $flags, $depth );
174 }
175
176 public static function from_wp_error( WP_Error $wp_error ): self {
177 return new self(
178 wp_kses_post( $wp_error->get_error_message() ),
179 esc_html( $wp_error->get_error_code() ),
180 $wp_error->get_error_data()
181 );
182 }
183
184 public static function convert_exception( Throwable $exception, string $wp_code = null, int $error_code = null, $data = null ): self {
185 if ( is_a( $exception, __CLASS__ ) ) {
186 return new self(
187 wp_kses_post( $exception->getMessage() ),
188 $wp_code ?? esc_html( $exception->get_wp_error_code() ),
189 $data ?? $exception->get_data(),
190 $error_code ?? $exception->getCode(),
191 $exception
192 );
193 }
194
195 return new self(
196 wp_kses_post( $exception->getMessage() ),
197 $wp_code ?? 'UNKNOWN_ERROR',
198 $data ?? [],
199 $error_code ?? $exception->getCode(),
200 $exception
201 );
202 }
203
204 public static function from_stripe_api_error( \StoreEngine\Stripe\Exception\ApiErrorException $exception, string $wp_code, array $extra = null ): self {
205 // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped
206 $data = [
207 'response' => [
208 'http_status' => esc_attr( $exception->getHttpStatus() ),
209 'requestId' => esc_attr( $exception->getRequestId() ),
210 'stripeCode' => esc_attr( $exception->getStripeCode() ),
211 'body' => $exception->getJsonBody() ?? $exception->getHttpBody(),
212 'original_msg' => esc_html( (string) $exception ),
213 ],
214 ];
215
216 if ( $extra ) {
217 $data = array_merge( $extra, $data );
218 }
219
220 return new self( esc_html( $exception->getMessage() ), $wp_code, $data, $exception->getCode(), $exception );
221 // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
222 }
223 }
224