Prevents overwriting existing subscribers' status (and other required fields) unless
the import object contains data for those fields
This commit is contained in:
@ -14,35 +14,43 @@ class Import {
|
|||||||
public $subscribers_data;
|
public $subscribers_data;
|
||||||
public $segments;
|
public $segments;
|
||||||
public $update_subscribers;
|
public $update_subscribers;
|
||||||
public $subscriber_fields;
|
public $subscribers_fields;
|
||||||
public $subscriber_custom_fields;
|
public $subscribers_custom_fields;
|
||||||
public $subscribers_count;
|
public $subscribers_count;
|
||||||
public $created_at;
|
public $created_at;
|
||||||
public $updated_at;
|
public $updated_at;
|
||||||
|
public $required_subscribers_fields;
|
||||||
|
const DB_QUERY_CHUNK_SIZE = 100;
|
||||||
|
|
||||||
public function __construct($data) {
|
public function __construct($data) {
|
||||||
$this->validateData($data);
|
$this->validateImportData($data);
|
||||||
$this->subscribers_data = $this->transformSubscribersData(
|
$this->subscribers_data = $this->transformSubscribersData(
|
||||||
$data['subscribers'],
|
$data['subscribers'],
|
||||||
$data['columns']
|
$data['columns']
|
||||||
);
|
);
|
||||||
$this->segments = $data['segments'];
|
$this->segments = $data['segments'];
|
||||||
$this->update_subscribers = $data['updateSubscribers'];
|
$this->update_subscribers = $data['updateSubscribers'];
|
||||||
$this->subscriber_fields = $this->getSubscriberFields(
|
$this->subscribers_fields = $this->getSubscribersFields(
|
||||||
array_keys($data['columns'])
|
array_keys($data['columns'])
|
||||||
);
|
);
|
||||||
$this->subscriber_custom_fields = $this->getCustomSubscriberFields(
|
$this->subscribers_custom_fields = $this->getCustomSubscribersFields(
|
||||||
array_keys($data['columns'])
|
array_keys($data['columns'])
|
||||||
);
|
);
|
||||||
$this->subscriber_fields_validation_rules = $this->getSubscriberFieldsValidationRules(
|
$this->subscribers_fields_validation_rules = $this->getSubscriberDataValidationRules(
|
||||||
$data['columns']
|
$data['columns']
|
||||||
);
|
);
|
||||||
$this->subscribers_count = count(reset($this->subscribers_data));
|
$this->subscribers_count = count(reset($this->subscribers_data));
|
||||||
$this->created_at = date('Y-m-d H:i:s', (int)$data['timestamp']);
|
$this->created_at = date('Y-m-d H:i:s', (int)$data['timestamp']);
|
||||||
$this->updated_at = date('Y-m-d H:i:s', (int)$data['timestamp'] + 1);
|
$this->updated_at = date('Y-m-d H:i:s', (int)$data['timestamp'] + 1);
|
||||||
|
$this->required_subscribers_fields = array(
|
||||||
|
'status' => Subscriber::STATUS_SUBSCRIBED,
|
||||||
|
'first_name' => '',
|
||||||
|
'last_name' => '',
|
||||||
|
'created_at' => $this->created_at
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateData($data) {
|
function validateImportData($data) {
|
||||||
$required_data_fields = array(
|
$required_data_fields = array(
|
||||||
'subscribers',
|
'subscribers',
|
||||||
'columns',
|
'columns',
|
||||||
@ -55,13 +63,13 @@ class Import {
|
|||||||
if(count(array_intersect_key(array_flip($required_data_fields), $data)) !== count($required_data_fields) ||
|
if(count(array_intersect_key(array_flip($required_data_fields), $data)) !== count($required_data_fields) ||
|
||||||
preg_grep('/[^a-zA-Z0-9_]/', array_keys($data['columns']))
|
preg_grep('/[^a-zA-Z0-9_]/', array_keys($data['columns']))
|
||||||
) {
|
) {
|
||||||
throw new \Exception(__('Missing or invalid subscriber data.', 'mailpoet'));
|
throw new \Exception(__('Missing or invalid import data.', 'mailpoet'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscriberFieldsValidationRules($subscriber_fields) {
|
function getSubscriberDataValidationRules($subscribers_fields) {
|
||||||
$validation_rules = array();
|
$validation_rules = array();
|
||||||
foreach($subscriber_fields as $column => $field) {
|
foreach($subscribers_fields as $column => $field) {
|
||||||
$validation_rules[$column] = (!empty($field['validation_rule'])) ?
|
$validation_rules[$column] = (!empty($field['validation_rule'])) ?
|
||||||
$field['validation_rule'] :
|
$field['validation_rule'] :
|
||||||
false;
|
false;
|
||||||
@ -69,21 +77,22 @@ class Import {
|
|||||||
return $validation_rules;
|
return $validation_rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process($a = false) {
|
||||||
$subscriber_fields = $this->subscriber_fields;
|
$this->a = $a;
|
||||||
$subscriber_custom_fields = $this->subscriber_custom_fields;
|
$subscribers_fields = $this->subscribers_fields;
|
||||||
$subscribers_data = $this->validateSubscribersFields(
|
$subscribers_custom_fields = $this->subscribers_custom_fields;
|
||||||
|
$subscribers_data = $this->validateSubscribersData(
|
||||||
$this->subscribers_data,
|
$this->subscribers_data,
|
||||||
$this->subscriber_fields_validation_rules
|
$this->subscribers_fields_validation_rules
|
||||||
);
|
);
|
||||||
list ($subscribers_data, $subscriber_fields) =
|
|
||||||
$this->filterSubscriberStatus($subscribers_data, $subscriber_fields);
|
|
||||||
$this->deleteExistingTrashedSubscribers($subscribers_data);
|
$this->deleteExistingTrashedSubscribers($subscribers_data);
|
||||||
list($subscribers_data, $subscriber_fields) = $this->extendSubscribersAndFields(
|
list($subscribers_data, $subscribers_fields) = $this->extendSubscribersDataAndFields(
|
||||||
$subscribers_data, $subscriber_fields
|
$subscribers_data, $subscribers_fields
|
||||||
);
|
);
|
||||||
list($existing_subscribers, $wp_users, $new_subscribers) =
|
list ($subscribers_data, $subscribers_fields) =
|
||||||
$this->filterExistingAndNewSubscribers($subscribers_data);
|
$this->filterSubscribersStatus($subscribers_data, $subscribers_fields);
|
||||||
|
list($existing_subscribers, $new_subscribers, $wp_users) =
|
||||||
|
$this->splitSubscribers($subscribers_data, $this->subscribers_fields);
|
||||||
$created_subscribers = $updated_subscribers = array();
|
$created_subscribers = $updated_subscribers = array();
|
||||||
try {
|
try {
|
||||||
if($new_subscribers) {
|
if($new_subscribers) {
|
||||||
@ -91,8 +100,8 @@ class Import {
|
|||||||
$this->createOrUpdateSubscribers(
|
$this->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$new_subscribers,
|
$new_subscribers,
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
$subscriber_custom_fields
|
$subscribers_custom_fields
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if($existing_subscribers && $this->update_subscribers) {
|
if($existing_subscribers && $this->update_subscribers) {
|
||||||
@ -100,8 +109,8 @@ class Import {
|
|||||||
$this->createOrUpdateSubscribers(
|
$this->createOrUpdateSubscribers(
|
||||||
'update',
|
'update',
|
||||||
$existing_subscribers,
|
$existing_subscribers,
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
$subscriber_custom_fields
|
$subscribers_custom_fields
|
||||||
);
|
);
|
||||||
if($wp_users) {
|
if($wp_users) {
|
||||||
$this->synchronizeWPUsers($wp_users);
|
$this->synchronizeWPUsers($wp_users);
|
||||||
@ -125,12 +134,12 @@ class Import {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateSubscribersFields($subscribers_data, $validation_rules) {
|
function validateSubscribersData($subscribers_data, $validation_rules) {
|
||||||
$invalid_records = array();
|
$invalid_records = array();
|
||||||
foreach($subscribers_data as $column => &$data) {
|
foreach($subscribers_data as $column => &$data) {
|
||||||
$validation_rule = $validation_rules[$column];
|
$validation_rule = $validation_rules[$column];
|
||||||
// if this is a custom column
|
// if this is a custom column
|
||||||
if(in_array($column, $this->subscriber_custom_fields)) {
|
if(in_array($column, $this->subscribers_custom_fields)) {
|
||||||
$custom_field = CustomField::findOne($column);
|
$custom_field = CustomField::findOne($column);
|
||||||
// validate date type
|
// validate date type
|
||||||
if($custom_field->type === 'date') {
|
if($custom_field->type === 'date') {
|
||||||
@ -162,82 +171,62 @@ class Import {
|
|||||||
return $transformed_subscribers;
|
return $transformed_subscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterExistingAndNewSubscribers($subscribers_data) {
|
function splitSubscribers($subscribers_data) {
|
||||||
$chunk_size = 200;
|
$temp_existing_subscribers = array();
|
||||||
$existing_records = array_filter(
|
foreach(array_chunk($subscribers_data['email'], self::DB_QUERY_CHUNK_SIZE) as $subscribers_emails) {
|
||||||
array_map(function($subscriber_emails) {
|
$temp_existing_subscribers = array_merge(
|
||||||
return Subscriber::selectMany(array('email', 'wp_user_id'))
|
$temp_existing_subscribers,
|
||||||
->whereIn('email', $subscriber_emails)
|
Subscriber::selectMany(array_keys($this->required_subscribers_fields))
|
||||||
|
->select('wp_user_id')
|
||||||
|
->selectExpr('LOWER(email)', 'email')
|
||||||
|
->whereIn('email', $subscribers_emails)
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->findArray();
|
->findArray()
|
||||||
}, array_chunk($subscribers_data['email'], $chunk_size))
|
|
||||||
);
|
|
||||||
if(!$existing_records) {
|
|
||||||
return array(
|
|
||||||
$existing_records = false,
|
|
||||||
$wp_users = false,
|
|
||||||
$subscribers_data
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$wp_users = array_map(function($subscriber) {
|
if(!$temp_existing_subscribers) {
|
||||||
return Helpers::arrayColumn($subscriber, 'wp_user_id');
|
return array(
|
||||||
}, $existing_records);
|
$existing_subscribers = false,
|
||||||
$wp_users = array_filter($wp_users[0]);
|
$new_subscribers = $subscribers_data,
|
||||||
$existing_records = Helpers::flattenArray($existing_records);
|
$wp_users = false
|
||||||
// convert existing subscribers' emails retrieved from the database to lowercase
|
);
|
||||||
// to be compared with the import UI data that has lowercase emails
|
}
|
||||||
$existing_records = array_map('strtolower', $existing_records);
|
$wp_users = array_filter(Helpers::arrayColumn($temp_existing_subscribers, 'wp_user_id'));
|
||||||
$new_records = array_keys(
|
$temp_new_subscribers = array_keys(
|
||||||
array_diff(
|
array_diff(
|
||||||
$subscribers_data['email'],
|
$subscribers_data['email'],
|
||||||
$existing_records
|
Helpers::arrayColumn($temp_existing_subscribers, 'email')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if(!$new_records) {
|
$existing_subscribers = $new_subscribers = array();
|
||||||
return array(
|
foreach($subscribers_data as $field => $values) {
|
||||||
$subscribers_data,
|
$existing_subscribers_data = Helpers::arrayColumn($temp_existing_subscribers, $field);
|
||||||
$wp_users,
|
$existing_subscribers[$field] = (!in_array($field, $this->subscribers_fields) && $existing_subscribers_data) ?
|
||||||
false
|
$existing_subscribers_data :
|
||||||
);
|
array_diff_key($values, array_flip($temp_new_subscribers));
|
||||||
|
if($temp_new_subscribers) {
|
||||||
|
$new_subscribers[$field] = array_values(array_intersect_key($values, array_flip($temp_new_subscribers)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$new_subscribers =
|
|
||||||
array_filter(
|
|
||||||
array_map(function($subscriber) use ($new_records) {
|
|
||||||
return array_map(function($index) use ($subscriber) {
|
|
||||||
return $subscriber[$index];
|
|
||||||
}, $new_records);
|
|
||||||
}, $subscribers_data)
|
|
||||||
);
|
|
||||||
$existing_subscribers =
|
|
||||||
array_map(function($subscriber) use ($new_records) {
|
|
||||||
return array_filter(
|
|
||||||
array_values( // reindex array
|
|
||||||
array_map(function($index, $data) use ($new_records) {
|
|
||||||
if(!in_array($index, $new_records)) return $data;
|
|
||||||
}, array_keys($subscriber), $subscriber)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}, $subscribers_data);
|
|
||||||
return array(
|
return array(
|
||||||
$existing_subscribers,
|
$existing_subscribers,
|
||||||
$wp_users,
|
$new_subscribers,
|
||||||
$new_subscribers
|
$wp_users
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteExistingTrashedSubscribers($subscribers_data) {
|
function deleteExistingTrashedSubscribers($subscribers_data) {
|
||||||
$chunk_size = 200;
|
|
||||||
$existing_trashed_records = array_filter(
|
$existing_trashed_records = array_filter(
|
||||||
array_map(function($subscriber_emails) {
|
array_map(function($subscriber_emails) {
|
||||||
return Subscriber::selectMany(array('id'))
|
return Subscriber::selectMany(array('id'))
|
||||||
->whereIn('email', $subscriber_emails)
|
->whereIn('email', $subscriber_emails)
|
||||||
->whereNotNull('deleted_at')
|
->whereNotNull('deleted_at')
|
||||||
->findArray();
|
->findArray();
|
||||||
}, array_chunk($subscribers_data['email'], $chunk_size))
|
}, array_chunk($subscribers_data['email'], self::DB_QUERY_CHUNK_SIZE))
|
||||||
);
|
);
|
||||||
if(!$existing_trashed_records) return;
|
if(!$existing_trashed_records) return;
|
||||||
$existing_trashed_records = Helpers::flattenArray($existing_trashed_records);
|
$existing_trashed_records = Helpers::flattenArray($existing_trashed_records);
|
||||||
foreach(array_chunk($existing_trashed_records, $chunk_size) as
|
foreach(array_chunk($existing_trashed_records, self::DB_QUERY_CHUNK_SIZE) as
|
||||||
$subscriber_ids) {
|
$subscriber_ids) {
|
||||||
Subscriber::whereIn('id', $subscriber_ids)
|
Subscriber::whereIn('id', $subscriber_ids)
|
||||||
->deleteMany();
|
->deleteMany();
|
||||||
@ -246,113 +235,109 @@ class Import {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extendSubscribersAndFields($subscribers_data, $subscriber_fields) {
|
function extendSubscribersDataAndFields($subscribers_data, $subscribers_fields) {
|
||||||
$subscribers_data['created_at'] =
|
foreach(array_keys($this->required_subscribers_fields) as $required_field) {
|
||||||
array_fill(0, $this->subscribers_count, $this->created_at);
|
if(in_array($required_field, $subscribers_fields)) continue;
|
||||||
$subscriber_fields[] = 'created_at';
|
$subscribers_data[$required_field] = array_fill(
|
||||||
|
0,
|
||||||
|
$this->subscribers_count,
|
||||||
|
$this->required_subscribers_fields[$required_field]
|
||||||
|
);
|
||||||
|
$subscribers_fields[] = $required_field;
|
||||||
|
}
|
||||||
return array(
|
return array(
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$subscriber_fields
|
$subscribers_fields
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscriberFields($subscriber_fields) {
|
function getSubscribersFields($subscribers_fields) {
|
||||||
return array_values(
|
return array_values(
|
||||||
array_filter(
|
array_filter(
|
||||||
array_map(function($field) {
|
array_map(function($field) {
|
||||||
if(!is_int($field)) return $field;
|
if(!is_int($field)) return $field;
|
||||||
}, $subscriber_fields)
|
}, $subscribers_fields)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCustomSubscriberFields($subscriber_fields) {
|
function getCustomSubscribersFields($subscribers_fields) {
|
||||||
return array_values(
|
return array_values(
|
||||||
array_filter(
|
array_filter(
|
||||||
array_map(function($field) {
|
array_map(function($field) {
|
||||||
if(is_int($field)) return $field;
|
if(is_int($field)) return $field;
|
||||||
}, $subscriber_fields)
|
}, $subscribers_fields)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterSubscriberStatus($subscribers_data, $subscriber_fields) {
|
function filterSubscribersStatus($subscribers_data, $subscribers_fields) {
|
||||||
if(!in_array('status', $subscriber_fields)) {
|
|
||||||
$subscribers_data['status'] =
|
|
||||||
array_fill(0, count($subscribers_data['email']), 'subscribed');
|
|
||||||
$subscriber_fields[] = 'status';
|
|
||||||
return array(
|
|
||||||
$subscribers_data,
|
|
||||||
$subscriber_fields
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$statuses = array(
|
$statuses = array(
|
||||||
'subscribed' => array(
|
Subscriber::STATUS_SUBSCRIBED => array(
|
||||||
'subscribed',
|
'subscribed',
|
||||||
'confirmed',
|
'confirmed',
|
||||||
1,
|
1,
|
||||||
'1',
|
'1',
|
||||||
'true'
|
'true'
|
||||||
),
|
),
|
||||||
'unconfirmed' => array(
|
Subscriber::STATUS_UNCONFIRMED => array(
|
||||||
'unconfirmed',
|
'unconfirmed',
|
||||||
0,
|
0,
|
||||||
"0"
|
"0"
|
||||||
),
|
),
|
||||||
'unsubscribed' => array(
|
Subscriber::STATUS_UNSUBSCRIBED => array(
|
||||||
'unsubscribed',
|
'unsubscribed',
|
||||||
-1,
|
-1,
|
||||||
'-1',
|
'-1',
|
||||||
'false'
|
'false'
|
||||||
),
|
),
|
||||||
'bounced' => array(
|
Subscriber::STATUS_BOUNCED => array(
|
||||||
'bounced'
|
'bounced'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$subscribers_data['status'] = array_map(function($state) use ($statuses) {
|
$subscribers_data['status'] = array_map(function($state) use ($statuses) {
|
||||||
if(in_array(strtolower($state), $statuses['subscribed'], true)) {
|
if(in_array(strtolower($state), $statuses[Subscriber::STATUS_SUBSCRIBED], true)) {
|
||||||
return 'subscribed';
|
return Subscriber::STATUS_SUBSCRIBED;
|
||||||
}
|
}
|
||||||
if(in_array(strtolower($state), $statuses['unsubscribed'], true)) {
|
if(in_array(strtolower($state), $statuses[Subscriber::STATUS_UNSUBSCRIBED], true)) {
|
||||||
return 'unsubscribed';
|
return Subscriber::STATUS_UNSUBSCRIBED;
|
||||||
}
|
}
|
||||||
if(in_array(strtolower($state), $statuses['unconfirmed'], true)) {
|
if(in_array(strtolower($state), $statuses[Subscriber::STATUS_UNCONFIRMED], true)) {
|
||||||
return 'unconfirmed';
|
return Subscriber::STATUS_UNCONFIRMED;
|
||||||
}
|
}
|
||||||
if(in_array(strtolower($state), $statuses['bounced'], true)) {
|
if(in_array(strtolower($state), $statuses[Subscriber::STATUS_BOUNCED], true)) {
|
||||||
return 'bounced';
|
return Subscriber::STATUS_BOUNCED;
|
||||||
}
|
}
|
||||||
return 'subscribed'; // make "subscribed" a default status
|
return Subscriber::STATUS_SUBSCRIBED;
|
||||||
}, $subscribers_data['status']);
|
}, $subscribers_data['status']);
|
||||||
return array(
|
return array(
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$subscriber_fields
|
$subscribers_fields
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOrUpdateSubscribers(
|
function createOrUpdateSubscribers(
|
||||||
$action,
|
$action,
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
$subscriber_custom_fields
|
$subscriber_custom_fields
|
||||||
) {
|
) {
|
||||||
$chunk_size = 100;
|
|
||||||
$subscribers_count = count(reset($subscribers_data)) - 1;
|
$subscribers_count = count(reset($subscribers_data)) - 1;
|
||||||
$subscribers = array_map(function($index) use ($subscribers_data, $subscriber_fields) {
|
$subscribers = array_map(function($index) use ($subscribers_data, $subscribers_fields) {
|
||||||
return array_map(function($field) use ($index, $subscribers_data) {
|
return array_map(function($field) use ($index, $subscribers_data) {
|
||||||
return $subscribers_data[$field][$index];
|
return $subscribers_data[$field][$index];
|
||||||
}, $subscriber_fields);
|
}, $subscribers_fields);
|
||||||
}, range(0, $subscribers_count));
|
}, range(0, $subscribers_count));
|
||||||
foreach(array_chunk($subscribers, $chunk_size) as $data) {
|
foreach(array_chunk($subscribers, self::DB_QUERY_CHUNK_SIZE) as $data) {
|
||||||
if($action == 'create') {
|
if($action == 'create') {
|
||||||
Subscriber::createMultiple(
|
Subscriber::createMultiple(
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if($action == 'update') {
|
if($action == 'update') {
|
||||||
Subscriber::updateMultiple(
|
Subscriber::updateMultiple(
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
$data,
|
$data,
|
||||||
$this->updated_at
|
$this->updated_at
|
||||||
);
|
);
|
||||||
@ -412,7 +397,7 @@ class Import {
|
|||||||
$subscriber_index++;
|
$subscriber_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach(array_chunk($subscriber_custom_fields_data, 200) as $data) {
|
foreach(array_chunk($subscriber_custom_fields_data, self::DB_QUERY_CHUNK_SIZE) as $data) {
|
||||||
SubscriberCustomField::createMultiple(
|
SubscriberCustomField::createMultiple(
|
||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
@ -429,7 +414,7 @@ class Import {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addSubscribersToSegments($subscriber_ids, $segment_ids) {
|
function addSubscribersToSegments($subscriber_ids, $segment_ids) {
|
||||||
foreach(array_chunk($subscriber_ids, 200) as $subscriber_ids_chunk) {
|
foreach(array_chunk($subscriber_ids, self::DB_QUERY_CHUNK_SIZE) as $subscriber_ids_chunk) {
|
||||||
SubscriberSegment::subscribeManyToSegments(
|
SubscriberSegment::subscribeManyToSegments(
|
||||||
$subscriber_ids_chunk, $segment_ids
|
$subscriber_ids_chunk, $segment_ids
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,7 @@ class ImportTest extends MailPoetTest {
|
|||||||
$custom_field->name = 'country';
|
$custom_field->name = 'country';
|
||||||
$custom_field->type = 'text';
|
$custom_field->type = 'text';
|
||||||
$custom_field->save();
|
$custom_field->save();
|
||||||
$this->subscriber_custom_fields = array((string)$custom_field->id);
|
$this->subscribers_custom_fields = array((string)$custom_field->id);
|
||||||
$this->segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1'));
|
$this->segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1'));
|
||||||
$this->segment_2 = Segment::createOrUpdate(array('name' => 'Segment 2'));
|
$this->segment_2 = Segment::createOrUpdate(array('name' => 'Segment 2'));
|
||||||
$this->data = array(
|
$this->data = array(
|
||||||
@ -44,7 +44,7 @@ class ImportTest extends MailPoetTest {
|
|||||||
'timestamp' => time(),
|
'timestamp' => time(),
|
||||||
'updateSubscribers' => true
|
'updateSubscribers' => true
|
||||||
);
|
);
|
||||||
$this->subscriber_fields = array(
|
$this->subscribers_fields = array(
|
||||||
'first_name',
|
'first_name',
|
||||||
'last_name',
|
'last_name',
|
||||||
'email'
|
'email'
|
||||||
@ -56,11 +56,11 @@ class ImportTest extends MailPoetTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanConstruct() {
|
function testItConstructs() {
|
||||||
expect(is_array($this->import->subscribers_data))->true();
|
expect(is_array($this->import->subscribers_data))->true();
|
||||||
expect($this->import->segments)->equals($this->data['segments']);
|
expect($this->import->segments)->equals($this->data['segments']);
|
||||||
expect(is_array($this->import->subscriber_fields))->true();
|
expect(is_array($this->import->subscribers_fields))->true();
|
||||||
expect(is_array($this->import->subscriber_custom_fields))->true();
|
expect(is_array($this->import->subscribers_custom_fields))->true();
|
||||||
expect($this->import->subscribers_count)->equals(2);
|
expect($this->import->subscribers_count)->equals(2);
|
||||||
expect($this->import->created_at)->notEmpty();
|
expect($this->import->created_at)->notEmpty();
|
||||||
expect($this->import->updated_at)->notEmpty();
|
expect($this->import->updated_at)->notEmpty();
|
||||||
@ -71,28 +71,28 @@ class ImportTest extends MailPoetTest {
|
|||||||
// exception should be thrown when one or more fields do not exist
|
// exception should be thrown when one or more fields do not exist
|
||||||
unset($data['timestamp']);
|
unset($data['timestamp']);
|
||||||
try {
|
try {
|
||||||
$this->import->validateData($data);
|
$this->import->validateImportData($data);
|
||||||
self::fail('Missing or invalid data exception not thrown.');
|
self::fail('Missing or invalid data exception not thrown.');
|
||||||
} catch(Exception $e) {
|
} catch(Exception $e) {
|
||||||
expect($e->getMessage())->equals('Missing or invalid subscriber data.');
|
expect($e->getMessage())->equals('Missing or invalid import data.');
|
||||||
}
|
}
|
||||||
// exception should not be thrown when all fields exist
|
// exception should not be thrown when all fields exist
|
||||||
$this->import->validateData($this->data);
|
$this->import->validateImportData($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItValidatesColumnNames() {
|
function testItValidatesColumnNames() {
|
||||||
$data = $this->data;
|
$data = $this->data;
|
||||||
$data['columns']['test) values ((ExtractValue(1,CONCAT(0x5c, (SELECT version())))))%23'] = true;
|
$data['columns']['test) values ((ExtractValue(1,CONCAT(0x5c, (SELECT version())))))%23'] = true;
|
||||||
try {
|
try {
|
||||||
$this->import->validateData($data);
|
$this->import->validateImportData($data);
|
||||||
self::fail('Missing or invalid data exception not thrown.');
|
self::fail('Missing or invalid data exception not thrown.');
|
||||||
} catch(Exception $e) {
|
} catch(Exception $e) {
|
||||||
expect($e->getMessage())->equals('Missing or invalid subscriber data.');
|
expect($e->getMessage())->equals('Missing or invalid import data.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanTransformSubscribers() {
|
function testItTransformsSubscribers() {
|
||||||
$custom_field = $this->subscriber_custom_fields[0];
|
$custom_field = $this->subscribers_custom_fields[0];
|
||||||
expect($this->import->subscribers_data['first_name'][0])
|
expect($this->import->subscribers_data['first_name'][0])
|
||||||
->equals($this->data['subscribers'][0][0]);
|
->equals($this->data['subscribers'][0][0]);
|
||||||
expect($this->import->subscribers_data['last_name'][0])
|
expect($this->import->subscribers_data['last_name'][0])
|
||||||
@ -103,8 +103,7 @@ class ImportTest extends MailPoetTest {
|
|||||||
->equals($this->data['subscribers'][0][3]);
|
->equals($this->data['subscribers'][0][3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanFilterExistingAndNewSubscribers() {
|
function testItSplitsSubscribers() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
|
||||||
$subscriber = Subscriber::create();
|
$subscriber = Subscriber::create();
|
||||||
$subscriber->hydrate(
|
$subscriber->hydrate(
|
||||||
array(
|
array(
|
||||||
@ -114,34 +113,93 @@ class ImportTest extends MailPoetTest {
|
|||||||
'wp_user_id' => 1
|
'wp_user_id' => 1
|
||||||
));
|
));
|
||||||
$subscriber->save();
|
$subscriber->save();
|
||||||
list($existing, $wp_users, $new) = $this->import->filterExistingAndNewSubscribers(
|
list($existing_subscribers, $new_subscribers, $wp_users, ) = $this->import->splitSubscribers(
|
||||||
$subscribers_data
|
$this->subscribers_data, $this->subscribers_fields
|
||||||
);
|
);
|
||||||
expect($existing['email'][0])->equals($subscribers_data['email'][0]);
|
expect($existing_subscribers['email'][0])->equals($this->subscribers_data['email'][0]);
|
||||||
|
expect($new_subscribers['email'][0])->equals($this->subscribers_data['email'][1]);
|
||||||
expect($wp_users[0])->equals($subscriber->wp_user_id);
|
expect($wp_users[0])->equals($subscriber->wp_user_id);
|
||||||
expect($new['email'][0])->equals($subscribers_data['email'][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanExtendSubscribersAndFields() {
|
function testItDoesNotUpdateExistingSubscribersStatusWhenStatusColumnIsNotPresent() {
|
||||||
expect(in_array('created_at', $this->import->subscriber_fields))->false();
|
$subscriber = Subscriber::create();
|
||||||
expect(isset($this->import->subscriber_fields['created_at']))->false();
|
$subscriber->hydrate(
|
||||||
list($subscribers, $fields) = $this->import->extendSubscribersAndFields(
|
array(
|
||||||
$this->import->subscribers_data,
|
'first_name' => 'Adam',
|
||||||
$this->import->subscriber_fields
|
'last_name' => 'Smith',
|
||||||
|
'email' => 'Adam@Smith.com',
|
||||||
|
'status' => 'unsubscribed'
|
||||||
|
));
|
||||||
|
$subscriber->save();
|
||||||
|
$result = $this->import->process();
|
||||||
|
$updated_subscriber = Subscriber::where('email', $subscriber->email)->findOne();
|
||||||
|
expect($updated_subscriber->status)->equals('unsubscribed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItUpdatesExistingSubscribersStatusWhenStatusColumnIsPresent() {
|
||||||
|
$data = $this->data;
|
||||||
|
$data['columns']['status'] = array('index' => 4);
|
||||||
|
$data['subscribers'][0][] = 'unsubscribed';
|
||||||
|
$data['subscribers'][1][] = 'subscribed';
|
||||||
|
$import = new Import($data);
|
||||||
|
$existing_subscriber = Subscriber::create();
|
||||||
|
$existing_subscriber->hydrate(
|
||||||
|
array(
|
||||||
|
'first_name' => 'Adam',
|
||||||
|
'last_name' => 'Smith',
|
||||||
|
'email' => 'Adam@Smith.com',
|
||||||
|
'status' => 'subscribed'
|
||||||
|
));
|
||||||
|
$existing_subscriber->save();
|
||||||
|
$result = $import->process();
|
||||||
|
$updated_subscriber = Subscriber::where('email', $existing_subscriber->email)->findOne();
|
||||||
|
expect($updated_subscriber->status)->equals('unsubscribed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItExtendsSubscribersDataAndFieldsWhenRequiredFieldsAreMissing() {
|
||||||
|
$data = array(
|
||||||
|
'subscribers' => array(
|
||||||
|
array(
|
||||||
|
'adam@smith.com'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'mary@jane.com'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'columns' => array(
|
||||||
|
'email' => array('index' => 0)
|
||||||
|
),
|
||||||
|
'segments' => array(1),
|
||||||
|
'timestamp' => time(),
|
||||||
|
'updateSubscribers' => true
|
||||||
);
|
);
|
||||||
expect(in_array('created_at', $fields))->true();
|
$import = new Import($data);
|
||||||
expect(isset($this->import->subscriber_fields['created_at']))->false();
|
list($subscribers_data, $subscribers_fields) = $import->extendSubscribersDataAndFields(
|
||||||
expect(count($subscribers['created_at']))
|
$import->subscribers_data,
|
||||||
->equals($this->import->subscribers_count);
|
$import->subscribers_fields
|
||||||
|
);
|
||||||
|
// "created_at", "status", "first_name" and "last_name" fields are added and populated
|
||||||
|
expect(in_array('status', $subscribers_fields))->true();
|
||||||
|
expect(count($subscribers_data['status']))->equals($import->subscribers_count);
|
||||||
|
expect($subscribers_data['status'][0])->equals($import->required_subscribers_fields['status']);
|
||||||
|
expect(in_array('first_name', $subscribers_fields))->true();
|
||||||
|
expect(count($subscribers_data['first_name']))->equals($import->subscribers_count);
|
||||||
|
expect($subscribers_data['first_name'][0])->equals($import->required_subscribers_fields['first_name']);
|
||||||
|
expect(in_array('last_name', $subscribers_fields))->true();
|
||||||
|
expect(count($subscribers_data['last_name']))->equals($import->subscribers_count);
|
||||||
|
expect($subscribers_data['last_name'][0])->equals($import->required_subscribers_fields['last_name']);
|
||||||
|
expect(in_array('created_at', $subscribers_fields))->true();
|
||||||
|
expect(count($subscribers_data['created_at']))->equals($import->subscribers_count);
|
||||||
|
expect($subscribers_data['created_at'][0])->equals($import->created_at);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanGetSubscriberFields() {
|
function testItGetsSubscriberFields() {
|
||||||
$data = array(
|
$data = array(
|
||||||
'one',
|
'one',
|
||||||
'two',
|
'two',
|
||||||
39
|
39
|
||||||
);
|
);
|
||||||
$fields = $this->import->getSubscriberFields($data);
|
$fields = $this->import->getSubscribersFields($data);
|
||||||
expect($fields)->equals(
|
expect($fields)->equals(
|
||||||
array(
|
array(
|
||||||
'one',
|
'one',
|
||||||
@ -149,27 +207,18 @@ class ImportTest extends MailPoetTest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanGetCustomSubscriberFields() {
|
function testItGetsCustomSubscribersFields() {
|
||||||
$data = array(
|
$data = array(
|
||||||
'one',
|
'one',
|
||||||
'two',
|
'two',
|
||||||
39
|
39
|
||||||
);
|
);
|
||||||
$fields = $this->import->getCustomSubscriberFields($data);
|
$fields = $this->import->getCustomSubscribersFields($data);
|
||||||
expect($fields)->equals(array(39));
|
expect($fields)->equals(array(39));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanFilterSubscriberStatus() {
|
function testItFiltersSubscribersStatus() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_fields = array('status');
|
||||||
$subscriber_fields = $this->subscriber_fields;
|
|
||||||
list($subscribers_data, $subsciber_fields) =
|
|
||||||
$this->import->filterSubscriberStatus($subscribers_data, $subscriber_fields);
|
|
||||||
// subscribers' status was set to "subscribed" & status column was added
|
|
||||||
// to subscribers fields
|
|
||||||
expect(array_pop($subsciber_fields))->equals('status');
|
|
||||||
expect($subscribers_data['status'][0])->equals('subscribed');
|
|
||||||
expect(count($subscribers_data['status']))->equals(2);
|
|
||||||
$subscriber_fields[] = 'status';
|
|
||||||
$subscribers_data = array(
|
$subscribers_data = array(
|
||||||
'status' => array(
|
'status' => array(
|
||||||
#subscribed
|
#subscribed
|
||||||
@ -194,8 +243,8 @@ class ImportTest extends MailPoetTest {
|
|||||||
null
|
null
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
list($subscribers_data, $subsciber_fields) =
|
list($subscribers_data, $subscibers_fields) =
|
||||||
$this->import->filterSubscriberStatus($subscribers_data, $subscriber_fields);
|
$this->import->filterSubscribersStatus($subscribers_data, $subscribers_fields);
|
||||||
expect($subscribers_data)->equals(
|
expect($subscribers_data)->equals(
|
||||||
array(
|
array(
|
||||||
'status' => array(
|
'status' => array(
|
||||||
@ -219,12 +268,12 @@ class ImportTest extends MailPoetTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanAddOrUpdateSubscribers() {
|
function testItAddsOrUpdatesSubscribers() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_data = $this->subscribers_data;
|
||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_fields,
|
$this->subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$subscribers = Subscriber::findArray();
|
$subscribers = Subscriber::findArray();
|
||||||
@ -235,7 +284,7 @@ class ImportTest extends MailPoetTest {
|
|||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'update',
|
'update',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_fields,
|
$this->subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$subscribers = Subscriber::findArray();
|
$subscribers = Subscriber::findArray();
|
||||||
@ -243,18 +292,18 @@ class ImportTest extends MailPoetTest {
|
|||||||
->equals($subscribers_data['first_name'][1]);
|
->equals($subscribers_data['first_name'][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanDeleteTrashedSubscribers() {
|
function testItDeletesTrashedSubscribers() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_data = $this->subscribers_data;
|
||||||
$subscriber_fields = $this->subscriber_fields;
|
$subscribers_fields = $this->subscribers_fields;
|
||||||
$subscribers_data['deleted_at'] = array(
|
$subscribers_data['deleted_at'] = array(
|
||||||
null,
|
null,
|
||||||
date('Y-m-d H:i:s')
|
date('Y-m-d H:i:s')
|
||||||
);
|
);
|
||||||
$subscriber_fields[] = 'deleted_at';
|
$subscribers_fields[] = 'deleted_at';
|
||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$db_subscribers = Helpers::arrayColumn(
|
$db_subscribers = Helpers::arrayColumn(
|
||||||
@ -278,13 +327,13 @@ class ImportTest extends MailPoetTest {
|
|||||||
expect(count($db_subscribers))->equals(1);
|
expect(count($db_subscribers))->equals(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanCreateOrUpdateCustomFields() {
|
function testItCreatesOrUpdatesCustomFields() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_data = $this->subscribers_data;
|
||||||
$custom_field = $this->subscriber_custom_fields[0];
|
$custom_field = $this->subscribers_custom_fields[0];
|
||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_fields,
|
$this->subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$db_subscribers_ids = Helpers::arrayColumn(
|
$db_subscribers_ids = Helpers::arrayColumn(
|
||||||
@ -300,30 +349,30 @@ class ImportTest extends MailPoetTest {
|
|||||||
'create',
|
'create',
|
||||||
$db_subscribers_ids,
|
$db_subscribers_ids,
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_custom_fields
|
$this->subscribers_custom_fields
|
||||||
);
|
);
|
||||||
$subscriber_custom_fields = SubscriberCustomField::findArray();
|
$subscribers_custom_fields = SubscriberCustomField::findArray();
|
||||||
expect(count($subscriber_custom_fields))->equals(2);
|
expect(count($subscribers_custom_fields))->equals(2);
|
||||||
expect($subscriber_custom_fields[0]['value'])
|
expect($subscribers_custom_fields[0]['value'])
|
||||||
->equals($subscribers_data[$custom_field][0]);
|
->equals($subscribers_data[$custom_field][0]);
|
||||||
$subscribers_data[$custom_field][1] = 'Rio';
|
$subscribers_data[$custom_field][1] = 'Rio';
|
||||||
$this->import->createOrUpdateCustomFields(
|
$this->import->createOrUpdateCustomFields(
|
||||||
'update',
|
'update',
|
||||||
$db_subscribers_ids,
|
$db_subscribers_ids,
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_custom_fields
|
$this->subscribers_custom_fields
|
||||||
);
|
);
|
||||||
$subscriber_custom_fields = SubscriberCustomField::findArray();
|
$subscribers_custom_fields = SubscriberCustomField::findArray();
|
||||||
expect($subscriber_custom_fields[1]['value'])
|
expect($subscribers_custom_fields[1]['value'])
|
||||||
->equals($subscribers_data[$custom_field][1]);
|
->equals($subscribers_data[$custom_field][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanAddSubscribersToSegments() {
|
function testItAddsSubscribersToSegments() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_data = $this->subscribers_data;
|
||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$this->subscriber_fields,
|
$this->subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$db_subscribers = Helpers::arrayColumn(
|
$db_subscribers = Helpers::arrayColumn(
|
||||||
@ -348,10 +397,10 @@ class ImportTest extends MailPoetTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanDeleteExistingTrashedSubscribers() {
|
function testItDeletesExistingTrashedSubscribers() {
|
||||||
$subscribers_data = $this->subscribers_data;
|
$subscribers_data = $this->subscribers_data;
|
||||||
$subscriber_fields = $this->subscriber_fields;
|
$subscribers_fields = $this->subscribers_fields;
|
||||||
$subscriber_fields[] = 'deleted_at';
|
$subscribers_fields[] = 'deleted_at';
|
||||||
$subscribers_data['deleted_at'] = array(
|
$subscribers_data['deleted_at'] = array(
|
||||||
null,
|
null,
|
||||||
date('Y-m-d H:i:s')
|
date('Y-m-d H:i:s')
|
||||||
@ -359,12 +408,12 @@ class ImportTest extends MailPoetTest {
|
|||||||
$this->import->createOrUpdateSubscribers(
|
$this->import->createOrUpdateSubscribers(
|
||||||
'create',
|
'create',
|
||||||
$subscribers_data,
|
$subscribers_data,
|
||||||
$subscriber_fields,
|
$subscribers_fields,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanUpdateSubscribers() {
|
function testItUpdatesSubscribers() {
|
||||||
$result = $this->import->process();
|
$result = $this->import->process();
|
||||||
expect($result['updated'])->equals(0);
|
expect($result['updated'])->equals(0);
|
||||||
$result = $this->import->process();
|
$result = $this->import->process();
|
||||||
@ -374,20 +423,19 @@ class ImportTest extends MailPoetTest {
|
|||||||
expect($result['updated'])->equals(0);
|
expect($result['updated'])->equals(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItCanProcess() {
|
function testItRunsImport() {
|
||||||
$result = $this->import->process();
|
$result = $this->import->process();
|
||||||
expect($result['created'])->equals(2);
|
expect($result['created'])->equals(2);
|
||||||
Subscriber::where('email', 'mary@jane.com')
|
Subscriber::where('email', 'mary@jane.com')
|
||||||
->findOne()
|
->findOne()
|
||||||
->delete();
|
->delete();
|
||||||
$timestamp = time() + 1;
|
$timestamp = time() + 1;
|
||||||
$this->import->created_at = date('Y-m-d H:i:s', $timestamp);
|
$this->import->created_at = $this->import->required_subscribers_fields['created_at'] = date('Y-m-d H:i:s', $timestamp);
|
||||||
$this->import->updated_at = date('Y-m-d H:i:s', $timestamp + 1);
|
$this->import->updated_at = date('Y-m-d H:i:s', $timestamp + 1);
|
||||||
$result = $this->import->process();
|
$result = $this->import->process('boo');
|
||||||
expect($result['created'])->equals(1);
|
expect($result['created'])->equals(1);
|
||||||
$db_subscribers = Helpers::arrayColumn(
|
$db_subscribers = Helpers::arrayColumn(
|
||||||
Subscriber::select('id')
|
Subscriber::select('id')->findArray(),
|
||||||
->findArray(),
|
|
||||||
'id'
|
'id'
|
||||||
);
|
);
|
||||||
// subscribers must be added to segments
|
// subscribers must be added to segments
|
||||||
|
Reference in New Issue
Block a user