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