PluginProbe ʕ •ᴥ•ʔ
Check & Log Email – Easy Email Testing & Mail logging / 2.0.7
Check & Log Email – Easy Email Testing & Mail logging v2.0.7
2.0.15 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 2.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.13.1 2.0.13.2 2.0.14 2.0.2 2.0.3 2.0.4 2.0.5 2.0.5.1 2.0.6 2.0.7 2.0.8 2.0.9 trunk 0.5.7 0.6.0 0.6.1 0.6.2 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.12.1 1.0.13 1.0.13.1 1.0.2 1.0.3
check-email / include / Core / DB / Check_Email_Table_Manager.php
check-email / include / Core / DB Last commit date
Check_Email_Table_Manager.php 1 year ago
Check_Email_Table_Manager.php
862 lines
1 <?php namespace CheckEmail\Core\DB;
2
3 /**
4 * Handle installation and db table creation.
5 */
6 use CheckEmail\Core\Loadie;
7 use CheckEmail\Util;
8
9 defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
10
11 /**
12 * Helper class to create table.
13 */
14 class Check_Email_Table_Manager implements Loadie {
15
16 /* Database table name */
17 const LOG_TABLE_NAME = 'check_email_log';
18 const ERROR_TRACKER_TABLE_NAME = 'check_email_error_logs';
19
20 /* Database option name */
21 const DB_OPTION_NAME = 'check_email-log-db';
22
23 /* Database version */
24 const DB_VERSION = '0.3';
25
26 /**
27 * Setup hooks.
28 */
29 public function load() {
30 add_action( 'wpmu_new_blog', array( $this, 'create_table_for_new_blog' ) );
31
32 add_filter( 'wpmu_drop_tables', array( $this, 'delete_table_from_deleted_blog' ) );
33
34 add_filter( 'admin_init', array( $this, 'add_backtrace_segment_field' ) );
35 add_filter( 'admin_init', array( $this, 'add_open_count_field' ) );
36
37 $option = get_option( 'check-email-log-core' );
38 if ((isset($option['is_retention_amount_enable']) && $option['is_retention_amount_enable']) || (isset($option['is_retention_period_enable']) && $option['is_retention_period_enable'])) {
39 add_action('admin_init', array( $this, 'ck_mail_cron_schedule' ));
40 add_action('check_mail_cron_hook', array( $this, 'ck_mail_cron_execute' ));
41 }
42
43 // Do any DB upgrades.
44 $this->update_table_if_needed();
45 }
46
47 public function on_activate( $network_wide ) {
48 if ( is_multisite() && $network_wide ) {
49 // Note: if there are more than 10,000 blogs or
50 // if `wp_is_large_network` filter is set, then this may fail.
51 $sites = get_sites();
52
53 foreach ( $sites as $site ) {
54 switch_to_blog( $site->blog_id );
55 $this->create_table_if_needed();
56 restore_current_blog();
57 if (function_exists('ck_mail_create_error_logs') ) {
58 ck_mail_create_error_logs();
59 }
60 if (function_exists('ck_mail_create_spam_analyzer_table') ) {
61 ck_mail_create_spam_analyzer_table();
62 }
63 }
64 } else {
65 $this->create_table_if_needed();
66 if (function_exists('ck_mail_create_error_logs') ) {
67 ck_mail_create_error_logs();
68 }
69 if (function_exists('ck_mail_create_spam_analyzer_table') ) {
70 ck_mail_create_spam_analyzer_table();
71 }
72 }
73 }
74
75 /**
76 * Create email log table when a new blog is created.
77 */
78 public function create_table_for_new_blog( $blog_id ) {
79 if ( is_plugin_active_for_network( 'check-email-log/check-email.php' ) ) {
80 switch_to_blog( $blog_id );
81 $this->create_table_if_needed();
82 restore_current_blog();
83 }
84 }
85
86 /**
87 * Add email log table to the list of tables deleted when a blog is deleted.
88 */
89 public function delete_table_from_deleted_blog( $tables ) {
90 $tables[] = $this->get_log_table_name();
91
92 return $tables;
93 }
94
95 /**
96 * Get email log table name.
97 */
98 public function get_log_table_name() {
99 global $wpdb;
100
101 return $wpdb->prefix . self::LOG_TABLE_NAME;
102 }
103 public function get_error_tracker_table_name() {
104 global $wpdb;
105
106 return $wpdb->prefix . self::ERROR_TRACKER_TABLE_NAME;
107 }
108
109 public function insert_log( $data ) {
110 global $wpdb;
111
112 $table_name = $this->get_log_table_name();
113 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: custom table on insert
114 $wpdb->insert( $table_name, $data );
115 }
116
117 public function delete_logs( $ids ) {
118 global $wpdb;
119
120 $table_name = $this->get_log_table_name();
121
122 $ids = esc_sql( $ids );
123 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: $table_name
124 $result = $wpdb->query( "DELETE FROM {$table_name} where id IN ( {$ids} )" );
125 $ids_array = array_map('intval', explode(',', $ids));
126 if ($result !== false) {
127 foreach ($ids_array as $id) {
128 wp_cache_delete($id, 'check_mail_log');
129 }
130 }
131 return $result;
132 }
133
134 public function delete_all_logs() {
135 global $wpdb;
136
137 $table_name = $this->get_log_table_name();
138 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: $table_name
139 $result = $wpdb->query( "DELETE FROM {$table_name}" );
140
141 if ($result !== false) {
142 wp_cache_delete('check_mail_log','check_mail_log');
143 }
144
145 return $result;
146 }
147
148 public function delete_error_tracker( $ids ) {
149 global $wpdb;
150
151 $table_name = $this->get_error_tracker_table_name();
152
153 $ids = esc_sql( $ids );
154 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: $table_name
155 $result = $wpdb->query( "DELETE FROM {$table_name} where id IN ( {$ids} )" );
156 $ids_array = array_map('intval', explode(',', $ids));
157 if ($result !== false) {
158 foreach ($ids_array as $id) {
159 wp_cache_delete($id, 'check_mail_log');
160 }
161 }
162 return $result;
163 }
164
165 public function delete_all_error_tracker() {
166 global $wpdb;
167
168 $table_name = $this->get_error_tracker_table_name();
169 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- Reason: $table_name
170 $result = $wpdb->query( "DELETE FROM {$table_name}" );
171
172 if ($result !== false) {
173 wp_cache_delete('check_mail_log','check_mail_log');
174 }
175
176 return $result;
177 }
178
179 public function delete_logs_older_than( $interval_in_days ) {
180 global $wpdb;
181 $table_name = $this->get_log_table_name();
182 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
183 $query = $wpdb->prepare( "DELETE FROM {$table_name} WHERE sent_date < DATE_SUB( CURDATE(), INTERVAL %d DAY )", $interval_in_days );
184 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- already prepare in query
185 $deleted_rows_count = $wpdb->query( $query );
186
187 return $deleted_rows_count;
188 }
189
190 public function fetch_log_items_by_id( $ids = array(), $additional_args = array() ) {
191 global $wpdb;
192 $table_name = $this->get_log_table_name();
193
194 $query = "SELECT * FROM {$table_name}";
195
196 $date_column_format_key = 'date_column_format';
197 if ( array_key_exists( $date_column_format_key, $additional_args ) && ! empty( $additional_args[ $date_column_format_key ] ) ) {
198 $query = "SELECT DATE_FORMAT(sent_date, \"{$additional_args[ $date_column_format_key ]}\") as sent_date_custom, el.* FROM {$table_name} as el";
199 }
200
201 if ( ! empty( $ids ) ) {
202 $ids = array_map( 'absint', $ids );
203
204 // Can't use wpdb->prepare for the below query.
205 $ids_list = esc_sql( implode( ',', $ids ) );
206
207 $query .= " where id IN ( {$ids_list} )";
208 }
209
210 return $wpdb->get_results( $query, 'ARRAY_A' ); //@codingStandardsIgnoreLine
211 }
212
213 public function fetch_log_items( $request, $per_page, $current_page_no ) {
214 global $wpdb;
215 $table_name = $this->get_log_table_name();
216
217 $query = 'SELECT * FROM ' . $table_name;
218 $count_query = 'SELECT count(*) FROM ' . $table_name;
219 $query_cond = '';
220
221 if ( isset( $request['s'] ) && is_string( $request['s'] ) && $request['s'] !== '' ) {
222 $search_term = trim( esc_sql( $request['s'] ) );
223
224 if ( Util\wp_chill_check_email_advanced_search_term( $search_term ) ) {
225 $predicates = Util\wp_chill_check_email_get_advanced_search_term_predicates( $search_term );
226
227 foreach ( $predicates as $column => $email ) {
228 switch ( $column ) {
229 case 'id':
230 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
231 $query_cond .= "id = '$email'";
232 break;
233 case 'to':
234 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
235 $query_cond .= "to_email LIKE '%$email%'";
236 break;
237 case 'email':
238 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
239 $query_cond .= ' ( '; /* Begin 1st */
240 $query_cond .= " ( to_email LIKE '%$email%' OR subject LIKE '%$email%' ) "; /* Begin 2nd & End 2nd */
241 $query_cond .= ' OR ';
242 $query_cond .= ' ( '; /* Begin 3rd */
243 $query_cond .= "headers <> ''";
244 $query_cond .= ' AND ';
245 $query_cond .= ' ( '; /* Begin 4th */
246 $query_cond .= "headers REGEXP '[F|f]rom:.*$email' OR ";
247 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' OR ";
248 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' OR ";
249 $query_cond .= "headers REGEXP '[R|r]eply-[T|t]o:.*$email'";
250 $query_cond .= ' ) '; /* End 4th */
251 $query_cond .= ' ) '; /* End 3rd */
252 $query_cond .= ' ) '; /* End 1st */
253 break;
254 case 'cc':
255 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
256 $query_cond .= ' ( '; /* Begin 1st */
257 $query_cond .= "headers <> ''";
258 $query_cond .= ' AND ';
259 $query_cond .= ' ( '; /* Begin 2nd */
260 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' ";
261 $query_cond .= ' ) '; /* End 2nd */
262 $query_cond .= ' ) '; /* End 1st */
263 break;
264 case 'bcc':
265 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
266 $query_cond .= ' ( '; /* Begin 1st */
267 $query_cond .= "headers <> ''";
268 $query_cond .= ' AND ';
269 $query_cond .= ' ( '; /* Begin 2nd */
270 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' ";
271 $query_cond .= ' ) '; /* End 2nd */
272 $query_cond .= ' ) '; /* End 1st */
273 break;
274 case 'reply-to':
275 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
276 $query_cond .= ' ( '; /* Begin 1st */
277 $query_cond .= "headers <> ''";
278 $query_cond .= ' AND ';
279 $query_cond .= ' ( '; /* Begin 2nd */
280 $query_cond .= "headers REGEXP '[R|r]eply-to:.*$email' ";
281 $query_cond .= ' ) '; /* End 2nd */
282 $query_cond .= ' ) '; /* End 1st */
283 break;
284 }
285 }
286 } else {
287 $query_cond .= " WHERE ( to_email LIKE '%$search_term%' OR subject LIKE '%$search_term%' OR message LIKE '%$search_term%' ) ";
288 }
289 }
290
291 if ( isset( $request['d'] ) && $request['d'] !== '' ) {
292 $search_date = trim( esc_sql( $request['d'] ) );
293 if ( '' === $query_cond ) {
294 $query_cond .= " WHERE sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
295 } else {
296 $query_cond .= " AND sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
297 }
298 }
299 if ( isset( $request['status'] ) && $request['status'] !== '' ) {
300 $status = trim( esc_sql( $request['status'] ) );
301 switch( $status ) {
302 case 'failed':
303 $query_cond .= " WHERE `result` IS NULL OR `result` = ''";
304 break;
305 case 'complete':
306 $query_cond .= " WHERE `result` IS NOT NULL AND `result` != ''";
307 break;
308 default:
309 break;
310 }
311 }
312
313 // Ordering parameters.
314 $orderby = ! empty( $request['orderby'] ) ? sanitize_sql_orderby( $request['orderby'] ) : 'sent_date';
315 if ( isset( $request['order'] ) ) {
316 $order = in_array( strtoupper($request['order']), array( 'DESC', 'ASC' ) ) ? esc_sql( $request['order'] ) : 'DESC';
317 }else{
318 $order = 'DESC';
319 }
320
321
322 if ( ! empty( $orderby ) & ! empty( $order ) ) {
323 $query_cond .= ' ORDER BY ' . $orderby . ' ' . $order;
324 }
325
326 // Find total number of items.
327 $count_query = $count_query . $query_cond;
328 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
329 $total_items = $wpdb->get_var( $count_query );
330
331 // Adjust the query to take pagination into account.
332 if ( ! empty( $current_page_no ) && ! empty( $per_page ) ) {
333 $offset = ( $current_page_no - 1 ) * $per_page;
334 $query_cond .= ' LIMIT ' . (int) $offset . ',' . (int) $per_page;
335 }
336
337 // Fetch the items.
338 $query = $query . $query_cond;
339 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Due to critical query not used prepare $table_name
340 $items = $wpdb->get_results( $query );
341
342 return array( $items, $total_items );
343 }
344
345 public function create_table_if_needed() {
346 global $wpdb;
347
348 $table_name = $this->get_log_table_name();
349 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
350 if ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s",$wpdb->esc_like( $table_name ))) != $table_name ) {
351
352 $sql = $this->get_create_table_query();
353
354 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
355 dbDelta( $sql );
356
357 add_option( self::DB_OPTION_NAME, self::DB_VERSION );
358 }
359 }
360
361 public function get_logs_count() {
362 global $wpdb;
363 $table_name = $this->get_log_table_name();
364 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
365 // $query = $wpdb->prepare("SELECT count(*) FROM `$table_name`");
366 $query = "SELECT count(*) FROM `$table_name`";
367 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason:already used prepare
368 return $wpdb->get_var( $query );
369 }
370
371 public function fetch_log_id_by_data( $data ) {
372 if ( empty( $data ) || ! is_array( $data ) ) {
373 return 0;
374 }
375
376 global $wpdb;
377 $table_name = $this->get_log_table_name();
378
379 $query = "SELECT ID FROM {$table_name}";
380 $query_cond = '';
381 $where = array();
382
383 // Execute the following `if` conditions only when $data is array.
384 if ( array_key_exists( 'to', $data ) ) {
385 // Since the value is stored as CSV in DB, convert the values from error data to CSV to compare.
386 $to_email = Util\wp_chill_check_email_stringify( $data['to'] );
387
388 $to_email = trim( esc_sql( $to_email ) );
389 $where[] = $wpdb->prepare("to_email = %s",$to_email);
390 }
391
392 if ( array_key_exists( 'subject', $data ) ) {
393 $subject = trim( esc_sql( $data['subject'] ) );
394 $where[] = $wpdb->prepare("subject = %s",$subject);
395 }
396
397 if ( array_key_exists( 'attachments', $data ) ) {
398 if ( is_array( $data['attachments'] ) ) {
399 $attachments = count( $data['attachments'] ) > 0 ? 'true' : 'false';
400 } else {
401 $attachments = empty( $data['attachments'] ) ? 'false' : 'true';
402 }
403 $attachments = trim( esc_sql( $attachments ) );
404 $where[] = $wpdb->prepare("attachments = %s",$attachments);
405 }
406
407 foreach ( $where as $index => $value ) {
408 $query_cond .= 0 === $index ? ' WHERE ' : ' AND ';
409 $query_cond .= $value;
410 }
411
412 // Get only the latest logged item when multiple rows match.
413 $query_cond .= ' ORDER BY id DESC LIMIT 1';
414
415 $query = $query . $query_cond;
416 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
417 return absint( $wpdb->get_var( $query ) );
418 }
419
420 public function mark_log_as_failed( $log_item_id, $message ) {
421 global $wpdb;
422 $table_name = $this->get_log_table_name();
423 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
424 $wpdb->update(
425 $table_name,
426 array(
427 'result' => '0',
428 'error_message' => $message,
429 ),
430 array( 'ID' => $log_item_id ),
431 array(
432 '%d', // `result` format.
433 '%s', // `error_message` format.
434 ),
435 array(
436 '%d', // `ID` format.
437 )
438 );
439 }
440
441 private function update_table_if_needed() {
442 if ( get_option( self::DB_OPTION_NAME, false ) === self::DB_VERSION ) {
443 return;
444 }
445
446 $sql = $this->get_create_table_query();
447
448 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
449 dbDelta( $sql );
450
451 update_option( self::DB_OPTION_NAME, self::DB_VERSION );
452 }
453
454 private function get_create_table_query() {
455 global $wpdb;
456 $table_name = $this->get_log_table_name();
457 $charset_collate = $wpdb->get_charset_collate();
458
459 $sql = 'CREATE TABLE ' . $table_name . ' (
460 id mediumint(9) NOT NULL AUTO_INCREMENT,
461 to_email VARCHAR(500) NOT NULL,
462 subject VARCHAR(500) NOT NULL,
463 message TEXT NOT NULL,
464 backtrace_segment TEXT NOT NULL,
465 headers TEXT NOT NULL,
466 attachments TEXT NOT NULL,
467 sent_date timestamp NOT NULL,
468 attachment_name VARCHAR(1000),
469 ip_address VARCHAR(15),
470 result TINYINT(1),
471 error_message VARCHAR(1000),
472 PRIMARY KEY (id)
473 ) ' . $charset_collate . ';';
474
475 return $sql;
476 }
477
478 private function validate_columns( $column ) {
479 return in_array( $column, array( 'to' ), true );
480 }
481
482 public function query_log_items_by_column( $columns ) {
483 if ( ! is_array( $columns ) ) {
484 return;
485 }
486
487 $columns_keys = array_keys( $columns );
488 if ( ! array_filter( $columns_keys, array( $this, 'validate_columns' ) ) ) {
489 return;
490 }
491
492 global $wpdb;
493
494 $table_name = $this->get_log_table_name();
495 $query = "SELECT id, sent_date, to_email, subject FROM {$table_name}";
496 $query_cond = '';
497 $where = array();
498
499 // Execute the following `if` conditions only when $data is array.
500 if ( array_key_exists( 'to', $columns ) ) {
501 // Since the value is stored as CSV in DB, convert the values from error data to CSV to compare.
502 $to_email = Util\wp_chill_check_email_stringify( $columns['to'] );
503
504 $to_email = trim( esc_sql( $to_email ) );
505 $where[] = "to_email = '$to_email'";
506
507 foreach ( $where as $index => $value ) {
508 $query_cond .= 0 === $index ? ' WHERE ' : ' AND ';
509 $query_cond .= $value;
510 }
511
512 // Get only the latest logged item when multiple rows match.
513 $query_cond .= ' ORDER BY id DESC';
514
515 $query = $query . $query_cond;
516 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
517 return $wpdb->get_results( $query );
518 }
519 }
520
521 /**
522 * Add new backtrace_segment field to check_email_log table
523 * @since 1.0.12
524 * */
525 public function add_backtrace_segment_field(){
526 global $wpdb;
527 $table_name = $this->get_log_table_name();
528
529 // Field to check
530 $field_name = 'backtrace_segment';
531
532 // Query to check if the field exists in the table
533 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
534 $field_exists = $wpdb->get_results(
535 $wpdb->prepare(
536 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
537 "SHOW COLUMNS FROM $table_name LIKE %s",
538 $field_name
539 )
540 );
541
542 if(empty($field_exists)){
543 $query = "ALTER TABLE $table_name ADD backtrace_segment TEXT NULL DEFAULT NULL AFTER message";
544 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
545 $wpdb->query($query);
546 }
547 }
548 /**
549 * Add new open_count field to check_email_log table = will check email is opened count by user
550 * @since 1.0.12
551 * */
552 public function add_open_count_field(){
553 global $wpdb;
554 $table_name = $this->get_log_table_name();
555
556 // Field to check
557 $field_name = 'open_count';
558
559 // Query to check if the field exists in the table
560 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
561 $field_exists = $wpdb->get_results(
562 $wpdb->prepare(
563 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
564 "SHOW COLUMNS FROM $table_name LIKE %s",
565 $field_name
566 )
567 );
568
569 if(empty($field_exists)){
570 $query = "ALTER TABLE $table_name ADD open_tracking_id TEXT NULL DEFAULT NULL, ADD open_count TEXT NULL DEFAULT NULL AFTER message";
571 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
572 $wpdb->query($query);
573 }
574 }
575
576 public function fetch_log_count_by_status( $request, $per_page, $current_page_no,$status='all' ) {
577 global $wpdb;
578 $table_name = $this->get_log_table_name();
579
580
581 $count_query = 'SELECT count(*) FROM ' . $table_name;
582 $query_cond = '';
583
584 if ( isset( $request['s'] ) && is_string( $request['s'] ) && $request['s'] !== '' ) {
585 $search_term = trim( esc_sql( $request['s'] ) );
586
587 if ( Util\wp_chill_check_email_advanced_search_term( $search_term ) ) {
588 $predicates = Util\wp_chill_check_email_get_advanced_search_term_predicates( $search_term );
589
590 foreach ( $predicates as $column => $email ) {
591 switch ( $column ) {
592 case 'id':
593 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
594 $query_cond .= "id = '$email'";
595 break;
596 case 'to':
597 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
598 $query_cond .= "to_email LIKE '%$email%'";
599 break;
600 case 'email':
601 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
602 $query_cond .= ' ( '; /* Begin 1st */
603 $query_cond .= " ( to_email LIKE '%$email%' OR subject LIKE '%$email%' ) "; /* Begin 2nd & End 2nd */
604 $query_cond .= ' OR ';
605 $query_cond .= ' ( '; /* Begin 3rd */
606 $query_cond .= "headers <> ''";
607 $query_cond .= ' AND ';
608 $query_cond .= ' ( '; /* Begin 4th */
609 $query_cond .= "headers REGEXP '[F|f]rom:.*$email' OR ";
610 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' OR ";
611 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' OR ";
612 $query_cond .= "headers REGEXP '[R|r]eply-[T|t]o:.*$email'";
613 $query_cond .= ' ) '; /* End 4th */
614 $query_cond .= ' ) '; /* End 3rd */
615 $query_cond .= ' ) '; /* End 1st */
616 break;
617 case 'cc':
618 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
619 $query_cond .= ' ( '; /* Begin 1st */
620 $query_cond .= "headers <> ''";
621 $query_cond .= ' AND ';
622 $query_cond .= ' ( '; /* Begin 2nd */
623 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' ";
624 $query_cond .= ' ) '; /* End 2nd */
625 $query_cond .= ' ) '; /* End 1st */
626 break;
627 case 'bcc':
628 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
629 $query_cond .= ' ( '; /* Begin 1st */
630 $query_cond .= "headers <> ''";
631 $query_cond .= ' AND ';
632 $query_cond .= ' ( '; /* Begin 2nd */
633 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' ";
634 $query_cond .= ' ) '; /* End 2nd */
635 $query_cond .= ' ) '; /* End 1st */
636 break;
637 case 'reply-to':
638 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
639 $query_cond .= ' ( '; /* Begin 1st */
640 $query_cond .= "headers <> ''";
641 $query_cond .= ' AND ';
642 $query_cond .= ' ( '; /* Begin 2nd */
643 $query_cond .= "headers REGEXP '[R|r]eply-to:.*$email' ";
644 $query_cond .= ' ) '; /* End 2nd */
645 $query_cond .= ' ) '; /* End 1st */
646 break;
647 }
648 }
649 } else {
650 $query_cond .= " WHERE ( to_email LIKE '%$search_term%' OR subject LIKE '%$search_term%' ) ";
651 }
652 }
653
654 if ( isset( $request['d'] ) && $request['d'] !== '' ) {
655 $search_date = trim( esc_sql( $request['d'] ) );
656 if ( '' === $query_cond ) {
657 $query_cond .= " WHERE sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
658 } else {
659 $query_cond .= " AND sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
660 }
661 }
662 if ( !empty($status) ) {
663 $status = trim( esc_sql( $status ) );
664 if ($status != 'all') {
665 if ( empty($request['d']) && empty($request['s']) ) {
666 $query_cond .= " WHERE ";
667 }else{
668 $query_cond .= " AND ";
669 }
670 }
671
672 // print_r($query_cond);die;
673
674 switch( $status ) {
675 case 'failed':
676 $query_cond .= " `result` = 0";
677 break;
678 case 'complete':
679 $query_cond .= " `result` != 0";
680 break;
681 default:
682 break;
683 }
684 }
685
686 // Ordering parameters.
687 $orderby = ! empty( $request['orderby'] ) ? sanitize_sql_orderby( $request['orderby'] ) : 'sent_date';
688 if ( isset( $request['order'] ) ) {
689 $order = in_array( strtoupper($request['order']), array( 'DESC', 'ASC' ) ) ? esc_sql( $request['order'] ) : 'DESC';
690 }else{
691 $order = 'DESC';
692 }
693
694 if ( ! empty( $orderby ) & ! empty( $order ) ) {
695 $query_cond .= ' ORDER BY ' . $orderby . ' ' . $order;
696 }
697
698 // Find total number of items.
699 $count_query = $count_query . $query_cond;
700 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason using critical conditions in query
701 $total_items = $wpdb->get_var( $count_query );
702 return $total_items;
703 }
704
705 public function delete_log_older_than($timeInterval = null)
706 {
707 if ( ! current_user_can( 'manage_check_email' ) ) {
708 return;
709 }
710 global $wpdb;
711 $table_name = $this->get_log_table_name();
712 $option = get_option( 'check-email-log-core' );
713 if (isset($option['is_retention_amount_enable']) && isset($option['retention_amount']) && $option['is_retention_amount_enable']) {
714 $limit= intval($option['retention_amount']);
715 if(!empty($limit)){
716 $count_query = 'SELECT count(*) FROM ' . $table_name;
717 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
718 $total_items = $wpdb->get_var( $count_query );
719 if ($total_items > $limit) {
720 $data_to_delete = $total_items - $limit;
721 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
722 $old_posts = $wpdb->get_col( $wpdb->prepare(
723 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
724 "SELECT ID FROM $table_name
725 ORDER BY ID ASC
726 LIMIT %d",$data_to_delete) );
727
728 // Delete the logs
729 foreach ($old_posts as $column_value) {
730 $sql = $wpdb->prepare(
731 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
732 "DELETE FROM $table_name WHERE ID = %d",
733 $column_value
734 );
735 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
736 $wpdb->query($sql);
737 }
738 }
739
740 }
741 }
742 if (isset($option['is_retention_period_enable']) && $option['is_retention_period_enable']) {
743
744 if ($option['log_retention_period'] == 'custom_in_days') {
745 $custom_in_days = empty($option['log_retention_period_in_days']) ? 1 : intval($option['log_retention_period_in_days']);
746 $time_interval = strtotime('+' . $custom_in_days. ' days');
747 }else{
748 $periods = array( '1_day' =>86400,
749 '1_week' =>604800,
750 '1_month' =>2419200,
751 '6_month' =>15780000,
752 '1_year' =>31560000
753 );
754 $time_interval = $periods[$option['log_retention_period']];
755 }
756 $timestamp = time() - $time_interval;
757
758 $sql = "DELETE FROM " . $table_name . " WHERE Unix_timestamp(sent_date) <= %d";
759 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
760 $sql = $wpdb->prepare($sql, $timestamp);
761 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
762 $wpdb->query($sql);
763 }
764 }
765
766 function ck_mail_cron_schedule() {
767 if (!wp_next_scheduled('check_mail_cron_hook')) {
768 wp_schedule_event(time(), 'daily', 'check_mail_cron_hook');
769 }
770 }
771
772 function ck_mail_cron_execute() {
773 $this->delete_log_older_than();
774 // error_log('Cron job executed at' . gmdate('Y-m-d H:i:s'));
775 }
776
777 public function fetch_error_tracker_items( $request, $per_page, $current_page_no ) {
778 global $wpdb;
779 $table_name = $this->get_error_tracker_table_name();
780
781 $query = 'SELECT * FROM ' . $table_name;
782 $count_query = 'SELECT count(*) FROM ' . $table_name;
783 $query_cond = '';
784
785 if ( isset( $request['d'] ) && $request['d'] !== '' ) {
786 $search_date = trim( esc_sql( $request['d'] ) );
787 if ( '' === $query_cond ) {
788 $query_cond .= " WHERE created_at BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
789 } else {
790 $query_cond .= " AND created_at BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
791 }
792 }
793 if ( isset( $request['status'] ) && $request['status'] !== '' ) {
794 $status = trim( esc_sql( $request['status'] ) );
795 switch( $status ) {
796 case 'failed':
797 $query_cond .= " WHERE `event_type` IS NULL OR `event_type` = ''";
798 break;
799 case 'complete':
800 $query_cond .= " WHERE `event_type` IS NOT NULL AND `event_type` != ''";
801 break;
802 default:
803 break;
804 }
805 }
806
807 // Ordering parameters.
808 $orderby = ! empty( $request['orderby'] ) ? sanitize_sql_orderby( $request['orderby'] ) : 'created_at';
809 if ( isset( $request['order'] ) ) {
810 $order = in_array( strtoupper($request['order']), array( 'DESC', 'ASC' ) ) ? esc_sql( $request['order'] ) : 'DESC';
811 }else{
812 $order = 'DESC';
813 }
814
815
816 if ( ! empty( $orderby ) & ! empty( $order ) ) {
817 $query_cond .= ' ORDER BY ' . $orderby . ' ' . $order;
818 }
819
820 // Find total number of items.
821 $count_query = $count_query . $query_cond;
822 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
823 $total_items = $wpdb->get_var( $count_query );
824
825 // Adjust the query to take pagination into account.
826 if ( ! empty( $current_page_no ) && ! empty( $per_page ) ) {
827 $offset = ( $current_page_no - 1 ) * $per_page;
828 $query_cond .= ' LIMIT ' . (int) $offset . ',' . (int) $per_page;
829 }
830
831 // Fetch the items.
832 $query = $query . $query_cond;
833 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Due to critical query not used prepare $table_name
834 $items = $wpdb->get_results( $query );
835
836 return array( $items, $total_items );
837 }
838
839 public function fetch_error_tracker_items_by_id( $ids = array(), $additional_args = array() ) {
840 global $wpdb;
841 $table_name = $this->get_error_tracker_table_name();
842
843 $query = "SELECT * FROM {$table_name}";
844
845 $date_column_format_key = 'date_column_format';
846 if ( array_key_exists( $date_column_format_key, $additional_args ) && ! empty( $additional_args[ $date_column_format_key ] ) ) {
847 $query = "SELECT DATE_FORMAT(created_at, \"{$additional_args[ $date_column_format_key ]}\") as sent_date_custom, el.* FROM {$table_name} as el";
848 }
849
850 if ( ! empty( $ids ) ) {
851 $ids = array_map( 'absint', $ids );
852
853 // Can't use wpdb->prepare for the below query.
854 $ids_list = esc_sql( implode( ',', $ids ) );
855
856 $query .= " where id IN ( {$ids_list} )";
857 }
858
859 return $wpdb->get_results( $query, 'ARRAY_A' ); //@codingStandardsIgnoreLine
860 }
861 }
862