- Update import to autodetect dates (UI) and convert them to datetime

format (backend)
- Fixes unit test
- Fixes code formatting in Date class
This commit is contained in:
Vlad
2016-08-11 23:02:53 -04:00
parent f8fea75130
commit 81c277ca93
5 changed files with 105 additions and 65 deletions

View File

@@ -51,6 +51,12 @@ define(
* STEP 1 (upload or copy/paste) * STEP 1 (upload or copy/paste)
*/ */
router.on('route:step1', function () { router.on('route:step1', function () {
// set or reset temporary validation rule on all columns
mailpoetColumns = jQuery.map(mailpoetColumns, function (column, columnIndex) {
column.validation_rule = false;
return column;
});
if (typeof (importData.step1) !== 'undefined') { if (typeof (importData.step1) !== 'undefined') {
showCurrentStep(); showCurrentStep();
return; return;
@@ -797,6 +803,7 @@ define(
}) })
}); });
jQuery(selectElement).data('column-id', new_column_data.id); jQuery(selectElement).data('column-id', new_column_data.id);
jQuery(selectElement).data('validation-rule', false);
filterSubscribers(); filterSubscribers();
// close popup // close popup
MailPoet.Modal.close(); MailPoet.Modal.close();
@@ -847,22 +854,22 @@ define(
.remove(); .remove();
var subscribersClone = jQuery.extend(true, {}, subscribers), var subscribersClone = jQuery.extend(true, {}, subscribers),
preventNextStep = false, preventNextStep = false,
displayedColumnsIds = jQuery.map( displayedColumns = jQuery.map(
jQuery('.mailpoet_subscribers_column_data_match'), function (data) { jQuery('.mailpoet_subscribers_column_data_match'), function (element, elementIndex) {
var columnId = jQuery(data).data('column-id'); var columnId = jQuery(element).data('column-id');
jQuery(data).val(columnId).trigger('change'); var validationRule = jQuery(element).data('validation-rule');
return columnId; jQuery(element).val(columnId).trigger('change');
return { id: columnId, index: elementIndex, validationRule: validationRule, element: element };
}); });
// iterate through the object of mailpoet columns // iterate through the object of mailpoet columns
jQuery.map(mailpoetColumns, function (column) { jQuery.map(mailpoetColumns, function (column, columnIndex) {
// check if the column id matches the selected id of one of the // check if the column id matches the selected id of one of the
// subscriber's data columns // subscriber's data columns
var matchedColumn = jQuery.inArray(column.id, displayedColumnsIds); var matchedColumn = _.find(displayedColumns, function(data) { return data.id === column.id; });
// EMAIL filter: if the first value in the column doesn't have a valid
// EMAIL filter: if the last value in the column doesn't have a valid
// email, hide the next button // email, hide the next button
if (column.id === "email") { if (column.id === 'email') {
if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn])) { if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn.index])) {
preventNextStep = true; preventNextStep = true;
if (!jQuery('[data-id="notice_invalidEmail"]').length) { if (!jQuery('[data-id="notice_invalidEmail"]').length) {
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidElement'), { MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidElement'), {
@@ -878,39 +885,63 @@ define(
} }
} }
// DATE filter: if column type is date, check if we can recognize it // DATE filter: if column type is date, check if we can recognize it
if (column.type === 'date' && matchedColumn !== -1) { if (column.type === 'date' && matchedColumn) {
jQuery.map(subscribersClone.subscribers, function (data, position) { var allowedDateFormats = [
var rowData = data[matchedColumn]; Moment.ISO_8601,
var dateFormat = column.params.date_format.toUpperCase(); 'YYYY/MM/DD',
var date = Moment(rowData, dateFormat, true); 'MM/DD/YYYY',
if (position !== fillerPosition) { 'DD/MM/YYYY',
// check if date exists 'YYYY/MM/DD',
if (rowData.trim() === '') { 'YYYY/DD/MM',
data[matchedColumn] = 'MM/YYYY',
'<span class="mailpoet_data_match mailpoet_import_error" title="' 'YYYY/MM',
+ MailPoet.I18n.t('noDateFieldMatch') + '">' 'YYYY'
+ MailPoet.I18n.t('emptyDate') ];
+ '</span>'; var firstRowData = subscribersClone.subscribers[0][matchedColumn.index];
preventNextStep = true; var validationRule = false;
return; // check if date exists
} if (firstRowData.trim() === '') {
// check if date is valid subscribersClone.subscribers[0][matchedColumn.index] =
if (date.isValid()) { '<span class="mailpoet_data_match mailpoet_import_error" title="'
data[matchedColumn] += + MailPoet.I18n.t('noDateFieldMatch') + '">'
'<span class="mailpoet_data_match" title="' + MailPoet.I18n.t('emptyDate')
+ MailPoet.I18n.t('verifyDateMatch') + '">' + '</span>';
+ MailPoet.Date.format(date) preventNextStep = true;
+ '</span>'; }
} else {
else { for (var format in allowedDateFormats) {
data[matchedColumn] += var testedFormat = allowedDateFormats[format]
'<span class="mailpoet_data_match mailpoet_import_error" title="' if (Moment(firstRowData, testedFormat, true).isValid()) {
+ MailPoet.I18n.t('noDateFieldMatch') + '">' var validationRule = (typeof(testedFormat) === 'function') ?
+ MailPoet.I18n.t('dateMatchError') + ' (' + dateFormat + ') ' 'datetime' :
+ '</span>'; testedFormat
preventNextStep = true; // set validation on the column element
jQuery(matchedColumn.element).data('validation-rule', validationRule);
break;
} }
if (validationRule === 'datetime') validationRule = Moment.ISO_8601;
} }
}
jQuery.map(subscribersClone.subscribers, function (data, index) {
if (index === fillerPosition) return;
var rowData = data[matchedColumn.index];
var date = Moment(rowData, testedFormat, true);
// validate date:
if (date.isValid()) {
data[matchedColumn.index] +=
'<span class="mailpoet_data_match" title="'
+ MailPoet.I18n.t('verifyDateMatch') + '">'
+ MailPoet.Date.format(date)
+ '</span>';
}
else {
data[matchedColumn.index] +=
'<span class="mailpoet_data_match mailpoet_import_error" title="'
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
+ MailPoet.I18n.t('dateMatchError')
+ '</span>';
preventNextStep = true;
};
}); });
if (preventNextStep && !jQuery('.mailpoet_invalidDate').length) { if (preventNextStep && !jQuery('.mailpoet_invalidDate').length) {
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidDate'), { MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidDate'), {
@@ -980,10 +1011,11 @@ define(
_.each(jQuery('select.mailpoet_subscribers_column_data_match'), _.each(jQuery('select.mailpoet_subscribers_column_data_match'),
function (column, columnIndex) { function (column, columnIndex) {
var columnId = jQuery(column).data('column-id'); var columnId = jQuery(column).data('column-id');
var validationRule = jQuery(column).data('validation-rule');
if (columnId === 'ignore') { if (columnId === 'ignore') {
return; return;
} }
columns[columnId] = columnIndex; columns[columnId] = { index: columnIndex, validation_rule: validationRule };
}); });
_.each(subscribers, function () { _.each(subscribers, function () {

View File

@@ -197,16 +197,15 @@ class Date extends Base {
static function convertDateToDatetime($date, $date_format) { static function convertDateToDatetime($date, $date_format) {
$datetime = false; $datetime = false;
if ($date_format === 'datetime') { if($date_format === 'datetime') {
$datetime = $date; $datetime = $date;
} } else {
else {
$parsed_date = explode('/', $date); $parsed_date = explode('/', $date);
$parsed_date_format = explode('/', $date_format); $parsed_date_format = explode('/', $date_format);
$year_position = array_search('YYYY', $parsed_date_format); $year_position = array_search('YYYY', $parsed_date_format);
$month_position = array_search('MM', $parsed_date_format); $month_position = array_search('MM', $parsed_date_format);
$day_position = array_search('DD', $parsed_date_format); $day_position = array_search('DD', $parsed_date_format);
if(count($parsed_date) === 3) { if(count($parsed_date) === 3) {
// create date from any combination of mm, dd and yyyy // create date from any combination of mm, dd and yyyy
$parsed_date = array( $parsed_date = array(
'year' => $parsed_date[$year_position], 'year' => $parsed_date[$year_position],

View File

@@ -169,7 +169,8 @@ class SubscriberTest extends MailPoetTest {
'name' => 'Birthday', 'name' => 'Birthday',
'type' => 'date', 'type' => 'date',
'params' => array( 'params' => array(
'date_type' => 'year_month_day' 'date_type' => 'year_month_day',
'date_format' => 'MM/DD/YYYY'
) )
)); ));
@@ -177,7 +178,8 @@ class SubscriberTest extends MailPoetTest {
'name' => 'Registered on', 'name' => 'Registered on',
'type' => 'date', 'type' => 'date',
'params' => array( 'params' => array(
'date_type' => 'year_month' 'date_type' => 'year_month',
'date_format' => 'MM/YYYY'
) )
)); ));
@@ -199,7 +201,7 @@ class SubscriberTest extends MailPoetTest {
expect($subscriber->email)->equals('user.with.cf@mailpoet.com'); expect($subscriber->email)->equals('user.with.cf@mailpoet.com');
expect($subscriber->{'cf_'.$custom_field->id})->equals('Paris'); expect($subscriber->{'cf_'.$custom_field->id})->equals('Paris');
// date specified as array gets converted to string // date specified as array gets converted to string
expect($subscriber->{'cf_'.$custom_field_2->id})->equals('1984-03-09'); expect($subscriber->{'cf_'.$custom_field_2->id})->equals('1984-03-09 00:00:00');
// date specified as string is stored as is // date specified as string is stored as is
expect($subscriber->{'cf_'.$custom_field_3->id})->equals('2013-07'); expect($subscriber->{'cf_'.$custom_field_3->id})->equals('2013-07');
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
use MailPoet\Models\CustomField;
use MailPoet\Models\Subscriber; use MailPoet\Models\Subscriber;
use MailPoet\Models\Segment; use MailPoet\Models\Segment;
use MailPoet\Models\SubscriberCustomField; use MailPoet\Models\SubscriberCustomField;
@@ -9,6 +10,13 @@ use MailPoet\Util\Helpers;
class ImportTest extends MailPoetTest { class ImportTest extends MailPoetTest {
function _before() { function _before() {
$custom_field = CustomField::create();
$custom_field->name = 'country';
$custom_field->type = 'text';
$custom_field->save();
$this->subscriber_custom_fields = array((string)$custom_field->id);
$this->segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1'));
$this->segment_2 = Segment::createOrUpdate(array('name' => 'Segment 2'));
$this->data = array( $this->data = array(
'subscribers' => array( 'subscribers' => array(
array( array(
@@ -25,13 +33,13 @@ class ImportTest extends MailPoetTest {
) )
), ),
'columns' => array( 'columns' => array(
'first_name' => 0, 'first_name' => array('index' => 0),
'last_name' => 1, 'last_name' => array('index' => 1),
'email' => 2, 'email' => array('index' => 2),
777 => 3 (string)$custom_field->id => array('index' => 3)
), ),
'segments' => array( 'segments' => array(
195 $this->segment_1->id
), ),
'timestamp' => time(), 'timestamp' => time(),
'updateSubscribers' => true 'updateSubscribers' => true
@@ -41,10 +49,6 @@ class ImportTest extends MailPoetTest {
'last_name', 'last_name',
'email' 'email'
); );
$this->segment_1 = Segment::createOrUpdate(array('name' => 'Segment 1'));
$this->segment_2 = Segment::createOrUpdate(array('name' => 'Segment 2'));
$this->subscriber_custom_fields = array(777);
$this->import = new Import($this->data); $this->import = new Import($this->data);
$this->subscribers_data = $this->import->transformSubscribersData( $this->subscribers_data = $this->import->transformSubscribersData(
$this->data['subscribers'], $this->data['subscribers'],
@@ -63,13 +67,14 @@ class ImportTest extends MailPoetTest {
} }
function testItCanTransformSubscribers() { function testItCanTransformSubscribers() {
$custom_field = $this->subscriber_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])
->equals($this->data['subscribers'][0][1]); ->equals($this->data['subscribers'][0][1]);
expect($this->import->subscribers_data['email'][0]) expect($this->import->subscribers_data['email'][0])
->equals($this->data['subscribers'][0][2]); ->equals($this->data['subscribers'][0][2]);
expect($this->import->subscribers_data['777'][0]) expect($this->import->subscribers_data[$custom_field][0])
->equals($this->data['subscribers'][0][3]); ->equals($this->data['subscribers'][0][3]);
} }
@@ -242,6 +247,7 @@ class ImportTest extends MailPoetTest {
function testItCanCreateOrUpdateCustomFields() { function testItCanCreateOrUpdateCustomFields() {
$subscribers_data = $this->subscribers_data; $subscribers_data = $this->subscribers_data;
$custom_field = $this->subscriber_custom_fields[0];
$this->import->createOrUpdateSubscribers( $this->import->createOrUpdateSubscribers(
'create', 'create',
$subscribers_data, $subscribers_data,
@@ -266,8 +272,8 @@ class ImportTest extends MailPoetTest {
$subscriber_custom_fields = SubscriberCustomField::findArray(); $subscriber_custom_fields = SubscriberCustomField::findArray();
expect(count($subscriber_custom_fields))->equals(2); expect(count($subscriber_custom_fields))->equals(2);
expect($subscriber_custom_fields[0]['value']) expect($subscriber_custom_fields[0]['value'])
->equals($subscribers_data[777][0]); ->equals($subscribers_data[$custom_field][0]);
$subscribers_data[777][1] = 'Rio'; $subscribers_data[$custom_field][1] = 'Rio';
$this->import->createOrUpdateCustomFields( $this->import->createOrUpdateCustomFields(
'update', 'update',
$db_subscribers, $db_subscribers,
@@ -276,7 +282,7 @@ class ImportTest extends MailPoetTest {
); );
$subscriber_custom_fields = SubscriberCustomField::findArray(); $subscriber_custom_fields = SubscriberCustomField::findArray();
expect($subscriber_custom_fields[1]['value']) expect($subscriber_custom_fields[1]['value'])
->equals($subscribers_data[777][1]); ->equals($subscribers_data[$custom_field][1]);
} }
@@ -320,7 +326,7 @@ class ImportTest extends MailPoetTest {
function testItCanUpdateSubscribers() { function testItCanUpdateSubscribers() {
$result = $this->import->process(); $result = $this->import->process();
expect($result['data']['updated'])->equals(0); expect($result['data']['updated'])->equals(0);
$result = $this->import->process(); $result = $this->import->process();
expect($result['data']['updated'])->equals(2); expect($result['data']['updated'])->equals(2);
$this->import->update_subscribers = false; $this->import->update_subscribers = false;
@@ -345,6 +351,7 @@ class ImportTest extends MailPoetTest {
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table); ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
ORM::raw_execute('TRUNCATE ' . Segment::$_table); ORM::raw_execute('TRUNCATE ' . Segment::$_table);
ORM::raw_execute('TRUNCATE ' . SubscriberSegment::$_table); ORM::raw_execute('TRUNCATE ' . SubscriberSegment::$_table);
ORM::raw_execute('TRUNCATE ' . CustomField::$_table);
ORM::raw_execute('TRUNCATE ' . SubscriberCustomField::$_table); ORM::raw_execute('TRUNCATE ' . SubscriberCustomField::$_table);
} }
} }

View File

@@ -92,7 +92,7 @@
{{#show_and_match_columns .}} {{#show_and_match_columns .}}
{{#.}} {{#.}}
<th> <th>
<select class="mailpoet_subscribers_column_data_match" id="{{column_id}}" data-column-id="{{column_id}}" id="column_{{@index}}"> <select class="mailpoet_subscribers_column_data_match" data-column-id="{{column_id}}" data-validation-rule="false" id="column_{{@index}}">
</th> </th>
{{/.}} {{/.}}
{{/show_and_match_columns}} {{/show_and_match_columns}}