PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Admin / DebugEvents / Event.php
wp-mail-smtp / src / Admin / DebugEvents Last commit date
DebugEvents.php 6 days ago Event.php 6 days ago EventsCollection.php 6 days ago Migration.php 6 days ago Table.php 6 days ago
Event.php
598 lines
1 <?php
2
3 namespace WPMailSMTP\Admin\DebugEvents;
4
5 use WPMailSMTP\WP;
6
7 /**
8 * Debug Event class.
9 *
10 * @since 3.0.0
11 */
12 class Event {
13
14 /**
15 * This is an error event.
16 *
17 * @since 3.0.0
18 */
19 const TYPE_ERROR = 0;
20
21 /**
22 * This is a debug event.
23 *
24 * @since 3.0.0
25 */
26 const TYPE_DEBUG = 1;
27
28 /**
29 * The event's ID.
30 *
31 * @since 3.0.0
32 *
33 * @var int
34 */
35 protected $id = 0;
36
37 /**
38 * The event's content.
39 *
40 * @since 3.0.0
41 *
42 * @var string
43 */
44 protected $content = '';
45
46 /**
47 * The event's initiator - who called the `wp_mail` function?
48 * JSON encoded string.
49 *
50 * @since 3.0.0
51 *
52 * @var string
53 */
54 protected $initiator = '';
55
56 /**
57 * The event's type.
58 *
59 * @since 3.0.0
60 *
61 * @var int
62 */
63 protected $event_type = 0;
64
65 /**
66 * The date and time when this event was created.
67 *
68 * @since 3.0.0
69 *
70 * @var \DateTime
71 */
72 protected $created_at;
73
74 /**
75 * Retrieve a particular event when constructing the object.
76 *
77 * @since 3.0.0
78 *
79 * @param int|object $id_or_row The event ID or object with event attributes.
80 */
81 public function __construct( $id_or_row = null ) {
82
83 $this->populate_event( $id_or_row );
84 }
85
86 /**
87 * Get and prepare the event data.
88 *
89 * @since 3.0.0
90 *
91 * @param int|object $id_or_row The event ID or object with event attributes.
92 */
93 private function populate_event( $id_or_row ) {
94
95 $event = null;
96
97 if ( is_numeric( $id_or_row ) ) {
98 // Get by ID.
99 $collection = new EventsCollection( [ 'id' => (int) $id_or_row ] );
100 $events = $collection->get();
101
102 if ( $events->valid() ) {
103 $event = $events->current();
104 }
105 } elseif (
106 is_object( $id_or_row ) &&
107 isset(
108 $id_or_row->id,
109 $id_or_row->content,
110 $id_or_row->initiator,
111 $id_or_row->event_type,
112 $id_or_row->created_at
113 )
114 ) {
115 $event = $id_or_row;
116 }
117
118 if ( $event !== null ) {
119 foreach ( get_object_vars( $event ) as $key => $value ) {
120 $this->{$key} = $value;
121 }
122 }
123 }
124
125 /**
126 * Event ID as per our DB table.
127 *
128 * @since 3.0.0
129 *
130 * @return int
131 */
132 public function get_id() {
133
134 return (int) $this->id;
135 }
136
137 /**
138 * Get the event title.
139 *
140 * @since 3.0.0
141 *
142 * @return string
143 */
144 public function get_title() {
145
146 /* translators: %d the event ID. */
147 return sprintf( esc_html__( 'Event #%d', 'wp-mail-smtp' ), $this->get_id() );
148 }
149
150 /**
151 * Get the content of the event.
152 *
153 * @since 3.0.0
154 *
155 * @return string
156 */
157 public function get_content() {
158
159 return $this->content;
160 }
161
162 /**
163 * Get the event's type.
164 *
165 * @since 3.0.0
166 *
167 * @return int
168 */
169 public function get_type() {
170
171 return (int) $this->event_type;
172 }
173
174 /**
175 * Get the list of all event types.
176 *
177 * @since 3.0.0
178 *
179 * @return array
180 */
181 public static function get_types() {
182
183 return [
184 self::TYPE_ERROR => esc_html__( 'Error', 'wp-mail-smtp' ),
185 self::TYPE_DEBUG => esc_html__( 'Debug', 'wp-mail-smtp' ),
186 ];
187 }
188
189 /**
190 * Get human readable type name.
191 *
192 * @since 3.0.0
193 *
194 * @return string
195 */
196 public function get_type_name() {
197
198 $types = self::get_types();
199
200 return isset( $types[ $this->get_type() ] ) ? $types[ $this->get_type() ] : '';
201 }
202
203 /**
204 * Get the date/time when this event was created.
205 *
206 * @since 3.0.0
207 *
208 * @throws \Exception Emits exception on incorrect date.
209 *
210 * @return \DateTime
211 */
212 public function get_created_at() {
213
214 $timezone = new \DateTimeZone( 'UTC' );
215 $date = false;
216
217 if ( ! empty( $this->created_at ) ) {
218 $date = \DateTime::createFromFormat( WP::datetime_mysql_format(), $this->created_at, $timezone );
219 }
220
221 if ( $date === false ) {
222 $date = new \DateTime( 'now', $timezone );
223 }
224
225 return $date;
226 }
227
228 /**
229 * Get the date/time when this event was created in a nicely formatted string.
230 *
231 * @since 3.0.0
232 *
233 * @return string
234 */
235 public function get_created_at_formatted() {
236
237 try {
238 $date = $this->get_created_at();
239 } catch ( \Exception $e ) {
240 $date = null;
241 }
242
243 if ( empty( $date ) ) {
244 return esc_html__( 'N/A', 'wp-mail-smtp' );
245 }
246
247 return esc_html(
248 date_i18n(
249 WP::datetime_format(),
250 strtotime( get_date_from_gmt( $date->format( WP::datetime_mysql_format() ) ) )
251 )
252 );
253 }
254
255 /**
256 * Get the event's initiator raw data.
257 * Who called the `wp_mail` function?
258 *
259 * @since 3.0.0
260 *
261 * @return array
262 */
263 public function get_initiator_raw() {
264
265 return json_decode( $this->initiator, true );
266 }
267
268 /**
269 * Get the event's initiator name.
270 * Which plugin/theme (or WP core) called the `wp_mail` function?
271 *
272 * @since 3.0.0
273 *
274 * @return string
275 */
276 public function get_initiator() {
277
278 $initiator = (array) $this->get_initiator_raw();
279
280 if ( empty( $initiator['file'] ) ) {
281 return '';
282 }
283
284 return WP::get_initiator_name( $initiator['file'] );
285 }
286
287 /**
288 * Get the event's initiator file path.
289 *
290 * @since 3.0.0
291 *
292 * @return string
293 */
294 public function get_initiator_file_path() {
295
296 $initiator = (array) $this->get_initiator_raw();
297
298 if ( empty( $initiator['file'] ) ) {
299 return '';
300 }
301
302 return $initiator['file'];
303 }
304
305 /**
306 * Get the event's initiator file line.
307 *
308 * @since 3.0.0
309 *
310 * @return string
311 */
312 public function get_initiator_file_line() {
313
314 $initiator = (array) $this->get_initiator_raw();
315
316 if ( empty( $initiator['line'] ) ) {
317 return '';
318 }
319
320 return $initiator['line'];
321 }
322
323 /**
324 * Get the event's initiator backtrace.
325 *
326 * @since 3.6.0
327 *
328 * @return array
329 */
330 private function get_initiator_backtrace() {
331
332 $initiator = (array) $this->get_initiator_raw();
333
334 if ( empty( $initiator['backtrace'] ) ) {
335 return [];
336 }
337
338 return $initiator['backtrace'];
339 }
340
341 /**
342 * Get the event preview HTML.
343 *
344 * @since 3.0.0
345 *
346 * @return string
347 */
348 public function get_details_html() {
349
350 $initiator = $this->get_initiator();
351 $initiator_backtrace = $this->get_initiator_backtrace();
352
353 ob_start();
354 ?>
355 <div class="wp-mail-smtp-debug-event-preview">
356 <div class="wp-mail-smtp-debug-event-preview-subtitle">
357 <span><?php esc_html_e( 'Debug Event Details', 'wp-mail-smtp' ); ?></span>
358 </div>
359 <div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-type">
360 <span class="debug-event-label"><?php esc_html_e( 'Type', 'wp-mail-smtp' ); ?></span>
361 <span class="debug-event-value"><?php echo esc_html( $this->get_type_name() ); ?></span>
362 </div>
363 <div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-date">
364 <span class="debug-event-label"><?php esc_html_e( 'Date', 'wp-mail-smtp' ); ?></span>
365 <span class="debug-event-value"><?php echo esc_html( $this->get_created_at_formatted() ); ?></span>
366 </div>
367 <div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-content">
368 <span class="debug-event-label"><?php esc_html_e( 'Content', 'wp-mail-smtp' ); ?></span>
369 <div class="debug-event-value">
370 <?php echo wp_kses( str_replace( [ "\r\n", "\r", "\n" ], '<br>', $this->get_content() ), [ 'br' => [] ] ); ?>
371 </div>
372 </div>
373 <?php if ( ! empty( $initiator ) ) : ?>
374 <div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-caller">
375 <span class="debug-event-label"><?php esc_html_e( 'Source', 'wp-mail-smtp' ); ?></span>
376 <div class="debug-event-value">
377 <span class="debug-event-initiator"><?php echo esc_html( $initiator ); ?></span>
378 <p class="debug-event-code">
379 <?php
380 printf( /* Translators: %1$s the path of a file, %2$s the line number in the file. */
381 esc_html__( '%1$s (line: %2$s)', 'wp-mail-smtp' ),
382 esc_html( $this->get_initiator_file_path() ),
383 esc_html( $this->get_initiator_file_line() )
384 );
385 ?>
386
387 <?php if ( ! empty( $initiator_backtrace ) ) : ?>
388 <br><br>
389 <b><?php esc_html_e( 'Backtrace:', 'wp-mail-smtp' ); ?></b>
390 <br>
391 <?php
392 foreach ( $initiator_backtrace as $i => $item ) {
393 printf(
394 /* translators: %1$d - index number; %2$s - function name; %3$s - file path; %4$s - line number. */
395 esc_html__( '[%1$d] %2$s called at [%3$s:%4$s]', 'wp-mail-smtp' ),
396 $i,
397 isset( $item['class'] ) ? esc_html( $item['class'] . $item['type'] . $item['function'] ) : esc_html( $item['function'] ),
398 isset( $item['file'] ) ? esc_html( $item['file'] ) : '', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
399 isset( $item['line'] ) ? esc_html( $item['line'] ) : '' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
400 );
401 echo '<br>';
402 }
403 ?>
404 <?php endif; ?>
405 </p>
406 </div>
407 </div>
408 <?php endif; ?>
409 </div>
410 <?php
411
412 return ob_get_clean();
413 }
414
415 /**
416 * Get the short details about this event (event content and the initiator's name).
417 *
418 * @since 3.0.0
419 *
420 * @return string
421 */
422 public function get_short_details() {
423
424 $result = [];
425
426 if ( ! empty( $this->get_initiator() ) ) {
427 $result[] = sprintf(
428 /* Translators: %s - Email initiator/source name. */
429 esc_html__( 'Email Source: %s', 'wp-mail-smtp' ),
430 esc_html( $this->get_initiator() )
431 );
432 }
433
434 $result[] = esc_html( $this->get_content() );
435
436 return implode( WP::EOL, $result );
437 }
438
439 /**
440 * Save a new or modified event in DB.
441 *
442 * @since 3.0.0
443 *
444 * @throws \Exception When event init fails.
445 *
446 * @return Event New or updated event class instance.
447 */
448 public function save() {
449
450 global $wpdb;
451
452 $table = DebugEvents::get_table_name();
453
454 if ( (bool) $this->get_id() ) {
455 // Update the existing DB table record.
456 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
457 $table,
458 [
459 'content' => $this->content,
460 'initiator' => $this->initiator,
461 'event_type' => $this->event_type,
462 'created_at' => $this->get_created_at()->format( WP::datetime_mysql_format() ),
463 ],
464 [
465 'id' => $this->get_id(),
466 ],
467 [
468 '%s', // content.
469 '%s', // initiator.
470 '%s', // type.
471 '%s', // created_at.
472 ],
473 [
474 '%d',
475 ]
476 );
477
478 $event_id = $this->get_id();
479 } else {
480 // Create a new DB table record.
481 $wpdb->insert(
482 $table,
483 [
484 'content' => $this->content,
485 'initiator' => $this->initiator,
486 'event_type' => $this->event_type,
487 'created_at' => $this->get_created_at()->format( WP::datetime_mysql_format() ),
488 ],
489 [
490 '%s', // content.
491 '%s', // initiator.
492 '%s', // type.
493 '%s', // created_at.
494 ]
495 );
496
497 $event_id = $wpdb->insert_id;
498 }
499
500 try {
501 $event = new Event( $event_id );
502 } catch ( \Exception $e ) {
503 $event = new Event();
504 }
505
506 return $event;
507 }
508
509 /**
510 * Set the content of this event.
511 *
512 * @since 3.0.0
513 *
514 * @param string|array $content The event's content.
515 */
516 public function set_content( $content ) {
517
518 if ( ! is_string( $content ) ) {
519 $this->content = wp_json_encode( $content );
520 } else {
521 $this->content = wp_strip_all_tags( str_replace( '<br>', "\r\n", $content ), false );
522 }
523 }
524
525 /**
526 * Set the initiator by checking the backtrace for the wp_mail function call.
527 *
528 * @since 3.0.0
529 */
530 public function set_initiator() {
531
532 $initiator = wp_mail_smtp()->get_wp_mail_initiator();
533
534 if ( empty( $initiator->get_file() ) ) {
535 return;
536 }
537
538 $data['file'] = $initiator->get_file();
539
540 if ( ! empty( $initiator->get_line() ) ) {
541 $data['line'] = $initiator->get_line();
542 }
543
544 if ( DebugEvents::is_debug_enabled() ) {
545 $data['backtrace'] = $initiator->get_backtrace();
546 }
547
548 $this->initiator = wp_json_encode( $data );
549 }
550
551 /**
552 * Set the type of this event.
553 *
554 * @since 3.0.0
555 *
556 * @param int $type The event's type.
557 */
558 public function set_type( $type ) {
559
560 $this->event_type = (int) $type;
561 }
562
563 /**
564 * Whether the event instance is a valid entity to work with.
565 *
566 * @since 3.0.0
567 */
568 public function is_valid() {
569
570 return ! ( empty( $this->id ) || empty( $this->created_at ) );
571 }
572
573 /**
574 * Whether this is an error event.
575 *
576 * @since 3.0.0
577 *
578 * @return bool
579 */
580 public function is_error() {
581
582 return self::TYPE_ERROR === $this->get_type();
583 }
584
585 /**
586 * Whether this is a debug event.
587 *
588 * @since 3.0.0
589 *
590 * @return bool
591 */
592 public function is_debug() {
593
594 return self::TYPE_DEBUG === $this->get_type();
595 }
596 }
597
598