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 / Queue / Queue.php
wp-mail-smtp / src / Queue Last commit date
Attachments.php 6 days ago Email.php 6 days ago Migration.php 6 days ago Queue.php 6 days ago
Queue.php
764 lines
1 <?php
2
3 namespace WPMailSMTP\Queue;
4
5 use DateTime;
6 use DateTimeZone;
7 use Exception;
8 use WPMailSMTP\Admin\DebugEvents\DebugEvents;
9 use WPMailSMTP\Tasks\Queue\SendEnqueuedEmailTask;
10 use WPMailSMTP\WPMailArgs;
11 use WPMailSMTP\WP;
12
13 /**
14 * Class Queue.
15 *
16 * @since 4.0.0
17 */
18 class Queue {
19
20 /**
21 * The email being currently handled.
22 *
23 * @since 4.0.0
24 *
25 * @var Email
26 */
27 private $email;
28
29 /**
30 * A list of registered hooks at the time
31 * of email sending.
32 *
33 * @since 4.0.0
34 *
35 * @var array
36 */
37 private $registered_wp_mail_hooks = [];
38
39 /**
40 * Whether the queue is currently enabled.
41 *
42 * @since 4.0.0
43 *
44 * @return bool
45 */
46 public function is_enabled() {
47
48 /**
49 * Filters whether the queue is currently enabled.
50 *
51 * @since 4.0.0
52 *
53 * @param bool $enabled Whether the queue is currently enabled.
54 */
55 return apply_filters( 'wp_mail_smtp_queue_is_enabled', false );
56 }
57
58 /**
59 * Short-circuit and handle an ongoing PHPMailer `send` call.
60 *
61 * @since 4.0.0
62 *
63 * @return bool
64 */
65 public function enqueue_email() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
66
67 if ( ! $this->is_valid_db() ) {
68 return false;
69 }
70
71 global $phpmailer;
72
73 $wp_mail_args = wp_mail_smtp()->get_processor()->get_filtered_wp_mail_args();
74 $initiator = wp_mail_smtp()->get_wp_mail_initiator();
75 $processor = wp_mail_smtp()->get_processor();
76 $initiator_state = [
77 'file' => $initiator->get_file(),
78 'line' => $initiator->get_line(),
79 'backtrace' => $initiator->get_backtrace(),
80 ];
81 $connection_data = [
82 'from_email' => $processor->get_filtered_from_email(),
83 'from_name' => $processor->get_filtered_from_name(),
84 ];
85
86 // Keep a reference to the original attachments,
87 // if something goes wrong while enqueueing the email.
88 $original_attachments = $phpmailer->getAttachments();
89
90 // Obfuscate attachment paths for the enqueued email.
91 $processed_attachments = ( new Attachments() )->process_attachments( $original_attachments );
92
93 // Set obfuscated path attachments.
94 $this->set_attachments( $processed_attachments );
95
96 // Add queued date header in the same format as "Date" header.
97 $phpmailer->addCustomHeader( 'X-WP-Mail-SMTP-Queued', $phpmailer::rfcDate() );
98
99 $email = ( new Email() )
100 ->set_wp_mail_args( $wp_mail_args )
101 ->set_initiator_state( $initiator_state )
102 ->set_connection_data( $connection_data )
103 ->set_mailer_state( $phpmailer->get_state() );
104
105 // Add the email to the queue.
106 try {
107 $this->add_email( $email );
108 } catch ( Exception $e ) {
109 // Cleanup any obfuscated path attachments.
110 $this->cleanup_attachments();
111
112 // Reset original attachments.
113 $this->set_attachments( $original_attachments );
114
115 $message = sprintf(
116 /* translators: %1$s - exception message. */
117 esc_html__( '[Emails Queue] Skipped enqueueing email. %1$s.', 'wp-mail-smtp' ),
118 esc_html( $e->getMessage() )
119 );
120
121 DebugEvents::add_debug( $message );
122
123 return false;
124 }
125
126 return true;
127 }
128
129 /**
130 * Send an email. Can only be called
131 * by a running SendEnqueuedEmailTask.
132 *
133 * @since 4.0.0
134 *
135 * @param int|string $email_id Email's ID.
136 */
137 public function send_email( $email_id ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
138
139 // This method can't be called directly.
140 if ( ! doing_action( SendEnqueuedEmailTask::ACTION ) ) {
141 $message = sprintf(
142 /* translators: %1$d - email ID. */
143 esc_html__( '[Emails Queue] Skipped email sending from the queue. Queue::send_email method was called directly. Email ID: %1$d.', 'wp-mail-smtp' ),
144 $email_id
145 );
146
147 DebugEvents::add_debug( $message );
148
149 return;
150 }
151
152 try {
153 $email = $this->get_email( $email_id );
154 } catch ( Exception $e ) {
155 $this->delete_email( $email_id );
156
157 $message = sprintf(
158 /* translators: %1$s - exception message; %2$s - email ID. */
159 esc_html__( '[Emails Queue] Skipped email sending from the queue. %1$s. Email ID: %2$s', 'wp-mail-smtp' ),
160 esc_html( $e->getMessage() ),
161 $email_id
162 );
163
164 DebugEvents::add_debug( $message );
165
166 return;
167 }
168
169 // Bail early if the email still enqueued, or already processed.
170 if ( $email->get_status() !== Email::STATUS_PROCESSING ) {
171 $message = sprintf(
172 /* translators: %1$d - email ID; %2$s - email status. */
173 esc_html__( '[Emails Queue] Skipped email sending from the queue. Wrong email status. Email ID: %1$d, email status: %2$s.', 'wp-mail-smtp' ),
174 $email_id,
175 $email->get_status()
176 );
177
178 DebugEvents::add_debug( $message );
179
180 return;
181 }
182
183 // Keep a reference to the email
184 // being sent so that it's accessible
185 // across hooks.
186 $this->email = $email;
187
188 // Un-hook all user-defined hooks.
189 $this->clear_wp_mail_hooks();
190
191 // Stop enqueueing emails.
192 add_filter( 'wp_mail_smtp_mail_catcher_send_enqueue_email', '__return_false', PHP_INT_MAX );
193
194 // Re-hook Processor functionality, before applying PHPMailer state,
195 // so that From and From Name are correctly filtered.
196 wp_mail_smtp()->get_processor()->hooks();
197
198 // Apply the email's PHPMailer state.
199 add_action( 'phpmailer_init', [ $this, 'apply_mailer_state' ], PHP_INT_MAX );
200
201 // Retrieve original wp_mail arguments.
202 $wp_mail_args = new WPMailArgs( $email->get_wp_mail_args() );
203
204 // Inject user-filtered From and From Name.
205 $wp_mail_headers = $wp_mail_args->get_headers();
206 $wp_mail_headers[] = $this->get_connection_from_header( $email->get_connection_data() );
207
208 // Inject the original initiator state.
209 add_filter( 'wp_mail_smtp_wp_mail_initiator_set_initiator', [ $this, 'apply_initiator_state' ] );
210
211 // Send the email.
212 wp_mail(
213 $wp_mail_args->get_to_email(),
214 $wp_mail_args->get_subject(),
215 $wp_mail_args->get_message(),
216 $wp_mail_headers,
217 $wp_mail_args->get_attachments()
218 );
219
220 // Update the email.
221 try {
222 $this->email->set_status( Email::STATUS_PROCESSED )
223 ->set_date_processed( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) )
224 ->anonymize()
225 ->save();
226 } catch ( Exception $e ) {
227 $this->delete_email( $email_id );
228
229 $message = sprintf(
230 /* translators: %1$s - exception message; %2$d - email ID. */
231 esc_html__( '[Emails Queue] Failed to update queue record after sending email from the queue. %1$s. Email ID: %2$d', 'wp-mail-smtp' ),
232 esc_html( $e->getMessage() ),
233 $email_id
234 );
235
236 DebugEvents::add_debug( $message );
237 }
238
239 // Cleanup any attachments.
240 $this->cleanup_attachments();
241
242 // Stop injecting the original initiator state.
243 remove_filter( 'wp_mail_smtp_wp_mail_initiator_set_initiator', [ $this, 'apply_initiator_state' ] );
244
245 // Stop applying PHPMailer state.
246 remove_action( 'phpmailer_init', [ $this, 'apply_mailer_state' ], PHP_INT_MAX );
247
248 // Clear the email reference.
249 $this->email = null;
250
251 // Re-hook all user-defined hooks.
252 $this->restore_wp_mail_hooks();
253
254 // Start enqueueing emails again.
255 remove_filter( 'wp_mail_smtp_mail_catcher_send_enqueue_email', '__return_false', PHP_INT_MAX );
256 }
257
258 /**
259 * Return the current email's WPMailInitiator state.
260 *
261 * @since 4.0.0
262 *
263 * @return array WPMailInitiator state.
264 */
265 public function apply_initiator_state() {
266
267 return $this->email->get_initiator_state();
268 }
269
270 /**
271 * Apply state to the current mailer.
272 *
273 * @since 4.0.0
274 *
275 * @param PHPMailer $phpmailer PHPMailer instance.
276 */
277 public function apply_mailer_state( &$phpmailer ) {
278
279 $phpmailer->set_state( $this->email->get_mailer_state() );
280 }
281
282 /**
283 * Get the table name.
284 *
285 * @since 4.0.0
286 *
287 * @return string Table name, prefixed.
288 */
289 public static function get_table_name() {
290
291 global $wpdb;
292
293 return $wpdb->prefix . 'wpmailsmtp_emails_queue';
294 }
295
296 /**
297 * Count processing or processed emails since a given date.
298 *
299 * @since 4.0.0
300 *
301 * @param null|DateTime $since_datetime Date to count from, or null for all emails.
302 *
303 * @return int Email count.
304 */
305 public function count_processed_emails( ?DateTime $since_datetime = null ) {
306
307 if ( ! $this->is_valid_db() ) {
308 return 0;
309 }
310
311 global $wpdb;
312
313 $table = self::get_table_name();
314 $where = $wpdb->prepare(
315 'status IN (%d, %d)',
316 Email::STATUS_PROCESSING,
317 Email::STATUS_PROCESSED
318 );
319
320 if ( ! is_null( $since_datetime ) ) {
321 $where .= $wpdb->prepare(
322 ' AND date_processed >= %s',
323 $since_datetime->format( WP::datetime_mysql_format() )
324 );
325 }
326
327 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
328 $count = $wpdb->get_var(
329 "SELECT COUNT(*)
330 FROM $table
331 WHERE $where;"
332 );
333 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
334
335 return (int) $count;
336 }
337
338 /**
339 * Count queued emails.
340 *
341 * @since 4.0.0
342 *
343 * @return int Email count.
344 */
345 public function count_queued_emails() {
346
347 if ( ! $this->is_valid_db() ) {
348 return 0;
349 }
350
351 global $wpdb;
352
353 $table = self::get_table_name();
354 $where = $wpdb->prepare( 'status = %d', Email::STATUS_QUEUED );
355 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
356 $count = $wpdb->get_var(
357 "SELECT COUNT(*)
358 FROM $table
359 WHERE $where;"
360 );
361 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
362
363 return (int) $count;
364 }
365
366 /**
367 * Schedule emails for sending.
368 *
369 * @since 4.0.0
370 */
371 public function process() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
372
373 if ( ! $this->is_valid_db() ) {
374 return;
375 }
376
377 /**
378 * Filters the amount of emails the queue should process.
379 *
380 * @since 4.0.0
381 *
382 * @param int|null $count Amount of emails to process.
383 */
384 $count = apply_filters( 'wp_mail_smtp_queue_process_count', null );
385
386 // If the queue has been disabled, just process all emails.
387 if ( ! $this->is_enabled() ) {
388 $count = null;
389 }
390
391 $emails = $this->get_emails( $count );
392 $task = new SendEnqueuedEmailTask();
393
394 foreach ( $emails as $email ) {
395 try {
396 $email->set_status( Email::STATUS_PROCESSING )
397 ->set_date_processed( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) )
398 ->save();
399 } catch ( Exception $e ) {
400 $this->delete_email( $email->get_id() );
401
402 $message = sprintf(
403 /* translators: %1$s - exception message. */
404 esc_html__( '[Emails Queue] Skipped processing enqueued email. %1$s. Email ID: %2$d', 'wp-mail-smtp' ),
405 esc_html( $e->getMessage() ),
406 $email->get_id()
407 );
408
409 DebugEvents::add_debug( $message );
410
411 continue;
412 }
413
414 $task->schedule( $email->get_id() );
415 }
416 }
417
418 /**
419 * Cleanup emails processed before a given date.
420 *
421 * @since 4.0.0
422 */
423 public function cleanup() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
424
425 /**
426 * Filters the date before which emails should
427 * be removed from the queue.
428 *
429 * @since 4.0.0
430 *
431 * @param DateTime|null $datetime Date before which to remove emails.
432 */
433 $datetime = apply_filters( 'wp_mail_smtp_queue_cleanup_before_datetime', null );
434
435 // If the queue has been disabled, just cleanup all emails.
436 if ( ! $this->is_enabled() ) {
437 $datetime = null;
438 }
439
440 $this->delete_emails_before( $datetime );
441 }
442
443 /**
444 * Whether the DB table exists.
445 *
446 * @since 4.0.0
447 *
448 * @return bool
449 */
450 public function is_valid_db() {
451
452 global $wpdb;
453
454 static $is_valid = null;
455
456 // Return cached value only if table already exists.
457 if ( $is_valid === true ) {
458 return true;
459 }
460
461 $table = self::get_table_name();
462 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
463 $is_valid = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s;', $table ) );
464
465 return $is_valid;
466 }
467
468 /**
469 * Set current email's attachments.
470 *
471 * @since 4.0.0
472 *
473 * @param array $attachments List of attachments.
474 */
475 private function set_attachments( $attachments ) {
476
477 global $phpmailer;
478
479 $phpmailer->clearAttachments();
480
481 foreach ( $attachments as $attachment ) {
482 [ $path, , $name, $encoding, $type, , $disposition ] = $attachment;
483
484 try {
485 $phpmailer->addAttachment( $path, $name, $encoding, $type, $disposition );
486 } catch ( Exception $e ) {
487 continue;
488 }
489 }
490 }
491
492 /**
493 * Remove email attachments after sending.
494 *
495 * @since 4.0.0
496 */
497 private function cleanup_attachments() {
498
499 global $phpmailer;
500
501 $attachments = $phpmailer->getAttachments();
502
503 ( new Attachments() )->delete_attachments( $attachments );
504 }
505
506 /**
507 * Get the From/From Name header
508 * from an email's connection data.
509 *
510 * @since 4.0.0
511 *
512 * @param array $connection_data Email's connection data.
513 */
514 private function get_connection_from_header( $connection_data ) {
515
516 [
517 'from_email' => $from_email,
518 'from_name' => $from_name
519 ] = $connection_data;
520
521 $from = (
522 $from_name === '' ?
523 $from_email :
524 sprintf( '%1s <%2s>', $from_name, $from_email )
525 );
526
527 $from_header = sprintf(
528 'From:%s',
529 $from
530 );
531
532 return $from_header;
533 }
534
535 /**
536 * Return a list of the `wp_mail` related hooks
537 * that should be de-registered before sending
538 * an enqueued email.
539 *
540 * @since 4.0.0
541 *
542 * @return array List of hooks.
543 */
544 private function get_wp_mail_hooks() {
545
546 return [
547 'wp_mail',
548 'pre_wp_mail',
549 'wp_mail_from',
550 'wp_mail_from_name',
551 'wp_mail_succeeded',
552 'wp_mail_failed',
553 ];
554 }
555
556 /**
557 * Clear any user-defined `wp_mail` related hooks
558 * before sending an enqueued email.
559 *
560 * @since 4.0.0
561 */
562 private function clear_wp_mail_hooks() {
563
564 global $wp_filter;
565
566 $wp_mail_hooks = array_intersect_key(
567 $wp_filter,
568 array_flip( $this->get_wp_mail_hooks() )
569 );
570
571 foreach ( $wp_mail_hooks as $hook_name => $hook ) {
572 foreach ( $hook->callbacks as $priority => $callbacks ) {
573 foreach ( $callbacks as $callback ) {
574 $this->registered_wp_mail_hooks[] = [
575 $hook_name,
576 $callback['function'],
577 $priority,
578 $callback['accepted_args'],
579 ];
580 }
581 }
582
583 remove_all_filters( $hook_name );
584 }
585 }
586
587 /**
588 * Re-register any previous de-registered `wp_mail` related hooks
589 * after sending an enqueued email.
590 *
591 * @since 4.0.0
592 */
593 private function restore_wp_mail_hooks() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
594
595 foreach ( $this->registered_wp_mail_hooks as $hook ) {
596 list( $hook_name, $callback, $priority, $accepted_args ) = $hook;
597
598 add_filter( $hook_name, $callback, $priority, $accepted_args );
599 }
600 }
601
602 /**
603 * Add an email to the queue.
604 *
605 * @since 4.0.0
606 *
607 * @throws Exception When email couldn't be saved.
608 *
609 * @param Email $email The email to enqueue.
610 */
611 private function add_email( Email $email ) {
612
613 if ( ! $this->is_valid_db() ) {
614 return;
615 }
616
617 $email->set_date_enqueued( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) )
618 ->set_status( Email::STATUS_QUEUED )
619 ->save();
620 }
621
622 /**
623 * Get an email.
624 *
625 * @since 4.0.0
626 *
627 * @param int|string $email_id The email's ID.
628 *
629 * @return null|Email The email, or null if not found.
630 */
631 private function get_email( $email_id ) {
632
633 if ( ! $this->is_valid_db() ) {
634 return null;
635 }
636
637 global $wpdb;
638
639 $table = self::get_table_name();
640 $where = $wpdb->prepare( 'ID = %d', (int) $email_id );
641 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
642 $data = $wpdb->get_row( "SELECT * FROM $table WHERE $where" );
643 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
644
645 $email = Email::from_data( $data );
646
647 return $email;
648 }
649
650 /**
651 * Get queued emails from the queue.
652 *
653 * @since 4.0.0
654 *
655 * @param null|int $count Amount of emails to return, or null for all emails.
656 *
657 * @return Email[] Array of emails.
658 */
659 private function get_emails( $count = null ) {
660
661 if ( ! $this->is_valid_db() ) {
662 return [];
663 }
664
665 global $wpdb;
666
667 $table = self::get_table_name();
668 $where = $wpdb->prepare( 'status = %d', Email::STATUS_QUEUED );
669 $limit = '';
670
671 if ( ! is_null( $count ) ) {
672 $limit = $wpdb->prepare(
673 'LIMIT 0, %d',
674 max( 0, intval( $count ) )
675 );
676 }
677
678 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
679 $data = $wpdb->get_results(
680 "SELECT *
681 FROM $table
682 WHERE $where
683 ORDER BY date_enqueued ASC
684 $limit;"
685 );
686 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
687
688 $emails = [];
689
690 foreach ( $data as $row ) {
691 try {
692 $emails[] = Email::from_data( $row );
693 } catch ( Exception $e ) {
694 $this->delete_email( $row->id );
695
696 $message = sprintf(
697 /* translators: %1$s - exception message. */
698 esc_html__( '[Emails Queue] Skipped processing enqueued email. %1$s. Email ID: %2$d', 'wp-mail-smtp' ),
699 esc_html( $e->getMessage() ),
700 $row->id
701 );
702
703 DebugEvents::add_debug( $message );
704 }
705 }
706
707 return $emails;
708 }
709
710 /**
711 * Delete emails processed before a given date.
712 *
713 * @since 4.0.0
714 *
715 * @param DateTime|null $before_datetime Date before which to remove emails, or null for all emails.
716 */
717 private function delete_emails_before( $before_datetime ) {
718
719 if ( ! $this->is_valid_db() ) {
720 return;
721 }
722
723 global $wpdb;
724
725 $table = self::get_table_name();
726 $where = $wpdb->prepare( 'status = %d', Email::STATUS_PROCESSED );
727
728 if ( is_a( $before_datetime, DateTime::class ) ) {
729 $where .= $wpdb->prepare(
730 ' AND date_processed < %s',
731 $before_datetime->format( WP::datetime_mysql_format() )
732 );
733 }
734
735 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
736 $wpdb->query( "DELETE FROM $table WHERE $where" );
737 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
738 }
739
740 /**
741 * Delete an email.
742 *
743 * @since 4.0.0
744 *
745 * @param int $email_id ID of the email.
746 */
747 private function delete_email( $email_id ) {
748
749 if ( ! $this->is_valid_db() ) {
750 return;
751 }
752
753 global $wpdb;
754
755 $table = self::get_table_name();
756
757 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
758 $wpdb->query(
759 $wpdb->prepare( "DELETE FROM $table WHERE ID = %d", $email_id )
760 );
761 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
762 }
763 }
764