prepare_import_subscriber_form(); } public function prepare_import_subscriber_form() { if ( is_multisite() && ! is_upload_space_available() ) { return; } $max_upload_size = $this->get_max_upload_size(); $post_params = array( 'action' => 'ig_es_import_subscribers_upload_handler', 'importing_from' => 'csv', 'security' => wp_create_nonce( 'ig-es-admin-ajax-nonce' ), ); $upload_action_url = admin_url( 'admin-ajax.php' ); $plupload_init = array( 'browse_button' => 'plupload-browse-button', 'container' => 'plupload-upload-ui', 'drop_element' => 'drag-drop-area', 'file_data_name' => 'async-upload', 'url' => $upload_action_url, 'filters' => array( 'max_file_size' => $max_upload_size . 'b', 'mime_types' => array( array( 'extensions' => 'csv' ) ), ), 'multipart_params' => $post_params, ); $allowedtags = ig_es_allowed_html_tags_in_esc(); ?>

is_pro() ) { $select_list_attr = 'multiple="multiple"'; $select_list_name = 'list_id[]'; $select_list_class = 'ig-es-form-multiselect'; } else { $select_list_attr = ''; $select_list_name = 'list_id'; $select_list_class = 'form-select'; } ?>


import_callback(); ?>
valid() && $i <= $check_lines ) { $line = $file->fgets(); foreach ( $delimiters as $delimiter ) { $regExp = '/[' . $delimiter . ']/'; $fields = preg_split( $regExp, $line ); if ( count( $fields ) > 1 ) { if ( ! empty( $results[ $delimiter ] ) ) { $results[ $delimiter ] ++; } else { $results[ $delimiter ] = 1; } } } $i ++; } if ( count( $results ) > 0 ) { $results = array_keys( $results, max( $results ) ); return $results[0]; } return ','; } /** * Method to get max upload size * * @return int $max_upload_size * * @since 4.4.6 */ public function get_max_upload_size() { $max_upload_size = 5242880; // 5MB. $wp_max_upload_size = wp_max_upload_size(); $max_upload_size = min( $max_upload_size, $wp_max_upload_size ); return apply_filters( 'ig_es_max_upload_size', $max_upload_size ); } /** * Ajax handler to insert import CSV data into temporary table. * * @since 4.6.6 */ public function ajax_import_subscribers_upload_handler() { check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' ); $response = array( 'success' => false, ); global $wpdb; $memory_limit = @ini_get( 'memory_limit' ); $max_execution_time = @ini_get( 'max_execution_time' ); @set_time_limit( 0 ); if ( (int) $max_execution_time < 300 ) { @set_time_limit( 300 ); } if ( (int) $memory_limit < 256 ) { // Add filter to increase memory limit add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' ); wp_raise_memory_limit( 'ig_es' ); // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on. remove_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' ); } $importing_from = ig_es_get_request_data( 'importing_from' ); if ( 'csv' === $importing_from && isset( $_FILES['async-upload'] ) ) { if ( isset( $_FILES['async-upload']['tmp_name'] ) && is_uploaded_file( sanitize_text_field( $_FILES['async-upload']['tmp_name'] ) ) ) { $tmp_file = sanitize_text_field( $_FILES['async-upload']['tmp_name'] ); $raw_data = file_get_contents( $tmp_file ); $seperator = $this->get_delimiter( $tmp_file ); $handle = fopen( $tmp_file, 'r' ); // Get Headers. $headers = array_map( 'trim', fgetcsv( $handle, 0, $seperator ) ); // Remove BOM characters from the first item. if ( isset( $headers[0] ) ) { $headers[0] = ig_es_remove_utf8_bom( $headers[0] ); } $data_contain_headers = true; $phpmailer = ES()->mailer->get_phpmailer(); if ( ! empty( $headers ) ) { foreach ( $headers as $header ) { if ( ! empty( $header ) ) { // Convert special characters in the email domain name to ascii. if ( is_callable( array( $phpmailer, 'punyencodeAddress' ) ) ) { $header = $phpmailer->punyencodeAddress( $header ); } if ( is_email( $header ) ) { $data_contain_headers = false; break; } } } } fclose( $handle ); if ( ! $data_contain_headers ) { $headers = array(); } if ( function_exists( 'mb_convert_encoding' ) ) { $raw_data = mb_convert_encoding( $raw_data, 'UTF-8', mb_detect_encoding( $raw_data, 'UTF-8, ISO-8859-1', true ) ); } } } elseif ( 'wordpress_users' === $importing_from ) { $roles = ig_es_get_request_data( 'selected_roles' ); $users = $wpdb->get_results( "SELECT u.user_email, IF(meta_role.meta_value = 'a:0:{}',NULL,meta_role.meta_value) AS '_role', meta_firstname.meta_value AS 'firstname', meta_lastname.meta_value AS 'lastname', u.display_name, u.user_nicename FROM {$wpdb->users} AS u LEFT JOIN {$wpdb->usermeta} AS meta_role ON meta_role.user_id = u.id AND meta_role.meta_key = '{$wpdb->prefix}capabilities' LEFT JOIN {$wpdb->usermeta} AS meta_firstname ON meta_firstname.user_id = u.id AND meta_firstname.meta_key = 'first_name' LEFT JOIN {$wpdb->usermeta} AS meta_lastname ON meta_lastname.user_id = u.id AND meta_lastname.meta_key = 'last_name' WHERE meta_role.user_id IS NOT NULL" ); if ( ! empty( $users ) ) { $raw_data = ''; $seperator = ';'; $data_contain_headers = false; $headers = array( __( 'Email', 'email-subscribers' ), __( 'First Name', 'email-subscribers' ), __( 'Last Name', 'email-subscribers' ), __( 'Nick Name', 'email-subscribers' ), __( 'Display Name', 'email-subscribers' ), ); foreach ( $users as $user ) { // User must have a role assigned. if ( ! $user->_role ) { continue; } // Role is set but not in the list if ( ! empty( $roles ) && ! array_intersect( array_keys( unserialize( $user->_role ) ), $roles ) ) { continue; } $user_data = array(); foreach ( $user as $key => $data ) { if ( '_role' === $key ) { continue; } if ( 'firstname' === $key && ! $data ) { $data = $user->display_name; } $user_data[] = $data; } $raw_data .= implode( ';', $user_data ); $raw_data .= "\n"; } } if ( empty( $raw_data ) ) { $response['message'] = __( 'We can\'t find any matching users. Please update your preferences and try again.', 'email-subscribers' ); } } if ( empty( $raw_data ) ) { wp_send_json( $response ); } $response = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, '', $importing_from ); $response['success'] = true; $response['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 ); wp_send_json( $response ); } /** * Ajax handler to get import data from temporary table. * * @since 4.6.6 */ public function ajax_get_import_data() { check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' ); $response = array( 'success' => false, ); global $wpdb; $identifier = ''; if ( isset( $_POST['identifier'] ) ) { $identifier = sanitize_text_field( $_POST['identifier'] ); } if ( ! empty( $identifier ) ) { $response['identifier'] = $identifier; $response['data'] = get_option( 'ig_es_bulk_import' ); // get first and last entry $entries = $wpdb->get_row( $wpdb->prepare( "SELECT (SELECT data FROM {$wpdb->prefix}ig_temp_import WHERE identifier = %s ORDER BY ID ASC LIMIT 1) AS first, (SELECT data FROM {$wpdb->prefix}ig_temp_import WHERE identifier = %s ORDER BY ID DESC LIMIT 1) AS last", $identifier, $identifier ) ); $first = unserialize( base64_decode( $entries->first ) ); $last = unserialize( base64_decode( $entries->last ) ); $data = str_getcsv( $first[0], $response['data']['separator'], '"' ); $cols = count( $data ); $contactcount = $response['data']['lines']; $fields = array( 'email' => __( 'Email', 'email-subscribers' ), 'first_name' => __( 'First Name', 'email-subscribers' ), 'last_name' => __( 'Last Name', 'email-subscribers' ), 'first_last' => __( '(First Name) (Last Name)', 'email-subscribers' ), 'last_first' => __( '(Last Name) (First Name)', 'email-subscribers' ), 'created_at' => __( 'Subscribed at', 'email-subscribers' ), ); if ( ! empty( $response['data']['importing_from'] ) && 'wordpress_users' !== $response['data']['importing_from'] ) { $fields['list_name'] = __( 'List Name', 'email-subscribers' ); $fields['status'] = __( 'Status', 'email-subscribers' ); } $fields = apply_filters( 'es_import_show_more_fields_for_mapping', $fields ); $html = '
'; $html .= '
'; $html .= ''; $phpmailer = ES()->mailer->get_phpmailer(); $headers = array(); if ( ! empty( $response['data']['headers'] ) ) { $headers = $response['data']['headers']; } for ( $i = 0; $i < $cols; $i++ ) { $col_data = trim( $data[ $i ] ); // Convert special characters in the email domain name to ascii. if ( is_callable( array( $phpmailer, 'punyencodeAddress' ) ) ) { $col_data = $phpmailer->punyencodeAddress( $col_data ); } $is_email = is_email( trim( $col_data ) ); $select = ''; $html .= ''; } $html .= ''; if ( ! empty( $headers ) ) { $html .= ''; foreach ( $headers as $header ) { $html .= ''; } $html .= ''; } $html .= ''; for ( $i = 0; $i < min( 3, $contactcount ); $i++ ) { $data = str_getcsv( ( $first[ $i ] ), $response['data']['separator'], '"' ); $html .= ''; foreach ( $data as $cell ) { if ( ! empty( $cell ) && is_email( $cell ) ) { $cell = sanitize_email( strtolower( $cell ) ); } $html .= ''; } $html .= ''; } if ( $contactcount > 3 ) { $hidden_contacts_count = $contactcount - 4; if ( $hidden_contacts_count > 0 ) { /* translators: %s: Hidden contacts count */ $html .= ''; } $data = str_getcsv( array_pop( $last ), $response['data']['separator'], '"' ); $html .= ''; foreach ( $data as $cell ) { $html .= ''; } $html .= ''; } $html .= ''; $html .= '
#' . $select . '
' . $header . '
' . number_format_i18n( $i + 1 ) . '' . ( $cell ) . '
 …' . sprintf( esc_html__( '%s contacts are hidden', 'email-subscribers' ), number_format_i18n( $contactcount - 4 ) ) . '…
' . number_format_i18n( $contactcount ) . '' . ( $cell ) . '
'; $html .= ''; $html .= '
'; $response['html'] = $html; $response['success'] = true; } wp_send_json( $response ); } /** * Ajax handler to import subscirbers from temporary table * * @since 4.6.6 */ public function ajax_do_import() { check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' ); global $wpdb; $phpmailer = ES()->mailer->get_phpmailer(); $memory_limit = @ini_get( 'memory_limit' ); $max_execution_time = @ini_get( 'max_execution_time' ); @set_time_limit( 0 ); if ( (int) $max_execution_time < 300 ) { @set_time_limit( 300 ); } if ( (int) $memory_limit < 256 ) { // Add filter to increase memory limit add_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' ); wp_raise_memory_limit( 'ig_es' ); // Remove the added filter function so that it won't be called again if wp_raise_memory_limit called later on. remove_filter( 'ig_es_memory_limit', 'ig_es_increase_memory_limit' ); } $return['success'] = false; $bulkdata = array(); if ( isset( $_POST['options'] ) ) { $bulkdata = ig_es_get_data( $_POST, 'options', array(), true ); } $bulkdata = wp_parse_args( $bulkdata, get_option( 'ig_es_bulk_import' ) ); $erroremails = get_option( 'ig_es_bulk_import_errors', array() ); $order = isset( $bulkdata['mapping_order'] ) ? $bulkdata['mapping_order'] : array(); $list_id = isset( $bulkdata['list_id'] ) ? $bulkdata['list_id'] : array(); $parts_at_once = 10; $selected_status = $bulkdata['status']; $send_optin_emails = isset( $bulkdata['send_optin_emails'] ) ? $bulkdata['send_optin_emails'] : 'no'; $need_to_send_welcome_emails = ( 'yes' === $send_optin_emails ); $update_subscribers_data = isset( $bulkdata['update_subscribers_data'] ) ? $bulkdata['update_subscribers_data'] : 'no'; $need_to_update_subscribers_data = ( 'yes' === $update_subscribers_data ); $error_codes = array( 'invalid' => __( 'Email address is invalid.', 'email-subscribers' ), 'empty' => __( 'Email address is empty.', 'email-subscribers' ), ); if ( ! empty( $list_id ) && ! is_array( $list_id ) ) { $list_id = array( $list_id ); } if ( isset( $_POST['id'] ) ) { set_transient( 'ig_es_contact_import_is_running', 'yes' ); $batch_id = (int) sanitize_text_field( $_POST['id'] ); $bulkdata['current'] = $batch_id; $raw_list_data = $wpdb->get_col( $wpdb->prepare( "SELECT data FROM {$wpdb->prefix}ig_temp_import WHERE identifier = %s ORDER BY ID ASC LIMIT %d, %d", $bulkdata['identifier'], $bulkdata['current'] * $parts_at_once, $parts_at_once ) ); if ( $raw_list_data ) { $contacts_data = array(); $gmt_offset = ig_es_get_gmt_offset( true ); $current_date_time = gmdate( 'Y-m-d H:i:s', time() - $gmt_offset ); $current_batch_emails = array(); $processed_emails = ! empty( $bulkdata['processed_emails'] ) ? $bulkdata['processed_emails'] : array(); $list_contact_data = array(); $es_status_mapping = array( __( 'Subscribed', 'email-subscribers' ) => 'subscribed', __( 'Unsubscribed', 'email-subscribers' ) => 'unsubscribed', __( 'Unconfirmed', 'email-subscribers' ) => 'unconfirmed', __( 'Hard Bounced', 'email-subscribers' ) => 'hard_bounced', ); $is_starting_import = 0 === $batch_id; if ( $is_starting_import ) { do_action( 'ig_es_before_bulk_contact_import' ); } foreach ( $raw_list_data as $raw_list ) { $raw_list = unserialize( base64_decode( $raw_list ) ); // each entry foreach ( $raw_list as $line ) { if ( ! trim( $line ) ) { $bulkdata['lines']--; continue; } $data = str_getcsv( $line, $bulkdata['separator'], '"' ); $cols_count = count( $data ); $insert = array(); for ( $col = 0; $col < $cols_count; $col++ ) { $d = trim( $data[ $col ] ); if ( ! isset( $order[ $col ] ) ) { continue; } switch ( $order[ $col ] ) { case 'email': $insert['email'] = $d; // Convert special characters in the email domain name to ascii. if ( is_callable( array( $phpmailer, 'punyencodeAddress' ) ) ) { $encoded_email = $phpmailer->punyencodeAddress( $insert['email'] ); if ( ! empty( $encoded_email ) ) { $insert['email'] = $encoded_email; } } break; case 'first_last': $name = explode( ' ', $d ); if ( ! empty( $name[0] ) ) { $insert['first_name'] = $name[0]; } if ( ! empty( $name[1] ) ) { $insert['last_name'] = $name[1]; } break; case 'last_first': $name = explode( ' ', $d ); if ( ! empty( $name[1] ) ) { $insert['first_name'] = $name[1]; } if ( ! empty( $name[0] ) ) { $insert['last_name'] = $name[0]; } break; case 'created_at': if ( ! is_numeric( $d ) && ! empty( $d ) ) { $d = sanitize_text_field( $d ); $insert['created_at'] = gmdate( 'Y-m-d H:i:s', strtotime( $d ) - $gmt_offset ); } break; case '-1': // ignored column break; default: $insert[ $order[ $col ] ] = $d; } } if ( empty( $insert['email'] ) || ! is_email( $insert['email'] ) ) { $error_data = array(); if ( empty( $insert['email'] ) ) { $error_data['cd'] = 'empty'; } elseif ( ! is_email( $insert['email'] ) ) { $error_data['cd'] = 'invalid'; $error_data['email'] = $insert['email']; } if ( ! empty( $insert['first_name'] ) ) { $error_data['fn'] = $insert['first_name']; } if ( ! empty( $insert['last_name'] ) ) { $error_data['ln'] = $insert['last_name']; } $bulkdata['errors']++; $erroremails[] = $error_data; continue; } $email = sanitize_email( strtolower( $insert['email'] ) ); if ( ! in_array( $email, $current_batch_emails, true ) && ! in_array( $email, $processed_emails, true ) ) { $first_name = isset( $insert['first_name'] ) ? ES_Common::handle_emoji_characters( sanitize_text_field( trim( $insert['first_name'] ) ) ) : ''; $last_name = isset( $insert['last_name'] ) ? ES_Common::handle_emoji_characters( sanitize_text_field( trim( $insert['last_name'] ) ) ) : ''; $created_at = isset( $insert['created_at'] ) ? $insert['created_at'] : $current_date_time; $guid = ES_Common::generate_guid(); $contact_data['first_name'] = $first_name; $contact_data['last_name'] = $last_name; $contact_data['email'] = $email; $contact_data['source'] = 'import'; $contact_data['status'] = 'verified'; $contact_data['hash'] = $guid; $contact_data['created_at'] = $created_at; $additional_contacts_data = apply_filters( 'es_prepare_additional_contacts_data_for_import', array(), $insert ); $contacts_data[$email] = array_merge( $contact_data, $additional_contacts_data ); $bulkdata['imported']++; } else { $bulkdata['duplicate_emails_count']++; } $list_names = isset( $insert['list_name'] ) ? sanitize_text_field( trim( $insert['list_name'] ) ) : ''; if ( empty( $insert['list_name'] ) ) { $list_names_arr = ES()->lists_db->get_lists_by_id( $list_id ); $list_names = implode( ',', array_column( $list_names_arr, 'name' ) ); } $status = 'unconfirmed'; $list_names = array_map( 'trim', explode( ',', $list_names ) ); if ( isset( $insert['status'] ) ) { $map_status = strtolower( str_replace( ' ', '_', $insert['status'] ) ); } if ( isset( $insert['status'] ) && in_array( $map_status, $es_status_mapping ) ) { $status = sanitize_text_field( trim( $map_status ) ); } elseif ( ! empty( $selected_status ) ) { $status = $selected_status; } if ( ! empty( $es_status_mapping[ $status ] ) ) { $status = $es_status_mapping[ $status ]; } foreach ( $list_names as $key => $list_name ) { if ( ! empty( $list_name ) ) { $list_contact_data[ $list_name ][ $status ][] = $email; } } $current_batch_emails[] = $email; } } if ( count( $current_batch_emails ) > 0 ) { $current_batch_emails = array_unique( $current_batch_emails ); $existing_contacts_email_id_map = ES()->contacts_db->get_email_id_map( $current_batch_emails ); if ( $need_to_update_subscribers_data ) { if ( ! empty( $existing_contacts_email_id_map ) ) { $existing_contacts = array_intersect_key( $contacts_data, $existing_contacts_email_id_map ); $updated_contacts = ES()->contacts_db->bulk_update( $existing_contacts, 100 ); if ( ! empty( $updated_contacts ) ) { $bulkdata['updated_contacts'] += $updated_contacts; } } } if ( ! empty( $existing_contacts_email_id_map ) ) { $contacts_data = array_diff_key( $contacts_data, $existing_contacts_email_id_map ); } if ( ! empty( $contacts_data ) ) { $insert_ids = ES()->contacts_db->bulk_insert( $contacts_data, 100, true ); if ( ! empty( $insert_ids ) && $need_to_send_welcome_emails ) { $imported_contacts_transient = get_transient( 'ig_es_imported_contact_ids_range' ); if ( ! empty( $imported_contacts_transient ) && is_array( $imported_contacts_transient ) && isset( $imported_contacts_transient['rows'] ) ) { $old_rows = is_array( $imported_contacts_transient['rows'] ) ? $imported_contacts_transient['rows'] : array(); $all_data = array_merge( $old_rows, $insert_ids ); $insert_ids = array( min( $all_data ), max( $all_data ) ); } $imported_contact_details = array( 'rows' => $insert_ids, 'lists' => $list_id ); set_transient( 'ig_es_imported_contact_ids_range', $imported_contact_details ); } } if ( ! empty( $list_contact_data ) ) { foreach ( $list_contact_data as $list_name => $list_data ) { $list = ES()->lists_db->get_list_by_name( $list_name ); if ( ! empty( $list ) ) { $list_id = $list['id']; } else { $list_id = ES()->lists_db->add_list( $list_name ); } foreach ( $list_data as $status => $contact_emails ) { $contact_id_date = ES()->contacts_db->get_contact_ids_created_at_date_by_emails( $contact_emails ); $contact_ids = array_keys( $contact_id_date ); if ( count( $contact_ids ) > 0 ) { ES()->lists_contacts_db->remove_contacts_from_lists( $contact_ids, $list_id ); ES()->lists_contacts_db->do_import_contacts_into_list( $list_id, $contact_id_date, $status, 1 ); } } } } } } $return['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 ); $return['errors'] = isset( $bulkdata['errors'] ) ? $bulkdata['errors'] : 0; $return['duplicate_emails_count'] = isset( $bulkdata['duplicate_emails_count'] ) ? $bulkdata['duplicate_emails_count'] : 0; $return['existing_contacts'] = isset( $bulkdata['existing_contacts'] ) ? $bulkdata['existing_contacts'] : 0; $return['updated_contacts'] = isset( $bulkdata['updated_contacts'] ) ? $bulkdata['updated_contacts'] : 0; $return['imported'] = ( $bulkdata['imported'] ); $return['total'] = ( $bulkdata['lines'] ); $return['f_errors'] = number_format_i18n( $bulkdata['errors'] ); $return['f_imported'] = number_format_i18n( $bulkdata['imported'] ); $return['f_total'] = number_format_i18n( $bulkdata['lines'] ); $return['f_duplicate_emails'] = number_format_i18n( $bulkdata['duplicate_emails_count'] ); $return['html'] = ''; if ( ( $bulkdata['imported'] + $bulkdata['errors'] + $bulkdata['duplicate_emails_count'] ) >= $bulkdata['lines'] ) { $return['html'] = '

'; $total_imported_contacts = $bulkdata['imported'] - $bulkdata['updated_contacts']; if ( $total_imported_contacts > 0 ) { /* translators: 1. Total imported contacts */ $return['html'] .= sprintf( esc_html__( '%1$s contacts imported.', 'email-subscribers' ) . ' ', '' . number_format_i18n( $total_imported_contacts ) . '' ); } if ( $bulkdata['updated_contacts'] > 0 ) { /* translators: 1. Total updated contacts */ $return['html'] .= sprintf( esc_html__( '%1$s contacts updated.', 'email-subscribers' ), '' . number_format_i18n( $bulkdata['updated_contacts'] ) . '' ); } if ( $bulkdata['duplicate_emails_count'] ) { $duplicate_email_string = _n( 'email', 'emails', $bulkdata['duplicate_emails_count'], 'email-subscribers' ); /* translators: 1. Duplicate emails count. 2. Email or emails string based on duplicate email count. */ $return['html'] .= sprintf( esc_html__( '%1$s duplicate %2$s found.', 'email-subscribers' ), '' . number_format_i18n( $bulkdata['duplicate_emails_count'] ) . '', $duplicate_email_string ); } $return['html'] .= '

'; if ( $bulkdata['errors'] ) { $i = 0; $skipped_contact_string = _n( 'contact was', 'contacts were', $bulkdata['errors'], 'email-subscribers' ); /* translators: %d Skipped emails count %s Skipped contacts string */ $table = '

' . __( sprintf( 'The following %d %s skipped', $bulkdata['errors'], $skipped_contact_string ), 'email-subscribers' ) . ':

'; $table .= ''; $table .= ''; $first_name_column_choosen = in_array( 'first_name', $order, true ); if ( $first_name_column_choosen ) { $table .= ''; } $last_name_column_choosen = in_array( 'last_name', $order, true ); if ( $last_name_column_choosen ) { $table .= ''; } $table .= ''; $table .= ''; $table .= ''; foreach ( $erroremails as $error_data ) { $table .= ''; $table .= ''; $email = ! empty( $error_data['email'] ) ? $error_data['email'] : '-'; if ( $first_name_column_choosen ) { $first_name = ! empty( $error_data['fn'] ) ? $error_data['fn'] : '-'; $table .= ''; } if ( $last_name_column_choosen ) { $last_name = ! empty( $error_data['ln'] ) ? $error_data['ln'] : '-'; $table .= ''; } $error_code = ! empty( $error_data['cd'] ) ? $error_data['cd'] : '-'; $reason = ! empty( $error_codes[ $error_code ] ) ? $error_codes[ $error_code ] : '-'; $table .= ''; } $table .= '
#' . esc_html__( 'First Name', 'email-subscribers' ) . '' . esc_html__( 'Last Name', 'email-subscribers' ) . '' . esc_html__( 'Email', 'email-subscribers' ) . '' . esc_html__( 'Reason', 'email-subscribers' ) . '
' . ( ++$i ) . '' . esc_html( $first_name ) . '' . esc_html( $last_name ) . '' . esc_html( $email ) . '' . esc_html( $reason ) . '
'; $return['html'] .= $table; } do_action( 'ig_es_remove_import_data' ); $next_task_time = time() + ( 1 * MINUTE_IN_SECONDS ); // Schedule next task after 1 minute from current time. IG_ES_Background_Process_Helper::add_action_scheduler_task( 'ig_es_after_bulk_contact_import', array(), false, false, $next_task_time ); } else { // Add current batch emails into the processed email list $processed_emails = array_merge( $processed_emails, $current_batch_emails ); $bulkdata['processed_emails'] = $processed_emails; update_option( 'ig_es_bulk_import', $bulkdata ); update_option( 'ig_es_bulk_import_errors', $erroremails ); } $return['success'] = true; delete_transient( 'ig_es_contact_import_is_running'); } wp_send_json( $return ); } /** * Handle adding contact id to excluded contact list * * @param $contact_id */ public function handle_new_contact_inserted( $contact_id ) { $import_status = get_transient( 'ig_es_contact_import_is_running' ); if ( ! empty( $import_status ) && 'yes' == $import_status && ! empty( $contact_id ) ) { $old_excluded_contact_ids = $this->get_excluded_contact_id_on_import(); array_push( $old_excluded_contact_ids, $contact_id ); $this->set_excluded_contact_id_on_import($old_excluded_contact_ids); } } /** * Get the excluded contact ID's list * * @return array|mixed */ public function get_excluded_contact_id_on_import() { $old_excluded_contact_ids = get_transient( 'ig_es_excluded_contact_ids_on_import' ); if ( empty( $old_excluded_contact_ids ) || ! is_array( $old_excluded_contact_ids ) ) { $old_excluded_contact_ids = array(); } return $old_excluded_contact_ids; } /** * Set the excluded contact ID's list in transient */ public function set_excluded_contact_id_on_import( $list ) { if ( ! is_array( $list ) ) { return false; } if ( empty( $list ) ) { delete_transient( 'ig_es_excluded_contact_ids_on_import' ); } else { set_transient( 'ig_es_excluded_contact_ids_on_import', $list, 24 * HOUR_IN_SECONDS ); } return true; } /** * Handle sending bulk welcome and confirmation email to customers using cron job */ public function handle_after_bulk_contact_import() { global $wpbd; $imported_contact_details = get_transient( 'ig_es_imported_contact_ids_range' ); if ( ! empty( $imported_contact_details ) && isset( $imported_contact_details['rows'] )) { $imported_row_details = is_array( $imported_contact_details['rows'] ) ? $imported_contact_details['rows'] : array(); if (2 == count( $imported_row_details ) ) { $first_row = intval( $imported_row_details[0] ); $last_row = intval( $imported_row_details[1] ); $total_rows = ( $last_row - $first_row ) + 1; if ( 0 < $total_rows ) { $per_batch = 100; $total_batches = ceil( $total_rows / $per_batch ); $excluded_contact_ids = $this->get_excluded_contact_id_on_import(); $excluded_contact_ids_in_range = ig_es_get_values_in_range( $excluded_contact_ids, $first_row, $first_row + $per_batch ); $sql = "SELECT contacts.id, lists_contacts.list_id, lists_contacts.status FROM {$wpbd->prefix}ig_contacts AS contacts"; $sql .= " LEFT JOIN {$wpbd->prefix}ig_lists_contacts AS lists_contacts ON contacts.id = lists_contacts.contact_id"; $sql .= " LEFT JOIN {$wpbd->prefix}ig_queue AS queue ON contacts.id = queue.contact_id AND queue.campaign_id = 0"; $sql .= ' WHERE 1=1'; $sql .= ' AND queue.contact_id IS NULL'; $sql .= ' AND contacts.id >= %d AND contacts.id <= %d '; if ( ! empty( $excluded_contact_ids_in_range ) ) { $excluded_ids_for_next_batch = array_diff( $excluded_contact_ids, $excluded_contact_ids_in_range ); $this->set_excluded_contact_id_on_import( $excluded_ids_for_next_batch ); $excluded_contact_ids_in_range = array_map( 'esc_sql', $excluded_contact_ids_in_range ); $sql .= ' AND contacts.id NOT IN (' . implode( ',', $excluded_contact_ids_in_range ) . ')'; } $sql .= ' GROUP BY contacts.id LIMIT %d'; $query = $wpbd->prepare( $sql, [ $first_row, $first_row + $per_batch, $per_batch ] ); $entries = $wpbd->get_results( $query ); if ( 0 < count( $entries ) ) { $subscriber_ids = array(); $subscriber_options = array(); foreach ( $entries as $entry ) { if ( in_array( $entry->status, array( 'subscribed', 'unconfirmed' ) ) ) { $subscriber_id = $entry->id; $subscriber_ids[] = $subscriber_id; $subscriber_options[ $subscriber_id ]['type'] = 'unconfirmed' === $entry->status ? 'optin_confirmation' : 'optin_welcome_email'; } } if ( ! empty( $subscriber_ids ) ) { $timestamp = time(); ES()->queue->bulk_add( 0, $subscriber_ids, $timestamp, 20, false, 1, false, $subscriber_options ); } } if ( 1 == $total_batches ) { delete_transient( 'ig_es_imported_contact_ids_range' ); } else { $imported_contact_details = get_transient( 'ig_es_imported_contact_ids_range' ); $insert_ids = array( $first_row + $per_batch, $last_row ); $imported_contact_details['rows'] = $insert_ids; set_transient( 'ig_es_imported_contact_ids_range', $imported_contact_details ); $next_task_time = time() + ( 1 * MINUTE_IN_SECONDS ); // Schedule next task after 1 minute from current time. IG_ES_Background_Process_Helper::add_action_scheduler_task( 'ig_es_after_bulk_contact_import', array(), false, false, $next_task_time ); //Process queued Welcome and Confirmation emails immidetly $request_args = array( 'action' => 'ig_es_process_queue', ); // Send an asynchronous request to trigger sending of confirmation emails. IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args, true ); } } } } } /** * Method to truncate temp import table and options used during import process * * @param string import identifier * * @since 4.6.6 * * @since 4.7.5 Renamed the function, converted to static method */ public static function remove_import_data( $identifier = '' ) { global $wpdb; // If identifier is empty that means, there isn't any importer running. We can safely delete the import data. if ( empty( $identifier ) ) { // Delete options used during import. delete_option( 'ig_es_bulk_import' ); delete_option( 'ig_es_bulk_import_errors' ); // We are trancating table so that primary key is reset to 1 otherwise ID column's value will increase on every insert and at some point ID column's data type may not be able to accomodate its value resulting in insert to fail. $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}ig_temp_import" ); } } public function api() { $mailchimp_apikey = ig_es_get_request_data( 'mailchimp_api_key' ); if ( ! $this->api ) { $this->api = new ES_Mailchimp_API( $mailchimp_apikey ); } return $this->api; } public function api_request() { check_ajax_referer( 'ig-es-admin-ajax-nonce', 'security' ); $endpoint = str_replace( 'wp_ajax_ig_es_mailchimp_', '', current_filter() ); switch ( $endpoint ) { case 'lists': $lists = $this->api()->lists(); wp_send_json_success( array( 'lists' => $lists, ) ); break; case 'import_list': $limit = ig_es_get_request_data( 'limit' ); $offset = ig_es_get_request_data( 'offset' ); $contact_status = ig_es_get_request_data( 'status' ); $import_identifier = ig_es_get_request_data( 'identifier' ); if ( ! isset( $_POST['id'] ) ) { wp_send_json_error( array( 'message' => 'no list', ) ); } $limit = isset( $limit ) ? (int) $limit : 1000; $offset = isset( $offset ) ? (int) $offset : 0; $status = isset( $contact_status ) ? (array) $contact_status : array( 'subscribed' ); $identifier = isset( $import_identifier ) ? $import_identifier : ''; $list_id = ig_es_get_request_data( 'id' ); $subscribers = $this->api()->members( $list_id, array( 'count' => $limit, 'offset' => $offset, 'status' => $status, ) ); $list_name = ig_es_get_request_data( 'list_name' ); $importing_from = 'mailchimp-api'; $raw_data = ''; $seperator = ';'; $data_contain_headers = false; $headers = array( __( 'Email', 'email-subscribers' ), __( 'First Name', 'email-subscribers' ), __( 'Last Name', 'email-subscribers' ), __( 'Status', 'email-subscribers' ), __( 'List Name', 'email-subscribers' ), ); $es_mailchimp_status_mapping = array( 'subscribed' => __( 'Subscribed', 'email-subscribers' ), 'unsubscribed' => __( 'Unsubscribed', 'email-subscribers' ), 'pending' => __( 'Unconfirmed', 'email-subscribers' ), 'cleaned' => __( 'Hard Bounced', 'email-subscribers' ), ); foreach ( $subscribers as $subscriber ) { if ( ! $subscriber->email_address ) { continue; } $user_data = array(); $list_name = ! empty( $list_name ) ? $list_name : 'Test'; $status = ! empty( $subscriber->status ) ? $subscriber->status : 'subscribed'; if ( ! empty( $es_mailchimp_status_mapping[ $status ] ) ) { $status = $es_mailchimp_status_mapping[ $status ]; } $user_data = array( $subscriber->email_address, $subscriber->merge_fields->FNAME, $subscriber->merge_fields->LNAME, $status, $list_name, ); $raw_data .= implode( $seperator, $user_data ); $raw_data .= "\n"; } $response = array(); if ( ! empty( $raw_data ) ) { $result = self::insert_into_temp_table( $raw_data, $seperator, $data_contain_headers, $headers, $identifier, 'mailchimp-api' ); $identifier = $result['identifier']; } $response = array( 'total' => $this->api()->get_total_items(), 'added' => count( $subscribers ), 'subscribers' => count( $subscribers ), 'identifier' => $identifier, ); wp_send_json_success( $response ); break; case 'verify_api_key': $result = $this->api()->ping(); if ( $result ) { wp_send_json_success( array( 'message' => $result->health_status, ) ); } break; } wp_send_json_error(); } public static function insert_into_temp_table( $raw_data, $seperator = ',', $data_contain_headers = false, $headers = array(), $identifier = '', $importing_from = 'csv' ) { global $wpdb; $raw_data = ( trim( str_replace( array( "\r", "\r\n", "\n\n" ), "\n", $raw_data ) ) ); if ( function_exists( 'mb_convert_encoding' ) ) { $encoding = mb_detect_encoding( $raw_data, 'auto' ); } else { $encoding = 'UTF-8'; } $lines = explode( "\n", $raw_data ); // If data itself contains headers(in case of CSV), then remove it. if ( $data_contain_headers ) { array_shift( $lines ); } $lines_count = count( $lines ); $batch_size = min( 500, max( 200, round( count( $lines ) / 200 ) ) ); // Each entry in temporary import table will have this much of subscribers data $parts = array_chunk( $lines, $batch_size ); $partcount = count( $parts ); do_action( 'ig_es_remove_import_data', $identifier ); $identifier = empty( $identifier ) ? uniqid() : $identifier; $response['identifier'] = $identifier; for ( $i = 0; $i < $partcount; $i++ ) { $part = $parts[ $i ]; $new_value = base64_encode( serialize( $part ) ); $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}ig_temp_import (data, identifier) VALUES (%s, %s)", $new_value, $identifier ) ); } $bulk_import_data = get_option( 'ig_es_bulk_import', array() ); if ( ! empty( $bulk_import_data ) ) { $partcount += $bulk_import_data['parts']; $lines_count += $bulk_import_data['lines']; } $bulkimport = array( 'imported' => 0, 'errors' => 0, 'duplicate_emails_count' => 0, 'existing_contacts' => 0, 'updated_contacts' => 0, 'encoding' => $encoding, 'parts' => $partcount, 'lines' => $lines_count, 'separator' => $seperator, 'importing_from' => $importing_from, 'data_contain_headers' => $data_contain_headers, 'headers' => $headers, ); $response['success'] = true; $response['memoryusage'] = size_format( memory_get_peak_usage( true ), 2 ); update_option( 'ig_es_bulk_import', $bulkimport, 'no' ); return $response; } }