Prevents overwriting existing subscribers' status (and other required fields) unless

the import object contains data for those fields
This commit is contained in:
Vlad
2017-04-09 21:51:21 -04:00
parent a9edb383b4
commit 3a9c006cf9
2 changed files with 229 additions and 196 deletions

View File

@ -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
); );

View File

@ -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