PluginProbe ʕ •ᴥ•ʔ
Check & Log Email – Easy Email Testing & Mail logging / 1.0.9
Check & Log Email – Easy Email Testing & Mail logging v1.0.9
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 2 years ago
Check_Email_Table_Manager.php
430 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
19 /* Database option name */
20 const DB_OPTION_NAME = 'check_email-log-db';
21
22 /* Database version */
23 const DB_VERSION = '0.3';
24
25 /**
26 * Setup hooks.
27 */
28 public function load() {
29 add_action( 'wpmu_new_blog', array( $this, 'create_table_for_new_blog' ) );
30
31 add_filter( 'wpmu_drop_tables', array( $this, 'delete_table_from_deleted_blog' ) );
32
33 // Do any DB upgrades.
34 $this->update_table_if_needed();
35 }
36
37 public function on_activate( $network_wide ) {
38 if ( is_multisite() && $network_wide ) {
39 // Note: if there are more than 10,000 blogs or
40 // if `wp_is_large_network` filter is set, then this may fail.
41 $sites = get_sites();
42
43 foreach ( $sites as $site ) {
44 switch_to_blog( $site->blog_id );
45 $this->create_table_if_needed();
46 restore_current_blog();
47 }
48 } else {
49 $this->create_table_if_needed();
50 }
51 }
52
53 /**
54 * Create email log table when a new blog is created.
55 */
56 public function create_table_for_new_blog( $blog_id ) {
57 if ( is_plugin_active_for_network( 'check-email-log/check-email.php' ) ) {
58 switch_to_blog( $blog_id );
59 $this->create_table_if_needed();
60 restore_current_blog();
61 }
62 }
63
64 /**
65 * Add email log table to the list of tables deleted when a blog is deleted.
66 */
67 public function delete_table_from_deleted_blog( $tables ) {
68 $tables[] = $this->get_log_table_name();
69
70 return $tables;
71 }
72
73 /**
74 * Get email log table name.
75 */
76 public function get_log_table_name() {
77 global $wpdb;
78
79 return $wpdb->prefix . self::LOG_TABLE_NAME;
80 }
81
82 public function insert_log( $data ) {
83 global $wpdb;
84
85 $table_name = $this->get_log_table_name();
86 $wpdb->insert( $table_name, $data );
87 }
88
89 public function delete_logs( $ids ) {
90 global $wpdb;
91
92 $table_name = $this->get_log_table_name();
93
94 $ids = esc_sql( $ids );
95
96 return $wpdb->query( "DELETE FROM {$table_name} where id IN ( {$ids} )" );
97 }
98
99 public function delete_all_logs() {
100 global $wpdb;
101
102 $table_name = $this->get_log_table_name();
103
104 return $wpdb->query( "DELETE FROM {$table_name}" );
105 }
106
107 public function delete_logs_older_than( $interval_in_days ) {
108 global $wpdb;
109 $table_name = $this->get_log_table_name();
110
111 $query = $wpdb->prepare( "DELETE FROM {$table_name} WHERE sent_date < DATE_SUB( CURDATE(), INTERVAL %d DAY )", $interval_in_days );
112 $deleted_rows_count = $wpdb->query( $query );
113
114 return $deleted_rows_count;
115 }
116
117 public function fetch_log_items_by_id( $ids = array(), $additional_args = array() ) {
118 global $wpdb;
119 $table_name = $this->get_log_table_name();
120
121 $query = "SELECT * FROM {$table_name}";
122
123 $date_column_format_key = 'date_column_format';
124 if ( array_key_exists( $date_column_format_key, $additional_args ) && ! empty( $additional_args[ $date_column_format_key ] ) ) {
125 $query = "SELECT DATE_FORMAT(sent_date, \"{$additional_args[ $date_column_format_key ]}\") as sent_date_custom, el.* FROM {$table_name} as el";
126 }
127
128 if ( ! empty( $ids ) ) {
129 $ids = array_map( 'absint', $ids );
130
131 // Can't use wpdb->prepare for the below query.
132 $ids_list = esc_sql( implode( ',', $ids ) );
133
134 $query .= " where id IN ( {$ids_list} )";
135 }
136
137 return $wpdb->get_results( $query, 'ARRAY_A' ); //@codingStandardsIgnoreLine
138 }
139
140 public function fetch_log_items( $request, $per_page, $current_page_no ) {
141 global $wpdb;
142 $table_name = $this->get_log_table_name();
143
144 $query = 'SELECT * FROM ' . $table_name;
145 $count_query = 'SELECT count(*) FROM ' . $table_name;
146 $query_cond = '';
147
148 if ( isset( $request['s'] ) && is_string( $request['s'] ) && $request['s'] !== '' ) {
149 $search_term = trim( esc_sql( $request['s'] ) );
150
151 if ( Util\wp_chill_check_email_advanced_search_term( $search_term ) ) {
152 $predicates = Util\wp_chill_check_email_get_advanced_search_term_predicates( $search_term );
153
154 foreach ( $predicates as $column => $email ) {
155 switch ( $column ) {
156 case 'id':
157 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
158 $query_cond .= "id = '$email'";
159 break;
160 case 'to':
161 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
162 $query_cond .= "to_email LIKE '%$email%'";
163 break;
164 case 'email':
165 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
166 $query_cond .= ' ( '; /* Begin 1st */
167 $query_cond .= " ( to_email LIKE '%$email%' OR subject LIKE '%$email%' ) "; /* Begin 2nd & End 2nd */
168 $query_cond .= ' OR ';
169 $query_cond .= ' ( '; /* Begin 3rd */
170 $query_cond .= "headers <> ''";
171 $query_cond .= ' AND ';
172 $query_cond .= ' ( '; /* Begin 4th */
173 $query_cond .= "headers REGEXP '[F|f]rom:.*$email' OR ";
174 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' OR ";
175 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' OR ";
176 $query_cond .= "headers REGEXP '[R|r]eply-[T|t]o:.*$email'";
177 $query_cond .= ' ) '; /* End 4th */
178 $query_cond .= ' ) '; /* End 3rd */
179 $query_cond .= ' ) '; /* End 1st */
180 break;
181 case 'cc':
182 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
183 $query_cond .= ' ( '; /* Begin 1st */
184 $query_cond .= "headers <> ''";
185 $query_cond .= ' AND ';
186 $query_cond .= ' ( '; /* Begin 2nd */
187 $query_cond .= "headers REGEXP '[CC|Cc|cc]:.*$email' ";
188 $query_cond .= ' ) '; /* End 2nd */
189 $query_cond .= ' ) '; /* End 1st */
190 break;
191 case 'bcc':
192 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
193 $query_cond .= ' ( '; /* Begin 1st */
194 $query_cond .= "headers <> ''";
195 $query_cond .= ' AND ';
196 $query_cond .= ' ( '; /* Begin 2nd */
197 $query_cond .= "headers REGEXP '[BCC|Bcc|bcc]:.*$email' ";
198 $query_cond .= ' ) '; /* End 2nd */
199 $query_cond .= ' ) '; /* End 1st */
200 break;
201 case 'reply-to':
202 $query_cond .= empty( $query_cond ) ? ' WHERE ' : ' AND ';
203 $query_cond .= ' ( '; /* Begin 1st */
204 $query_cond .= "headers <> ''";
205 $query_cond .= ' AND ';
206 $query_cond .= ' ( '; /* Begin 2nd */
207 $query_cond .= "headers REGEXP '[R|r]eply-to:.*$email' ";
208 $query_cond .= ' ) '; /* End 2nd */
209 $query_cond .= ' ) '; /* End 1st */
210 break;
211 }
212 }
213 } else {
214 $query_cond .= " WHERE ( to_email LIKE '%$search_term%' OR subject LIKE '%$search_term%' ) ";
215 }
216 }
217
218 if ( isset( $request['d'] ) && $request['d'] !== '' ) {
219 $search_date = trim( esc_sql( $request['d'] ) );
220 if ( '' === $query_cond ) {
221 $query_cond .= " WHERE sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
222 } else {
223 $query_cond .= " AND sent_date BETWEEN '$search_date 00:00:00' AND '$search_date 23:59:59' ";
224 }
225 }
226
227 // Ordering parameters.
228 $orderby = ! empty( $request['orderby'] ) ? sanitize_sql_orderby( $request['orderby'] ) : 'sent_date';
229 if ( isset( $request['order'] ) ) {
230 $order = in_array( strtoupper($request['order']), array( 'DESC', 'ASC' ) ) ? esc_sql( $request['order'] ) : 'DESC';
231 }else{
232 $order = 'DESC';
233 }
234
235
236 if ( ! empty( $orderby ) & ! empty( $order ) ) {
237 $query_cond .= ' ORDER BY ' . $orderby . ' ' . $order;
238 }
239
240 // Find total number of items.
241 $count_query = $count_query . $query_cond;
242 $total_items = $wpdb->get_var( $count_query );
243
244 // Adjust the query to take pagination into account.
245 if ( ! empty( $current_page_no ) && ! empty( $per_page ) ) {
246 $offset = ( $current_page_no - 1 ) * $per_page;
247 $query_cond .= ' LIMIT ' . (int) $offset . ',' . (int) $per_page;
248 }
249
250 // Fetch the items.
251 $query = $query . $query_cond;
252 $items = $wpdb->get_results( $query );
253
254 return array( $items, $total_items );
255 }
256
257 public function create_table_if_needed() {
258 global $wpdb;
259
260 $table_name = $this->get_log_table_name();
261
262 if ( $wpdb->get_var( "show tables like '{$table_name}'" ) != $table_name ) {
263
264 $sql = $this->get_create_table_query();
265
266 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
267 dbDelta( $sql );
268
269 add_option( self::DB_OPTION_NAME, self::DB_VERSION );
270 }
271 }
272
273 public function get_logs_count() {
274 global $wpdb;
275
276 $query = 'SELECT count(*) FROM ' . $this->get_log_table_name();
277
278 return $wpdb->get_var( $query );
279 }
280
281 public function fetch_log_id_by_data( $data ) {
282 if ( empty( $data ) || ! is_array( $data ) ) {
283 return 0;
284 }
285
286 global $wpdb;
287 $table_name = $this->get_log_table_name();
288
289 $query = "SELECT ID FROM {$table_name}";
290 $query_cond = '';
291 $where = array();
292
293 // Execute the following `if` conditions only when $data is array.
294 if ( array_key_exists( 'to', $data ) ) {
295 // Since the value is stored as CSV in DB, convert the values from error data to CSV to compare.
296 $to_email = Util\wp_chill_check_email_stringify( $data['to'] );
297
298 $to_email = trim( esc_sql( $to_email ) );
299 $where[] = "to_email = '$to_email'";
300 }
301
302 if ( array_key_exists( 'subject', $data ) ) {
303 $subject = trim( esc_sql( $data['subject'] ) );
304 $where[] = "subject = '$subject'";
305 }
306
307 if ( array_key_exists( 'attachments', $data ) ) {
308 if ( is_array( $data['attachments'] ) ) {
309 $attachments = count( $data['attachments'] ) > 0 ? 'true' : 'false';
310 } else {
311 $attachments = empty( $data['attachments'] ) ? 'false' : 'true';
312 }
313 $attachments = trim( esc_sql( $attachments ) );
314 $where[] = "attachments = '$attachments'";
315 }
316
317 foreach ( $where as $index => $value ) {
318 $query_cond .= 0 === $index ? ' WHERE ' : ' AND ';
319 $query_cond .= $value;
320 }
321
322 // Get only the latest logged item when multiple rows match.
323 $query_cond .= ' ORDER BY id DESC LIMIT 1';
324
325 $query = $query . $query_cond;
326
327 return absint( $wpdb->get_var( $query ) );
328 }
329
330 public function mark_log_as_failed( $log_item_id, $message ) {
331 global $wpdb;
332 $table_name = $this->get_log_table_name();
333
334 $wpdb->update(
335 $table_name,
336 array(
337 'result' => '0',
338 'error_message' => $message,
339 ),
340 array( 'ID' => $log_item_id ),
341 array(
342 '%d', // `result` format.
343 '%s', // `error_message` format.
344 ),
345 array(
346 '%d', // `ID` format.
347 )
348 );
349 }
350
351 private function update_table_if_needed() {
352 if ( get_option( self::DB_OPTION_NAME, false ) === self::DB_VERSION ) {
353 return;
354 }
355
356 $sql = $this->get_create_table_query();
357
358 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
359 dbDelta( $sql );
360
361 update_option( self::DB_OPTION_NAME, self::DB_VERSION );
362 }
363
364 private function get_create_table_query() {
365 global $wpdb;
366 $table_name = $this->get_log_table_name();
367 $charset_collate = $wpdb->get_charset_collate();
368
369 $sql = 'CREATE TABLE ' . $table_name . ' (
370 id mediumint(9) NOT NULL AUTO_INCREMENT,
371 to_email VARCHAR(500) NOT NULL,
372 subject VARCHAR(500) NOT NULL,
373 message TEXT NOT NULL,
374 headers TEXT NOT NULL,
375 attachments TEXT NOT NULL,
376 sent_date timestamp NOT NULL,
377 attachment_name VARCHAR(1000),
378 ip_address VARCHAR(15),
379 result TINYINT(1),
380 error_message VARCHAR(1000),
381 PRIMARY KEY (id)
382 ) ' . $charset_collate . ';';
383
384 return $sql;
385 }
386
387 private function validate_columns( $column ) {
388 return in_array( $column, array( 'to' ), true );
389 }
390
391 public function query_log_items_by_column( $columns ) {
392 if ( ! is_array( $columns ) ) {
393 return;
394 }
395
396 $columns_keys = array_keys( $columns );
397 if ( ! array_filter( $columns_keys, array( $this, 'validate_columns' ) ) ) {
398 return;
399 }
400
401 global $wpdb;
402
403 $table_name = $this->get_log_table_name();
404 $query = "SELECT id, sent_date, to_email, subject FROM {$table_name}";
405 $query_cond = '';
406 $where = array();
407
408 // Execute the following `if` conditions only when $data is array.
409 if ( array_key_exists( 'to', $columns ) ) {
410 // Since the value is stored as CSV in DB, convert the values from error data to CSV to compare.
411 $to_email = Util\wp_chill_check_email_stringify( $columns['to'] );
412
413 $to_email = trim( esc_sql( $to_email ) );
414 $where[] = "to_email = '$to_email'";
415
416 foreach ( $where as $index => $value ) {
417 $query_cond .= 0 === $index ? ' WHERE ' : ' AND ';
418 $query_cond .= $value;
419 }
420
421 // Get only the latest logged item when multiple rows match.
422 $query_cond .= ' ORDER BY id DESC';
423
424 $query = $query . $query_cond;
425
426 return $wpdb->get_results( $query );
427 }
428 }
429 }
430