This commit is contained in:
2026-07-02 15:54:39 -06:00
commit 9883323161
17470 changed files with 4470592 additions and 0 deletions
@@ -0,0 +1,293 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models;
use Gravity_Forms\Gravity_SMTP\Gravity_SMTP;
use Gravity_Forms\Gravity_SMTP\Logging\Debug\Debug_Logger;
use Gravity_Forms\Gravity_SMTP\Logging\Logging_Service_Provider;
use Gravity_Forms\Gravity_Tools\Logging\DB_Logging_Provider;
use Gravity_Forms\Gravity_Tools\Logging\Log_Line;
class Debug_Log_Model {
protected $table_name = 'gravitysmtp_debug_log';
public function get_table_name() {
global $wpdb;
return $wpdb->prefix . $this->table_name;
}
public function create( $line, $priority ) {
global $wpdb;
if ( is_numeric( $priority ) ) {
$priority = $this->map_priority_number_to_string( $priority );
}
$wpdb->insert(
$this->get_table_name(),
array(
'line' => $line,
'priority' => $priority,
'date_created' => current_time( 'mysql', true ),
'date_updated' => current_time( 'mysql', true ),
)
);
return $wpdb->insert_id;
}
private function map_priority_number_to_string( $number ) {
$map = array(
DB_Logging_Provider::DEBUG => 'debug',
DB_Logging_Provider::INFO => 'info',
DB_Logging_Provider::WARN => 'warning',
DB_Logging_Provider::ERROR => 'error',
DB_Logging_Provider::FATAL => 'fatal',
);
return $map[ $number ];
}
public function all() {
global $wpdb;
$sql = 'SELECT * FROM %1$s ORDER BY %2$s DESC, %3$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), 'date_updated', 'id' ), ARRAY_A );
return $this->hydrate( $results );
}
public function delete_all() {
$this->clear();
}
public function clear() {
global $wpdb;
$sql = 'TRUNCATE %1$s;';
$wpdb->query( $wpdb->prepare( $sql, $this->get_table_name() ), ARRAY_A );
}
public function slice( $count, $offset ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = "SELECT * FROM $table_name LIMIT %d, %d;";
$results = $wpdb->get_results( $wpdb->prepare( $sql, $offset, $count ), ARRAY_A );
return $this->hydrate( $results );
}
public function count( $search_term = null, $search_type = null, $priority = null ) {
global $wpdb;
$table_name = $this->get_table_name();
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause = $wpdb->prepare(
"WHERE `line` LIKE '%%%s%%'",
$search_term
);
}
$priority_clause = null;
if ( ! empty( $priority ) ) {
$priority_clause = $wpdb->prepare( "`priority` = %s", $priority );
if ( ! empty( $search_term ) ) {
$priority_clause = ' AND ' . $priority_clause;
} else {
$priority_clause = 'WHERE ' . $priority_clause;
}
}
$sql = "SELECT COUNT(1) as 'count' FROM $table_name $search_clause $priority_clause;";
$results = $wpdb->get_row( $sql, ARRAY_A );
return $results['count'];
}
public function paginate( $page, $per_page, $max_date = false, $search_term = null, $search_type = null, $priority = null ) {
global $wpdb;
$table_name = $this->get_table_name();
$offset = ( $page - 1 ) * $per_page;
if ( ! $max_date ) {
$max_date = current_time( 'mysql', true );
}
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause = $wpdb->prepare(
"`line` LIKE '%%%s%%' AND",
$search_term
);
}
$priority_clause = null;
if ( ! empty( $priority ) ) {
$priority_clause = $wpdb->prepare( "`priority` = %s AND", $priority );
}
$prepared_sql = $wpdb->prepare(
"SELECT * FROM $table_name WHERE $search_clause $priority_clause `date_created` <= %s ORDER BY `date_created` DESC, `id` DESC LIMIT %d, %d",
$max_date,
$offset,
$per_page
);
$results = $wpdb->get_results( $prepared_sql, ARRAY_A );
return $this->hydrate( $results );
}
public function lines_as_data_grid( $lines ) {
$return = array();
$status_map = array(
'fatal' => array(
'label' => esc_html__( 'Fatal', 'gravitysmtp' ),
'status' => 'error',
),
'error' => array(
'label' => esc_html__( 'Error', 'gravitysmtp' ),
'status' => 'error',
),
'warning' => array(
'label' => esc_html__( 'Warning', 'gravitysmtp' ),
'status' => 'warning',
),
'debug' => array(
'label' => esc_html__( 'Debug', 'gravitysmtp' ),
'status' => 'active',
),
'info' => array(
'label' => esc_html__( 'Info', 'gravitysmtp' ),
'status' => 'gray',
),
);
foreach ( $lines as $line ) {
$priority = $line->priority();
$status = isset( $status_map[ $priority ] ) ? $status_map[ $priority ]['status'] : '';
$label = isset( $status_map[ $priority ] ) ? $status_map[ $priority ]['label'] : '';
$return[] = array(
'id' => array(
'component' => 'Text',
'props' => array(
'content' => $line->id(),
'size' => 'text-xs',
'weight' => 'medium',
)
),
'status' => array(
'component' => 'StatusIndicator',
'props' => array(
'hasDot' => false,
'label' => $label,
'status' => $status,
),
),
'date' => array(
'component' => 'Text',
'props' => array(
'content' => $line->timestamp(),
'size' => 'text-sm',
),
),
'log' => array(
'component' => 'Button',
'props' => array(
'action' => 'view',
'customClasses' => array( 'gravitysmtp-tools-app__debug-log-table-subject' ),
'data' => array( 'id' => $line->id() ),
'disabled' => false,
'label' => str_replace( '&quot;', '"', $line->line() ),
'type' => 'unstyled',
),
),
'actions' => array(
'component' => 'Box',
'components' => array(
array(
'component' => 'Button',
'props' => array(
'action' => 'view',
'customClasses' => array( 'gravitysmtp-tools-app__debug-log-table-action' ),
'data' => array( 'id' => $line->id() ),
'disabled' => false,
'icon' => 'information-circle',
'iconPrefix' => 'gravity-component-icon',
'label' => 'View',
'size' => 'size-height-s',
'type' => 'icon-white',
),
),
),
),
);
}
return $return;
}
public function before( $date, $inclusive = true ) {
global $wpdb;
$comparator = $inclusive ? '<=' : '<';
$sql = 'SELECT * FROM %1$s WHERE `date_created` %2$s "%3$s" ORDER BY %4$s DESC, %5$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), $comparator, $date, 'date_updated', 'id' ), ARRAY_A );
return $this->hydrate( $results );
}
public function after( $date, $inclusive = true ) {
global $wpdb;
$comparator = $inclusive ? '>=' : '>';
$sql = 'SELECT * FROM %1$s WHERE `date_created` %2$s "%3$s" ORDER BY %4$s DESC, %5$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), $comparator, $date, 'date_updated', 'id' ), ARRAY_A );
return $this->hydrate( $results );
}
public function between( $start, $end, $inclusive = true ) {
global $wpdb;
$a_comp = $inclusive ? '<=' : '<';
$b_comp = $inclusive ? '>=' : '>';
$sql = 'SELECT * FROM %1$s WHERE `date_created` %2$s "%3$s" AND `date_created` %4$s "%5$s" ORDER BY %6$s DESC, %7$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), $b_comp, $start, $a_comp, $end, 'date_updated', 'id' ), ARRAY_A );
return $this->hydrate( $results );
}
public function by_priority( $priority ) {
global $wpdb;
$sql = 'SELECT * FROM %1$s WHERE `priority` = %2$s ORDER BY %3$s DESC, %4$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), $priority, 'date_updated', 'id' ), ARRAY_A );
return $this->hydrate( $results );
}
protected function hydrate( $items ) {
return array_map( function( $item ) {
$parsed_date = get_date_from_gmt( $item['date_created'], 'Y-m-d H:i:s' );
return new Log_Line( $parsed_date, $item['priority'], $item['line'], $item['id'] );
}, $items );
}
}
@@ -0,0 +1,610 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models;
use Gravity_Forms\Gravity_SMTP\Connectors\Endpoints\Save_Plugin_Settings_Endpoint;
use Gravity_Forms\Gravity_SMTP\Data_Store\Data_Store_Router;
use Gravity_Forms\Gravity_SMTP\Models\Hydrators\Hydrator_Factory;
use Gravity_Forms\Gravity_SMTP\Models\Traits\Can_Compare_Dynamically;
use Gravity_Forms\Gravity_SMTP\Utils\Booliesh;
use Gravity_Forms\Gravity_SMTP\Utils\Recipient_Parser;
use Gravity_Forms\Gravity_SMTP\Utils\SQL_Filter_Parser;
class Event_Model {
use Can_Compare_Dynamically;
protected $table_name = 'gravitysmtp_events';
/**
* @var Hydrator_Factory $hydrator_factory
*/
protected $hydrator_factory;
/**
* @var Data_Store_Router
*/
protected $opts;
/**
* @var Recipient_Parser
*/
protected $recipient_parser;
/**
* The ID of the most-recently-created record.
*
* @var int
*/
protected $latest_id;
/**
* @var SQL_Filter_Parser
*/
protected $filter_parser;
protected $queryable = array(
'id',
'date_created',
'date_updated',
'service',
'subject',
'message',
'status',
);
protected $fillable = array(
'date_created',
'date_updated',
'service',
'subject',
'message',
'extra',
'status',
);
public function __construct( $hydrator_factory, $plugin_opts, $recipient_parser, $filter_parser ) {
$this->hydrator_factory = $hydrator_factory;
$this->opts = $plugin_opts;
$this->recipient_parser = $recipient_parser;
$this->filter_parser = $filter_parser;
}
protected function get_table_name() {
global $wpdb;
return $wpdb->prefix . $this->table_name;
}
public function get_latest_id() {
return $this->latest_id;
}
public function all() {
global $wpdb;
$sql = 'SELECT * FROM %1$s ORDER BY %2$s DESC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), 'date_updated' ), ARRAY_A );
return $this->hydrate( $results );
}
public function find( $where ) {
global $wpdb;
$post_hydrate_filters = array();
$table_name = $this->get_table_name();
$values = array();
$sql = "SELECT mt.* FROM $table_name AS mt WHERE ";
foreach ( $where as $condition ) {
if ( count( $condition ) === 3 ) {
$key = $condition[0];
$comparator = $condition[1];
$value = $condition[2];
} else {
$key = $condition[0];
$comparator = '=';
$value = $condition[1];
}
if ( ! in_array( $key, $this->queryable ) ) {
$post_hydrate_filters[] = array( 'key' => $key, 'value' => $value, 'comparator' => $comparator );
continue;
}
$key = sprintf( 'mt.%s', $key );
$sql .= sprintf( '%s %s %%s AND ', $key, $comparator );
$values[] = $value;
}
$sql = rtrim( $sql, ' AND ' ) . ';';
if ( strpos( $sql, '%s' ) !== false ) {
$sql = $wpdb->prepare( $sql, $values );
} else {
$sql = rtrim( $sql, ' WHERE;' ) . ';';
}
$results = $wpdb->get_results( $sql, ARRAY_A );
$hydrated = $this->hydrate( $results );
return array_filter( $hydrated, function ( $row ) use ( $post_hydrate_filters ) {
foreach ( $post_hydrate_filters as $ph_condition ) {
if ( ! isset( $row[ $ph_condition['key'] ] ) ) {
return false;
}
$value_a = $row[ $ph_condition['key'] ];
$value_b = $ph_condition['value'];
if ( ! $this->compare( $value_a, $value_b, $ph_condition['comparator'] ) ) {
return false;
}
}
return true;
} );
}
public function slice( $count, $offset = 0 ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = "SELECT * FROM $table_name LIMIT %d, %d;";
$results = $wpdb->get_results( $wpdb->prepare( $sql, $offset, $count ), ARRAY_A );
return $this->hydrate( $results );
}
public function count( $search_term = null, $search_type = null, $filters = array() ) {
global $wpdb;
$table_name = $this->get_table_name();
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause = $this->get_search_clause( $search_term, $search_type );
$search_clause = 'WHERE ' . preg_replace( '/ AND$/', '', $search_clause );
}
$filter_clause = null;
if ( ! empty( $filters ) ) {
$filter_clause = $this->filter_parser->process_filters( $filters );
if ( empty( $search_clause ) ) {
$filter_clause = 'WHERE ' . $filter_clause;
} else {
$filter_clause = ' AND ' . $filter_clause;
}
}
$sql = "SELECT COUNT(1) as 'count' FROM $table_name $search_clause $filter_clause;";
$results = $wpdb->get_row( $sql, ARRAY_A );
return $results['count'];
}
public function paginate( $page, $per_page, $max_date = false, $search_term = null, $search_type = null, $sort_by = null, $sort_order = null, $filters = array() ) {
global $wpdb;
$table_name = $this->get_table_name();
$offset = ( $page - 1 ) * $per_page;
if ( ! $max_date ) {
$max_date = current_time( 'mysql', true );
}
if ( empty( $sort_by ) ) {
$sort_by = 'date_created';
}
if ( empty( $sort_order ) ) {
$sort_order = 'DESC';
}
// Ensure sort column is one of the approved options.
$allowed_sort_columns = array( 'date_created', 'status', 'service', 'subject' );
$sort_by = in_array( $sort_by, $allowed_sort_columns ) ? $sort_by : 'date_created';
$allowed_directions = array( 'ASC', 'DESC' );
$sort_order = in_array( $sort_order, $allowed_directions ) ? $sort_order : 'DESC';
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause = $this->get_search_clause( $search_term, $search_type );
}
$filter_clause = null;
if ( ! empty( $filters ) ) {
$filter_clause = $this->filter_parser->process_filters( $filters, true );
}
$prepared_sql = $wpdb->prepare(
"SELECT mt.* FROM $table_name AS mt WHERE $search_clause $filter_clause `date_created` <= %s ORDER BY `$sort_by` $sort_order LIMIT %d, %d",
$max_date,
$offset,
$per_page
);
$results = $wpdb->get_results( $prepared_sql, ARRAY_A );
return $this->hydrate( $results );
}
private function get_search_clause( $search_term, $search_type ) {
global $wpdb;
$table_name = $this->get_table_name();
switch ( $search_type ) {
case 'email_and_headers':
$prepared_sql = $wpdb->prepare(
"`extra` LIKE '%%%s%%' AND",
$search_term
);
break;
case 'content':
$prepared_sql = $wpdb->prepare(
"`message` LIKE '%%%s%%' AND",
$search_term
);
break;
case 'subject':
$prepared_sql = $wpdb->prepare(
"`subject` LIKE '%%%s%%' AND",
$search_term
);
break;
default:
$prepared_sql = $wpdb->prepare(
"( `subject` LIKE '%%%s%%' OR `message` LIKE '%%%s%%' OR `extra` LIKE '%%%s%%' ) AND",
$search_term,
$search_term,
$search_term
);
}
return $prepared_sql;
}
public function create( $service, $status, $to, $from, $subject, $message, $extra ) {
if ( ! $this->is_logging_enabled() ) {
return 0;
}
if ( ! $this->save_email_body() ) {
$message = '';
$extra['message_omitted'] = true;
}
global $wpdb;
unset ( $extra['params']['body'] );
$extra['to'] = $to;
$extra['from'] = $from;
$wpdb->insert(
$this->get_table_name(),
array(
'date_created' => current_time( 'mysql', true ),
'date_updated' => current_time( 'mysql', true ),
'status' => $status,
'service' => $service,
'subject' => substr( $subject, 0, 95 ), // DB Column is varchar(100), trim with some buffer space for non-Latin chars.
'message' => $message,
'extra' => serialize( $extra ),
)
);
$created_id = $wpdb->insert_id;
$this->latest_id = $created_id;
do_action( 'gravitysmtp_after_mail_created', $created_id, compact( 'service', 'status', 'to', 'from', 'subject', 'message', 'extra' ) );
return $created_id;
}
public function get_records_over_limit( $limit ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT id FROM $table_name ORDER BY `date_created` DESC LIMIT %d, %d", $limit, PHP_INT_MAX );
$results = $wpdb->get_results( $sql, ARRAY_A );
return $results;
}
public function update( $values, $id ) {
// Don't do anything for 0 id.
if ( empty( $id ) ) {
return;
}
if ( isset( $values['extra'] ) && ! $this->save_email_body() ) {
unset( $values['message'] );
$extra = isset( $values['extra'] ) ? unserialize( $values['extra'] ) : array();
$extra['message_omitted'] = true;
$values['extra'] = serialize( $extra );
}
if ( isset( $values['subject'] ) ) {
$values['subject'] = substr( $values['subject'], 0, 95 ); // DB Column is varchar(100), trim with some buffer space for non-Latin chars
}
if ( isset( $values['message'] ) && strlen( $values['message'] ) > 64500 ) {
$values['message'] = substr( $values['message'], 0, 64500 ) . __( '...(original message truncated)', 'gravitysmtp' );
$extra = isset( $values['extra'] ) ? unserialize( $values['extra'] ) : array();
$extra['message_truncated'] = true;
$values['extra'] = serialize( $extra );
}
global $wpdb;
$self = $this;
$values = array_filter( $values, function ( $key ) use ( $self ) {
return in_array( $key, $self->fillable );
}, ARRAY_FILTER_USE_KEY );
$wpdb->update(
$this->get_table_name(),
$values,
array( 'id' => $id )
);
do_action( 'gravitysmtp_after_mail_updated', $id, $values );
}
public function delete( $id ) {
global $wpdb;
$wpdb->query( "SET FOREIGN_KEY_CHECKS = 0;" );
$wpdb->delete( $this->get_table_name(), array( 'id' => $id ) );
}
public function delete_before( $date ) {
global $wpdb;
$table_name = $this->get_table_name();
$query = $wpdb->prepare( "DELETE FROM $table_name WHERE `date_created` <= %s", get_gmt_from_date( $date ) );
$wpdb->query( "SET FOREIGN_KEY_CHECKS = 0;" );
$wpdb->query( $query );
}
public function delete_all() {
global $wpdb;
$table_name = $this->get_table_name();
$wpdb->query( "SET FOREIGN_KEY_CHECKS = 0;" );
$wpdb->query( "TRUNCATE TABLE $table_name" );
}
public function get_counts() {
global $wpdb;
$table_name = $this->get_table_name();
$sql = "SELECT service, COUNT(id) AS count FROM {$table_name} GROUP BY service";
$service_counts = $wpdb->get_results( $sql, ARRAY_A );
$sql = "SELECT status, COUNT(id) AS count FROM {$table_name} GROUP BY status";
$status_counts = $wpdb->get_results( $sql, ARRAY_A );
$total = array_sum( wp_list_pluck( $service_counts, 'count' ) );
return array(
'total' => $total,
'service' => $service_counts,
'status' => $status_counts,
);
}
protected function hydrate( $rows ) {
static $hydrators = array();
foreach ( $rows as $idx => $row ) {
$service = $row['service'];
if ( $service === 'amazon-ses' ) {
$service = 'amazon';
}
// Cleanup bad old data.
if ( $row['service'] === 'phpmail' ) {
$row['service'] = 'php';
}
$extra = strpos( $row['extra'], '{' ) === 0 ? json_decode( $row['extra'], true ) : unserialize( $row['extra'] );
try {
if ( isset( $hydrators[ $service ] ) ) {
$hydrator = $hydrators[ $service ];
} else {
$hydrator = $this->hydrator_factory->create( $service );
$hydrators[ $service ] = $hydrator;
}
} catch ( \Exception $e ) {
$hydrator = false;
}
$row['source'] = isset( $extra['source'] ) ? $extra['source'] : __( 'N/A', 'gravitysmtp' );
$row['email_counts'] = $this->get_email_counts( $extra );
$row['can_resend'] = empty( $extra['message_truncated'] ) && empty( $extra['message_omitted'] ) && ( empty( $extra['attachments'] ) || ( ! empty( $extra['attachments_saved'] ) ) );
if ( $hydrator ) {
$rows[ $idx ] = $hydrator->hydrate( $row );
} else {
$rows[ $idx ] = $row;
}
}
return $rows;
}
public function get( $id ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT * FROM $table_name WHERE id = %s", $id );
$email = $wpdb->get_row( $sql, ARRAY_A );
$hydrated = $this->hydrate( array( $email ) );
return $hydrated[0];
}
public function get_earliest_event_date() {
static $found;
if ( ! empty( $found ) ) {
return $found;
}
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT date_created FROM $table_name ORDER BY date_created ASC LIMIT %d, %d", 0, 1 );
$results = $wpdb->get_results( $sql, ARRAY_A );
if ( empty( $results ) ) {
return gmdate( 'Y-m-d 00:00:00', time() );
}
$found = get_date_from_gmt( $results[0]['date_created'] );
return gmdate( 'Y-m-d 00:00:00', strtotime( $found ) );
}
public function get_top_sending_sources( $start, $end ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT SUBSTRING_INDEX(
SUBSTRING_INDEX( SUBSTRING(extra, (INSTR(extra, CONCAT('source', '\";')) + CHAR_LENGTH('source') + 1)), '\"', 2),
'\"', -1) as source,
count(*) as total
FROM ( SELECT * FROM $table_name WHERE date_created >= %s AND date_created <= %s ORDER BY date_created DESC LIMIT 0, 5000 ) AS timeboxed
GROUP BY source
ORDER BY total DESC
LIMIT 0, 8", get_gmt_from_date( $start ), get_gmt_from_date( $end ) );
$results = $wpdb->get_results( $sql, ARRAY_A );
return $results;
}
public function get_all_sending_sources() {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT SUBSTRING_INDEX(
SUBSTRING_INDEX( SUBSTRING(extra, (INSTR(extra, CONCAT('source', '\";')) + CHAR_LENGTH('source') + 1)), '\"', 2),
'\"', -1) as source
FROM ( SELECT * FROM $table_name LIMIT 0, %d ) AS timeboxed
GROUP BY source", 5000 );
$results = $wpdb->get_results( $sql, ARRAY_A );
$sources = wp_list_pluck( $results, 'source' );
$filtered = array_filter( $sources, function ( $source ) {
if ( strpos( $source, ':[' ) !== false || strpos( $source, ':{' ) !== false ) {
return false;
}
if ( $source === 'headers' || $source === 'params' || $source === 'to' || $source === 'message_omitted' ) {
return false;
}
return true;
} );
return $filtered;
}
public function get_top_recipients( $start, $end ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT SUBSTRING_INDEX(
SUBSTRING_INDEX( SUBSTRING(extra, (INSTR(extra, CONCAT('email', '\";')) + CHAR_LENGTH('email') + 1)), '\"', 2),
'\"', -1) as recipients,
count(*) as total
FROM ( SELECT * FROM $table_name WHERE date_created >= %s AND date_created <= %s ORDER BY date_created DESC LIMIT 0, 5000 ) AS timeboxed
GROUP BY recipients
ORDER BY total DESC
LIMIT 0, 8", get_gmt_from_date( $start ), get_gmt_from_date( $end ) );
$results = $wpdb->get_results( $sql, ARRAY_A );
return $results;
}
public function get_event_stats( $start, $end ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT status, count( * ) AS total FROM ( SELECT * FROM $table_name WHERE date_created >= %s AND date_created <= %s AND status != 'pending' ORDER BY date_created DESC ) AS timeboxed GROUP BY status", get_gmt_from_date( $start ), get_gmt_from_date( $end ) );
$results = $wpdb->get_results( $sql, ARRAY_A );
$return = array(
'failed' => 0,
'sent' => 0,
);
// Map to key/value pair.
foreach ( $results as $result ) {
$return[ $result['status'] ] = (int) $result['total'];
}
return $return;
}
public function get_chart_data( $start, $end ) {
// switch ( $period ) {
// case 'day':
// default:
// $format = '%b %d';
// break;
// case 'month':
// $format = '%b %Y';
// break;
// case 'hour':
// $format = '%H:00 %b %d';
// break;
// }
//
global $wpdb;
$table_name = $this->get_table_name();
// $sql = $wpdb->prepare( "SELECT count(*) as total, DATE_FORMAT(date_created, %s) as date_created, date_created as sort_date, status FROM ( SELECT * FROM $table_name WHERE date_created >= %s AND date_created <= %s AND status != 'pending' ) AS timeboxed GROUP BY DATE_FORMAT(date_created, %s), status", $format, get_gmt_from_date( $start ), get_gmt_from_date( $end ), $format );
$sql = $wpdb->prepare( "SELECT date_created, status FROM $table_name WHERE date_created >= %s AND date_created <= %s AND status != 'pending'", get_gmt_from_date( $start ), get_gmt_from_date( $end ) );
$results = $wpdb->get_results( $sql, ARRAY_A );
return $results;
}
private function get_email_counts( $extra ) {
return $this->recipient_parser->get_email_counts( $extra );
}
private function is_logging_enabled() {
$logging_enabled = $this->opts->get_plugin_setting( Save_Plugin_Settings_Endpoint::PARAM_EVENT_LOG_ENABLED, 'true' );
return Booliesh::get( $logging_enabled );
}
private function save_email_body() {
$save_email_body = $this->opts->get_plugin_setting( Save_Plugin_Settings_Endpoint::PARAM_SAVE_EMAIL_BODY_ENABLED, 'true' );
return empty( $save_email_body ) ? true : $save_email_body !== 'false';
}
}
@@ -0,0 +1,263 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models;
use Gravity_Forms\Gravity_SMTP\Connectors\Connector_Service_Provider;
use Gravity_Forms\Gravity_SMTP\Connectors\Endpoints\Save_Plugin_Settings_Endpoint;
use Gravity_Forms\Gravity_SMTP\Data_Store\Plugin_Opts_Data_Store;
use Gravity_Forms\Gravity_SMTP\Enums\Status_Enum;
use Gravity_Forms\Gravity_SMTP\Gravity_SMTP;
use Gravity_Forms\Gravity_Tools\Utils\Utils_Service_Provider;
class Log_Details_Model {
protected $table_name = 'gravitysmtp_event_logs';
protected $events_table_name = 'gravitysmtp_events';
/**
* @var Plugin_Opts_Data_Store
*/
protected $opts;
public function __construct( $plugin_opts ) {
$this->opts = $plugin_opts;
}
protected function get_table_name() {
global $wpdb;
return $wpdb->prefix . $this->table_name;
}
protected function get_events_table_name() {
global $wpdb;
return $wpdb->prefix . $this->events_table_name;
}
public function create( $event_id, $action_name, $log_value ) {
if ( ! $this->is_logging_enabled() ) {
return 0;
}
global $wpdb;
$log_value = is_string( $log_value ) ? $log_value : json_encode( $log_value );
$wpdb->insert(
$this->get_table_name(),
array(
'event_id' => $event_id,
'action_name' => $action_name,
'log_value' => $log_value,
'date_created' => current_time( 'mysql', true ),
'date_updated' => current_time( 'mysql', true ),
)
);
return $wpdb->insert_id;
}
public function all() {
global $wpdb;
$sql = 'SELECT * FROM %1$s;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name() ), ARRAY_A );
return $results;
}
public function by_id( $id ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = "SELECT * FROM $table_name WHERE event_id = %d";
$results = $wpdb->get_results( $wpdb->prepare( $sql, $id ), ARRAY_A );
return $results;
}
public function delete( $id ) {
global $wpdb;
$wpdb->delete( $this->get_table_name(), array( 'id' => $id ) );
}
public function delete_by_event_id( $id ) {
global $wpdb;
$wpdb->delete( $this->get_table_name(), array( 'event_id' => $id ) );
}
public function delete_all() {
global $wpdb;
$table_name = $this->get_table_name();
$wpdb->query( "TRUNCATE TABLE $table_name" );
}
public function get_next_id( $current_id ) {
global $wpdb;
$table_name = $this->get_events_table_name();
$sql = "SELECT id FROM $table_name WHERE id > %d ORDER BY id ASC LIMIT 1";
$next_id = $wpdb->get_var( $wpdb->prepare( $sql, $current_id ) );
return $next_id !== null ? intval( $next_id ) : null;
}
public function get_prev_id( $current_id ) {
global $wpdb;
$table_name = $this->get_events_table_name();
$sql = "SELECT id FROM $table_name WHERE id < %d ORDER BY id DESC LIMIT 1";
$prev_id = $wpdb->get_var( $wpdb->prepare( $sql, $current_id ) );
return $prev_id !== null ? intval( $prev_id ) : null;
}
private function is_logging_enabled() {
$logging_enabled = $this->opts->get( Save_Plugin_Settings_Endpoint::PARAM_EVENT_LOG_ENABLED, 'config', 'true' );
if ( empty( $logging_enabled ) ) {
$logging_enabled = true;
} else {
$logging_enabled = $logging_enabled !== 'false';
}
return $logging_enabled;
}
public function full_details( $id ) {
$container = Gravity_SMTP::container();
$plugin_data_store = $container->get( Connector_Service_Provider::DATA_STORE_ROUTER );
$emails = $container->get( Connector_Service_Provider::EVENT_MODEL );
$data = $this->by_id( $id );
$email = $emails->find( array( array( 'id', '=', $id ) ) );
$log_rows = array();
if ( empty( $email[0] ) ) {
return array();
}
$row = $email[0];
$extra = strpos( $row['extra'], '{' ) === 0 ? json_decode( $row['extra'], true ) : unserialize( $row['extra'] );
foreach ( $data as $val ) {
$log_rows[] = $val['log_value'];
}
$map = $container->get( Connector_Service_Provider::NAME_MAP );
$parser = $container->get( Utils_Service_Provider::RECIPIENT_PARSER );
$params = isset( $extra['params'] ) ? $extra['params'] : array();
$to = isset( $extra['to'] ) ? $extra['to'] : '';
if ( empty( $to ) && ! empty( $extra['headers']['to'] ) ) {
$to = $extra['headers']['to'];
}
$to = $parser->parse( $to );
$to = $to->as_string( true );
$clean_from_email = $this->extract_email( $extra['from'] );
$cc = array();
$bcc = array();
if ( ! empty( $extra['headers']['cc'] ) ) {
// @var Recipient_Collection $cc_values
$cc_values = $extra['headers']['cc'];
foreach( $cc_values->as_array() as $cc_value ) {
$cc[] = $cc_value['email'];
}
}
if ( ! empty( $extra['headers']['bcc'] ) ) {
$bcc_values = $extra['headers']['bcc'];
foreach( $bcc_values->as_array() as $bcc_value ) {
$bcc[] = $bcc_value['email'];
}
}
unset ( $params['headers'] );
$details = array(
'date' => $this->convert_dates_to_timezone( $row['date_updated'] ),
'from' => $extra['from'],
'fromHash' => ! empty( $clean_from_email ) ? hash( 'sha256', strtolower( trim( $clean_from_email ) ) ) : '',
'to' => $to,
'subject' => $row['subject'],
'is_html' => $row['message'] !== strip_tags( $row['message'] ),
'technical_information' => array(
'log' => $log_rows,
'headers' => $params,
),
'status' => array(
'label' => ucfirst( $row['status'] ),
'status' => Status_Enum::indicator( $row['status'] ),
'hasDot' => false,
),
'service' => empty( $map[ $row['service'] ] ) ? $row['service'] : $map[ $row['service'] ],
'has_attachment' => isset( $extra['attachments'] ) && is_array( $extra['attachments'] ) ? count( $extra['attachments'] ) : 0,
'attachments' => isset( $extra['attachments'] ) ? $this->get_attachments( $extra['attachments'] ) : array(),
'log_id' => $row['id'],
'next_id' => $this->get_next_id( $row['id'] ),
'prev_id' => $this->get_prev_id( $row['id'] ),
'source' => isset( $row['source'] ) ? $row['source'] : __( 'N/A', 'gravitysmtp' ),
'can_resend' => $row['can_resend'],
);
if ( ! empty( $cc ) ) {
$details['cc'] = implode( ', ', $cc );
}
if ( ! empty( $bcc ) ) {
$details['bcc'] = implode( ', ', $bcc );
}
return $details;
}
private function extract_email( $string ) {
$regex = '/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}/';
preg_match( $regex, $string, $matches );
return $matches ? $matches[0] : null;
}
private function convert_dates_to_timezone( $date ) {
$gmt_time = new \DateTimeZone( 'UTC' );
$local_time = new \DateTimeZone( wp_timezone_string() );
$datetime = new \DateTime( $date, $gmt_time );
$datetime->setTimezone( $local_time );
return $datetime->format( 'F d, Y \a\t h:ia' );
}
private function get_attachments( $attachments ) {
if ( ! is_array( $attachments ) ) {
return array();
}
$uploads_dir = wp_upload_dir();
$attachments_arr = array();
$base_dir = $uploads_dir['basedir'];
$base_url = $uploads_dir['baseurl'];
foreach ( $attachments as $custom_name => $attachment ) {
$attachments_arr[] = array(
'file_name' => esc_html( is_numeric( $custom_name ) ? basename( $attachment ) : $custom_name ),
'file_path' => esc_html( str_replace( $base_dir, $base_url, $attachment ) ),
'file_extension' => esc_html( pathinfo( $attachment, PATHINFO_EXTENSION ) ),
);
}
return $attachments_arr;
}
}
@@ -0,0 +1,46 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models;
class Notifications_Model {
protected $table_name = 'gf_form_meta';
protected function get_table_name() {
global $wpdb;
return $wpdb->prefix . $this->table_name;
}
public function all() {
global $wpdb;
$sql = 'SELECT * FROM %1$s ORDER BY %2$s ASC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), 'form_id' ), ARRAY_A );
return $results;
}
public function slice( $count, $offset = 0 ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = "SELECT * FROM $table_name LIMIT %d, %d;";
$results = $wpdb->get_results( $wpdb->prepare( $sql, $offset, $count ), ARRAY_A );
return $results;
}
public function by_service( $service_name ) {
global $wpdb;
$like = sprintf( '%%service":"%1$s%%', esc_sql( $service_name ) );
$sql = 'SELECT * FROM %1$s WHERE %2$s LIKE \'%3$s\' ORDER BY %4$s ASC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), 'notifications', $like, 'form_id' ), ARRAY_A );
return $results;
}
}
@@ -0,0 +1,267 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models;
use Gravity_Forms\Gravity_SMTP\Enums\Suppression_Reason_Enum;
use Gravity_Forms\Gravity_SMTP\Users\Roles;
class Suppressed_Emails_Model {
protected $table_name = 'gravitysmtp_suppressed_emails';
protected $fillable = array(
'email',
'reason',
'notes',
);
protected function get_table_name() {
global $wpdb;
return $wpdb->prefix . $this->table_name;
}
public function suppress_email( $email, $reason, $notes = '' ) {
/**
* Allows third-parties to abort suppressing a given email based on the data.
*
* @since 1.5.1
*
* @param string $email
* @param string $reason
* @param string $notes
*
* @return boolean
*/
$skip = apply_filters( 'gravitysmtp_abort_email_suppression', false, $email, $reason, $notes );
if ( $skip ) {
return;
}
global $wpdb;
$table_name = $this->get_table_name();
$data = array(
'date_created' => current_time( 'mysql', true ),
'email' => $email,
'reason' => $reason,
'notes' => $notes,
);
$sql = $wpdb->prepare( "SELECT * FROM $table_name WHERE email = %s", $email );
$existing = $wpdb->get_results( $sql, ARRAY_A );
if ( ! empty( $existing ) ) {
$data = array(
'notes' => $notes,
);
$this->update( $email, array( 'notes' => $notes ) );
return $existing[0]['id'];
}
$wpdb->insert(
$table_name,
array(
'date_created' => current_time( 'mysql', true ),
'email' => $email,
'reason' => $reason,
'notes' => $notes,
)
);
$created_id = $wpdb->insert_id;
/**
* Allows third-parties to perform an action after an email is suppressed.
*
* @since 1.5.1
*
* @param string $email
* @param string $reason
* @param string $notes
*
* @return boolean
*/
do_action( 'gravitysmtp_after_email_suppressed', $created_id, $email, $reason, $notes );
return $created_id;
}
public function is_email_suppressed( $email ) {
global $wpdb;
$table_name = $this->get_table_name();
$sql = $wpdb->prepare( "SELECT * FROM $table_name WHERE email = %s", $email );
$results = $wpdb->get_results( $sql, ARRAY_A );
return ! empty( $results );
}
public function update( $email, $values ) {
global $wpdb;
$self = $this;
$values = array_filter( $values, function ( $key ) use ( $self ) {
return in_array( $key, $self->fillable );
}, ARRAY_FILTER_USE_KEY );
$wpdb->update(
$this->get_table_name(),
$values,
array( 'email' => $email )
);
}
public function reactivate_email( $email ) {
global $wpdb;
$wpdb->delete( $this->get_table_name(), array( 'email' => $email ) );
}
public function delete_all() {
global $wpdb;
$table_name = $this->get_table_name();
$wpdb->query( "TRUNCATE TABLE $table_name" );
}
public function all() {
global $wpdb;
$sql = 'SELECT * FROM %1$s ORDER BY %2$s ASC;';
$results = $wpdb->get_results( $wpdb->prepare( $sql, $this->get_table_name(), 'date_created' ), ARRAY_A );
return $results;
}
public function paginate( $page, $per_page, $search_term = null, $sort_by = null, $sort_order = null ) {
global $wpdb;
$table_name = $this->get_table_name();
$offset = ( $page - 1 ) * $per_page;
if ( empty( $sort_by ) ) {
$sort_by = 'date_created';
}
if ( empty( $sort_order ) ) {
$sort_order = 'DESC';
}
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause .= $wpdb->prepare( "WHERE email = %s", $search_term );
}
$prepared_sql = $wpdb->prepare(
"SELECT * FROM $table_name $search_clause ORDER BY `$sort_by` $sort_order LIMIT %d, %d",
$offset,
$per_page
);
$results = $wpdb->get_results( $prepared_sql, ARRAY_A );
return $results;
}
public function count( $search_term = null ) {
global $wpdb;
$table_name = $this->get_table_name();
$search_clause = null;
if ( ! empty( $search_term ) ) {
$search_clause = $wpdb->prepare( "WHERE MATCH(email,notes) AGAINST(%s IN NATURAL LANGUAGE MODE)", $search_term );
}
$sql = "SELECT COUNT(1) as 'count' FROM $table_name $search_clause;";
$results = $wpdb->get_row( $sql, ARRAY_A );
return $results['count'];
}
public function format_as_data_rows( $data ) {
$rows = array();
foreach ( $data as $row ) {
$grid_actions = $this->get_suppression_grid_actions( $row['id'] );
$row_data = array(
'id' => $row['id'],
'email' => array(
'component' => 'Text',
'props' => array(
'content' => $row['email'],
'size' => 'text-sm',
),
),
'reason' => array(
'component' => 'StatusIndicator',
'props' => array(
'label' => Suppression_Reason_Enum::label( $row['reason'] ),
'status' => Suppression_Reason_Enum::indicator( $row['reason'] ),
'hasDot' => false,
),
),
'date' => array(
'component' => 'Text',
'props' => array(
'content' => $this->convert_dates_to_timezone( $row['date_created'] ),
'size' => 'text-sm',
),
),
'notes' => array(
'component' => 'Text',
'props' => array(
'content' => $row['notes'],
'size' => 'text-sm',
),
),
'actions' => $grid_actions,
);
$rows[] = $row_data;
}
return $rows;
}
private function convert_dates_to_timezone( $date ) {
$gmt_time = new \DateTimeZone( 'UTC' );
$local_time = new \DateTimeZone( wp_timezone_string() );
$datetime = new \DateTime( $date, $gmt_time );
$datetime->setTimezone( $local_time );
return $datetime->format( 'F d, Y \a\t h:ia' );
}
private function get_suppression_grid_actions( $email_id ) {
$actions = array(
'component' => 'Box',
'components' => array(
array(
'component' => 'Button',
'props' => array(
'action' => 'reactivate',
'customAttributes' => array(
'title' => esc_html__( 'Reactivate', 'gravitysmtp' ),
),
'customClasses' => array( 'gravitysmtp-data-grid__action' ),
'icon' => 'reactivate',
'iconPrefix' => 'gravity-admin-icon',
'size' => 'size-height-s',
'type' => 'icon-white',
'data' => array(
'email_id' => $email_id,
),
),
),
),
);
return apply_filters( 'gravitysmtp_email_suppression_actions', $actions );
}
}
@@ -0,0 +1,13 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Amazon implements Hydrator {
public function hydrate( $row ) {
$row['service'] = 'amazon';
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Brevo implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,10 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Cloudflare implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,23 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Factory {
/**
* @param $type
*
* @return Hydrator
*/
public function create( $type ) {
$class_postfix = $type === 'wp_mail' ? 'WP_Mail' : ucfirst( $type );
$classname = sprintf( '%s\Hydrator_%s', __NAMESPACE__, $class_postfix );
if ( ! class_exists( $classname ) ) {
throw new \InvalidArgumentException( 'Hydrator type for type ' . $type . ' with class ' . $classname . ' does not exist.' );
}
return new $classname();
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Generic implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Google implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Mailgun implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Microsoft implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Phpmail implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Postmark implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_Sendgrid implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,11 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
class Hydrator_WP_Mail implements Hydrator {
public function hydrate( $row ) {
return $row;
}
}
@@ -0,0 +1,9 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Hydrators;
interface Hydrator {
public function hydrate( $row );
}
@@ -0,0 +1,25 @@
<?php
namespace Gravity_Forms\Gravity_SMTP\Models\Traits;
trait Can_Compare_Dynamically {
public function compare( $value_a, $value_b, $op ) {
switch( $op ) {
default:
case '=':
return $value_a == $value_b;
case '>':
return $value_a > $value_b;
case '>=':
return $value_a >= $value_b;
case '<':
return $value_a < $value_b;
case '<=':
return $value_a <= $value_b;
case '!=':
return $value_a != $value_b;
}
}
}