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