PATH:
home
/
cf7x
/
public_html
/
wp-content_
/
plugins
/
email-validator
/
includes
<?php /** * Core service for importing and validating email records. */ use SMTPValidateEmail\Validator; if ( ! defined( 'ABSPATH' ) ) { exit; } class Email_Validator_Service { private const TABLE = 'all_emails'; private const LOG_MAX_LENGTH = 255; private const DEFAULT_IMPORT_VALUES = [ 'email' => '', 'first_name' => '', 'last_name' => '', 'status' => '', 'syn_date' => '1970-01-01', 'syn_status' => '', 'log' => '', 'brand' => '', ]; private static ?Email_Validator_Service $instance = null; private ?string $table_name = null; private ?string $sender_email = null; public static function instance(): Email_Validator_Service { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } private function __construct() {} public function import_csv( string $file_path ): array { $handle = fopen( $file_path, 'r' ); if ( ! $handle ) { return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0, 'skipped' => 0 ]; } $header = fgetcsv( $handle ); if ( ! $header ) { fclose( $handle ); return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0, 'skipped' => 0 ]; } $header_is_data = false; $header_map = $this->normalize_header( $header ); // Detect headerless CSV: if any header cell looks like an email OR we failed to map an email column. $mapped_has_email = in_array( 'email', $header_map, true ); foreach ( $header as $cell ) { if ( is_string( $cell ) && strpos( $cell, '@' ) !== false && is_email( trim( $cell ) ) ) { $header_is_data = true; break; } } if ( ! $mapped_has_email && $header_is_data ) { // Create a generic header map so indices exist; email will be auto-detected per row. $header_map = []; foreach ( $header as $index => $cell ) { $header_map[ $index ] = 'col_' . $index; // placeholder keys } } $stats = [ 'csv_total' => 0, // total rows in CSV 'processed' => 0, // valid, unique emails only 'inserted' => 0, 'updated' => 0, 'skipped' => 0, 'duplicates' => 0, // accurate duplicate count ]; $seen_emails = []; // If first line is actually data, process it first. if ( $header_is_data ) { $stats['csv_total']++; $record = $this->map_row_to_record( $header, $header_map ); $email = strtolower( trim( $record['email'] ?? '' ) ); if ( empty( $email ) || ! is_email( $email ) ) { $stats['skipped']++; } elseif ( isset( $seen_emails[ $email ] ) ) { $stats['duplicates']++; } else { $seen_emails[ $email ] = true; $stats['processed']++; $operation = $this->upsert_record( $record ); if ( 'insert' === $operation ) { $stats['inserted']++; } elseif ( 'update' === $operation ) { $stats['updated']++; $stats['duplicates']++; } else { $stats['skipped']++; } } } $batch = []; $batch_emails = []; $batch_size = 500; // tuneable while ( ( $row = fgetcsv( $handle ) ) !== false ) { $stats['csv_total']++; $record = $this->map_row_to_record( $row, $header_map ); $email = strtolower( trim( $record['email'] ?? '' ) ); if ( empty( $email ) || ! is_email( $email ) ) { $stats['skipped']++; continue; } if ( isset( $seen_emails[ $email ] ) ) { $stats['duplicates']++; continue; } $seen_emails[ $email ] = true; $stats['processed']++; $batch[] = $record; $batch_emails[] = $record['email']; if ( count( $batch ) >= $batch_size ) { $counts = $this->batch_upsert( $batch, $batch_emails ); $stats['inserted'] += $counts['inserted']; $stats['updated'] += $counts['updated']; $stats['duplicates'] += $counts['updated']; // count DB duplicates $batch = []; $batch_emails = []; } } if ( ! empty( $batch ) ) { $counts = $this->batch_upsert( $batch, $batch_emails ); $stats['inserted'] += $counts['inserted']; $stats['updated'] += $counts['updated']; $stats['duplicates'] += $counts['updated']; // count DB duplicates } fclose( $handle ); return $stats; } /** * Import a CSV in batches using persistent state in $state * $state fields mutated: line, initialized, header_map, header_is_data, processed, inserted, updated, total */ public function import_csv_batch( string $file_path, array &$state, int $batch_rows = 10000 ): array { if ( ! file_exists( $file_path ) ) { return [ 'done' => true ]; } if ( ! isset( $state['failed'] ) ) { $state['failed'] = 0; } if ( ! isset( $state['duplicates'] ) ) { $state['duplicates'] = isset( $state['updated'] ) ? (int) $state['updated'] : 0; } // Initialize header & detection once if ( empty( $state['initialized'] ) ) { $handle = fopen( $file_path, 'r' ); if ( ! $handle ) { return [ 'done' => true ]; } $header = fgetcsv( $handle ); fclose( $handle ); if ( ! $header ) { return [ 'done' => true ]; } $header_is_data = false; $header_map = $this->normalize_header( $header ); $mapped_has_email = in_array( 'email', $header_map, true ); foreach ( $header as $cell ) { if ( is_string( $cell ) && strpos( $cell, '@' ) !== false && is_email( trim( $cell ) ) ) { $header_is_data = true; break; } } if ( ! $mapped_has_email && $header_is_data ) { $header_map = []; foreach ( $header as $index => $cell ) { $header_map[ $index ] = 'col_' . $index; } } $state['initialized'] = true; $state['header_map'] = $header_map; $state['header_is_data'] = $header_is_data; $state['line'] = 1; // we've read header line // Count total lines in CSV for csv_total (only set once, never overwrite) if ( ! isset( $state['csv_total'] ) ) { try { $spl = new SplFileObject( $file_path ); $spl->seek( PHP_INT_MAX ); $lines = $spl->key() + 1; // Subtract 1 for header row $state['csv_total'] = ($lines > 0) ? $lines - 1 : 0; } catch ( Throwable $e ) { $state['csv_total'] = 0; } } // For legacy, also set total if ( empty( $state['total'] ) ) { $state['total'] = $state['csv_total']; } } $header_map = (array) $state['header_map']; $header_is_data = (bool) $state['header_is_data']; $line = (int) $state['line']; $handle = fopen( $file_path, 'r' ); if ( ! $handle ) { return [ 'done' => true ]; } // fast-forward to current line for ( $i = 0; $i < $line; $i++ ) { if ( feof( $handle ) ) { break; } fgets( $handle ); } $batch = []; $batch_emails = []; $row_count = 0; $failed_rows = 0; $seen_emails = isset($state['seen_emails']) ? $state['seen_emails'] : []; $duplicates = 0; // If header is actually data and we are at line 1, process header row as data first if ( $header_is_data && $line === 1 ) { // Re-read file to get first row rewind( $handle ); $first = fgetcsv( $handle ); $line++; if ( is_array( $first ) ) { $rec = $this->map_row_to_record( $first, $header_map ); $email = strtolower( trim( $rec['email'] ?? '' ) ); if ( ! empty( $email ) && is_email( $email ) ) { if ( isset( $seen_emails[ $email ] ) ) { $duplicates++; } else { $batch[] = $rec; $batch_emails[] = $rec['email']; $row_count++; $seen_emails[ $email ] = true; } } else { $failed_rows++; } } } while ( $row_count < $batch_rows && ( $row = fgetcsv( $handle ) ) !== false ) { $line++; $rec = $this->map_row_to_record( $row, $header_map ); $email = strtolower( trim( $rec['email'] ?? '' ) ); if ( empty( $email ) || ! is_email( $email ) ) { $failed_rows++; continue; } if ( isset( $seen_emails[ $email ] ) ) { $duplicates++; continue; } $batch[] = $rec; $batch_emails[] = $rec['email']; $row_count++; $seen_emails[ $email ] = true; } fclose( $handle ); if ( ! empty( $batch ) ) { $counts = $this->batch_upsert( $batch, $batch_emails ); $state['inserted'] = (int) $state['inserted'] + (int) $counts['inserted']; $state['updated'] = (int) $state['updated'] + (int) $counts['updated']; $state['duplicates'] = (int) $state['duplicates'] + (int) $counts['updated'] + $duplicates; $state['processed'] = (int) $state['processed'] + $row_count; } else { $state['duplicates'] = (int) $state['duplicates'] + $duplicates; } if ( $failed_rows > 0 ) { $state['failed'] = (int) $state['failed'] + $failed_rows; } $state['line'] = $line; $done = feof( fopen( $file_path, 'r' ) ) || ( $state['total'] && $state['line'] >= $state['total'] ); // Always return csv_total for UI return [ 'done' => $done, 'csv_total' => $state['csv_total'] ?? 0 ]; } public function run_validation( int $limit = 500 ): int { $records = $this->get_pending_records( $limit ); if ( empty( $records ) ) { return 0; } $updated = 0; foreach ( $records as $record ) { $result = $this->validate_email( $record->email ); $status = ( 'Valid Email' === $result ) ? 'active' : 'invalid'; $updated += (int) $this->update_record_status( (int) $record->id, $record->email, $status, $result ); } return $updated; } /** * Validate pending records and return detailed logs for runtime display. * * @param int $limit Max records to process. * @return array{processed:int,updated:int,items:array<int,array{id:int,email:string,result:string,status:string,updated:bool}>} */ public function validate_pending_with_logs( int $limit = 500 ): array { $records = $this->get_pending_records( $limit ); $items = []; $updated = 0; foreach ( $records as $record ) { $result = $this->validate_email( $record->email ); $status = ( 'Valid Email' === $result ) ? 'active' : 'invalid'; $did_save = $this->update_record_status( (int) $record->id, $record->email, $status, $result ); if ( $did_save ) { $updated++; } $items[] = [ 'id' => (int) $record->id, 'email' => (string) $record->email, 'result' => (string) $result, 'status' => (string) $status, 'updated' => (bool) $did_save, ]; } return [ 'processed' => count( $records ), 'updated' => $updated, ]; } private function normalize_header( array $header ): array { $map = []; foreach ( $header as $index => $column ) { $normalized = strtolower( trim( (string) $column ) ); $map[ $index ] = match ( $normalized ) { 'email address', 'mail', 'e-mail', 'e_mail' => 'email', 'firstname', 'first', 'first name' => 'first_name', 'lastname', 'last', 'last name' => 'last_name', 'sync date', 'send date' => 'syn_date', 'sync status' => 'syn_status', default => $normalized, }; } return $map; } private function map_row_to_record( array $row, array $header_map ): array { $record = self::DEFAULT_IMPORT_VALUES; $email_index = null; foreach ( $row as $index => $value ) { if ( ! isset( $header_map[ $index ] ) ) { continue; } $key = $header_map[ $index ]; $record[ $key ] = is_string( $value ) ? trim( $value ) : $value; } // Fallback: attempt to detect email if not mapped. if ( empty( $record['email'] ) ) { foreach ( $row as $idx => $candidate ) { if ( is_string( $candidate ) ) { $candidate_trim = trim( $candidate ); if ( strpos( $candidate_trim, '@' ) !== false && is_email( $candidate_trim ) ) { $record['email'] = $candidate_trim; $email_index = $idx; break; } } } } // If names are empty and we detected an email index, try to take next two columns as first/last name. if ( $email_index !== null ) { if ( empty( $record['first_name'] ) && isset( $row[ $email_index + 1 ] ) ) { $record['first_name'] = is_string( $row[ $email_index + 1 ] ) ? trim( (string) $row[ $email_index + 1 ] ) : ''; } if ( empty( $record['last_name'] ) && isset( $row[ $email_index + 2 ] ) ) { $record['last_name'] = is_string( $row[ $email_index + 2 ] ) ? trim( (string) $row[ $email_index + 2 ] ) : ''; } } // Optional: detect brand word if brand empty and a recognizable value appears. if ( empty( $record['brand'] ) ) { foreach ( $row as $candidate ) { if ( is_string( $candidate ) ) { $candidate_trim = trim( $candidate ); if ( preg_match( '/^(WP\s+EASY\s+PAY)$/i', $candidate_trim ) ) { $record['brand'] = 'WP EASY PAY'; break; } } } } if ( empty( $record['syn_date'] ) || ! $this->is_valid_date( $record['syn_date'] ) ) { $record['syn_date'] = current_time( 'Y-m-d' ); } foreach ( $record as $key => $value ) { if ( 'syn_date' === $key ) { continue; } if ( 'log' === $key ) { $record[ $key ] = sanitize_textarea_field( (string) $value ); } else { $record[ $key ] = sanitize_text_field( (string) $value ); } } return $record; } /** * Perform a fast batch upsert using a single INSERT ... ON DUPLICATE KEY UPDATE statement. * Stats are computed by prechecking existing emails for the batch. * * @param array $records List of associative arrays matching table columns. * @param array $batch_emails Parallel array of emails for lookup. * @return array{inserted:int,updated:int} */ private function batch_upsert( array $records, array $batch_emails ): array { global $wpdb; $table = $this->get_table_name(); // Check which emails already exist (for stats only). $placeholders = implode( ',', array_fill( 0, count( $batch_emails ), '%s' ) ); $existing = []; if ( ! empty( $batch_emails ) ) { $sql = "SELECT email FROM {$table} WHERE email IN ($placeholders)"; $existing = $wpdb->get_col( $wpdb->prepare( $sql, $batch_emails ) ); } $existing_map = array_fill_keys( (array) $existing, true ); $inserted = 0; $updated = 0; foreach ( $records as $rec ) { if ( ! empty( $existing_map[ $rec['email'] ] ) ) { $updated++; } else { $inserted++; } } // Build multi-row insert with ON DUPLICATE KEY UPDATE based on unique(email) $columns = [ 'email', 'first_name', 'last_name', 'status', 'syn_date', 'syn_status', 'log', 'brand' ]; $values_parts = []; $params = []; foreach ( $records as $rec ) { $values_parts[] = '( %s, %s, %s, %s, %s, %s, %s, %s )'; foreach ( $columns as $col ) { $params[] = (string) ( $rec[ $col ] ?? '' ); } } if ( empty( $values_parts ) ) { return [ 'inserted' => 0, 'updated' => 0 ]; } $sql = "INSERT INTO {$table} (`email`,`first_name`,`last_name`,`status`,`syn_date`,`syn_status`,`log`,`brand`) VALUES " . implode( ',', $values_parts ) . " ON DUPLICATE KEY UPDATE `first_name`=VALUES(`first_name`), `last_name`=VALUES(`last_name`), `status`=VALUES(`status`), `syn_date`=VALUES(`syn_date`), `syn_status`=VALUES(`syn_status`), `log`=VALUES(`log`), `brand`=VALUES(`brand`)"; $prepared = $wpdb->prepare( $sql, $params ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( $prepared ); return [ 'inserted' => $inserted, 'updated' => $updated ]; } private function upsert_record( array $record ): string { global $wpdb; $table = $this->get_table_name(); $existing_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} WHERE email = %s LIMIT 1", $record['email'] ) ); if ( $existing_id ) { $updated = $wpdb->update( $table, [ 'email' => $record['email'], 'first_name' => $record['first_name'], 'last_name' => $record['last_name'], 'status' => $record['status'], 'syn_date' => $record['syn_date'], 'syn_status' => $record['syn_status'], 'log' => $this->truncate_log( $record['log'] ?? '' ), 'brand' => $record['brand'] ?? '', ], [ 'id' => (int) $existing_id ], [ '%s', '%s', '%s', '%s', '%s', '%s', '%s' ], [ '%d' ] ); return $updated ? 'update' : 'skip'; } $inserted = $wpdb->insert( $table, [ 'email' => $record['email'], 'first_name' => $record['first_name'], 'last_name' => $record['last_name'], 'status' => $record['status'], 'syn_date' => $record['syn_date'], 'syn_status' => $record['syn_status'], 'log' => $this->truncate_log( $record['log'] ?? '' ), 'brand' => $record['brand'] ?? '', ], [ '%s', '%s', '%s', '%s', '%s', '%s', '%s' ] ); return $inserted ? 'insert' : 'skip'; } private function get_pending_records( int $limit ): array { global $wpdb; $table = $this->get_table_name(); return $wpdb->get_results( $wpdb->prepare( "SELECT id, email FROM {$table} WHERE status IN (%s, %s) ORDER BY id ASC LIMIT %d", '', 'pending', $limit ) ); } private function validate_email( string $email ): string { if ( ! is_email( $email ) ) { return 'Invalid Email Syntax'; } $domain = substr( strrchr( $email, '@' ), 1 ); if ( ! $domain || ! $this->has_mx_records( $domain ) ) { return 'No MX Records Found for Domain'; } $sender = $this->get_sender_address(); if ( ! class_exists( Validator::class ) ) { return 'Valid Email'; } try { $validator = new Validator( [ $email ], $sender, [ 'connect_timeout' => 10, 'from_email' => $sender, 'helo_host' => wp_parse_url( home_url(), PHP_URL_HOST ) ?: 'localhost', ] ); $results = $validator->validate(); if ( is_array( $results ) ) { $is_valid = ! empty( $results[ $email ] ); } else { $is_valid = (bool) $results; } return $is_valid ? 'Valid Email' : 'SMTP Validation Failed'; } catch ( Throwable $throwable ) { error_log( sprintf( 'SMTP validation error for %s: %s', $email, $throwable->getMessage() ) ); return 'SMTP Validation Error'; } } private function update_record_status( int $id, string $email, string $status, string $result ): bool { global $wpdb; $table = $this->get_table_name(); $today = current_time( 'Y-m-d' ); $log_message = sprintf( 'Validation: %s | Status: %s | Date: %s', $result, $status, $today ); $updated = $wpdb->update( $table, [ 'status' => $status, 'syn_date' => $today, 'syn_status' => 'completed', 'log' => $this->truncate_log( $log_message ), ], [ 'id' => $id ], [ '%s', '%s', '%s', '%s' ], [ '%d' ] ); return (bool) $updated; } private function has_mx_records( string $domain ): bool { if ( str_contains( $domain, 'localhost' ) ) { return false; } return checkdnsrr( $domain, 'MX' ); } private function truncate_log( string $message ): string { return substr( $message, 0, self::LOG_MAX_LENGTH ); } private function log_turbo_debug( string $step, string $detail = '' ): void { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { $message = '[EVA Turbo] ' . $step; if ( '' !== $detail ) { $message .= ' :: ' . $detail; } error_log( $message ); } } private function get_table_name(): string { if ( null !== $this->table_name ) { return $this->table_name; } global $wpdb; $prefixed = $wpdb->prefix . self::TABLE; $prefixed_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $prefixed ) ); if ( $prefixed_exists ) { $this->table_name = $prefixed; return $this->table_name; } $plain_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', self::TABLE ) ); $this->table_name = $plain_exists ? self::TABLE : $prefixed; return $this->table_name; } private function is_valid_date( string $value ): bool { $date = date_create_from_format( 'Y-m-d', $value ); return $date && $date->format( 'Y-m-d' ) === $value; } private function get_sender_address(): string { if ( null !== $this->sender_email ) { return $this->sender_email; } $admin_email = get_option( 'admin_email' ); if ( is_email( $admin_email ) ) { $this->sender_email = $admin_email; return $this->sender_email; } $domain = wp_parse_url( home_url(), PHP_URL_HOST ) ?: 'localhost.localdomain'; $this->sender_email = 'no-reply@' . $domain; return $this->sender_email; } /** * Determine if the environment allows LOAD DATA LOCAL INFILE. * * @return bool */ public function is_turbo_available(): bool { if ( function_exists( 'ini_set' ) ) { @ini_set( 'mysqli.allow_local_infile', '1' ); @ini_set( 'mysql.allow_local_infile', '1' ); } if ( ! function_exists( 'mysqli_init' ) ) { $this->log_turbo_debug( 'mysqli_init missing' ); return false; } $db = @mysqli_init(); if ( ! $db ) { $this->log_turbo_debug( 'mysqli_init failed to initialize' ); return false; } if ( defined( 'MYSQLI_OPT_LOCAL_INFILE' ) ) { @mysqli_options( $db, MYSQLI_OPT_LOCAL_INFILE, true ); } $host = defined( 'DB_HOST' ) ? DB_HOST : ini_get( 'mysqli.default_host' ); $user = defined( 'DB_USER' ) ? DB_USER : ini_get( 'mysqli.default_user' ); $pass = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : ini_get( 'mysqli.default_pw' ); $name = defined( 'DB_NAME' ) ? DB_NAME : ''; $client_flags = defined( 'MYSQLI_CLIENT_LOCAL_FILES' ) ? MYSQLI_CLIENT_LOCAL_FILES : 0; if ( ! @$db->real_connect( $host, $user, $pass, $name, null, null, $client_flags ) ) { $this->log_turbo_debug( 'mysqli real_connect failed', mysqli_connect_error() ?: 'unknown error' ); return false; } @$db->set_charset( 'utf8mb4' ); $supports = false; $result = @$db->query( "SHOW VARIABLES LIKE 'local_infile'" ); if ( $result ) { $row = $result->fetch_assoc(); if ( $row ) { $value = ''; if ( isset( $row['Value'] ) ) { $value = (string) $row['Value']; } elseif ( isset( $row['value'] ) ) { $value = (string) $row['value']; } $value = strtoupper( $value ); $supports = ( 'ON' === $value || '1' === $value ); $this->log_turbo_debug( 'local_infile variable', $value ); } $result->free(); } if ( ! $supports ) { $result = @$db->query( 'SELECT @@local_infile AS local_infile' ); if ( $result ) { $row = $result->fetch_assoc(); if ( $row && isset( $row['local_infile'] ) ) { $supports = (int) $row['local_infile'] === 1; $this->log_turbo_debug( '@@local_infile value', (string) $row['local_infile'] ); } $result->free(); } } if ( ! $supports ) { @$db->query( 'SET SESSION local_infile = 1' ); $result = @$db->query( 'SELECT @@session.local_infile AS local_infile' ); if ( $result ) { $row = $result->fetch_assoc(); if ( $row && isset( $row['local_infile'] ) ) { $supports = (int) $row['local_infile'] === 1; $this->log_turbo_debug( 'session local_infile after SET', (string) $row['local_infile'] ); } $result->free(); } } if ( ! $supports ) { $result = @$db->query( "SHOW VARIABLES LIKE 'have_local_infile'" ); if ( $result ) { $row = $result->fetch_assoc(); if ( $row ) { $value = ''; if ( isset( $row['Value'] ) ) { $value = (string) $row['Value']; } elseif ( isset( $row['value'] ) ) { $value = (string) $row['value']; } $value = strtoupper( $value ); $supports = ( 'YES' === $value || 'ON' === $value || '1' === $value ); $this->log_turbo_debug( 'have_local_infile variable', $value ); } $result->free(); } } if ( $supports ) { $ini = ini_get( 'mysqli.allow_local_infile' ); if ( false !== $ini ) { $supports = ! in_array( strtolower( (string) $ini ), [ '0', 'off', '' ], true ); if ( ! $supports ) { $this->log_turbo_debug( 'php.ini mysqli.allow_local_infile blocked', (string) $ini ); } } if ( $supports ) { $legacy = ini_get( 'mysql.allow_local_infile' ); if ( false !== $legacy ) { $supports = ! in_array( strtolower( (string) $legacy ), [ '0', 'off', '' ], true ); if ( ! $supports ) { $this->log_turbo_debug( 'php.ini mysql.allow_local_infile blocked', (string) $legacy ); } } } } $db->close(); if ( ! $supports ) { $this->log_turbo_debug( 'Turbo unavailable after checks' ); } return $supports; } /** * Ultra-fast import using MySQL LOAD DATA LOCAL INFILE into a staging table then merge. * Requires DB/host to allow LOCAL INFILE. * * @param string $file_path Absolute CSV path. * @param array $opts { has_header: bool } * @return array{processed:int,inserted:int,updated:int} */ public function turbo_import_load_data( string $file_path, array $opts = [] ): array { global $wpdb; $has_header = ! empty( $opts['has_header'] ); $table = $this->get_table_name(); if ( ! file_exists( $file_path ) ) { return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0 ]; } $db = mysqli_init(); if ( ! $db ) { return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0 ]; } if ( defined( 'MYSQLI_OPT_LOCAL_INFILE' ) ) { mysqli_options( $db, MYSQLI_OPT_LOCAL_INFILE, true ); } $host = defined( 'DB_HOST' ) ? DB_HOST : ini_get( 'mysqli.default_host' ); $user = defined( 'DB_USER' ) ? DB_USER : ini_get( 'mysqli.default_user' ); $pass = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : ini_get( 'mysqli.default_pw' ); $name = defined( 'DB_NAME' ) ? DB_NAME : ''; $client_flags = defined( 'MYSQLI_CLIENT_LOCAL_FILES' ) ? MYSQLI_CLIENT_LOCAL_FILES : 0; if ( ! $db->real_connect( $host, $user, $pass, $name, null, null, $client_flags ) ) { return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0 ]; } $db->set_charset( 'utf8mb4' ); @$db->query( 'SET SESSION local_infile = 1' ); $tmp = $wpdb->prefix . 'eva_tmp_' . wp_generate_password( 6, false, false ); $columns = []; for ( $i = 1; $i <= 20; $i++ ) { $columns[] = sprintf( '`raw%d` TEXT', $i ); } $create_sql = sprintf( 'CREATE TEMPORARY TABLE `%s` (%s) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4', $tmp, implode( ',', $columns ) ); $db->query( $create_sql ); $escaped_path = str_replace( "'", "''", str_replace( '\\', '\\\\', $file_path ) ); $column_list = implode( ',', array_map( fn( $i ) => sprintf( '`raw%d`', $i ), range( 1, 20 ) ) ); $ignore = $has_header ? ' IGNORE 1 LINES ' : ' '; $load_sql = sprintf( 'LOAD DATA LOCAL INFILE \'%s\' INTO TABLE `%s` FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\' ESCAPED BY \'"\' LINES TERMINATED BY \'\\n\'%s(%s)', $escaped_path, $tmp, $ignore, $column_list ); $loaded = $db->query( $load_sql ); if ( false === $loaded ) { $error = $db->error; $db->close(); return [ 'processed' => 0, 'inserted' => 0, 'updated' => 0, 'error' => $error ]; } $count_sql = sprintf( "SELECT COUNT(*) AS total FROM `%s` WHERE `raw2` LIKE '%%@%%'", $tmp ); $total_res = $db->query( $count_sql ); $total_row = $total_res ? $total_res->fetch_assoc() : [ 'total' => 0 ]; $total = (int) ( $total_row['total'] ?? 0 ); $existing_sql = sprintf( "SELECT COUNT(*) AS matched FROM `%s` t JOIN `%s` m ON m.email = TRIM(t.raw2) WHERE t.raw2 LIKE '%%@%%'", $tmp, $table ); $existing_res = $db->query( $existing_sql ); $existing_row = $existing_res ? $existing_res->fetch_assoc() : [ 'matched' => 0 ]; $existing = (int) ( $existing_row['matched'] ?? 0 ); $inserts = max( 0, $total - $existing ); $merge_sql = sprintf( "INSERT INTO `%s` (`email`,`first_name`,`last_name`,`status`,`syn_date`,`syn_status`,`log`,`brand`) SELECT TRIM(raw2), TRIM(raw3), TRIM(raw4), '', CURDATE(), '', '', CASE WHEN raw10 REGEXP 'WP\\\s*EASY\\\s*PAY' THEN 'WP EASY PAY' ELSE COALESCE(TRIM(raw10), '') END FROM `%s` WHERE raw2 LIKE '%%@%%' ON DUPLICATE KEY UPDATE `first_name`=VALUES(`first_name`), `last_name`=VALUES(`last_name`), `status`=VALUES(`status`), `syn_date`=VALUES(`syn_date`), `syn_status`=VALUES(`syn_status`), `log`=VALUES(`log`), `brand`=VALUES(`brand`)", $table, $tmp ); $db->query( $merge_sql ); $db->close(); return [ 'processed' => $total, 'inserted' => $inserts, 'updated' => $existing ]; } }
[-] class-email-validator-service.php
[open]
[+]
..
[-] class-email-validator-admin.php
[open]