Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,769 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class BWFCRM_AFFWP_Importer
*
* @package Autonami CRM
*/
#[AllowDynamicProperties]
class BWFCRM_AFFWP_Importer extends BWFCRM_Importer_Base {
/**
* WordPress importer action hook
*
* @var string
*/
private $action_hook = 'bwfcrm_affwp_import';
/**
* Working Import ID
*
* @var int
*/
private $import_id = 0;
/**
* Working import DB data
*
* @var array
*/
private $db_import_row = array();
/**
* Working import meta data
*
* @var array
*/
private $import_meta = array();
/**
* Import start time
*
* @var int
*/
private $start_import_time = 0;
/**
* Array of users fetched
*
* @var array
*/
private $affiliates = array();
/** Import Contacts Results */
private $skipped = 0;
private $failed = 0;
private $succeed = 0;
private $processed = 0;
private $count = 0;
private $offset = 0;
private $log_handle = null;
/**
* Create Import & Start Import
*
* @param array $tags
* @param array $lists
* @param bool $update_existing
* @param bool $marketing_status
*/
public function create_import( $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = true, $imported_contact_status = 1 ) {
$this->log_file = BWFCRM_Importer::get_log_file_name( 'affwp' );
$import_id = $this->create_affwp_import_record( $tags, $lists, $update_existing, $marketing_status, $disable_events, $imported_contact_status );
$log_file_header = array( 'Email', 'User ID', 'Status', 'Error Message' );
BWFCRM_Importer::create_importer_log_file( $this->log_file, $log_file_header );
/** Schedule the Import */
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
return $import_id;
}
/**
* Get Import Status or Start Import
*
* @param int $import_id
*
* @return array|string
*/
public function get_import_status( $import_id = 0 ) {
/**
* Check for import record exists
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
/**
* Get percent completed
*/
$percent = $this->get_percent_completed();
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
$status = absint( $this->db_import_row['status'] );
if ( BWFCRM_Importer::$IMPORT_IN_PROGRESS === $status && bwf_has_action_scheduled( $this->action_hook, array( 'import_id' => absint( $import_id ) ) && empty( $this->db_import_row['meta']['is_running'] ) ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $import_id ) ) );
add_filter( 'bwfan_as_per_call_time', function () {
return 10;
} );
$this->import( $import_id );
/** If still in progress, return the status */
$this->db_import_row = null;
$this->maybe_get_import( $import_id );
/** Get percent completed */
$percent = $this->get_percent_completed();
$status = absint( $this->db_import_row['status'] );
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
}
$data = array(
'import_id' => $this->import_id,
'percent' => $percent,
'status' => BWFCRM_Importer::get_status_text( $status ),
'log' => $this->get_import_meta( 'log' ),
);
/** If import completed 100% and import has log file */
if ( 100 === $percent && ! empty( $this->import_meta['log_file'] ) ) {
$data['has_log_file'] = true;
}
return $data;
}
/**
* Returns import stat and create import record if not found
*
* @param int $import_id
* @param array $roles
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param false $disable_events
* @param int $imported_contact_status
*
* @return bool
*/
public function maybe_get_import( $import_id = 0 ) {
/**
* check if import data already fetched
*/
if ( is_array( $this->db_import_row ) && ! empty( $this->db_import_row ) && absint( $this->db_import_row['id'] ) === absint( $import_id ) ) {
return true;
}
/**
* Create import entry in table if not exists
*/
$this->import_id = absint( $import_id );
/**
* Get import data from DB
*/
$this->db_import_row = BWFAN_Model_Import_Export::get( $this->import_id );
$this->import_meta = ! empty( $this->db_import_row['meta'] ) ? json_decode( $this->db_import_row['meta'], true ) : array();
/**
* Set log data
*/
if ( isset( $this->import_meta['log'] ) ) {
$this->skipped = isset( $this->import_meta['log']['skipped'] ) && empty( $this->skipped ) ? absint( $this->import_meta['log']['skipped'] ) : $this->skipped;
$this->succeed = isset( $this->import_meta['log']['succeed'] ) && empty( $this->succeed ) ? absint( $this->import_meta['log']['succeed'] ) : $this->succeed;
$this->failed = isset( $this->import_meta['log']['failed'] ) && empty( $this->failed ) ? absint( $this->import_meta['log']['failed'] ) : $this->failed;
}
if ( isset( $this->import_meta['log_file'] ) ) {
$this->log_file = $this->import_meta['log_file'];
}
$this->processed = isset( $this->db_import_row['processed'] ) && empty( $this->processed ) ? absint( $this->db_import_row['processed'] ) : $this->processed;
$this->count = isset( $this->db_import_row['count'] ) && empty( $this->count ) ? absint( $this->db_import_row['count'] ) : $this->count;
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
return is_array( $this->db_import_row ) && ! empty( $this->db_import_row );
}
/**
* Populate AFFWP Affiliates
*
* @param $role
*/
public function populate_affiliates() {
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
$user_ids = $this->get_affiliates( $this->offset, 25 );
/**
* Fetching uses to import
*/
$users = get_users( array(
'include' => $user_ids,
) );
$this->affiliates = array();
/**
* Formatting user data
*/
if ( ! empty( $users ) ) {
/** @var WP_User $user */
foreach ( $users as $user ) {
$this->affiliates[ absint( $user->ID ) ] = $user;
}
krsort( $this->affiliates, 1 );
}
}
public function get_affiliates( $offset, $limit ) {
return $this->get_affiliates_id( array(
'before' => $offset,
'limit' => $limit,
'order' => 'DESC',
) );
}
/**
* Insert a new row for importer
*
* @param array $roles
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param bool $disable_events
*
* @return int
*/
public function create_affwp_import_record( $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1 ) {
/**
* Adding affwp importer entry in DB
*/
$affiliates = $this->get_affiliates( 0, 1 );
BWFAN_Model_Import_Export::insert( array(
'offset' => $affiliates[0] + 1,
'processed' => 0,
'count' => $this->get_affiliates_count(),
'type' => BWFCRM_Importer::$IMPORT,
'status' => BWFCRM_Importer::$IMPORT_IN_PROGRESS,
'meta' => wp_json_encode( array(
'import_type' => 'affwp',
'update_existing' => $update_existing,
'tags' => $tags,
'lists' => $lists,
'marketing_status' => $marketing_status,
'disable_events' => $disable_events,
'imported_contact_status' => $imported_contact_status,
'log_file' => $this->log_file,
) ),
'created_date' => current_time( 'mysql', 1 ),
'last_modified' => date( 'Y-m-d H:i:s', time() - 6 ),
) );
return BWFAN_Model_Import_Export::insert_id();
}
/**
* Check if import action is run less than 5 seconds ago
*
* @return bool
*/
public function is_recently_imported() {
$last_modified_seconds = time() - strtotime( $this->db_import_row['last_modified'] );
return $last_modified_seconds <= 5;
}
/**
* Returns progress of the importer
*
* @return int
*/
public function get_percent_completed() {
$count = isset( $this->db_import_row['count'] ) && ! empty( intval( $this->db_import_row['count'] ) ) ? intval( $this->db_import_row['count'] ) : 0;
$processed = isset( $this->db_import_row['processed'] ) && ! empty( intval( $this->db_import_row['processed'] ) ) ? intval( $this->db_import_row['processed'] ) : 0;
if ( 0 === $count ) {
return 100;
}
if ( 0 === $processed ) {
return 0;
}
return absint( min( ( ( $processed / $count ) * 100 ), 100 ) );
}
/**
* Update last_modified to inform subsequent requests
*/
public function update_last_modified( $minus = 0 ) {
$last_modified_time = time() - $minus;
$last_modified_time = date( 'Y-m-d H:i:s', $last_modified_time );
BWFAN_Model_Import_Export::update( array(
'last_modified' => $last_modified_time,
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['last_modified'] = $last_modified_time;
}
/**
* Action Scheduler Contact Import
*
* @param $import_id
*/
public function import( $import_id ) {
/**
* End import when import data is not found
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
$this->end_import( 2, 'Unable to get Import ID: ' . $import_id );
return;
}
if ( $this->is_recently_imported() || ! empty( $this->db_import_row['meta']['is_running'] ) ) {
return;
}
/** Update last_modified to inform subsequent requests */
$this->update_last_modified();
/** Set Import to running */
$this->update_status_to_running();
$this->start_import_time = time();
$this->log_handle = fopen( $this->log_file, 'a' );
$run_time = BWFCRM_Common::get_contact_export_per_call_time();
while ( ( ( time() - $this->start_import_time ) < $run_time ) && ! BWFCRM_Common::memory_exceeded() ) {
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Populate Next Set of Affiliates */
$this->populate_affiliates();
foreach ( array_keys( $this->affiliates ) as $user_id ) {
$this->offset = $user_id;
/**
* Import contact from user array
*/
$this->import_contact();
/**
* Updated import entry record
*/
$this->update_import_record();
}
}
if ( ! empty( $this->log_handle ) ) {
fclose( $this->log_handle );
}
/** Remove import running status */
$this->update_status_to_running( true );
/**
* End import if completed
*/
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Update Last modified - 7 to run next iteration immediately */
$this->update_last_modified( 7 );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
}
/**
* Returns import meta
*
* @param string $key
*
* @return mixed|string
*/
public function get_import_meta( $key = '' ) {
return ! empty( $key ) && isset( $this->import_meta[ $key ] ) ? $this->import_meta[ $key ] : '';
}
/**
* Import contact
*/
public function import_contact() {
/**
* Get formatted contact data from user
*/
$contact_data = $this->prepare_contact_data();
if ( false === $contact_data ) {
return;
}
/** Disable Events */
$disable_events = $this->get_import_meta( 'disable_events' );
if ( true === $disable_events ) {
$contact_data['data']['disable_events'] = true;
}
/** Setting Unsubscribe data before initializing contact, because if contact is new then need to update the status */
$do_unsubscribe = false;
if ( 3 === absint( $contact_data['data']['status'] ) ) {
$contact_data['data']['status'] = 1;
$do_unsubscribe = true;
}
/** Get or Create contact and updated status accordingly */
try {
/** Initialising/Creating the Contact */
$contact = new BWFCRM_Contact( $contact_data['email'], true, $contact_data['data'] );
/** If Contact does exists, but doesn't have wpid */
if ( $contact->is_contact_exists() && empty( $contact->contact->get_wpid() ) ) {
$contact->contact->set_wpid( absint( $contact_data['data']['wp_id'] ) );
$contact->contact->save();
}
} catch ( Exception $e ) {
/**
* If failed add failed count and set next user to process
*/
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return;
}
/** Check if contact need to update if existing */
$update_existing = $this->get_import_meta( 'update_existing' );
/** If contact already exists (old) and Update Existing flag is off, then unset status */
if ( $contact->already_exists && ! $update_existing ) {
unset( $contact_data['data']['status'] );
}
/**
* Update contact if update_existing = true
*/
$fields_updated = false;
try {
/** If needed to do unsubscribe */
if ( $do_unsubscribe && $update_existing ) {
$contact->unsubscribe( $disable_events );
}
/** If contact was unsubscribed, and new status is not unsubscribed, then remove the entries from Unsubscriber Table */
if ( ! $do_unsubscribe && $update_existing ) {
/** NOTE: Checking for: "If the contact was unsubscribed" is already in this below function */
$contact->remove_unsubscribe_status();
}
/** Set Data only if contact already exists, as in case of new contact, data is already been set in above code. */
if ( $contact->already_exists ) {
$result = $contact->set_data( $contact_data['data'] );
$fields_updated = $result['fields_changed'];
}
/** Apply tags */
$contact->set_tags( $this->get_import_meta( 'tags' ), true, $disable_events );
/** Apply lists */
$contact->set_lists( $this->get_import_meta( 'lists' ), true, $disable_events );
} catch ( Exception $e ) {
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return;
}
if ( $fields_updated ) {
$contact->save_fields();
}
$contact->save();
/** Contact Imported, increase success count and move to next user */
$this->succeed ++;
$this->processed ++;
}
/**
* Returns formatted contact data
*
* @return array
*/
public function prepare_contact_data() {
/**
* Get user data form wp_user based on current position
*/
$user = $this->affiliates[ $this->offset ];
/**
* Fallback if WP_User data not found
*/
if ( ! $user instanceof WP_User ) {
$user = get_user_by( 'id', $this->offset );
}
/**
* Get contact fields
*/
$contact_fields = BWFCRM_Fields::get_contact_fields_from_db( 'slug' );
/**
* Set marketing status to set
*/
$import_status = isset( $this->import_meta['marketing_status'] ) ? absint( $this->import_meta['marketing_status'] ) : 0;
if ( isset( $this->import_meta['imported_contact_status'] ) ) {
$import_status = $this->get_import_meta( 'imported_contact_status' );
}
/**
* Form contact data form user data
*/
$email = $user->user_email;
$data = array(
'f_name' => $user->first_name,
'l_name' => $user->last_name,
'status' => $import_status,
'wp_id' => $user->ID
);
/** WooCommerce User Meta */
$phone = get_user_meta( $user->ID, 'billing_phone', true );
$city = get_user_meta( $user->ID, 'billing_city', true );
$state = get_user_meta( $user->ID, 'billing_state', true );
$country = get_user_meta( $user->ID, 'billing_country', true );
$postcode = get_user_meta( $user->ID, 'billing_postcode', true );
$address1 = get_user_meta( $user->ID, 'billing_address_1', true );
$address2 = get_user_meta( $user->ID, 'billing_address_2', true );
$company = get_user_meta( $user->ID, 'billing_company', true );
$data['f_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_first_name', true ) : $data['f_name'];
$data['l_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_last_name', true ) : $data['l_name'];
$email = empty( $email ) ? get_user_meta( $user->ID, 'billing_email', true ) : $email;
! empty( $postcode ) ? $data[ $contact_fields['postcode']['ID'] ] = $postcode : null;
! empty( $address1 ) ? $data[ $contact_fields['address-1']['ID'] ] = $address1 : null;
! empty( $address2 ) ? $data[ $contact_fields['address-2']['ID'] ] = $address2 : null;
! empty( $company ) ? $data[ $contact_fields['company']['ID'] ] = $company : null;
! empty( $city ) ? $data[ $contact_fields['city']['ID'] ] = $city : null;
! empty( $phone ) ? $data['contact_no'] = $phone : null;
! empty( $state ) ? $data['state'] = $state : null;
! empty( $country ) ? $data['country'] = BWFAN_PRO_Common::get_country_iso_code( $country ) : null;
$data['source'] = 'affwp';
return array(
'email' => $email,
'data' => $data
);
}
/**
* Update the importer data in table
*/
public function update_import_record() {
/**
* Set new stat of importer
*/
$this->import_meta['log'] = array( 'succeed' => $this->succeed, 'failed' => $this->failed, 'skipped' => $this->skipped );
$import_meta = wp_json_encode( $this->import_meta );
BWFAN_Model_Import_Export::update( array(
"offset" => $this->offset,
'processed' => $this->processed,
"meta" => $import_meta,
'last_modified' => current_time( 'mysql', 1 )
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['offset'] = $this->offset;
$this->db_import_row['processed'] = $this->processed;
$this->db_import_row['meta'] = $import_meta;
}
public function update_status_to_running( $remove = false ) {
if ( $remove && isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
} else {
$this->import_meta['is_running'] = true;
}
$import_meta = wp_json_encode( $this->import_meta );
/** Update status to running */
BWFAN_Model_Import_Export::update( array( 'meta' => $import_meta ), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['meta'] = $import_meta;
}
/**
* Stops importer running
*
* @param int $status
* @param string $status_message
*/
public function end_import( $status = 3, $status_message = '' ) {
/**
* Checks importer entry exists
*/
if ( empty( $this->import_id ) ) {
return;
}
/**
* Check if import action is scheduled and status is in progress
*/
$db_status = absint( $this->db_import_row['status'] );
if ( bwf_has_action_scheduled( $this->action_hook ) && $db_status === BWFCRM_Importer::$IMPORT_IN_PROGRESS ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $this->import_id ) ), 'bwfcrm' );
}
/**
* Adding log message
*/
if ( ! empty( $status_message ) ) {
BWFAN_Core()->logger->log( $status_message, 'import_contacts_crm' );
} elseif ( 3 === $status ) {
$status_message = 'Contacts imported. Import ID: ' . $this->import_id;
}
$this->db_import_row['status'] = $status;
$this->import_meta['status_msg'] = $status_message;
/** Checking log file is empty */
$file_data = file( $this->log_file );
if ( empty( $file_data ) || ! is_array( $file_data ) ) {
unset( $this->import_meta['log_file'] );
wp_delete_file( $this->log_file );
}
if ( isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
}
/**
* Updating importer data in DB
*/
BWFAN_Model_Import_Export::update( array(
'status' => $status,
'meta' => wp_json_encode( $this->import_meta ),
), array( 'id' => absint( $this->import_id ) ) );
$key = 'bwfan_import_done';
$imported = get_option( $key, [] );
$imported['affwp'] = 1;
update_option( $key, $imported );
}
/**
* Prepare log data and append data to file
*
* @param $email
* @param $status
* @param $err_msg
* @param $user_id
*/
public function prepare_log_data( $email, $status, $err_msg, $user_id = '' ) {
$data = array(
$email,
$user_id,
$status,
$err_msg,
);
if ( ! empty( $this->log_handle ) ) {
fputcsv( $this->log_handle, $data );
}
}
public function get_affiliates_count() {
return $this->get_affiliates_id( array(
'count_only' => true,
) );
}
/**
* Get affiliates
*
* @return int
*/
public function get_affiliates_id( $args = array() ) {
global $wpdb;
$args = wp_parse_args( $args, array(
'offset' => 0,
'limit' => 25,
'order' => 'ASC',
'order_by' => 'user_id',
'before' => 0,
'count_only' => false,
) );
$pagination_query = '';
if ( ! empty( $args['offset'] ) || ! empty( $args['limit'] ) ) {
$pagination_query = 'LIMIT ' . $args['offset'] . ', ' . $args['limit'];
}
$where_query = '';
if ( ! empty( $args['before'] ) ) {
$where_query .= 'AND user_id < ' . $args['before'];
}
$order = $args['order'];
$order_by = $args['order_by'];
if ( true === $args['count_only'] ) {
$count = $wpdb->get_col( "SELECT count(DISTINCT user_id) from {$wpdb->prefix}affiliate_wp_affiliates WHERE 1=1 $where_query" ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
return ! empty( $count ) ? absint( $count[0] ) : 0;
}
$users = $wpdb->get_results( "SELECT DISTINCT user_id from {$wpdb->prefix}affiliate_wp_affiliates WHERE 1=1 $where_query ORDER BY $order_by $order $pagination_query", ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( empty( $users ) ) {
return array();
}
$users = array_column( $users, 'user_id' );
$users = array_map( 'absint', $users );
$users = array_filter( $users );
return $users;
}
}
BWFCRM_Core()->importer->register( 'affwp', 'BWFCRM_AFFWP_Importer' );

View File

@@ -0,0 +1,850 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class BWFCRM_CSV_Importer
* @package Autonami CRM
*/
#[AllowDynamicProperties]
class BWFCRM_CSV_Importer {
/**
* CSV importer action hook
*
* @var string
*/
private $action_hook = 'bwfcrm_csv_import';
/**
* Working import ID
*
* @var int
*/
private $import_id = 0;
/**
* Working import DB data
*
* @var array
*/
private $db_import_row = array();
/**
* Working import meta data
*
* @var array
*/
private $import_meta = array();
/**
* Import start time
*
* @var int
*/
private $start_import_time = 0;
/**
* Flag for the iterated users from populated data
*
* @var int
*/
private $current_pos = 0;
/**
* Mapped CSV field array
*
* @var array
*/
private $mapped_fields = array();
/** Import Contacts Results */
private $skipped = 0;
private $failed = 0;
private $succeed = 0;
private $log_handle = null;
private $newTags = [];
private $newLists = [];
public $log_file = null;
/**
* Create Import
*
* @param $import_meta
*
* @return int
*/
public static function create_import( $import_meta ) {
/** Adding CSV importer entry in DB */
BWFAN_Model_Import_Export::insert( array(
'offset' => 0,
'type' => BWFCRM_Importer::$IMPORT,
'status' => BWFCRM_Importer::$IMPORT_IN_PROGRESS,
'created_date' => current_time( 'mysql', 1 ),
'last_modified' => date( 'Y-m-d H:i:s', time() - 6 ),
'meta' => wp_json_encode( $import_meta )
) );
/** Fetch importer ID */
return BWFAN_Model_Import_Export::insert_id();
}
/**
* Create import from CSV file
*
* @param $file
* @param string $delimiter
*
* @return array|string
*/
public static function create_import_from_csv( $file, $delimiter = ',' ) {
$import_meta = array(
'import_type' => 'csv',
'delimiter' => $delimiter
);
/** Check for import directory and create if not exists */
if ( ! file_exists( BWFCRM_IMPORT_DIR . '/' ) ) {
wp_mkdir_p( BWFCRM_IMPORT_DIR );
}
/** Move the file to directory */
$new_file_name = md5( rand() . time() );
$new_file = BWFCRM_IMPORT_DIR . '/' . $new_file_name;
$move_new_file = @move_uploaded_file( $file['tmp_name'], $new_file );
/** Validating the file and delete importer entry if encountered error */
if ( false === $move_new_file ) {
return __( 'Invalid CSV file / Unable to upload file', 'wp-marketing-automations-pro' );
}
$log_file = BWFCRM_Importer::get_log_file_name( 'csv' );
$import_meta['file'] = $new_file;
$import_meta['log_file'] = $log_file;
/** Create import with meta */
$import_id = self::create_import( $import_meta );
$log_file_header = array( 'ID', 'Email', 'First Name', 'Last Name', 'Status', 'Message' );
BWFCRM_Importer::create_importer_log_file( $log_file, $log_file_header );
return array(
'import_id' => $import_id,
'file' => $new_file,
);
}
/**
* Get mapping headers from uploaded CSV and CRM fields from DB
*
* @param string $csv_file
* @param string $delimiter
*
* @return array|string
*/
public static function get_mapping_options_from_csv( $csv_file, $delimiter ) {
$handle = fopen( $csv_file, 'r' );
/** Fetching CSV header */
$headers = false !== $handle ? fgetcsv( $handle, 0, $delimiter ) : false;
if ( ! is_array( $headers ) ) {
return __( 'Unable to read file', 'wp-marketing-automations-pro' );
}
if ( isset( $headers[0] ) ) {
$headers[0] = self::remove_utf8_bom( $headers[0] );
}
/** Formatting CSV header for mapping */
foreach ( $headers as $index => $header ) {
$headers[ $index ] = array( 'index' => $index, 'header' => $header );
}
$extra_data = [
'id' => 0,
'name' => 'Map Tags and Lists',
'fields' => [
[
'id' => 'tags',
'name' => 'Tags',
],
[
'id' => 'lists',
'name' => 'Lists',
]
]
];
/** Get contact fields */
$fields = BWFCRM_Fields::get_groups_with_fields( true, true, true, true );
$fields[] = $extra_data;
return array(
'headers' => $headers,
'fields' => $fields,
);
}
/**
* Remove UTF8_bom
*
* @param string $string
*
* @return string
*/
private static function remove_utf8_bom( $string ) {
if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) {
$string = substr( $string, 3 );
}
return $string;
}
/**
* Start the Import
*
* @param int $import_id
* @param array $mapped_fields
* @param array $tags
* @param array $lists
* @param bool $update_existing
* @param bool $marketing_status
* @param int $imported_contact_status
*
* @return string|true
*/
public function start_import( $import_id, $mapped_fields = array(), $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1, $dont_update_blank_values = true ) {
/** Check for import record exists */
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
return $this->maybe_initiate_import( $import_id, $mapped_fields, $tags, $lists, $update_existing, $marketing_status, $disable_events, $imported_contact_status, $dont_update_blank_values );
}
/**
* Get Import Status or Start Import
*
* @param $import_id
*
* @return array|string
*/
public function get_import_status( $import_id ) {
/** Check for import record exists */
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
/** Get percent completed */
$percent = $this->get_percent_completed();
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
$status = absint( $this->db_import_row['status'] );
if ( BWFCRM_Importer::$IMPORT_IN_PROGRESS === $status && bwf_has_action_scheduled( $this->action_hook, array( 'import_id' => absint( $import_id ) ) && empty( $this->db_import_row['meta']['is_running'] ) ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $import_id ) ) );
add_filter( 'bwfan_as_per_call_time', function () {
return 10;
} );
$this->import( $import_id );
/** If still in progress, return the status */
$this->db_import_row = null;
$this->maybe_get_import( $import_id );
/** Get percent completed */
$percent = $this->get_percent_completed();
$status = absint( $this->db_import_row['status'] );
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
}
$data = array(
'percent' => $percent,
'status' => BWFCRM_Importer::get_status_text( $status ),
'log' => $this->get_import_meta( 'log' )
);
/** If import completed 100% and import has log file */
if ( 100 === $percent && ! empty( $this->import_meta['log_file'] ) ) {
$data['has_log_file'] = true;
}
return $data;
}
/**
* Get importer data
*
* @param $import_id
*
* @return bool
*/
public function maybe_get_import( $import_id ) {
/** Check if import data already fetched */
if ( is_array( $this->db_import_row ) && ! empty( $this->db_import_row ) && absint( $this->db_import_row['id'] ) === absint( $import_id ) ) {
return true;
}
$this->import_id = absint( $import_id );
/** Get import data from DB */
$this->db_import_row = BWFAN_Model_Import_Export::get( $this->import_id );
$this->import_meta = ! empty( $this->db_import_row['meta'] ) ? json_decode( $this->db_import_row['meta'], true ) : array();
/** Set log data */
if ( isset( $this->import_meta['log'] ) && is_array( $this->import_meta['log'] ) ) {
$this->skipped = isset( $this->import_meta['log']['skipped'] ) && empty( $this->skipped ) ? absint( $this->import_meta['log']['skipped'] ) : $this->skipped;
$this->succeed = isset( $this->import_meta['log']['succeed'] ) && empty( $this->succeed ) ? absint( $this->import_meta['log']['succeed'] ) : $this->succeed;
$this->failed = isset( $this->import_meta['log']['failed'] ) && empty( $this->failed ) ? absint( $this->import_meta['log']['failed'] ) : $this->failed;
}
if ( isset( $this->import_meta['log_file'] ) ) {
$this->log_file = $this->import_meta['log_file'];
}
return is_array( $this->db_import_row ) && ! empty( $this->db_import_row );
}
/**
* Check if import action is run less than 5 seconds ago
*
* @return bool
*/
public function is_recently_imported() {
$last_modified_seconds = time() - strtotime( $this->db_import_row['last_modified'] );
return $last_modified_seconds <= 5;
}
/**
* Get Import Status or Start Import
*
* @param $import_id
* @param array $mapped_fields
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param false $disable_events
* @param int $imported_contact_status
*/
public function maybe_initiate_import( $import_id, $mapped_fields = array(), $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1, $dont_update_blank_values = true ) {
$start_pos = absint( $this->db_import_row['offset'] );
/** Returns if mapped field not found */
if ( empty( $mapped_fields ) || ! is_array( $mapped_fields ) ) {
return __( 'Mapped Fields are required', 'wp-marketing-automations-pro' );
}
/** Set importer meta data */
$meta = wp_json_encode( array(
'mapped_fields' => $mapped_fields,
'tags' => $tags,
'lists' => $lists,
'update_existing' => $update_existing,
'marketing_status' => $marketing_status,
'delimiter' => $this->get_import_meta( 'delimiter' ),
'file' => $this->get_import_meta( 'file' ),
'disable_events' => $disable_events,
'imported_contact_status' => $imported_contact_status,
'dont_update_blank' => $dont_update_blank_values,
'log_file' => $this->log_file,
) );
/** Update importer entry */
BWFAN_Model_Import_Export::update( array( "offset" => $start_pos, "meta" => $meta ), array( 'id' => absint( $import_id ) ) );
/** Check if import action is scheduled and status is in progress */
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
return true;
}
/**
* Returns the progress of importer
*
* @return int
*/
public function get_percent_completed() {
$meta = json_decode( $this->db_import_row['meta'], true );
/** Because file gets deleted after import is completed, so returning 100% */
if ( ! isset( $meta['file'] ) || ! file_exists( $meta['file'] ) || empty( filesize( $meta['file'] ) ) ) {
return 100;
}
$start_pos = isset( $this->db_import_row['offset'] ) && ! empty( absint( $this->db_import_row['offset'] ) ) ? absint( $this->db_import_row['offset'] ) : 1;
return absint( min( ( ( $start_pos / filesize( $meta['file'] ) ) * 100 ), 100 ) );
}
/**
* Update last_modified to inform subsequent requests
*/
public function update_last_modified( $minus = 0 ) {
$last_modified_time = time() - $minus;
$last_modified_time = date( 'Y-m-d H:i:s', $last_modified_time );
BWFAN_Model_Import_Export::update( array(
'last_modified' => $last_modified_time,
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['last_modified'] = $last_modified_time;
}
/**
* Action Scheduler Contact Import
*
* @param $import_id
*/
public function import( $import_id ) {
/** End import when import data is not found */
if ( ! $this->maybe_get_import( $import_id ) ) {
$this->end_import( 2, 'Unable to get Import ID: ' . $import_id );
return;
}
if ( $this->is_recently_imported() || ! empty( $this->db_import_row['meta']['is_running'] ) ) {
return;
}
/** Update last_modified to inform subsequent requests */
$this->update_last_modified();
$delimiter = $this->get_import_meta( 'delimiter' );
$delimiter = ( empty( $delimiter ) ? ',' : $delimiter );
/** Get File handle */
$file = $this->get_import_meta( 'file' );
$handle = fopen( $file, 'r' );
if ( false === $handle ) {
$this->end_import( 2, 'Unable to make handle for File: ' . $file );
return;
}
/** Get File (CSV) Headers */
$headers = fgetcsv( $handle, 0, $delimiter );
if ( ! is_array( $headers ) ) {
$this->end_import( 2, 'Unable to get headers: ' . $file );
return;
}
if ( isset( $headers[0] ) ) {
$headers[0] = self::remove_utf8_bom( $headers[0] );
}
/** Get Mapped Data */
$this->mapped_fields = $this->get_import_meta( 'mapped_fields' );
if ( ! is_array( $this->mapped_fields ) || empty( $this->mapped_fields ) ) {
$this->end_import( 2, 'Mapped Fields Empty' );
return;
}
/** Set Import to running */
$this->update_status_to_running();
/** Seek file cursor to current location */
$this->current_pos = absint( $this->db_import_row['offset'] );
if ( 0 !== $this->current_pos ) {
fseek( $handle, $this->current_pos );
} else {
$this->db_import_row['offset'] = ftell( $handle );
$this->current_pos = $this->db_import_row['offset'];
}
$this->start_import_time = time();
$this->log_handle = fopen( $this->log_file, 'a' );
$run_time = BWFCRM_Common::get_contact_export_per_call_time();
if ( ! empty( $this->import_meta['tags'] ) ) {
$this->newTags = BWFAN_Model_Terms::get_crm_term_ids( $this->import_meta['tags'], BWFCRM_Term_Type::$TAG );
}
if ( ! empty( $this->import_meta['lists'] ) ) {
$this->newLists = BWFAN_Model_Terms::get_crm_term_ids( $this->import_meta['lists'], BWFCRM_Term_Type::$LIST );
}
while ( ( ( time() - $this->start_import_time ) < $run_time ) && ! BWFCRM_Common::memory_exceeded() ) {
$row = fgetcsv( $handle, 0, $delimiter );
if ( false === $row ) {
break;
}
$this->current_pos = ftell( $handle );
/** Import contact from CSV row data */
$this->import_contact( $row );
/** Update offset & log */
$this->update_offset_and_log();
}
if ( ! empty( $this->log_handle ) ) {
fclose( $this->log_handle );
}
/** Remove the import running status */
$this->update_status_to_running( true );
/** End import if completed */
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Reschedule action for immediate run */
$this->update_last_modified( 7 );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
}
/**
* Returns import meta data
*
* @param string $key
*
* @return mixed|string
*/
public function get_import_meta( $key = '' ) {
return ! empty( $key ) && isset( $this->import_meta[ $key ] ) ? $this->import_meta[ $key ] : '';
}
/**
* Import Contact from CSV row data
*
* @param $csv_row
*/
public function import_contact( $csv_row ) {
/** Format contact data form CSV row data */
$contact_data = $this->prepare_contact_data( $csv_row );
if ( false === $contact_data ) {
return;
}
/** Disable Events */
$disable_events = $this->get_import_meta( 'disable_events' );
if ( true === $disable_events ) {
$contact_data['data']['disable_events'] = true;
}
/** Setting Unsubscribe data before initializing contact, because if contact is new then need to update the status */
$do_unsubscribe = false;
if ( 3 === absint( $contact_data['data']['status'] ) ) {
$contact_data['data']['status'] = 1;
$do_unsubscribe = true;
}
/** Get or Create contact and updated status accordingly */
try {
$contact = new BWFCRM_Contact( $contact_data['email'], true, $contact_data['data'] );
} catch ( Exception $e ) {
/** If failed add failed count and set next user to process */
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, '', $contact_data['data'] );
return;
}
/** Check if contact need to update if existing */
$update_existing = $this->get_import_meta( 'update_existing' );
/** If contact already exists (old) and Update Existing flag is off, then unset status */
if ( $contact->already_exists && ! $update_existing ) {
unset( $contact_data['data']['status'] );
}
/** Update contact if update_existing (setting) = true & contact already exists */
$fields_updated = false;
try {
/** If needed to do unsubscribe */
if ( ( $do_unsubscribe && $update_existing ) || ( $do_unsubscribe && ! $contact->already_exists ) ) {
$contact->unsubscribe( $disable_events );
}
/** If contact was unsubscribed, and new status is not unsubscribed, then remove the entries from Unsubscriber Table */
if ( ! $do_unsubscribe && $update_existing ) {
/** NOTE: Checking for: "If the contact was unsubscribed" is already in this below function */
$contact->remove_unsubscribe_status();
}
if ( $contact->already_exists ) {
// unset creation date if it is already present
if ( isset( $contact_data['data']['creation_date'] ) && ! empty( $contact->contact->get_creation_date() ) ) {
unset( $contact_data['data']['creation_date'] );
}
/** Disable Events */
$dont_update_blank = $this->get_import_meta( 'dont_update_blank' );
// unset fields for which values are blank
if ( true === $dont_update_blank ) {
$contact_cols = array( 'email', 'f_name', 'l_name', 'state', 'country', 'contact_no', 'timezone', 'creation_date', 'gender', 'company', 'dob' );
foreach ( $contact_cols as $col ) {
if ( ! isset( $contact_data['data'][ $col ] ) || ! empty( trim( $contact_data['data'][ $col ] ) ) ) {
continue;
}
unset( $contact_data['data'][ $col ] );
}
}
$result = $contact->set_data( $contact_data['data'] );
$fields_updated = $result['fields_changed'];
}
$tags_to_add = $this->newTags;
/** Tags column in CSV */
if ( isset( $contact_data['data']['tags'] ) && ! empty( $contact_data['data']['tags'] ) ) {
$csv_tag = explode( ',', $contact_data['data']['tags'] );
$column_tags = array_filter( array_map( function ( $tag ) {
return ! empty( $tag ) ? array(
'id' => 0,
'name' => trim( $tag ),
) : [];
}, $csv_tag ) );
$tags_to_add = array_unique( array_merge( $tags_to_add, BWFAN_Model_Terms::get_crm_term_ids( $column_tags, BWFCRM_Term_Type::$TAG ) ) );
}
$lists_to_add = $this->newLists;
/** Lists column in CSV */
if ( isset( $contact_data['data']['lists'] ) && ! empty( $contact_data['data']['lists'] ) ) {
$csv_list = explode( ',', $contact_data['data']['lists'] );
$column_lists = array_filter( array_map( function ( $list ) {
return ! empty( $list ) ? array(
'id' => 0,
'name' => trim( $list ),
) : [];
}, $csv_list ) );
$lists_to_add = array_unique( array_merge( $lists_to_add, BWFAN_Model_Terms::get_crm_term_ids( $column_lists, BWFCRM_Term_Type::$LIST ) ) );
}
/** Apply tags */
if ( ! empty( $tags_to_add ) ) {
$contact->set_tags_v2( $tags_to_add, $disable_events );
}
/** Apply lists */
if ( ! empty( $lists_to_add ) ) {
$contact->set_lists_v2( $lists_to_add, $disable_events );
}
} catch ( Exception $e ) {
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact, $contact_data['data'] );
return;
}
if ( $fields_updated ) {
$contact->save_fields();
}
$contact->save();
/** Contact Imported, increase success count */
$this->succeed ++;
}
/**
* Returns formatted contact data
*
* @param $csv_row
*
* @return array|false
*/
public function prepare_contact_data( $csv_row ) {
/** Get marketing status */
$marketing_status = $this->get_import_meta( 'marketing_status' );
$contact_data = array( 'status' => empty( $marketing_status ) ? 0 : $marketing_status );
if ( isset( $this->import_meta['imported_contact_status'] ) ) {
$contact_data['status'] = 0;
}
$import_status = $this->get_import_meta( 'imported_contact_status' );
if ( ! empty( $import_status ) ) {
$contact_data['status'] = intval( $import_status );
}
/** Formatting CSV row data */
$email = '';
$use_mb = function_exists( 'mb_convert_encoding' );
$error = false;
$error_msg = '';
foreach ( $csv_row as $index => $csv_col ) {
$csv_col_val = trim( $csv_col );
if ( ! isset( $this->mapped_fields[ $index ] ) ) {
continue;
}
$field_id = $this->mapped_fields[ $index ];
if ( $use_mb ) {
$encoding = mb_detect_encoding( $csv_col_val, mb_detect_order(), true );
if ( $encoding ) {
$csv_col_val = mb_convert_encoding( $csv_col_val, 'UTF-8', $encoding );
} else {
$csv_col_val = mb_convert_encoding( $csv_col_val, 'UTF-8', 'UTF-8' );
}
} else {
$csv_col_val = wp_check_invalid_utf8( $csv_col_val, true );
}
/** Email */
if ( 'email' === $field_id ) {
if ( ! is_email( $csv_col_val ) ) {
$error = true;
$this->failed ++;
$error_msg = __( 'Email is not valid.', 'wp-marketing-automations-pro' );
}
$email = $csv_col_val;
continue;
}
$contact_data[ $field_id ] = 'country' === $field_id ? BWFAN_PRO_Common::get_country_iso_code( $csv_col_val ) : $csv_col_val;
}
if ( empty( $email ) || empty( $contact_data ) ) {
$this->failed ++;
$error_msg = __( 'Email is empty.', 'wp-marketing-automations-pro' );
$this->prepare_log_data( '', 'failed', $error_msg, '', $contact_data );
}
if ( true === $error ) {
$this->prepare_log_data( $email, 'failed', $error_msg, '', $contact_data );
return false;
}
$contact_data['source'] = 'csv';
return array(
'email' => $email,
'data' => $contact_data,
);
}
public function update_status_to_running( $remove = false ) {
if ( $remove && isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
} else {
$this->import_meta['is_running'] = true;
}
$import_meta = wp_json_encode( $this->import_meta );
/** Update status to running */
BWFAN_Model_Import_Export::update( array( 'meta' => $import_meta ), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['meta'] = $import_meta;
}
/**
* Updated importer log
*/
public function update_offset_and_log() {
$this->import_meta['log'] = array(
'succeed' => $this->succeed,
'failed' => $this->failed,
'skipped' => $this->skipped,
);
$import_meta = wp_json_encode( $this->import_meta );
BWFAN_Model_Import_Export::update( array(
'offset' => $this->current_pos,
'meta' => $import_meta,
'last_modified' => current_time( 'mysql', 1 ),
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['offset'] = $this->current_pos;
$this->db_import_row['meta'] = $import_meta;
}
/**
* Stop importer running
*
* @param int $status
* @param string $status_message
*/
public function end_import( $status = 3, $status_message = '' ) {
/** Checks importer entry exists */
if ( empty( $this->import_id ) ) {
return;
}
/** Check if import action is scheduled */
if ( bwf_has_action_scheduled( $this->action_hook ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $this->import_id ) ), 'bwfcrm' );
}
if ( ! empty( $status_message ) ) {
/** Adding log message */
BWFAN_Core()->logger->log( $status_message, 'import_contacts_crm' );
} else if ( 3 === $status ) {
$status_message = 'Contacts imported. Import ID: ' . $this->import_id;
if ( isset( $this->import_meta['file'] ) && file_exists( $this->import_meta['file'] ) ) {
/** Checking csv log file is empty */
$file_data = ! empty( $this->log_file ) ? file( $this->log_file ) : [];
if ( ! empty( $this->log_file ) && ! is_array( $file_data ) && empty( $file_data ) ) {
wp_delete_file( $this->log_file );
}
wp_delete_file( $this->import_meta['file'] );
unset( $this->import_meta['file'] );
}
}
$this->db_import_row['status'] = $status;
$this->import_meta['status_msg'] = $status_message;
if ( isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
}
/** Updating importer data in DB */
BWFAN_Model_Import_Export::update( array( "status" => $status, "meta" => wp_json_encode( $this->import_meta ) ), array( 'id' => absint( $this->import_id ) ) );
}
/**
* Prepare log data and append to log file
*
* @param $email
* @param $status
* @param $err_msg
* @param $contact
*/
public function prepare_log_data( $email, $status, $err_msg, $contact = '', $data = [] ) {
$data = array(
$contact instanceof BWFCRM_Contact ? $contact->get_id() : 0,
$email,
isset( $data['f_name'] ) ? $data['f_name'] : '',
isset( $data['l_name'] ) ? $data['l_name'] : '',
$status,
$err_msg,
);
if ( ! empty( $this->log_handle ) ) {
fputcsv( $this->log_handle, $data );
}
}
}
BWFCRM_Core()->importer->register( 'csv', 'BWFCRM_CSV_Importer' );

View File

@@ -0,0 +1,753 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class BWFCRM_WC_Importer
*
* @package Autonami CRM
*/
#[AllowDynamicProperties]
class BWFCRM_WC_Importer extends BWFCRM_Importer_Base {
/**
* WooCommerce importer action hook
*
* @var string
*/
private $action_hook = 'bwfcrm_wc_import';
/**
* Working import ID
*
* @var int
*/
private $import_id = 0;
/**
* Working import DB data
*
* @var array
*/
private $db_import_row = array();
/**
* Working import meta data
*
* @var array
*/
private $import_meta = array();
/**
* Import start time
*
* @var int
*/
private $start_import_time = 0;
/**
* Flag for the iterated users from populated data
*
* @var int
*/
private $current_pos = 0;
/**
* Array of orders fetched
*
* @var array
*/
private $wc_orders = array();
/** Import Contacts Results */
private $skipped = 0;
private $failed = 0;
private $succeed = 0;
private $processed = 0;
private $count = 0;
private $offset = 0;
private $log_handle = null;
/**
* BWFCRM_WC_Importer constructor.
*/
public function __construct() {
add_action( 'bwf_normalize_contact_meta_before_save', array( $this, 'bwfcrm_update_contact_data_before_import' ), 19, 3 );
add_action( 'bwf_normalize_contact_meta_after_save', array( $this, 'bwfcrm_update_contact_data_after_import' ), 20, 3 );
}
public function reset_bwf_wc_customers() {
global $wpdb;
$bwf_table = $wpdb->prefix . 'bwf_wc_customers';
$c = $wpdb->get_row( "SHOW TABLES LIKE '$bwf_table'", ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( ! empty( $c ) ) {
$wpdb->query( "TRUNCATE TABLE $bwf_table" ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
$table = $wpdb->prefix . 'postmeta';
$wpdb->delete( $table, array( 'meta_key' => '_woofunnel_cid' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
$wpdb->delete( $table, array( 'meta_key' => '_woofunnel_custid' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
if ( method_exists( 'BWF_WC_Compatibility', 'is_hpos_enabled' ) && BWF_WC_Compatibility::is_hpos_enabled() ) {
$table = $wpdb->prefix . 'wc_orders_meta';
$wpdb->delete( $table, array( 'meta_key' => '_woofunnel_cid' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
$wpdb->delete( $table, array( 'meta_key' => '_woofunnel_custid' ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
}
BWFAN_Core()->logger->log( 'Customers data reset done, as the start of WC Importer', 'import_wc_contacts' );
}
public function create_import( $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1 ) {
/** Create Log File */
$this->log_file = BWFCRM_Importer::get_log_file_name( 'wc' );
$import_id = $this->import_id = $this->create_wc_import_record( $tags, $lists, $marketing_status, $disable_events, $imported_contact_status, $update_existing );
$log_file_header = array( 'Email', 'Order ID', 'Status', 'Error Message' );
BWFCRM_Importer::create_importer_log_file( $this->log_file, $log_file_header );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
return $import_id;
}
/**
* Update contact data before contact normalization
*
* @param $bwf_contact
* @param $order_id
* @param $order
*/
public function bwfcrm_update_contact_data_before_import( $bwf_contact, $order_id, $order ) {
if ( empty( $this->import_id ) ) {
return;
}
$contact = new BWFCRM_Contact( $bwf_contact );
$created_on = strtotime( $contact->contact->get_creation_date() );
if ( false === $created_on ) {
return;
}
$already_exists = $created_on < ( time() - 5 );
/** Check if contact need to update status if existing */
$update_existing = $this->get_import_meta( 'update_existing' );
if ( $already_exists && ! $update_existing ) {
return;
}
/**
* Update contact status
*/
$disable_events = $this->get_import_meta( 'disable_events' );
$import_status = $this->get_import_meta( 'imported_contact_status' );
switch ( absint( $import_status ) ) {
case 0:
$contact->unverify();
break;
case 1:
$contact->resubscribe( $disable_events );
break;
case 2:
$contact->mark_as_bounced( $disable_events );
break;
case 3:
if ( $order instanceof WC_Order ) {
$order->delete_meta_data( 'marketing_status' );
$order->save();
}
$contact->contact->is_subscribed = false;
$contact->unsubscribe( $disable_events );
break;
case 4:
if ( method_exists( $contact, 'mark_as_soft_bounced' ) ) {
$contact->mark_as_soft_bounced( $disable_events );
} else {
$contact->mark_as_bounced( $disable_events );
}
break;
case 5:
if ( method_exists( $contact, 'mark_as_complaint' ) ) {
$contact->mark_as_complaint( $disable_events );
} else {
$contact->mark_as_bounced( $disable_events );
}
break;
}
}
/**
* Update contact data after contact normalization
*
* @param $bwf_contact
* @param $order_id
* @param $order
*/
public function bwfcrm_update_contact_data_after_import( $bwf_contact, $order_id, $order ) {
if ( ! empty( $this->import_id ) ) {
/**
* Get contact data by id
*/
$contact = new BWFCRM_Contact( $bwf_contact->get_id() );
if ( 0 === $contact->get_id() ) {
BWFAN_Core()->logger->log( 'order id #' . $order_id . ' contact not found', 'import_wc_failed_contacts' );
return;
}
/**
* Checks if add list and tag event needed to run
*/
$disable_events = $this->get_import_meta( 'disable_events' );
$contact_changed = false;
/**
* Apply tags if contains tag data in importer
*/
if ( ! empty( $this->get_import_meta( 'tags' ) ) ) {
$tags = BWFAN_Model_Terms::get_crm_term_ids( $this->get_import_meta( 'tags' ), BWFCRM_Term_Type::$TAG );
$contact->set_tags_v2( $tags, $disable_events );
$contact_changed = true;
}
/**
* Apply lists if contains list data in importer
*/
if ( ! empty( $this->get_import_meta( 'lists' ) ) ) {
$lists = BWFAN_Model_Terms::get_crm_term_ids( $this->get_import_meta( 'lists' ), BWFCRM_Term_Type::$LIST );
$contact->set_lists_v2( $lists, $disable_events );
$contact_changed = true;
}
/** Only run when contact has changes */
if ( $contact_changed ) {
$contact->save();
}
}
}
/**
* Get Import Status or Start Import
*
* @param int $import_id
*
* @return array|string|void
* @throws Exception
*/
public function get_import_status( $import_id = 0 ) {
/**
* Check for import record exists
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
$percent = $this->get_percent_completed();
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
$status = absint( $this->db_import_row['status'] );
if ( BWFCRM_Importer::$IMPORT_IN_PROGRESS === $status && bwf_has_action_scheduled( $this->action_hook, array( 'import_id' => absint( $import_id ) ) && empty( $this->db_import_row['meta']['is_running'] ) ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $import_id ) ) );
add_filter( 'bwfan_as_per_call_time', function () {
return 10;
} );
$this->import( $import_id );
/** If still in progress, return the status */
$this->db_import_row = null;
$this->maybe_get_import( $import_id );
/** Get percent completed */
$percent = $this->get_percent_completed();
$status = absint( $this->db_import_row['status'] );
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
}
$data = array(
'import_id' => $this->import_id,
'percent' => $percent,
'status' => BWFCRM_Importer::get_status_text( $status ),
'log' => $this->get_import_meta( 'log' ),
);
/** If import completed 100% and import has log file */
if ( 100 === $percent && ! empty( $this->import_meta['log_file'] ) ) {
$data['has_log_file'] = true;
}
return $data;
}
/**
* Check for importer to start
*
* @param $import_id
*
* @return bool
*/
public function maybe_get_import( $import_id = 0 ) {
/**
* Check if import data already fetched
*/
if ( is_array( $this->db_import_row ) && ! empty( $this->db_import_row ) && absint( $this->db_import_row['id'] ) === absint( $import_id ) ) {
return true;
}
/**
* Create import entry in table if not exists
*/
$this->import_id = absint( $import_id );
/**
* Get import data from DB
*/
$this->db_import_row = BWFAN_Model_Import_Export::get( $this->import_id );
$this->import_meta = ! empty( $this->db_import_row['meta'] ) ? json_decode( $this->db_import_row['meta'], true ) : array();
/**
* Set log data
*/
if ( isset( $this->import_meta['log'] ) ) {
$this->skipped = isset( $this->import_meta['log']['skipped'] ) && empty( $this->skipped ) ? absint( $this->import_meta['log']['skipped'] ) : $this->skipped;
$this->succeed = isset( $this->import_meta['log']['succeed'] ) && empty( $this->succeed ) ? absint( $this->import_meta['log']['succeed'] ) : $this->succeed;
$this->failed = isset( $this->import_meta['log']['failed'] ) && empty( $this->failed ) ? absint( $this->import_meta['log']['failed'] ) : $this->failed;
}
if ( isset( $this->import_meta['log_file'] ) ) {
$this->log_file = $this->import_meta['log_file'];
}
$this->processed = isset( $this->db_import_row['processed'] ) && empty( $this->processed ) ? absint( $this->db_import_row['processed'] ) : $this->processed;
$this->count = isset( $this->db_import_row['count'] ) && empty( $this->count ) ? absint( $this->db_import_row['count'] ) : $this->count;
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
return is_array( $this->db_import_row ) && ! empty( $this->db_import_row );
}
/**
* Get total orders to import
*
* @return int
*/
public function get_orders_count() {
/**
* Get total order id
*/
$all_order_ids = wc_get_orders( array(
'return' => 'ids',
'numberposts' => '-1',
'type' => 'shop_order',
'parent' => 0,
'date_created' => '<' . time(),
'status' => wc_get_is_paid_statuses(),
) );
/**
* Count orders
*/
$get_threshold_order = count( $all_order_ids );
return $get_threshold_order;
}
/**
* Create a new row in import_export table for importer
*
* @param array $tags
* @param array $lists
* @param false $marketing_status
* @param bool $disable_events
*
* @return int
*/
public function create_wc_import_record( $tags = array(), $lists = array(), $marketing_status = false, $disable_events = false, $imported_contact_status = 1, $update_existing = false ) {
/**
* Adding wp importer entry in DB
*/
BWFAN_Model_Import_Export::insert( array(
'offset' => 0,
'processed' => 0,
'count' => $this->get_orders_count(),
'type' => BWFCRM_Importer::$IMPORT,
'status' => BWFCRM_Importer::$IMPORT_IN_PROGRESS,
'meta' => wp_json_encode( array(
'import_type' => 'wc',
'tags' => $tags,
'lists' => $lists,
'marketing_status' => $marketing_status,
'disable_events' => $disable_events,
'imported_contact_status' => $imported_contact_status,
'update_existing' => $update_existing,
'log_file' => $this->log_file,
) ),
'created_date' => current_time( 'mysql', 1 ),
'last_modified' => date( 'Y-m-d H:i:s', time() - 6 ),
) );
return BWFAN_Model_Import_Export::insert_id();
}
/**
* Returns meta data by key provided
*
* @param string $key
*
* @return mixed|string
*/
public function get_import_meta( $key = '' ) {
return ! empty( $key ) && isset( $this->import_meta[ $key ] ) ? $this->import_meta[ $key ] : '';
}
/**
* Populate order to import
*
* @throws Exception
*/
private function populate_wc_orders() {
$this->current_pos = 0;
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
/**
* Fetching orders to import from
*/
$orders = wc_get_orders( array(
'return' => 'ids',
'type' => 'shop_order',
'parent' => 0,
'limit' => 25,
'offset' => $this->offset,
'date_created' => '<' . strtotime( $this->db_import_row['created_date'] ),
'status' => wc_get_is_paid_statuses(),
) );
// $orders_str = is_array( $orders ) ? implode( ',', $orders ) : '';
// BWFAN_Core()->logger->log( 'order IDs populated for import: ' . $orders_str , 'import_wc_contacts' );
$this->wc_orders = $orders;
}
/**
* Returns the progress of importer
*
* @return int
*/
public function get_percent_completed() {
$processed = isset( $this->db_import_row['processed'] ) && ! empty( absint( $this->db_import_row['processed'] ) ) ? absint( $this->db_import_row['processed'] ) : 0;
$count = isset( $this->db_import_row['count'] ) && ! empty( absint( $this->db_import_row['count'] ) ) ? absint( $this->db_import_row['count'] ) : 0;
if ( 0 === $count ) {
return 100;
}
if ( 0 === $processed ) {
return 0;
}
return absint( min( ( ( $processed / $count ) * 100 ), 100 ) );
}
/**
* Update last_modified to inform subsequent requests
*/
public function update_last_modified( $minus = 0 ) {
$last_modified_time = time() - $minus;
$last_modified_time = date( 'Y-m-d H:i:s', $last_modified_time );
BWFAN_Model_Import_Export::update( array(
'last_modified' => $last_modified_time,
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['last_modified'] = $last_modified_time;
}
/**
* Action Scheduler Contact Import
*
* @param $import_id
*
* @throws Exception
*/
public function import( $import_id ) {
/**
* End import when import data is not found
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
$this->end_import( 2, 'Unable to get Import ID: ' . $import_id );
return;
}
if ( $this->is_recently_imported() || ! empty( $this->db_import_row['meta']['is_running'] ) ) {
return;
}
/** Update Last Modified time to inform subsequent requests */
$this->update_last_modified();
/** Set Import to running */
$this->update_status_to_running();
/** Populate the Woocommerce Orders */
$this->populate_wc_orders();
$this->start_import_time = time();
/** Create log file for failed and skipped contacts */
$this->log_handle = fopen( $this->log_file, 'a' );
/** Set */
$run_time = BWFCRM_Common::get_contact_export_per_call_time();
while ( ( ( time() - $this->start_import_time ) < $run_time ) && ! BWFCRM_Common::memory_exceeded() ) {
/** End Import on 100% */
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Populate Orders when previous orders are done importing */
if ( $this->current_pos >= count( $this->wc_orders ) ) {
/**
* Fetch next set of orders to import
*/
$this->populate_wc_orders();
}
/** if no orders found */
if ( empty( $this->wc_orders ) ) {
$this->processed ++;
$this->offset ++;
$this->current_pos ++;
}
/**
* Import contact from order data
*/
$this->import_order();
/**
* Updated import entry record
*/
$this->update_import_record();
}
if ( ! empty( $this->log_handle ) ) {
fclose( $this->log_handle );
}
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Remove the import running status */
$this->update_status_to_running( true );
$this->update_last_modified( 7 );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
}
/**
* Check if import action is run less than 5 seconds ago
*
* @return bool
*/
public function is_recently_imported() {
$last_modified_seconds = time() - strtotime( $this->db_import_row['last_modified'] );
return $last_modified_seconds <= 5;
}
/**
* Import Order
*/
public function import_order() {
$order_id = $this->wc_orders[ $this->current_pos ];
/**
* Check for order id
*/
if ( empty( absint( $order_id ) ) ) {
return;
}
WooFunnels_DB_Updater::$indexing = true;
try {
/**
* Get or create contact.
*/
$contact_data = bwf_create_update_contact( $order_id, array(), 0, true );
} catch ( Error $e ) {
/**
* Adding error log if import failed
*/
$error_msg = $e->getMessage();
BWFAN_Core()->logger->log( 'order id #' . $order_id . ' parsing broke with error message: ' . $error_msg, 'import_wc_failed_contacts' );
}
WooFunnels_DB_Updater::$indexing = null;
if ( empty( $contact_data ) ) {
/**
* If failed add failed count
*/
$this->failed ++;
$error_msg = empty( $error_msg ) ? __( 'Order data is not valid.', 'wp-marketing-automations-pro' ) : $error_msg;
$order = wc_get_order( $order_id );
$email = $order instanceof WC_Order ? $order->get_billing_email() : '';
$this->prepare_log_data( $email, 'failed', $error_msg, $order_id );
} else {
/**
* Contact Imported , increase success count
*/
$this->succeed ++;
}
/**
* Updating importer count and move to next order
*/
$this->processed ++;
$this->offset ++;
$this->current_pos ++;
}
/**
* Update table data after importing contact
*/
public function update_import_record() {
/**
* Set new stat of importer
*/
$this->import_meta['log'] = array(
'succeed' => $this->succeed,
'failed' => $this->failed,
'skipped' => $this->skipped,
);
$import_meta = wp_json_encode( $this->import_meta );
BWFAN_Model_Import_Export::update( array(
'offset' => $this->offset,
'processed' => $this->processed,
'meta' => $import_meta,
'last_modified' => current_time( 'mysql', 1 ),
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['offset'] = $this->offset;
$this->db_import_row['processed'] = $this->processed;
$this->db_import_row['meta'] = $import_meta;
}
public function update_status_to_running( $remove = false ) {
if ( $remove && isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
} else {
$this->import_meta['is_running'] = true;
}
$import_meta = wp_json_encode( $this->import_meta );
/** Update status to running */
BWFAN_Model_Import_Export::update( array( 'meta' => $import_meta ), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['meta'] = $import_meta;
}
/**
* Stop the importer running
*
* @param int $status
* @param string $status_message
*/
public function end_import( $status = 3, $status_message = '' ) {
/**
* Checks importer entry exists
*/
if ( empty( $this->import_id ) ) {
return;
}
$db_status = absint( $this->db_import_row['status'] );
/**
* Check if import action is scheduled and status is in progress
*/
if ( bwf_has_action_scheduled( $this->action_hook ) && $db_status === BWFCRM_Importer::$IMPORT_IN_PROGRESS ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $this->import_id ) ), 'bwfcrm' );
}
/**
* Adding log message
*/
if ( ! empty( $status_message ) ) {
BWFAN_Core()->logger->log( $status_message, 'import_wc_contacts' );
} elseif ( 3 === $status ) {
$status_message = 'Contacts imported. Import ID: ' . $this->import_id;
if ( ! empty( get_option( 'bwfan_show_contacts_from' ) ) ) {
delete_option( 'bwfan_show_contacts_from' );
}
}
$this->db_import_row['status'] = $status;
$this->import_meta['status_msg'] = $status_message;
/** Checking csv log file row count is greater 1 */
$file_data = file( $this->log_file );
if ( ! is_array( $file_data ) || empty( $file_data ) ) {
unset( $this->import_meta['log_file'] );
wp_delete_file( $this->log_file );
}
if ( isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
}
/**
* Updating importer data in DB
*/
BWFAN_Model_Import_Export::update( array(
'status' => $status,
'meta' => wp_json_encode( $this->import_meta ),
), array( 'id' => absint( $this->import_id ) ) );
}
/**
* Prepare log data & append data to file
*
* @param $email
* @param $status
* @param $err_msg
* @param $order_id
*/
public function prepare_log_data( $email, $status, $err_msg, $order_id = '' ) {
$data = array(
$email,
$order_id,
$status,
$err_msg,
);
if ( ! empty( $this->log_handle ) ) {
fputcsv( $this->log_handle, $data );
}
}
}
BWFCRM_Core()->importer->register( 'wc', 'BWFCRM_WC_Importer' );

View File

@@ -0,0 +1,735 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class BWFCRM_WLM_Importer
*
* @package Autonami CRM
*/
#[AllowDynamicProperties]
class BWFCRM_WLM_Importer extends BWFCRM_Importer_Base {
private $action_hook = 'bwfcrm_wlm_import';
private $import_id = 0;
private $db_import_row = array();
private $import_meta = array();
private $start_import_time = 0;
private $members = array();
/** Import Contacts Results */
private $skipped = 0;
private $failed = 0;
private $succeed = 0;
private $processed = 0;
private $count = 0;
private $offset = 0;
private $log_handle = null;
/**
* Create & Start Import
*
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param bool $disable_events
* @param int $imported_contact_status
*
* @return int
*/
public function create_import( $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = true, $imported_contact_status = 1 ) {
$this->log_file = BWFCRM_Importer::get_log_file_name( 'wlm' );
$import_id = $this->create_wlm_import( $tags, $lists, $update_existing, $marketing_status, $disable_events, $imported_contact_status );
$log_file_header = array( 'Email', 'User ID', 'Status', 'Error Message' );
BWFCRM_Importer::create_importer_log_file( $this->log_file, $log_file_header );
$this->maybe_create_wlm_table();
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
return $import_id;
}
public function maybe_create_wlm_table() {
/** @var BWFCRM_Integration_Wishlist_Member $ins */
$ins = BWFCRM_Core()->integrations->get_integration( 'wishlist_member' );
$ins->maybe_create_db_table();
$ins->maybe_drop_unwanted_columns();
BWF_Model_Contact_WLM_Fields::truncate();
}
/**
* Insert a new row for importer
*
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param bool $disable_events
*
* @return int
*/
public function create_wlm_import( $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1 ) {
$members = $this->get_members( 0, 1 );
BWFAN_Model_Import_Export::insert( array(
'offset' => $members[0] + 1,
'processed' => 0,
'count' => $this->get_members_count(),
'type' => BWFCRM_Importer::$IMPORT,
'status' => BWFCRM_Importer::$IMPORT_IN_PROGRESS,
'meta' => wp_json_encode( array(
'import_type' => 'wlm',
'update_existing' => $update_existing,
'tags' => $tags,
'lists' => $lists,
'marketing_status' => $marketing_status,
'disable_events' => $disable_events,
'imported_contact_status' => $imported_contact_status,
'log_file' => $this->log_file,
) ),
'created_date' => current_time( 'mysql', 1 ),
'last_modified' => date( 'Y-m-d H:i:s', time() - 6 ),
) );
return BWFAN_Model_Import_Export::insert_id();
}
/**
* Functions: Get Import Status or Start Import
*
* @param $import_id
*
* @return array|string|null
*/
public function get_import_status( $import_id = 0 ) {
/**
* Check for import record exists
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
/**
* Get percent completed
*/
$percent = $this->get_percent_completed();
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
$status = absint( $this->db_import_row['status'] );
if ( BWFCRM_Importer::$IMPORT_IN_PROGRESS === $status && bwf_has_action_scheduled( $this->action_hook, array( 'import_id' => absint( $import_id ) ) && empty( $this->db_import_row['meta']['is_running'] ) ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $import_id ) ) );
add_filter( 'bwfan_as_per_call_time', function () {
return 10;
} );
$this->import( $import_id );
/** If still in progress, return the status */
$this->db_import_row = null;
$this->maybe_get_import( $import_id );
/** Get percent completed */
$percent = $this->get_percent_completed();
$status = absint( $this->db_import_row['status'] );
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
}
$data = array(
'import_id' => $this->import_id,
'percent' => $percent,
'status' => BWFCRM_Importer::get_status_text( $status ),
'log' => $this->get_import_meta( 'log' ),
);
/** If import completed 100% and import has log file */
if ( 100 === $percent && ! empty( $this->import_meta['log_file'] ) ) {
$data['has_log_file'] = true;
}
return $data;
}
public function maybe_get_import( $import_id = 0 ) {
/**
* check if import data already fetched
*/
if ( is_array( $this->db_import_row ) && ! empty( $this->db_import_row ) && absint( $this->db_import_row['id'] ) === absint( $import_id ) ) {
return true;
}
/**
* Create import entry in table if not exists
*/
$this->import_id = absint( $import_id );
/**
* Get import data from DB
*/
$this->db_import_row = BWFAN_Model_Import_Export::get( $this->import_id );
$this->import_meta = ! empty( $this->db_import_row['meta'] ) ? json_decode( $this->db_import_row['meta'], true ) : array();
/**
* Set log data
*/
if ( isset( $this->import_meta['log'] ) ) {
$this->skipped = isset( $this->import_meta['log']['skipped'] ) && empty( $this->skipped ) ? absint( $this->import_meta['log']['skipped'] ) : $this->skipped;
$this->succeed = isset( $this->import_meta['log']['succeed'] ) && empty( $this->succeed ) ? absint( $this->import_meta['log']['succeed'] ) : $this->succeed;
$this->failed = isset( $this->import_meta['log']['failed'] ) && empty( $this->failed ) ? absint( $this->import_meta['log']['failed'] ) : $this->failed;
}
$this->processed = isset( $this->db_import_row['processed'] ) && empty( $this->processed ) ? absint( $this->db_import_row['processed'] ) : $this->processed;
$this->count = isset( $this->db_import_row['count'] ) && empty( $this->count ) ? absint( $this->db_import_row['count'] ) : $this->count;
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
return is_array( $this->db_import_row ) && ! empty( $this->db_import_row );
}
/**
* Populate Wishlist Members
*
* @param $role
*/
public function populate_members() {
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
$user_ids = $this->get_members( $this->offset, 25 );
/**
* Fetching uses to import
*/
$users = get_users( array(
'include' => $user_ids,
) );
$this->members = array();
/**
* Formatting user data
*/
if ( ! empty( $users ) ) {
/** @var WP_User $user */
foreach ( $users as $user ) {
$this->members[ absint( $user->ID ) ] = $user;
}
krsort( $this->members, 1 );
}
}
public function get_members( $offset, $limit ) {
/** @var BWFCRM_Integration_Wishlist_Member $ins */
$ins = BWFCRM_Core()->integrations->get_integration( 'wishlist_member' );
return $ins->get_member_ids( array(
'before' => $offset,
'limit' => $limit,
'order' => 'DESC',
) );
}
public function get_members_count() {
/** @var BWFCRM_Integration_Wishlist_Member $ins */
$ins = BWFCRM_Core()->integrations->get_integration( 'wishlist_member' );
return $ins->get_member_ids( array(
'count_only' => true,
) );
}
/**
* Rerurns progress of the importer
*
* @return int
*/
public function get_percent_completed() {
$count = isset( $this->db_import_row['count'] ) && ! empty( intval( $this->db_import_row['count'] ) ) ? intval( $this->db_import_row['count'] ) : 0;
$processed = isset( $this->db_import_row['processed'] ) && ! empty( intval( $this->db_import_row['processed'] ) ) ? intval( $this->db_import_row['processed'] ) : 0;
if ( 0 === $count ) {
return 100;
}
if ( 0 === $processed ) {
return 0;
}
return absint( min( ( ( $processed / $count ) * 100 ), 100 ) );
}
/**
* Check if import action is run less than 5 seconds ago
*
* @return bool
*/
public function is_recently_imported() {
$last_modified_seconds = time() - strtotime( $this->db_import_row['last_modified'] );
return $last_modified_seconds <= 5;
}
/**
* Update last_modified to inform subsequent requests
*/
public function update_last_modified( $minus = 0 ) {
$last_modified_time = time() - $minus;
$last_modified_time = date( 'Y-m-d H:i:s', $last_modified_time );
BWFAN_Model_Import_Export::update( array(
'last_modified' => $last_modified_time,
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['last_modified'] = $last_modified_time;
}
/**
* Action Scheduler Contact Import
*
* @param $import_id
*/
public function import( $import_id ) {
/**
* End import when import data is not found
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
$this->end_import( 2, 'Unable to get Import ID: ' . $import_id );
return;
}
if ( $this->is_recently_imported() || ! empty( $this->db_import_row['meta']['is_running'] ) ) {
return;
}
/** Update last_modified to inform subsequent requests */
$this->update_last_modified();
/** Set Import to running */
$this->update_status_to_running();
$this->start_import_time = time();
$this->log_handle = fopen( $this->log_file, 'a' );
$run_time = BWFCRM_Common::get_contact_export_per_call_time();
while ( ( ( time() - $this->start_import_time ) < $run_time ) && ! BWFCRM_Common::memory_exceeded() ) {
$this->populate_members();
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
foreach ( array_keys( $this->members ) as $user_id ) {
$this->offset = $user_id;
/**
* Import contact from user array
*/
$contact_id = absint( $this->import_contact() );
if ( ! empty( $contact_id ) ) {
$this->import_wlm_member( $contact_id, $user_id );
}
/**
* Updated import entry record
*/
$this->update_import_record();
}
}
if ( ! empty( $this->log_handle ) ) {
fclose( $this->log_handle );
}
/**
* End import if completed
*/
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Remove import running status */
$this->update_status_to_running( true );
/** Update Last modified - 7 to run next iteration immediately */
$this->update_last_modified( 7 );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
}
/**
* Returns import meta
*
* @param string $key
*
* @return mixed|string
*/
public function get_import_meta( $key = '' ) {
return ! empty( $key ) && isset( $this->import_meta[ $key ] ) ? $this->import_meta[ $key ] : '';
}
/**
* Import contact
*/
public function import_contact() {
/**
* Get formatted contact data from user
*/
$contact_data = $this->prepare_contact_data();
if ( false === $contact_data ) {
return 0;
}
/** Disable Events */
$disable_events = $this->get_import_meta( 'disable_events' );
if ( true === $disable_events ) {
$contact_data['data']['disable_events'] = true;
}
/** Setting Unsubscribe data before initializing contact, because if contact is new then need to update the status */
$do_unsubscribe = false;
if ( 3 === absint( $contact_data['data']['status'] ) ) {
$contact_data['data']['status'] = 1;
$do_unsubscribe = true;
}
/**
* Get or Create contact and updated status accordingly
*/
$contact = null;
try {
/** Initialising/Creating the Contact */
$contact = new BWFCRM_Contact( $contact_data['email'], true, $contact_data['data'] );
/** If Contact does exists, but doesn't have wpid */
if ( $contact->is_contact_exists() && empty( $contact->contact->get_wpid() ) ) {
$contact->contact->set_wpid( absint( $contact_data['data']['wp_id'] ) );
$contact->contact->save();
}
} catch ( Exception $e ) {
/**
* If failed add failed count and set next user to process
*/
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return $contact instanceof BWFCRM_Contact && $contact->is_contact_exists() ? $contact->get_id() : 0;
}
/** Check if contact need to update if existing */
$update_existing = $this->get_import_meta( 'update_existing' );
/** If contact already exists (old) and Update Existing flag is off, then unset status */
if ( $contact->already_exists && ! $update_existing ) {
unset( $contact_data['data']['status'] );
}
/**
* Update contact if update_existing = true
*/
$fields_updated = false;
try {
/** If needed to do unsubscribe */
if ( $do_unsubscribe && $update_existing ) {
$contact->unsubscribe( $disable_events );
}
/** If contact was unsubscribed, and new status is not unsubscribed, then remove the entries from Unsubscriber Table */
if ( ! $do_unsubscribe && $update_existing ) {
/** NOTE: Checking for: "If the contact was unsubscribed" is already in this below function */
$contact->remove_unsubscribe_status();
}
/** Set Data only if contact already exists, as in case of new contact, data is already been set in above code. */
if ( $contact->already_exists ) {
$result = $contact->set_data( $contact_data['data'] );
$fields_updated = $result['fields_changed'];
}
/** Apply tags */
$contact->set_tags( $this->get_import_meta( 'tags' ), true, $disable_events );
/** Apply lists */
$contact->set_lists( $this->get_import_meta( 'lists' ), true, $disable_events );
} catch ( Exception $e ) {
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return $contact->get_id();
}
if ( $fields_updated ) {
$contact->save_fields();
}
$contact->save();
/** Contact Imported, increase success count and move to next user */
$this->succeed ++;
$this->processed ++;
return $contact->get_id();
}
/** Import Contact to WLM */
public function import_wlm_member( $contact_id, $user_id ) {
$levels = wlmapi_get_member_levels( $user_id );
if ( ! is_array( $levels ) || empty( $levels ) ) {
return;
}
/** @var BWFCRM_Integration_Wishlist_Member $wlm_integration */
$wlm_integration = BWFCRM_Core()->integrations->get_integration( 'wishlist_member' );
$status = array();
$reg = array();
$exp = array();
foreach ( $levels as $id => $level ) {
$status[ absint( $id ) ] = strval( $wlm_integration->get_status_code_from_api( $level ) );
$reg[ absint( $id ) ] = date( 'Y-m-d H:i:s', absint( $level->Timestamp ) );
if ( ! empty( $level->ExpiryDate ) ) {
$exp[ absint( $id ) ] = date( 'Y-m-d H:i:s', absint( $level->ExpiryDate ) );
}
}
BWF_Model_Contact_WLM_Fields::insert( $contact_id, $status, $reg, $exp );
}
/**
* Returns formatted contact data
*
* @return array
*/
public function prepare_contact_data() {
/**
* Get user data form wp_user based on current position
*/
$user = $this->members[ $this->offset ];
/**
* Fallback if WP_User data not found
*/
if ( ! $user instanceof WP_User ) {
$user = get_user_by( 'id', $this->offset );
}
/**
* Get contact fields
*/
$contact_fields = BWFCRM_Fields::get_contact_fields_from_db( 'slug' );
/**
* Set marketing status to set
*/
$import_status = isset( $this->import_meta['marketing_status'] ) ? absint( $this->import_meta['marketing_status'] ) : 0;
if ( isset( $this->import_meta['imported_contact_status'] ) ) {
$import_status = $this->get_import_meta( 'imported_contact_status' );
}
/**
* Form contact data form user data
*/
$email = $user->user_email;
$data = array(
'f_name' => $user->first_name,
'l_name' => $user->last_name,
'status' => $import_status,
'wp_id' => $user->ID,
);
// /** WLM User Meta */
// $address = $this->get_member_address( $user->ID );
// $city = ! empty( $address['city'] ) ? $address['city'] : get_user_meta( $user->ID, 'billing_city', true );
// $state = ! empty( $address['state'] ) ? $address['state'] : get_user_meta( $user->ID, 'billing_state', true );
// $country = ! empty( $address['country'] ) ? $address['country'] : get_user_meta( $user->ID, 'billing_country', true );
// $postcode = ! empty( $address['zip'] ) ? $address['zip'] : get_user_meta( $user->ID, 'billing_postcode', true );
// $address1 = ! empty( $address['address1'] ) ? $address['address1'] : get_user_meta( $user->ID, 'billing_address_1', true );
// $address2 = ! empty( $address['address2'] ) ? $address['address2'] : get_user_meta( $user->ID, 'billing_address_2', true );
// $company = ! empty( $address['company'] ) ? $address['company'] : get_user_meta( $user->ID, 'billing_company', true );
/** WooCommerce User Meta */
$phone = get_user_meta( $user->ID, 'billing_phone', true );
$city = get_user_meta( $user->ID, 'billing_city', true );
$state = get_user_meta( $user->ID, 'billing_state', true );
$country = get_user_meta( $user->ID, 'billing_country', true );
$postcode = get_user_meta( $user->ID, 'billing_postcode', true );
$address1 = get_user_meta( $user->ID, 'billing_address_1', true );
$address2 = get_user_meta( $user->ID, 'billing_address_2', true );
$company = get_user_meta( $user->ID, 'billing_company', true );
$data['f_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_first_name', true ) : $data['f_name'];
$data['l_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_last_name', true ) : $data['l_name'];
$email = empty( $email ) ? get_user_meta( $user->ID, 'billing_email', true ) : $email;
! empty( $postcode ) ? $data[ $contact_fields['postcode']['ID'] ] = $postcode : null;
! empty( $address1 ) ? $data[ $contact_fields['address-1']['ID'] ] = $address1 : null;
! empty( $address2 ) ? $data[ $contact_fields['address-2']['ID'] ] = $address2 : null;
! empty( $company ) ? $data[ $contact_fields['company']['ID'] ] = $company : null;
! empty( $city ) ? $data[ $contact_fields['city']['ID'] ] = $city : null;
! empty( $phone ) ? $data['contact_no'] = $phone : null;
! empty( $state ) ? $data['state'] = $state : null;
! empty( $country ) ? $data['country'] = BWFAN_PRO_Common::get_country_iso_code( $country ) : null;
$data['source'] = 'wlm';
return array(
'email' => $email,
'data' => $data,
);
}
public function get_member_address( $member_id ) {
/** @var BWFCRM_Integration_Wishlist_Member $ins */
$ins = BWFCRM_Core()->integrations->get_integration( 'wishlist_member' );
return $ins->get_member_address( $member_id );
}
/**
* Update the importer data in table
*/
public function update_import_record() {
/**
* Set new stat of importer
*/
$this->import_meta['log'] = array(
'succeed' => $this->succeed,
'failed' => $this->failed,
'skipped' => $this->skipped,
);
$import_meta = wp_json_encode( $this->import_meta );
BWFAN_Model_Import_Export::update( array(
'offset' => $this->offset,
'processed' => $this->processed,
'meta' => $import_meta,
'last_modified' => current_time( 'mysql', 1 ),
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['offset'] = $this->offset;
$this->db_import_row['processed'] = $this->processed;
$this->db_import_row['meta'] = $import_meta;
}
public function update_status_to_running( $remove = false ) {
if ( $remove && isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
} else {
$this->import_meta['is_running'] = true;
}
$import_meta = wp_json_encode( $this->import_meta );
/** Update status to running */
BWFAN_Model_Import_Export::update( array( 'meta' => $import_meta ), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['meta'] = $import_meta;
}
/**
* Stops importer running
*
* @param int $status
* @param string $status_message
*/
public function end_import( $status = 3, $status_message = '' ) {
/**
* Checks importer entry exists
*/
if ( empty( $this->import_id ) ) {
return;
}
/**
* Check if import action is scheduled and status is in progress
*/
$db_status = absint( $this->db_import_row['status'] );
if ( bwf_has_action_scheduled( $this->action_hook ) && $db_status === BWFCRM_Importer::$IMPORT_IN_PROGRESS ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $this->import_id ) ), 'bwfcrm' );
}
/**
* Adding log message
*/
if ( ! empty( $status_message ) ) {
BWFAN_Core()->logger->log( $status_message, 'import_contacts_crm' );
} elseif ( 3 === $status ) {
$status_message = 'Contacts imported. Import ID: ' . $this->import_id;
}
$this->db_import_row['status'] = $status;
$this->import_meta['status_msg'] = $status_message;
/** Checking csv file row count is greater 1 */
$file_data = file( $this->log_file );
if ( empty( $file_data ) || ! is_array( $file_data ) ) {
unset( $this->import_meta['log_file'] );
wp_delete_file( $this->log_file );
}
if ( isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
}
/**
* Updating importer data in DB
*/
BWFAN_Model_Import_Export::update( array(
'status' => $status,
'meta' => wp_json_encode( $this->import_meta ),
), array( 'id' => absint( $this->import_id ) ) );
$key = 'bwfan_import_done';
$imported = get_option( $key, [] );
$imported['wlm'] = 1;
update_option( $key, $imported );
}
/**
* Prepare log data and append data to file
*
* @param $email
* @param $status
* @param $err_msg
* @param $contact
*/
public function prepare_log_data( $email, $status, $err_msg, $user_id = '' ) {
$data = array(
$email,
$user_id,
$status,
$err_msg,
);
if ( ! empty( $this->log_handle ) ) {
fputcsv( $this->log_handle, $data );
}
}
}
BWFCRM_Core()->importer->register( 'wlm', 'BWFCRM_WLM_Importer' );

View File

@@ -0,0 +1,805 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class BWFCRM_WP_Importer
*
* @package Autonami CRM
*/
#[AllowDynamicProperties]
class BWFCRM_WP_Importer {
/**
* WordPress importer action hook
*
* @var string
*/
private $action_hook = 'bwfcrm_wp_import';
/**
* Working Import ID
*
* @var int
*/
private $import_id = 0;
/**
* Working import DB data
*
* @var array
*/
private $db_import_row = array();
/**
* Working import meta data
*
* @var array
*/
private $import_meta = array();
/**
* Import start time
*
* @var int
*/
private $start_import_time = 0;
/**
* Array of users fetched
*
* @var array
*/
private $wp_users = array();
/** Import Contacts Results */
private $skipped = 0;
private $failed = 0;
private $succeed = 0;
private $processed = 0;
private $count = 0;
private $offset = 0;
private $log_handle = null;
private $newTags = [];
private $newLists = [];
private $log_file = null;
/**
* Returns all user roles for selection in import process
*
* @return mixed|string|void
*/
public static function get_wp_roles() {
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
}
/**
* Get all editable roles
*/
$roles = get_editable_roles();
if ( ! is_array( $roles ) || empty( $roles ) ) {
return __( 'Invalid User Roles / Unknow Error', 'wp-marketing-automations-pro' );
}
/**
* Formatting role array
*/
$roles_for_api = array();
foreach ( $roles as $slug => $role ) {
$roles_for_api[ $slug ] = isset( $role['name'] ) ? $role['name'] : $slug;
}
return apply_filters( 'bwfcrm_wp_roles_for_import', $roles_for_api );
}
/**
* Create Import & Start Import
*
* @param array $roles
* @param array $tags
* @param array $lists
* @param bool $update_existing
* @param bool $marketing_status
*/
public function create_import( $roles = array(), $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = true, $imported_contact_status = 1 ) {
$this->log_file = BWFCRM_Importer::get_log_file_name( 'wp' );
$import_id = $this->create_wp_import_record( $roles, $tags, $lists, $update_existing, $marketing_status, $disable_events, $imported_contact_status );
/** Create Log File */
$log_file_header = array( 'Email', 'User ID', 'Status', 'Error Message' );
BWFCRM_Importer::create_importer_log_file( $this->log_file, $log_file_header );
/** Schedule the Import */
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
return $import_id;
}
/**
* Get Import Status or Start Import
*
* @param int $import_id
*
* @return array|string
*/
public function get_import_status( $import_id = 0 ) {
/**
* Check for import record exists
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
return __( 'Import record not found', 'wp-marketing-automations-pro' );
}
/**
* Get percent completed
*/
$percent = $this->get_percent_completed();
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
$status = absint( $this->db_import_row['status'] );
if ( BWFCRM_Importer::$IMPORT_IN_PROGRESS === $status && bwf_has_action_scheduled( $this->action_hook, array( 'import_id' => absint( $import_id ) ) && empty( $this->db_import_row['meta']['is_running'] ) ) ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $import_id ) ) );
add_filter( 'bwfan_as_per_call_time', function () {
return 10;
} );
$this->import( $import_id );
/** If still in progress, return the status */
$this->db_import_row = null;
$this->maybe_get_import( $import_id );
/** Get percent completed */
$percent = $this->get_percent_completed();
$status = absint( $this->db_import_row['status'] );
/** End import if completed */
if ( $percent >= 100 ) {
$this->end_import();
}
}
$data = array(
'import_id' => $this->import_id,
'percent' => $percent,
'status' => BWFCRM_Importer::get_status_text( $status ),
'log' => $this->get_import_meta( 'log' ),
);
/** If import completed 100% and import has log file */
if ( 100 === $percent && ! empty( $this->import_meta['log_file'] ) ) {
$data['has_log_file'] = true;
}
return $data;
}
/**
* Returns import stat and create import record if not found
*
* @param $import_id
*
* @return bool
*/
public function maybe_get_import( $import_id = 0 ) {
/**
* check if import data already fetched
*/
if ( is_array( $this->db_import_row ) && ! empty( $this->db_import_row ) && absint( $this->db_import_row['id'] ) === absint( $import_id ) ) {
return true;
}
/**
* Create import entry in table if not exists
*/
$this->import_id = absint( $import_id );
/**
* Get import data from DB
*/
$this->db_import_row = BWFAN_Model_Import_Export::get( $this->import_id );
$this->import_meta = ! empty( $this->db_import_row['meta'] ) ? json_decode( $this->db_import_row['meta'], true ) : array();
/**
* Set log data
*/
if ( isset( $this->import_meta['log'] ) ) {
$this->skipped = isset( $this->import_meta['log']['skipped'] ) && empty( $this->skipped ) ? absint( $this->import_meta['log']['skipped'] ) : $this->skipped;
$this->succeed = isset( $this->import_meta['log']['succeed'] ) && empty( $this->succeed ) ? absint( $this->import_meta['log']['succeed'] ) : $this->succeed;
$this->failed = isset( $this->import_meta['log']['failed'] ) && empty( $this->failed ) ? absint( $this->import_meta['log']['failed'] ) : $this->failed;
}
$this->processed = isset( $this->db_import_row['processed'] ) && empty( $this->processed ) ? absint( $this->db_import_row['processed'] ) : $this->processed;
$this->count = isset( $this->db_import_row['count'] ) && empty( $this->count ) ? absint( $this->db_import_row['count'] ) : $this->count;
$this->offset = isset( $this->db_import_row['offset'] ) && empty( $this->offset ) ? absint( $this->db_import_row['offset'] ) : $this->offset;
if ( isset( $this->import_meta['log_file'] ) ) {
$this->log_file = $this->import_meta['log_file'];
}
return is_array( $this->db_import_row ) && ! empty( $this->db_import_row );
}
/**
* Returns current processing users id
*
* @param int $offset
* @param array $role__in
* @param string $limit
*
* @return array
*/
public function get_wp_users_array( $offset = 0, $role__in = array(), $limit = '' ) {
global $wpdb;
/**
* Passing roles data with OR relation
*/
$role__in_clauses = array( 'relation' => 'OR' );
/**
* Checking role and formatting for WP_Meta_Query
*/
if ( ! empty( $role__in ) ) {
foreach ( $role__in as $role ) {
$role__in_clauses[] = array(
'key' => $wpdb->prefix . 'capabilities',
'value' => '"' . $role . '"',
'compare' => 'LIKE',
);
}
}
/**
* Forming meta sql query for role.
*/
$meta_query = new WP_Meta_Query();
$meta_query->queries = array(
'relation' => 'AND',
array( $role__in_clauses ),
);
$offset_query = '';
if ( intval( $offset ) > 0 ) {
$offset_query = "AND ID < $offset";
}
$metadata = $meta_query->get_sql( 'user', $wpdb->users, 'ID', $role__in_clauses );
$query = 'SELECT ID from ' . $wpdb->users . ' ' . $metadata['join'] . " WHERE 1 = 1 $offset_query " . $metadata['where'] . ' ORDER BY ID DESC ';
if ( intval( $limit > 0 ) ) {
$query .= "LIMIT 0, $limit";
}
return $wpdb->get_col( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
/**
* Populate the user data
*
* @param $role
*/
public function populate_wp_users( $role ) {
if ( $this->offset <= 1 ) {
$this->wp_users = array();
return;
}
/**
* Set offset
*/
$user_arr = $this->get_wp_users_array( $this->offset, $role, 25 );
if ( empty( $user_arr ) ) {
$this->wp_users = array();
return;
}
/**
* Fetching uses to import
*/
$users = get_users( array(
'include' => $user_arr,
) );
$this->wp_users = array();
/**
* Formatting user data
*/
if ( ! empty( $users ) ) {
/** @var WP_User $user */
foreach ( $users as $user ) {
$this->wp_users[ absint( $user->ID ) ] = $user;
}
krsort( $this->wp_users, 1 );
}
}
/**
* Insert a new row for importer
*
* @param array $roles
* @param array $tags
* @param array $lists
* @param false $update_existing
* @param false $marketing_status
* @param bool $disable_events
*
* @return int
*/
public function create_wp_import_record( $roles = array(), $tags = array(), $lists = array(), $update_existing = false, $marketing_status = false, $disable_events = false, $imported_contact_status = 1 ) {
$user_ids = $this->get_wp_users_array( 0, $roles, '' );
krsort( $user_ids );
/**
* Adding wp importer entry in DB
*/
BWFAN_Model_Import_Export::insert( array(
'offset' => $user_ids[0] + 1,
'processed' => 0,
'count' => count( $user_ids ),
'type' => BWFCRM_Importer::$IMPORT,
'status' => BWFCRM_Importer::$IMPORT_IN_PROGRESS,
'meta' => wp_json_encode( array(
'import_type' => 'wp',
'roles' => $roles,
'update_existing' => $update_existing,
'tags' => $tags,
'lists' => $lists,
'marketing_status' => $marketing_status,
'disable_events' => $disable_events,
'imported_contact_status' => $imported_contact_status,
'log_file' => $this->log_file,
) ),
'created_date' => current_time( 'mysql', 1 ),
'last_modified' => date( 'Y-m-d H:i:s', time() - 6 ),
) );
return BWFAN_Model_Import_Export::insert_id();
}
/**
* Check if import action is run less than 5 seconds ago
*
* @return bool
*/
public function is_recently_imported() {
$last_modified_seconds = time() - strtotime( $this->db_import_row['last_modified'] );
return $last_modified_seconds <= 5;
}
/**
* Returns progress of the importer
*
* @return int
*/
public function get_percent_completed() {
$count = isset( $this->db_import_row['count'] ) && ! empty( intval( $this->db_import_row['count'] ) ) ? intval( $this->db_import_row['count'] ) : 0;
$processed = isset( $this->db_import_row['processed'] ) && ! empty( intval( $this->db_import_row['processed'] ) ) ? intval( $this->db_import_row['processed'] ) : 0;
if ( 0 === $count ) {
return 100;
}
if ( 0 === $processed ) {
return 0;
}
return absint( min( ( ( $processed / $count ) * 100 ), 100 ) );
}
/**
* Update last_modified to inform subsequent requests
*/
public function update_last_modified( $minus = 0 ) {
$last_modified_time = time() - $minus;
$last_modified_time = date( 'Y-m-d H:i:s', $last_modified_time );
BWFAN_Model_Import_Export::update( array(
'last_modified' => $last_modified_time,
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['last_modified'] = $last_modified_time;
}
/**
* Action Scheduler Contact Import
*
* @param $import_id
*/
public function import( $import_id ) {
/**
* End import when import data is not found
*/
if ( ! $this->maybe_get_import( $import_id ) ) {
$this->end_import( 2, 'Unable to get Import ID: ' . $import_id );
return;
}
if ( $this->is_recently_imported() ) {
return;
}
/** Update last_modified to inform subsequent requests */
$this->update_last_modified();
/** Set Import to running */
$this->update_status_to_running();
$this->start_import_time = time();
$this->log_handle = fopen( $this->log_file, 'a' );
$run_time = BWFCRM_Common::get_contact_export_per_call_time();
if ( ! empty( $this->get_import_meta( 'tags' ) ) ) {
$this->newTags = BWFAN_Model_Terms::get_crm_term_ids( $this->get_import_meta( 'tags' ), BWFCRM_Term_Type::$TAG );
}
if ( ! empty( $this->get_import_meta( 'lists' ) ) ) {
$this->newLists = BWFAN_Model_Terms::get_crm_term_ids( $this->get_import_meta( 'lists' ), BWFCRM_Term_Type::$LIST );
}
while ( ( ( time() - $this->start_import_time ) < $run_time ) && ! BWFCRM_Common::memory_exceeded() ) {
/** Populate Next Set of WP Users */
$this->populate_wp_users( $this->get_import_meta( 'roles' ) );
if ( empty( $this->wp_users ) ) {
break;
}
foreach ( array_keys( $this->wp_users ) as $user_id ) {
$this->offset = $user_id;
/**
* Import contact from user array
*/
$this->import_contact();
/**
* Updated import entry record
*/
$this->update_import_record();
}
}
if ( ! empty( $this->log_handle ) ) {
fclose( $this->log_handle );
}
/**
* End import if completed
*/
if ( $this->get_percent_completed() >= 100 ) {
$this->end_import();
return;
}
/** Remove import running status */
$this->update_status_to_running( true );
/** Update Last modified - 7 to run next iteration immediately */
$this->update_last_modified( 7 );
BWFCRM_Core()->importer->reschedule_background_action( $import_id, $this->action_hook );
}
/**
* Returns import meta
*
* @param string $key
*
* @return mixed|string
*/
public function get_import_meta( $key = '' ) {
return ! empty( $key ) && isset( $this->import_meta[ $key ] ) ? $this->import_meta[ $key ] : '';
}
/**
* Import contact
*/
public function import_contact() {
/**
* Get formatted contact data from user
*/
$contact_data = $this->prepare_contact_data();
if ( false === $contact_data ) {
return;
}
/** Disable Events */
$disable_events = $this->get_import_meta( 'disable_events' );
if ( true === $disable_events ) {
$contact_data['data']['disable_events'] = true;
}
/** Setting Unsubscribe data before initializing contact, because if contact is new then need to update the status */
$do_unsubscribe = false;
if ( 3 === absint( $contact_data['data']['status'] ) ) {
$contact_data['data']['status'] = 1;
$do_unsubscribe = true;
}
/** Get or Create contact and updated status accordingly */
try {
/** Initialising/Creating the Contact */
$contact = new BWFCRM_Contact( $contact_data['email'], true, $contact_data['data'] );
/** If Contact does exists, but doesn't have wpid */
if ( $contact->is_contact_exists() && empty( $contact->contact->get_wpid() ) ) {
$contact->contact->set_wpid( absint( $contact_data['data']['wp_id'] ) );
$contact->contact->save();
}
} catch ( Exception $e ) {
/**
* If failed add failed count and set next user to process
*/
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return;
}
/** Check if contact need to update if existing */
$update_existing = $this->get_import_meta( 'update_existing' );
/** If contact already exists (old) and Update Existing flag is off, then unset status */
if ( $contact->already_exists && ! $update_existing ) {
unset( $contact_data['data']['status'] );
}
/**
* Update contact if update_existing = true
*/
$fields_updated = false;
try {
/** If needed to do unsubscribe */
if ( $do_unsubscribe && $update_existing ) {
$contact->unsubscribe( $disable_events );
}
/** If contact was unsubscribed, and new status is not unsubscribed, then remove the entries from Unsubscriber Table */
if ( ! $do_unsubscribe && $update_existing ) {
/** NOTE: Checking for: "If the contact was unsubscribed" is already in this below function */
$contact->remove_unsubscribe_status();
}
/** Set Data only if contact already exists, as in case of new contact, data is already been set in above code. */
if ( $contact->already_exists ) {
$result = $contact->set_data( $contact_data['data'] );
$fields_updated = $result['fields_changed'];
}
/** Apply tags */
if ( ! empty( $this->newTags ) ) {
$contact->set_tags_v2( $this->newTags, $disable_events );
}
/** Apply lists */
if ( ! empty( $this->newLists ) ) {
$contact->set_lists_v2( $this->newLists, $disable_events );
}
} catch ( Exception $e ) {
$this->processed ++;
$this->failed ++;
$error_msg = $e->getMessage();
$this->prepare_log_data( $contact_data['email'], 'failed', $error_msg, $contact_data['data']['wp_id'] );
return;
}
if ( $fields_updated ) {
$contact->save_fields();
}
$contact->save();
/** Contact Imported, increase success count and move to next user */
$this->succeed ++;
$this->processed ++;
}
/**
* Returns formatted contact data
*
* @return array
*/
public function prepare_contact_data() {
/**
* Get user data form wp_user based on current position
*/
$user = $this->wp_users[ $this->offset ];
/**
* Fallback if WP_User data not found
*/
if ( ! $user instanceof WP_User ) {
$user = get_user_by( 'id', $this->offset );
}
/**
* Get contact fields
*/
$contact_fields = BWFCRM_Fields::get_contact_fields_from_db( 'slug' );
/**
* Set marketing status to set
*/
$import_status = isset( $this->import_meta['marketing_status'] ) ? absint( $this->import_meta['marketing_status'] ) : 0;
if ( isset( $this->import_meta['imported_contact_status'] ) ) {
$import_status = $this->get_import_meta( 'imported_contact_status' );
}
/**
* Form contact data form user data
*/
$email = $user->user_email;
$data = array(
'f_name' => $user->first_name,
'l_name' => $user->last_name,
'status' => $import_status,
'wp_id' => $user->ID
);
/** WooCommerce User Meta */
$phone = get_user_meta( $user->ID, 'billing_phone', true );
$city = get_user_meta( $user->ID, 'billing_city', true );
$state = get_user_meta( $user->ID, 'billing_state', true );
$country = get_user_meta( $user->ID, 'billing_country', true );
$postcode = get_user_meta( $user->ID, 'billing_postcode', true );
$address1 = get_user_meta( $user->ID, 'billing_address_1', true );
$address2 = get_user_meta( $user->ID, 'billing_address_2', true );
$company = get_user_meta( $user->ID, 'billing_company', true );
$data['f_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_first_name', true ) : $data['f_name'];
$data['l_name'] = empty( $data['f_name'] ) ? get_user_meta( $user->ID, 'billing_last_name', true ) : $data['l_name'];
$email = empty( $email ) ? get_user_meta( $user->ID, 'billing_email', true ) : $email;
! empty( $postcode ) ? $data[ $contact_fields['postcode']['ID'] ] = $postcode : null;
! empty( $address1 ) ? $data[ $contact_fields['address-1']['ID'] ] = $address1 : null;
! empty( $address2 ) ? $data[ $contact_fields['address-2']['ID'] ] = $address2 : null;
! empty( $company ) ? $data[ $contact_fields['company']['ID'] ] = $company : null;
! empty( $city ) ? $data[ $contact_fields['city']['ID'] ] = $city : null;
! empty( $phone ) ? $data['contact_no'] = $phone : null;
! empty( $state ) ? $data['state'] = $state : null;
! empty( $country ) ? $data['country'] = BWFAN_PRO_Common::get_country_iso_code( $country ) : null;
$data['source'] = 'wp_user';
return array(
'email' => $email,
'data' => $data
);
}
/**
* Update the importer data in table
*/
public function update_import_record() {
/**
* Set new stat of importer
*/
$this->import_meta['log'] = array( 'succeed' => $this->succeed, 'failed' => $this->failed, 'skipped' => $this->skipped );
$import_meta = wp_json_encode( $this->import_meta );
BWFAN_Model_Import_Export::update( array(
"offset" => $this->offset,
'processed' => $this->processed,
"meta" => $import_meta,
'last_modified' => current_time( 'mysql', 1 )
), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['offset'] = $this->offset;
$this->db_import_row['processed'] = $this->processed;
$this->db_import_row['meta'] = $import_meta;
}
public function update_status_to_running( $remove = false ) {
if ( $remove && isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
} else {
$this->import_meta['is_running'] = true;
}
$import_meta = wp_json_encode( $this->import_meta );
/** Update status to running */
BWFAN_Model_Import_Export::update( array( 'meta' => $import_meta ), array( 'id' => absint( $this->import_id ) ) );
$this->db_import_row['meta'] = $import_meta;
}
/**
* Stops importer running
*
* @param int $status
* @param string $status_message
*/
public function end_import( $status = 3, $status_message = '' ) {
/**
* Checks importer entry exists
*/
if ( empty( $this->import_id ) ) {
return;
}
/**
* Check if import action is scheduled and status is in progress
*/
$db_status = absint( $this->db_import_row['status'] );
if ( bwf_has_action_scheduled( $this->action_hook ) && $db_status === BWFCRM_Importer::$IMPORT_IN_PROGRESS ) {
bwf_unschedule_actions( $this->action_hook, array( 'import_id' => absint( $this->import_id ) ), 'bwfcrm' );
}
/**
* Adding log message
*/
if ( ! empty( $status_message ) ) {
BWFAN_Core()->logger->log( $status_message, 'import_contacts_crm' );
} elseif ( 3 === $status ) {
$status_message = 'Contacts imported. Import ID: ' . $this->import_id;
if ( file_exists( $this->log_file ) ) {
/** Checking wp log file row count is greater 1 */
$file_data = file( $this->log_file );
if ( empty( $file_data ) || ! is_array( $file_data ) ) {
wp_delete_file( $wp_log_file );
}
}
}
$this->db_import_row['status'] = $status;
$this->import_meta['status_msg'] = $status_message;
if ( isset( $this->import_meta['is_running'] ) ) {
unset( $this->import_meta['is_running'] );
}
/**
* Updating importer data in DB
*/
BWFAN_Model_Import_Export::update( array(
'status' => $status,
'meta' => wp_json_encode( $this->import_meta ),
), array( 'id' => absint( $this->import_id ) ) );
}
/**
* Prepare log data and append data to file
*
* @param $email
* @param $status
* @param $err_msg
* @param $user_id
*
* @return void
*/
public function prepare_log_data( $email, $status, $err_msg, $user_id = '' ) {
$data = array(
$email,
$user_id,
$status,
$err_msg,
);
if ( ! empty( $this->log_handle ) ) {
fputcsv( $this->log_handle, $data );
}
}
}
BWFCRM_Core()->importer->register( 'wp', 'BWFCRM_WP_Importer' );