Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
1d756e95a7 | |||
1fb0da9fda | |||
a0017b91ee | |||
444ab17342 | |||
44f3058326 | |||
ec09fbcb78 | |||
ed352bb1d3 | |||
375bbd2759 | |||
9fb9d25132 | |||
30f79aa589 | |||
69f8daac95 | |||
03f3a6080c | |||
44f84c6cdb | |||
31008a6895 | |||
2490d8c919 | |||
5886dbfd25 | |||
e48d55f0b1 | |||
42339927cf | |||
b492bcecc0 | |||
6ab7debb7b | |||
b76ce6c26f | |||
6fbc7b1593 | |||
69c8670b01 | |||
da44a87415 | |||
9fb17d4a6b | |||
16dd286f9d | |||
5025f10f9f | |||
1278d9648c | |||
289811a595 | |||
916ae97f73 | |||
876e386966 | |||
9582e58dda | |||
213bca8050 | |||
dc97d3115e | |||
90eb443965 | |||
c5a02c6136 | |||
7f091d7188 | |||
81c277ca93 | |||
f8fea75130 | |||
46b0fcf37b | |||
b07c4d0e6e | |||
eb107799a7 | |||
4eec0a42f9 | |||
9a5a3a08c6 | |||
151683c632 | |||
fd2103d1aa | |||
7696b6ec5d | |||
d972b96255 |
@ -127,37 +127,12 @@ define([
|
||||
return;
|
||||
}
|
||||
|
||||
const dateType = this.props.field.params.date_type;
|
||||
const dateParts = value.split('-');
|
||||
let year = '';
|
||||
let month = '';
|
||||
let day = '';
|
||||
|
||||
switch(dateType) {
|
||||
case 'year_month_day':
|
||||
year = ~~(dateParts[0]);
|
||||
month = ~~(dateParts[1]);
|
||||
day = ~~(dateParts[2]);
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
year = ~~(dateParts[0]);
|
||||
month = ~~(dateParts[1]);
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
month = ~~(dateParts[0]);
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
year = ~~(dateParts[0]);
|
||||
break;
|
||||
}
|
||||
const dateTime = Moment(value);
|
||||
|
||||
this.setState({
|
||||
year: year,
|
||||
month: month,
|
||||
day: day
|
||||
year: dateTime.format('YYYY'),
|
||||
month: dateTime.format('M'),
|
||||
day: dateTime.format('D')
|
||||
});
|
||||
}
|
||||
formatValue() {
|
||||
@ -228,7 +203,7 @@ define([
|
||||
|
||||
const fields = dateSelects.map(type => {
|
||||
switch(type) {
|
||||
case 'yyyy':
|
||||
case 'YYYY':
|
||||
return (<FormFieldDateYear
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'year' }
|
||||
@ -239,7 +214,7 @@ define([
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'mm':
|
||||
case 'MM':
|
||||
return (<FormFieldDateMonth
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'month' }
|
||||
@ -251,7 +226,7 @@ define([
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'dd':
|
||||
case 'DD':
|
||||
return (<FormFieldDateDay
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'day' }
|
||||
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Show Settings Behavior
|
||||
*
|
||||
* Opens up settings of a BlockView if contents are clicked upon
|
||||
*/
|
||||
define([
|
||||
'backbone.marionette',
|
||||
'jquery',
|
||||
'newsletter_editor/behaviors/BehaviorsLookup',
|
||||
], function(Marionette, jQuery, BehaviorsLookup) {
|
||||
|
||||
BehaviorsLookup.ShowSettingsBehavior = Marionette.Behavior.extend({
|
||||
defaults: {
|
||||
ignoreFrom: '', // selector
|
||||
},
|
||||
events: {
|
||||
'click .mailpoet_content': 'showSettings',
|
||||
},
|
||||
showSettings: function(event) {
|
||||
if(!this.isIgnoredElement(event.target)) {
|
||||
this.view.triggerMethod('showSettings');
|
||||
}
|
||||
},
|
||||
isIgnoredElement: function(element) {
|
||||
return this.options.ignoreFrom
|
||||
&& this.options.ignoreFrom.length > 0
|
||||
&& jQuery(element).is(this.options.ignoreFrom);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -180,17 +180,17 @@ define([
|
||||
"change .mailpoet_automated_latest_content_title_format": 'changeTitleFormat',
|
||||
"change .mailpoet_automated_latest_content_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||
"change .mailpoet_automated_latest_content_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||
"keyup .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
||||
"input .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
||||
"change .mailpoet_automated_latest_content_content_type": _.partial(this.changeField, "contentType"),
|
||||
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_automated_latest_content_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"input .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
"keyup .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"keyup .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"input .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"input .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"change .mailpoet_automated_latest_content_sort_by": _.partial(this.changeField, "sortBy"),
|
||||
"click .mailpoet_done_editing": "close",
|
||||
};
|
||||
|
@ -44,6 +44,9 @@ define([
|
||||
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block",
|
||||
getTemplate: function() { return templates.buttonBlock; },
|
||||
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
||||
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||
ShowSettingsBehavior: {},
|
||||
}),
|
||||
initialize: function() {
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
|
||||
@ -65,8 +68,8 @@ define([
|
||||
getTemplate: function() { return templates.buttonBlockSettings; },
|
||||
events: function() {
|
||||
return {
|
||||
"keyup .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
||||
"keyup .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
||||
"input .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
||||
"input .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
||||
"change .mailpoet_field_button_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||
"change .mailpoet_field_button_font_color": _.partial(this.changeColorField, "styles.block.fontColor"),
|
||||
"change .mailpoet_field_button_font_family": _.partial(this.changeField, "styles.block.fontFamily"),
|
||||
@ -77,23 +80,19 @@ define([
|
||||
|
||||
"input .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"keyup .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"input .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"change .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"change .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"keyup .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"input .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"change .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"change .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"keyup .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"input .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"change .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"change .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"keyup .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"input .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
|
||||
"click .mailpoet_field_button_replace_all_styles": "applyToAll",
|
||||
"click .mailpoet_done_editing": "close",
|
||||
|
@ -43,6 +43,9 @@ define([
|
||||
minLength: 0, // TODO: Move this number to editor configuration
|
||||
modelField: 'styles.block.padding',
|
||||
},
|
||||
ShowSettingsBehavior: {
|
||||
ignoreFrom: '.mailpoet_resize_handle'
|
||||
},
|
||||
}, base.BlockView.prototype.behaviors),
|
||||
onDragSubstituteBy: function() { return Module.DividerWidgetView; },
|
||||
initialize: function() {
|
||||
@ -88,8 +91,7 @@ define([
|
||||
|
||||
"input .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"keyup .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"input .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
|
||||
"change .mailpoet_field_divider_border_color": _.partial(this.changeColorField, "styles.block.borderColor"),
|
||||
"change .mailpoet_field_divider_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
|
||||
|
@ -41,6 +41,9 @@ define([
|
||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||
},
|
||||
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||
ShowSettingsBehavior: {},
|
||||
}),
|
||||
onRender: function() {
|
||||
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
||||
this.toolsRegion.show(this.toolsView);
|
||||
@ -61,9 +64,9 @@ define([
|
||||
getTemplate: function() { return templates.imageBlockSettings; },
|
||||
events: function() {
|
||||
return {
|
||||
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||
"input .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||
"input .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||
"input .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
|
||||
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
||||
|
@ -273,7 +273,7 @@ define([
|
||||
return {
|
||||
'change .mailpoet_settings_posts_content_type': _.partial(this.changeField, 'contentType'),
|
||||
'change .mailpoet_posts_post_status': _.partial(this.changeField, 'postStatus'),
|
||||
'keyup .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||
};
|
||||
},
|
||||
constructor: function() {
|
||||
@ -414,17 +414,17 @@ define([
|
||||
"change .mailpoet_posts_title_format": 'changeTitleFormat',
|
||||
"change .mailpoet_posts_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||
"change .mailpoet_posts_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||
"keyup .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
||||
"input .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
||||
"change .mailpoet_posts_content_type": _.partial(this.changeField, "contentType"),
|
||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_posts_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"input .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
"keyup .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"keyup .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"input .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"input .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"change .mailpoet_posts_sort_by": _.partial(this.changeField, "sortBy"),
|
||||
};
|
||||
},
|
||||
|
@ -141,6 +141,7 @@ define([
|
||||
},
|
||||
},
|
||||
HighlightEditingBehavior: {},
|
||||
ShowSettingsBehavior: {},
|
||||
},
|
||||
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
|
||||
constructor: function() {
|
||||
@ -149,6 +150,7 @@ define([
|
||||
Marionette.CompositeView.apply(this, arguments);
|
||||
},
|
||||
initialize: function() {
|
||||
this.on('showSettings', this.showSettings, this);
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
@ -176,6 +178,9 @@ define([
|
||||
this.$(this.ui.tools).hide();
|
||||
_event.stopPropagation();
|
||||
},
|
||||
showSettings: function(options) {
|
||||
this.toolsView.triggerMethod('showSettings', options);
|
||||
},
|
||||
getDropFunc: function() {
|
||||
return function() {
|
||||
return this.model.clone();
|
||||
@ -275,9 +280,9 @@ define([
|
||||
return {
|
||||
"click .mailpoet_delete_block": "deleteIcon",
|
||||
"change .mailpoet_social_icon_field_type": _.partial(this.changeField, "iconType"),
|
||||
"keyup .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
||||
"keyup .mailpoet_social_icon_field_link": this.changeLink,
|
||||
"keyup .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
||||
"input .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
||||
"input .mailpoet_social_icon_field_link": this.changeLink,
|
||||
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
||||
};
|
||||
},
|
||||
modelEvents: {
|
||||
|
@ -36,6 +36,9 @@ define([
|
||||
minLength: 20, // TODO: Move this number to editor configuration
|
||||
modelField: 'styles.block.height',
|
||||
},
|
||||
ShowSettingsBehavior: {
|
||||
ignoreFrom: '.mailpoet_resize_handle'
|
||||
},
|
||||
}, base.BlockView.prototype.behaviors),
|
||||
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
|
||||
onDragSubstituteBy: function() { return Module.SpacerWidgetView; },
|
||||
|
@ -232,6 +232,12 @@ define([
|
||||
'click .mailpoet_show_preview': 'showPreview',
|
||||
'click #mailpoet_send_preview': 'sendPreview',
|
||||
},
|
||||
onBeforeDestroy: function() {
|
||||
if (this.previewView) {
|
||||
this.previewView.destroy();
|
||||
this.previewView = null;
|
||||
}
|
||||
},
|
||||
showPreview: function() {
|
||||
var json = App.toJSON();
|
||||
|
||||
@ -246,18 +252,32 @@ define([
|
||||
endpoint: 'newsletters',
|
||||
action: 'showPreview',
|
||||
data: json,
|
||||
}).done(function(response){
|
||||
MailPoet.Modal.loading(false);
|
||||
|
||||
}).done(function(response) {
|
||||
if (response.result === true) {
|
||||
window.open(response.data.url, '_blank')
|
||||
this.previewView = new Module.NewsletterPreviewView({
|
||||
previewUrl: response.data.url
|
||||
});
|
||||
|
||||
var view = this.previewView.render();
|
||||
|
||||
MailPoet.Modal.popup({
|
||||
template: '',
|
||||
element: this.previewView.$el,
|
||||
title: MailPoet.I18n.t('newsletterPreview'),
|
||||
onCancel: function() {
|
||||
this.previewView.destroy();
|
||||
this.previewView = null;
|
||||
}.bind(this)
|
||||
});
|
||||
} else {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}).fail(function(error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
}.bind(this)).fail(function(error) {
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('newsletterPreviewFailed')
|
||||
);
|
||||
}).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
});
|
||||
},
|
||||
sendPreview: function() {
|
||||
@ -308,6 +328,22 @@ define([
|
||||
},
|
||||
});
|
||||
|
||||
Module.NewsletterPreviewView = Marionette.ItemView.extend({
|
||||
getTemplate: function() { return templates.newsletterPreview; },
|
||||
initialize: function(options) {
|
||||
this.previewUrl = options.previewUrl;
|
||||
this.width = App.getConfig().get('newsletterPreview.width');
|
||||
this.height = App.getConfig().get('newsletterPreview.height')
|
||||
},
|
||||
templateHelpers: function() {
|
||||
return {
|
||||
previewUrl: this.previewUrl,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function(options) {
|
||||
App.registerWidget = Module.registerWidget;
|
||||
App.getWidgets = Module.getWidgets;
|
||||
|
@ -133,8 +133,7 @@ define(
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processExport',
|
||||
data: JSON.stringify({
|
||||
@ -144,25 +143,22 @@ define(
|
||||
'segments': (exportData.segments) ? segmentsContainerElement.val() : false,
|
||||
'subscriber_fields': subscriberFieldsContainerElement.val()
|
||||
})
|
||||
})
|
||||
.done(function (response) {
|
||||
}).always(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
} else {
|
||||
resultMessage = MailPoet.I18n.t('exportMessage')
|
||||
.replace('%1$s', '<strong>' + parseInt(response.data.totalExported).toLocaleString() + '</strong>')
|
||||
.replace('[link]', '<a href="' + response.data.exportFileURL + '" target="_blank" >')
|
||||
.replace('[/link]', '</a>');
|
||||
jQuery('#export_result_notice').html('<p>' + resultMessage + '</p>').show();
|
||||
window.location.href = response.data.exportFileURL;
|
||||
}).done(function(response) {
|
||||
resultMessage = MailPoet.I18n.t('exportMessage')
|
||||
.replace('%1$s', '<strong>' + parseInt(response.data.totalExported).toLocaleString() + '</strong>')
|
||||
.replace('[link]', '<a href="' + response.data.exportFileURL + '" target="_blank" >')
|
||||
.replace('[/link]', '</a>');
|
||||
jQuery('#export_result_notice').html('<p>' + resultMessage + '</p>').show();
|
||||
window.location.href = response.data.exportFileURL;
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -51,6 +51,12 @@ define(
|
||||
* STEP 1 (upload or copy/paste)
|
||||
*/
|
||||
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') {
|
||||
showCurrentStep();
|
||||
return;
|
||||
@ -185,68 +191,59 @@ define(
|
||||
mailChimpKeyVerifyButtonElement.click(function () {
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
endpoint: 'importExport',
|
||||
action: 'getMailChimpLists',
|
||||
data: {api_key: mailChimpKeyInputElement.val()}
|
||||
}).done(function (response) {
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(response.errors);
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-error');
|
||||
data: {
|
||||
api_key: mailChimpKeyInputElement.val()
|
||||
}
|
||||
}).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function(response) {
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.html('')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-ok');
|
||||
if (response.data.length === 0) {
|
||||
jQuery('.mailpoet_mailchimp-key-status').html(MailPoet.I18n.t('noMailChimpLists'));
|
||||
mailChimpListsContainerElement.hide();
|
||||
toggleNextStepButton(mailChimpProcessButtonElement, 'off');
|
||||
} else {
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.html('')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-ok');
|
||||
if (!response.data) {
|
||||
jQuery('.mailpoet_mailchimp-key-status').html(MailPoet.I18n.t('noMailChimpLists'));
|
||||
mailChimpListsContainerElement.hide();
|
||||
toggleNextStepButton(mailChimpProcessButtonElement, 'off');
|
||||
} else {
|
||||
displayMailChimpLists(response.data);
|
||||
}
|
||||
displayMailChimpLists(response.data);
|
||||
}
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
MailPoet.Modal.loading(false);
|
||||
}).error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
MailPoet.Modal.loading(false);
|
||||
});
|
||||
|
||||
mailChimpProcessButtonElement.click(function () {
|
||||
if (mailChimpProcessButtonElement.closest('table a').hasClass('disabled')) {
|
||||
if (mailChimpProcessButtonElement.closest('table a').hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
endpoint: 'importExport',
|
||||
action: 'getMailChimpSubscribers',
|
||||
data: {
|
||||
api_key: mailChimpKeyInputElement.val(),
|
||||
lists: mailChimpListsContainerElement.find('select').val()
|
||||
}
|
||||
}).done(function (response) {
|
||||
if (response.result === true) {
|
||||
importData.step1 = response.data;
|
||||
router.navigate('step2', {trigger: true});
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}
|
||||
}).always(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).error(function () {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + result.statusText.toLowerCase() + '.'
|
||||
);
|
||||
}).done(function(response) {
|
||||
importData.step1 = response.data;
|
||||
router.navigate('step2', {trigger: true});
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -455,7 +452,7 @@ define(
|
||||
null,
|
||||
new Array(subscribers.subscribers[0].length)
|
||||
).map(String.prototype.valueOf, filler),
|
||||
fillterPosition;
|
||||
fillerPosition;
|
||||
|
||||
showCurrentStep();
|
||||
|
||||
@ -565,79 +562,54 @@ define(
|
||||
})
|
||||
}
|
||||
|
||||
jQuery('.mailpoet_create_segment').click(function () {
|
||||
jQuery('.mailpoet_create_segment').click(function() {
|
||||
MailPoet.Modal.popup({
|
||||
title: MailPoet.I18n.t('addNewList'),
|
||||
template: jQuery('#new_segment_template').html()
|
||||
})
|
||||
jQuery('#new_segment_name').keypress(function (e) {
|
||||
jQuery('#new_segment_name').keypress(function(e) {
|
||||
if (e.which == 13) {
|
||||
jQuery('#new_segment_process').click();
|
||||
}
|
||||
});
|
||||
jQuery('#new_segment_process').click(function () {
|
||||
var segmentName = jQuery('#new_segment_name').val().trim(),
|
||||
segmentDescription = jQuery('#new_segment_description').val().trim(),
|
||||
isDuplicateListName = ( jQuery.map(mailpoetSegments, function (el) {
|
||||
if (el.name.toLowerCase() === segmentName.toLowerCase()) {
|
||||
return true;
|
||||
}
|
||||
}).length && segmentName) ? true : false;
|
||||
if (segmentName === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:hidden').show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:visible').hide();
|
||||
}
|
||||
if (isDuplicateListName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_not_unique"]:hidden').show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_not_unique"]:visible').hide();
|
||||
}
|
||||
if (segmentName && !isDuplicateListName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:visible').hide();
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addSegment',
|
||||
data: {
|
||||
name: segmentName,
|
||||
description: segmentDescription
|
||||
}
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === true) {
|
||||
mailpoetSegments.push({
|
||||
'id': response.segment.id,
|
||||
'name': response.segment.name
|
||||
});
|
||||
var segmentName = jQuery('#new_segment_name').val().trim();
|
||||
var segmentDescription = jQuery('#new_segment_description').val().trim();
|
||||
|
||||
var selected_values = segmentSelectElement.val();
|
||||
if (selected_values === null) {
|
||||
selected_values = [response.segment.id]
|
||||
} else {
|
||||
selected_values.push(response.segment.id);
|
||||
}
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addSegment',
|
||||
data: {
|
||||
name: segmentName,
|
||||
description: segmentDescription
|
||||
}
|
||||
}).done(function(response) {
|
||||
mailpoetSegments.push({
|
||||
'id': response.data.id,
|
||||
'name': response.data.name
|
||||
});
|
||||
|
||||
enableSegmentSelection(mailpoetSegments);
|
||||
segmentSelectElement.val(selected_values).trigger('change');
|
||||
jQuery('.mailpoet_segments:hidden').show();
|
||||
jQuery('.mailpoet_no_segments:visible').hide();
|
||||
MailPoet.Modal.close();
|
||||
}
|
||||
else {
|
||||
MailPoet.Modal.close();
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('segmentCreateError') + response.message + '.'
|
||||
);
|
||||
}
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.close();
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
}
|
||||
var selected_values = segmentSelectElement.val();
|
||||
if (selected_values === null) {
|
||||
selected_values = [response.data.id]
|
||||
} else {
|
||||
selected_values.push(response.data.id);
|
||||
}
|
||||
|
||||
enableSegmentSelection(mailpoetSegments);
|
||||
segmentSelectElement.val(selected_values).trigger('change');
|
||||
jQuery('.mailpoet_segments:hidden').show();
|
||||
jQuery('.mailpoet_no_segments:visible').hide();
|
||||
MailPoet.Modal.close();
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ positionAfter: '#new_segment_name' }
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
jQuery('#new_segment_cancel').click(function () {
|
||||
MailPoet.Modal.close();
|
||||
@ -707,7 +679,7 @@ define(
|
||||
// display filler data (e.g., ellipsis) if we've reached the maximum number of rows and
|
||||
// subscribers count is greater than the maximum number of rows we're displaying
|
||||
if (index === maxRowsToShow && subscribers.subscribersCount > (maxRowsToShow + 1)) {
|
||||
fillterPosition = index;
|
||||
fillerPosition = index;
|
||||
return filler;
|
||||
}
|
||||
// if we're on the last line, show the total count of subscribers data
|
||||
@ -745,114 +717,70 @@ define(
|
||||
.on('select2:selecting', function (selectEvent) {
|
||||
var selectElement = this,
|
||||
selectedOptionId = selectEvent.params.args.data.id;
|
||||
// CREATE CUSTOM FIELD
|
||||
if (selectedOptionId === 'create') {
|
||||
selectEvent.preventDefault();
|
||||
jQuery(selectElement).select2('close');
|
||||
MailPoet.Modal.popup({
|
||||
title: MailPoet.I18n.t('addNewColumn'),
|
||||
template: jQuery('#new_column_template').html()
|
||||
title: MailPoet.I18n.t('addNewField'),
|
||||
template: jQuery('#form_template_field_form').html()
|
||||
});
|
||||
jQuery('#new_column_name').keypress(function (e) {
|
||||
if (e.which == 13) {
|
||||
jQuery('#new_column_process').click();
|
||||
}
|
||||
});
|
||||
jQuery('#new_column_process').click(function () {
|
||||
var name = jQuery('#new_column_name').val().trim(),
|
||||
type = jQuery('#new_column_type').val().trim(),
|
||||
columnNames = mailpoetColumns.map(function (el) {
|
||||
return el.name.toLowerCase();
|
||||
jQuery('#form_field_new').parsley().on('form:submit', function(parsley) {
|
||||
// get data
|
||||
var data = jQuery(this.$element).serializeObject();
|
||||
|
||||
// save custom field
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'customFields',
|
||||
action: 'save',
|
||||
data: data
|
||||
}).done(function(response) {
|
||||
var new_column_data = {
|
||||
'id': response.data.id,
|
||||
'name': response.data.name,
|
||||
'type': response.data.type,
|
||||
'params': response.data.params,
|
||||
'custom': true
|
||||
};
|
||||
// if this is the first custom column, create an "optgroup"
|
||||
if (mailpoetColumnsSelect2.length === 2) {
|
||||
mailpoetColumnsSelect2.push({
|
||||
'name': MailPoet.I18n.t('userColumns'),
|
||||
'children': []
|
||||
});
|
||||
isDuplicateColumnName =
|
||||
(name && columnNames.indexOf(name.toLowerCase()) > -1)
|
||||
? true
|
||||
: false;
|
||||
if (name === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_required"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_required"]')
|
||||
.hide();
|
||||
}
|
||||
if (type === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="type_required"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="type_required"]')
|
||||
.hide();
|
||||
}
|
||||
if (isDuplicateColumnName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_not_unique"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_not_unique"]')
|
||||
.hide();
|
||||
}
|
||||
// create new field
|
||||
if (name && type && !isDuplicateColumnName) {
|
||||
MailPoet.Modal
|
||||
.close()
|
||||
.loading(true);
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addCustomField',
|
||||
data: {
|
||||
name: name,
|
||||
type: type
|
||||
}
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === true) {
|
||||
var new_column_data = {
|
||||
'id': response.customField.id,
|
||||
'name': name,
|
||||
'type': type,
|
||||
'custom': true,
|
||||
};
|
||||
// if this is the first custom column, create an "optgroup"
|
||||
if (mailpoetColumnsSelect2.length === 2) {
|
||||
mailpoetColumnsSelect2.push({
|
||||
'name': MailPoet.I18n.t('userColumns'),
|
||||
'children': []
|
||||
});
|
||||
}
|
||||
mailpoetColumnsSelect2[2].children.push(new_column_data);
|
||||
mailpoetColumns.push(new_column_data);
|
||||
jQuery('select.mailpoet_subscribers_column_data_match')
|
||||
.each(function () {
|
||||
jQuery(this)
|
||||
.html('')
|
||||
.select2('destroy')
|
||||
.select2({
|
||||
data: mailpoetColumnsSelect2,
|
||||
width: '15em',
|
||||
templateResult: function (item) {
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return item.name;
|
||||
}
|
||||
mailpoetColumnsSelect2[2].children.push(new_column_data);
|
||||
mailpoetColumns.push(new_column_data);
|
||||
jQuery('select.mailpoet_subscribers_column_data_match')
|
||||
.each(function () {
|
||||
jQuery(this)
|
||||
.html('')
|
||||
.select2('destroy')
|
||||
.select2({
|
||||
data: mailpoetColumnsSelect2,
|
||||
width: '15em',
|
||||
templateResult: function (item) {
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return item.name;
|
||||
}
|
||||
})
|
||||
});
|
||||
jQuery(selectElement).data('column-id', new_column_data.id);
|
||||
filterSubscribers();
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('customFieldCreateError'));
|
||||
}
|
||||
MailPoet.Modal.loading(false);
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
jQuery('#new_column_cancel').click(function () {
|
||||
MailPoet.Modal.close();
|
||||
})
|
||||
});
|
||||
jQuery(selectElement).data('column-id', new_column_data.id);
|
||||
jQuery(selectElement).data('validation-rule', false);
|
||||
filterSubscribers();
|
||||
// close popup
|
||||
MailPoet.Modal.close();
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ positionAfter: '#field_name' }
|
||||
);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
// CHANGE COLUMN
|
||||
@ -890,22 +818,22 @@ define(
|
||||
.remove();
|
||||
var subscribersClone = jQuery.extend(true, {}, subscribers),
|
||||
preventNextStep = false,
|
||||
displayedColumnsIds = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (data) {
|
||||
var columnId = jQuery(data).data('column-id');
|
||||
jQuery(data).val(columnId).trigger('change');
|
||||
return columnId;
|
||||
displayedColumns = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (element, elementIndex) {
|
||||
var columnId = jQuery(element).data('column-id');
|
||||
var validationRule = jQuery(element).data('validation-rule');
|
||||
jQuery(element).val(columnId).trigger('change');
|
||||
return { id: columnId, index: elementIndex, validationRule: validationRule, element: element };
|
||||
});
|
||||
// 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
|
||||
// subscriber's data columns
|
||||
var matchedColumn = jQuery.inArray(column.id, displayedColumnsIds);
|
||||
|
||||
// EMAIL filter: if the last value in the column doesn't have a valid
|
||||
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, hide the next button
|
||||
if (column.id === "email") {
|
||||
if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn])) {
|
||||
if (column.id === 'email') {
|
||||
if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn.index])) {
|
||||
preventNextStep = true;
|
||||
if (!jQuery('[data-id="notice_invalidEmail"]').length) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidElement'), {
|
||||
@ -921,35 +849,63 @@ define(
|
||||
}
|
||||
}
|
||||
// DATE filter: if column type is date, check if we can recognize it
|
||||
if (column.type === 'date' && matchedColumn !== -1) {
|
||||
jQuery.map(subscribersClone.subscribers, function (data, position) {
|
||||
var rowData = data[matchedColumn];
|
||||
if (position !== fillterPosition) {
|
||||
// check if date exists
|
||||
if (rowData.trim() === '') {
|
||||
data[matchedColumn] =
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('emptyDate')
|
||||
+ '</span>';
|
||||
preventNextStep = true;
|
||||
return;
|
||||
}
|
||||
// check if date is valid and is before today
|
||||
if (Moment(rowData).isValid() && Moment(rowData).isBefore(Moment())) {
|
||||
data[matchedColumn] +=
|
||||
'<span class="mailpoet_data_match" title="'
|
||||
+ MailPoet.I18n.t('verifyDateMatch') + '">'
|
||||
+ MailPoet.Date.format(rowData) + '</span>';
|
||||
}
|
||||
else {
|
||||
data[matchedColumn] +=
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('dateMatchError') + '</span>';
|
||||
preventNextStep = true;
|
||||
if (column.type === 'date' && matchedColumn) {
|
||||
var allowedDateFormats = [
|
||||
Moment.ISO_8601,
|
||||
'YYYY/MM/DD',
|
||||
'MM/DD/YYYY',
|
||||
'DD/MM/YYYY',
|
||||
'YYYY/MM/DD',
|
||||
'YYYY/DD/MM',
|
||||
'MM/YYYY',
|
||||
'YYYY/MM',
|
||||
'YYYY'
|
||||
];
|
||||
var firstRowData = subscribersClone.subscribers[0][matchedColumn.index];
|
||||
var validationRule = false;
|
||||
// check if date exists
|
||||
if (firstRowData.trim() === '') {
|
||||
subscribersClone.subscribers[0][matchedColumn.index] =
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('emptyFirstRowDate')
|
||||
+ '</span>';
|
||||
preventNextStep = true;
|
||||
}
|
||||
else {
|
||||
for (var format in allowedDateFormats) {
|
||||
var testedFormat = allowedDateFormats[format]
|
||||
if (Moment(firstRowData, testedFormat, true).isValid()) {
|
||||
var validationRule = (typeof(testedFormat) === 'function') ?
|
||||
'datetime' :
|
||||
testedFormat
|
||||
// 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) {
|
||||
var rowData = data[matchedColumn.index];
|
||||
if (index === fillerPosition || rowData.trim() === '') return;
|
||||
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) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidDate'), {
|
||||
@ -983,11 +939,11 @@ define(
|
||||
nextStepButton.addClass(disabled);
|
||||
}
|
||||
|
||||
previousStepButton.off().click(function () {
|
||||
router.navigate('step1', {trigger: true});
|
||||
previousStepButton.off().on('click', function () {
|
||||
router.navigate('step1', { trigger: true });
|
||||
});
|
||||
|
||||
nextStepButton.off().click(function () {
|
||||
nextStepButton.off().on('click', function () {
|
||||
if (jQuery(this).hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
@ -1019,44 +975,41 @@ define(
|
||||
_.each(jQuery('select.mailpoet_subscribers_column_data_match'),
|
||||
function (column, columnIndex) {
|
||||
var columnId = jQuery(column).data('column-id');
|
||||
var validationRule = jQuery(column).data('validation-rule');
|
||||
if (columnId === 'ignore') {
|
||||
return;
|
||||
}
|
||||
columns[columnId] = columnIndex;
|
||||
columns[columnId] = { index: columnIndex, validation_rule: validationRule };
|
||||
});
|
||||
|
||||
_.each(subscribers, function () {
|
||||
queue.add(function (queue) {
|
||||
queue.add(function(queue) {
|
||||
queue.pause();
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processImport',
|
||||
data: JSON.stringify({
|
||||
columns: columns,
|
||||
subscribers: subscribers[batchNumber],
|
||||
timestamp: timestamp,
|
||||
segments: segmentSelectElement.val(),
|
||||
updateSubscribers: (jQuery(':radio[name="subscriber_update_option"]:checked').val() === 'yes') ? true : false
|
||||
})
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processImport',
|
||||
data: JSON.stringify({
|
||||
columns: columns,
|
||||
subscribers: subscribers[batchNumber],
|
||||
timestamp: timestamp,
|
||||
segments: segmentSelectElement.val(),
|
||||
updateSubscribers: (jQuery(':radio[name="subscriber_update_option"]:checked').val() === 'yes') ? true : false
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === false) {
|
||||
importResults.errors.push(response.errors);
|
||||
} else {
|
||||
importResults.created = response.data.created;
|
||||
importResults.updated = response.data.updated;
|
||||
importResults.segments = response.data.segments;
|
||||
importResults.added_to_segment_with_welcome_notification = response.data.added_to_segment_with_welcome_notification;
|
||||
}
|
||||
queue.run();
|
||||
})
|
||||
.error(function (error) {
|
||||
importResults.errors.push(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
}).done(function(response) {
|
||||
importResults.created = response.data.created;
|
||||
importResults.updated = response.data.updated;
|
||||
importResults.segments = response.data.segments;
|
||||
importResults.added_to_segment_with_welcome_notification = response.data.added_to_segment_with_welcome_notification;
|
||||
queue.run();
|
||||
}).fail(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
queue.run();
|
||||
});
|
||||
}
|
||||
});
|
||||
batchNumber++;
|
||||
})
|
||||
});
|
||||
@ -1146,4 +1099,4 @@ define(
|
||||
Backbone.history.start();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@ -1,34 +1,32 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\Models\CustomField;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CustomFields {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
class CustomFields extends APIEndpoint {
|
||||
function getAll() {
|
||||
$collection = CustomField::findMany();
|
||||
$custom_fields = array_map(function($custom_field) {
|
||||
return $custom_field->asArray();
|
||||
}, $collection);
|
||||
|
||||
return $custom_fields;
|
||||
return $this->successResponse($custom_fields);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false or !$custom_field->id()) {
|
||||
return array('result' => false);
|
||||
if($custom_field === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
$custom_field->delete();
|
||||
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
);
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,24 +35,23 @@ class CustomFields {
|
||||
$errors = $custom_field->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
return $this->successResponse(
|
||||
CustomField::findOne($custom_field->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function get($id) {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false) {
|
||||
return false;
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $custom_field->asArray();
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Subscribers\ImportExport\Import\MailChimp;
|
||||
use MailPoet\Models\CustomField;
|
||||
@ -7,58 +9,69 @@ use MailPoet\Models\Segment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class ImportExport {
|
||||
class ImportExport extends APIEndpoint {
|
||||
function getMailChimpLists($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
return $mailChimp->getLists();
|
||||
try {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
$lists = $mailChimp->getLists();
|
||||
return $this->successResponse($lists);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function getMailChimpSubscribers($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
return $mailChimp->getSubscribers($data['lists']);
|
||||
try {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
$subscribers = $mailChimp->getSubscribers($data['lists']);
|
||||
return $this->successResponse($subscribers);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function addSegment($data) {
|
||||
$segment = Segment::createOrUpdate($data);
|
||||
return (
|
||||
($segment->id) ?
|
||||
array(
|
||||
'result' => true,
|
||||
'segment' => $segment->asArray()
|
||||
) :
|
||||
array(
|
||||
'result' => false
|
||||
)
|
||||
);
|
||||
}
|
||||
$errors = $segment->getErrors();
|
||||
|
||||
function addCustomField($data) {
|
||||
$customField = CustomField::create();
|
||||
$customField->hydrate($data);
|
||||
$result = $customField->save();
|
||||
return (
|
||||
($result) ?
|
||||
array(
|
||||
'result' => true,
|
||||
'customField' => $customField->asArray()
|
||||
) :
|
||||
array(
|
||||
'result' => false
|
||||
)
|
||||
);
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function processImport($data) {
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $import->process();
|
||||
try {
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
|
||||
json_decode($data, true)
|
||||
);
|
||||
$process = $import->process();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function processExport($data) {
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $export->process();
|
||||
try {
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
||||
json_decode($data, true)
|
||||
);
|
||||
$process = $export->process();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\NewsletterTemplate;
|
||||
use MailPoet\Models\NewsletterSegment;
|
||||
@ -252,8 +253,10 @@ class Newsletters extends APIEndpoint {
|
||||
$data
|
||||
);
|
||||
$listing_data = $listing->get();
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
|
||||
foreach($listing_data['items'] as $key => $newsletter) {
|
||||
$queue = false;
|
||||
|
||||
if($newsletter->type === Newsletter::TYPE_STANDARD) {
|
||||
$newsletter
|
||||
@ -277,8 +280,15 @@ class Newsletters extends APIEndpoint {
|
||||
->withStatistics();
|
||||
}
|
||||
|
||||
if($newsletter->status === Newsletter::STATUS_SENT ||
|
||||
$newsletter->status === Newsletter::STATUS_SENDING
|
||||
) {
|
||||
$queue = $newsletter->getQueue();
|
||||
}
|
||||
|
||||
// get preview url
|
||||
$newsletter->preview_url = NewsletterUrl::getViewInBrowserUrl($newsletter);
|
||||
$newsletter->preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
$newsletter, $subscriber, $queue, $preview = true);
|
||||
|
||||
// convert object to array
|
||||
$listing_data['items'][$key] = $newsletter->asArray();
|
||||
|
@ -379,7 +379,12 @@ class Menu {
|
||||
function import() {
|
||||
$import = new ImportExportFactory('import');
|
||||
$data = $import->bootstrap();
|
||||
$data['sub_menu'] = 'mailpoet-subscribers';
|
||||
$data = array_merge($data, array(
|
||||
'date_types' => Block\Date::getDateTypes(),
|
||||
'date_formats' => Block\Date::getDateFormats(),
|
||||
'month_names' => Block\Date::getMonthNames(),
|
||||
'sub_menu' => 'mailpoet-subscribers'
|
||||
));
|
||||
echo $this->renderer->render('subscribers/importExport/import.html', $data);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ class Newsletter {
|
||||
);
|
||||
if($this->tracking_enabled) {
|
||||
$prepared_newsletter = NewsletterLinks::replaceSubscriberData(
|
||||
$newsletter['id'],
|
||||
$subscriber['id'],
|
||||
$queue['id'],
|
||||
$prepared_newsletter
|
||||
|
@ -2,7 +2,7 @@
|
||||
namespace MailPoet\Form\Block;
|
||||
|
||||
abstract class Base {
|
||||
protected static function getInputValidation($block) {
|
||||
protected static function getInputValidation($block, $extra_rules = array()) {
|
||||
$rules = array();
|
||||
|
||||
if($block['id'] === 'email') {
|
||||
@ -37,8 +37,15 @@ abstract class Base {
|
||||
$rules['required-message'] = __('Please select at least one option');
|
||||
}
|
||||
|
||||
if($block['type'] === 'date') {
|
||||
$rules['group'] = 'custom_field_'.$block['id'];
|
||||
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||
}
|
||||
|
||||
$validation = array();
|
||||
|
||||
$rules = array_merge($rules, $extra_rules);
|
||||
|
||||
if(!empty($rules)) {
|
||||
$rules = array_unique($rules);
|
||||
foreach($rules as $rule => $value) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Form\Block;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Date extends Base {
|
||||
|
||||
static function render($block) {
|
||||
@ -17,7 +19,6 @@ class Date extends Base {
|
||||
$html = '';
|
||||
|
||||
$field_name = static::getFieldName($block);
|
||||
$field_validation = static::getInputValidation($block);
|
||||
|
||||
$date_formats = static::getDateFormats();
|
||||
|
||||
@ -65,27 +66,38 @@ class Date extends Base {
|
||||
}
|
||||
|
||||
foreach($date_selectors as $date_selector) {
|
||||
if($date_selector === 'dd') {
|
||||
if($date_selector === 'DD') {
|
||||
$block['selected'] = $day;
|
||||
$html .= '<select class="mailpoet_date_day" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a day')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[day]" placeholder="'.__('Day').'">';
|
||||
$html .= static::getDays($block);
|
||||
$html .= '</select>';
|
||||
} else if($date_selector === 'mm') {
|
||||
} else if($date_selector === 'MM') {
|
||||
$block['selected'] = $month;
|
||||
$html .= '<select class="mailpoet_date_month" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a month')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[month]" placeholder="'.__('Month').'">';
|
||||
$html .= static::getMonths($block);
|
||||
$html .= '</select>';
|
||||
} else if($date_selector === 'yyyy') {
|
||||
} else if($date_selector === 'YYYY') {
|
||||
$block['selected'] = $year;
|
||||
$html .= '<select class="mailpoet_date_year" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a year')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[year]" placeholder="'.__('Year').'">';
|
||||
$html .= static::getYears($block);
|
||||
$html .= '</select>';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
@ -100,10 +112,10 @@ class Date extends Base {
|
||||
|
||||
static function getDateFormats() {
|
||||
return array(
|
||||
'year_month_day' => array('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy/mm/dd'),
|
||||
'year_month' => array('mm/yyyy', 'yyyy/mm'),
|
||||
'year' => array('yyyy'),
|
||||
'month' => array('mm')
|
||||
'year_month_day' => array('MM/DD/YYYY', 'DD/MM/YYYY', 'YYYY/MM/DD'),
|
||||
'year_month' => array('MM/YYYY', 'YYYY/MM'),
|
||||
'year' => array('YYYY'),
|
||||
'month' => array('MM')
|
||||
);
|
||||
}
|
||||
static function getMonthNames() {
|
||||
@ -192,4 +204,85 @@ class Date extends Base {
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
static function convertDateToDatetime($date, $date_format) {
|
||||
$datetime = false;
|
||||
if($date_format === 'datetime') {
|
||||
$datetime = $date;
|
||||
} else {
|
||||
$parsed_date = explode('/', $date);
|
||||
$parsed_date_format = explode('/', $date_format);
|
||||
$year_position = array_search('YYYY', $parsed_date_format);
|
||||
$month_position = array_search('MM', $parsed_date_format);
|
||||
$day_position = array_search('DD', $parsed_date_format);
|
||||
if(count($parsed_date) === 3) {
|
||||
// create date from any combination of month, day and year
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => $parsed_date[$day_position]
|
||||
);
|
||||
} else if(count($parsed_date) === 2) {
|
||||
// create date from any combination of month and year
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => '01'
|
||||
);
|
||||
} else if($date_format === 'MM' && count($parsed_date) === 1) {
|
||||
// create date from month
|
||||
if((int)$parsed_date[$month_position] === 0) {
|
||||
$datetime = '';
|
||||
$parsed_date = false;
|
||||
} else {
|
||||
$parsed_date = array(
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => '01',
|
||||
'year' => date('Y')
|
||||
);
|
||||
}
|
||||
} else if($date_format === 'YYYY' && count($parsed_date) === 1) {
|
||||
// create date from year
|
||||
if((int)$parsed_date[$year_position] === 0) {
|
||||
$datetime = '';
|
||||
$parsed_date = false;
|
||||
} else {
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => '01',
|
||||
'day' => '01'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$parsed_date = false;
|
||||
}
|
||||
if($parsed_date) {
|
||||
$year = $parsed_date['year'];
|
||||
$month = $parsed_date['month'];
|
||||
$day = $parsed_date['day'];
|
||||
// if all date parts are set to 0, date value is empty
|
||||
if((int)$year === 0 && (int)$month === 0 && (int)$day === 0) {
|
||||
$datetime = '';
|
||||
} else {
|
||||
if((int)$year === 0) $year = date('Y');
|
||||
if((int)$month === 0) $month = date('m');
|
||||
if((int)$day === 0) $day = date('d');
|
||||
$datetime = sprintf(
|
||||
'%s-%s-%s 00:00:00',
|
||||
$year,
|
||||
$month,
|
||||
$day
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($datetime !== false && !empty($datetime)) {
|
||||
try {
|
||||
$datetime = Carbon::parse($datetime)->toDateTimeString();
|
||||
} catch(\Exception $e) {
|
||||
$datetime = false;
|
||||
}
|
||||
}
|
||||
return $datetime;
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
use MailPoet\Form\Block\Date;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CustomField extends Model {
|
||||
@ -43,28 +45,27 @@ class CustomField extends Model {
|
||||
// format custom field data depending on type
|
||||
if(is_array($value) && $this->type === 'date' ) {
|
||||
$custom_field_data = $this->asArray();
|
||||
|
||||
$date_format = $custom_field_data['params']['date_format'];
|
||||
$date_type = (isset($custom_field_data['params']['date_type'])
|
||||
? $custom_field_data['params']['date_type']
|
||||
: 'year_month_day'
|
||||
);
|
||||
$date_parts = explode('_', $date_type);
|
||||
|
||||
switch($date_type) {
|
||||
case 'year_month_day':
|
||||
$value = sprintf(
|
||||
'%04d-%02d-%02d',
|
||||
$value['year'],
|
||||
'%s/%s/%s',
|
||||
$value['month'],
|
||||
$value['day']
|
||||
$value['day'],
|
||||
$value['year']
|
||||
);
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
$value = sprintf(
|
||||
'%04d-%02d',
|
||||
$value['year'],
|
||||
$value['month']
|
||||
'%s/%s',
|
||||
$value['month'],
|
||||
$value['year']
|
||||
);
|
||||
break;
|
||||
|
||||
@ -73,12 +74,23 @@ class CustomField extends Model {
|
||||
$value = '';
|
||||
} else {
|
||||
$value = sprintf(
|
||||
'%02d',
|
||||
'%s',
|
||||
$value['month']
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'day':
|
||||
if((int)$value['day'] === 0) {
|
||||
$value = '';
|
||||
} else {
|
||||
$value = sprintf(
|
||||
'%s',
|
||||
$value['day']
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
if((int)$value['year'] === 0) {
|
||||
$value = '';
|
||||
@ -90,6 +102,10 @@ class CustomField extends Model {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!empty($value)) {
|
||||
$value = Date::convertDateToDatetime($value, $date_format);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
@ -5,6 +5,7 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Model extends \Sudzy\ValidModel {
|
||||
protected $_errors;
|
||||
protected $_new_record;
|
||||
|
||||
function __construct() {
|
||||
$this->_errors = array();
|
||||
@ -36,6 +37,7 @@ class Model extends \Sudzy\ValidModel {
|
||||
|
||||
function save() {
|
||||
$this->setTimestamp();
|
||||
$this->_new_record = $this->isNew();
|
||||
try {
|
||||
parent::save();
|
||||
} catch(\Sudzy\ValidationException $e) {
|
||||
@ -63,6 +65,12 @@ class Model extends \Sudzy\ValidModel {
|
||||
return $this;
|
||||
}
|
||||
|
||||
function isNew() {
|
||||
return (isset($this->_new_record)) ?
|
||||
$this->_new_record :
|
||||
parent::isNew();
|
||||
}
|
||||
|
||||
function trash() {
|
||||
return $this->set_expr('deleted_at', 'NOW()')->save();
|
||||
}
|
||||
@ -157,4 +165,4 @@ class Model extends \Sudzy\ValidModel {
|
||||
static function getTrashed() {
|
||||
return static::whereNotNull('deleted_at');
|
||||
}
|
||||
}
|
||||
}
|
@ -5,4 +5,9 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterLink extends Model {
|
||||
public static $_table = MP_NEWSLETTER_LINKS_TABLE;
|
||||
|
||||
static function getByHash($hash) {
|
||||
return parent::where('hash', $hash)
|
||||
->findOne();
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,15 @@ class SendingQueue extends Model {
|
||||
return $subscribers;
|
||||
}
|
||||
|
||||
function getRenderedNewsletterBody() {
|
||||
return json_decode($this->newsletter_rendered_body, true);
|
||||
}
|
||||
|
||||
function isSubscriberProcessed($subscriber_id) {
|
||||
$subscribers = $this->getSubscribers();
|
||||
return in_array($subscriber_id, $subscribers['processed']);
|
||||
}
|
||||
|
||||
function asArray() {
|
||||
$model = parent::asArray();
|
||||
$model['subscribers'] = (is_serialized($this->subscribers))
|
||||
|
@ -5,4 +5,23 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsClicks extends Model {
|
||||
public static $_table = MP_STATISTICS_CLICKS_TABLE;
|
||||
|
||||
static function createOrUpdateClickCount($link_id, $subscriber_id, $newsletter_id, $queue_id) {
|
||||
$statistics = self::where('link_id', $link_id)
|
||||
->where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = self::create();
|
||||
$statistics->link_id = $link_id;
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->count = 1;
|
||||
} else {
|
||||
$statistics->count++;
|
||||
}
|
||||
return $statistics->save();
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,19 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsOpens extends Model {
|
||||
public static $_table = MP_STATISTICS_OPENS_TABLE;
|
||||
|
||||
static function getOrCreate($subscriber_id, $newsletter_id, $queue_id) {
|
||||
$statistics = self::where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = self::create();
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->save();
|
||||
}
|
||||
return $statistics;
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,19 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsUnsubscribes extends Model {
|
||||
public static $_table = MP_STATISTICS_UNSUBSCRIBES_TABLE;
|
||||
|
||||
static function getOrCreate($subscriber_id, $newsletter_id, $queue_id) {
|
||||
$statistics = self::where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = self::create();
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->save();
|
||||
}
|
||||
return $statistics;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Links;
|
||||
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Router\Front as FrontRouter;
|
||||
use MailPoet\Router\Endpoints\Track as TrackEndpoint;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
@ -92,10 +93,10 @@ class Links {
|
||||
}
|
||||
|
||||
static function replaceSubscriberData(
|
||||
$newsletter_id,
|
||||
$subscriber_id,
|
||||
$queue_id,
|
||||
$content
|
||||
$content,
|
||||
$preview = false
|
||||
) {
|
||||
// match data tags
|
||||
$regex = sprintf(
|
||||
@ -103,6 +104,7 @@ class Links {
|
||||
preg_quote(self::DATA_TAG_CLICK),
|
||||
preg_quote(self::DATA_TAG_OPEN)
|
||||
);
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
preg_match_all($regex, $content, $matches);
|
||||
foreach($matches[1] as $index => $match) {
|
||||
$hash = null;
|
||||
@ -110,10 +112,11 @@ class Links {
|
||||
list(, $hash) = explode('-', $match);
|
||||
}
|
||||
$data = array(
|
||||
'newsletter' => $newsletter_id,
|
||||
'subscriber' => $subscriber_id,
|
||||
'queue' => $queue_id,
|
||||
'hash' => $hash
|
||||
'subscriber_id' => $subscriber->id,
|
||||
'subscriber_token' => Subscriber::generateToken($subscriber->email),
|
||||
'queue_id' => $queue_id,
|
||||
'link_hash' => $hash,
|
||||
'preview' => $preview
|
||||
);
|
||||
$router_action = ($matches[2][$index] === self::DATA_TAG_CLICK) ?
|
||||
TrackEndpoint::ACTION_CLICK :
|
||||
|
@ -89,14 +89,14 @@ class Link {
|
||||
}
|
||||
|
||||
static function processShortcodeAction(
|
||||
$shortcode_action, $newsletter, $subscriber, $queue
|
||||
$shortcode_action, $newsletter, $subscriber, $queue, $wp_user_preview
|
||||
) {
|
||||
switch($shortcode_action) {
|
||||
case 'subscription_unsubscribe_url':
|
||||
// track unsubscribe event
|
||||
if((boolean)Setting::getValue('tracking.enabled')) {
|
||||
$unsubscribe = new Unsubscribes();
|
||||
$unsubscribe->track($newsletter['id'], $subscriber['id'], $queue['id']);
|
||||
if((boolean)Setting::getValue('tracking.enabled') && !$wp_user_preview) {
|
||||
$unsubscribe_event = new Unsubscribes();
|
||||
$unsubscribe_event->track($newsletter->id, $subscriber->id, $queue->id);
|
||||
}
|
||||
$url = SubscriptionUrl::getUnsubscribeUrl($subscriber);
|
||||
break;
|
||||
@ -113,7 +113,8 @@ class Link {
|
||||
$shortcode,
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$queue
|
||||
$queue,
|
||||
$wp_user_preview
|
||||
);
|
||||
$url = ($url !== $shortcode_action) ? $url : false;
|
||||
break;
|
||||
|
@ -30,18 +30,19 @@ class Url {
|
||||
$queue = ($queue) ? $queue->asArray() : false;
|
||||
}
|
||||
$data = array(
|
||||
'newsletter' => (!empty($newsletter['id'])) ?
|
||||
'newsletter_id' => (!empty($newsletter['id'])) ?
|
||||
$newsletter['id'] :
|
||||
$newsletter,
|
||||
'subscriber' => (!empty($subscriber['id'])) ?
|
||||
'subscriber_id' => (!empty($subscriber['id'])) ?
|
||||
$subscriber['id'] :
|
||||
$subscriber,
|
||||
'subscriber_token' => (!empty($subscriber['id'])) ?
|
||||
Subscriber::generateToken($subscriber['email']) :
|
||||
false,
|
||||
'queue' => (!empty($queue['id'])) ?
|
||||
'queue_id' => (!empty($queue['id'])) ?
|
||||
$queue['id'] :
|
||||
$queue
|
||||
$queue,
|
||||
'preview' => $preview
|
||||
);
|
||||
return FrontRouter::buildRequest(
|
||||
ViewInBrowserEndpoint::ENDPOINT,
|
||||
|
@ -10,46 +10,58 @@ use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
|
||||
class ViewInBrowser {
|
||||
public $data;
|
||||
|
||||
function __construct($data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function view($data = false) {
|
||||
$data = ($data) ? $data : $this->data;
|
||||
$newsletter = ($data['newsletter'] !== false) ?
|
||||
Newsletter::findOne($data['newsletter']) :
|
||||
false;
|
||||
if(!$newsletter) $this->abort();
|
||||
$subscriber = ($data['subscriber'] !== false) ?
|
||||
$this->verifySubscriber($data['subscriber'], $data['subscriber_token']) :
|
||||
false;
|
||||
$queue = ($data['queue'] !== false) ?
|
||||
SendingQueue::findOne($data['queue']) :
|
||||
false;
|
||||
static function view($data) {
|
||||
$data = self::preProcessData($data);
|
||||
if(!self::validateData($data)) self::abort();
|
||||
$rendered_newsletter =
|
||||
$this->getAndRenderNewsletter($newsletter, $subscriber, $queue);
|
||||
self::getAndRenderNewsletter(
|
||||
$data->newsletter,
|
||||
$data->subscriber,
|
||||
$data->queue,
|
||||
$data->preview
|
||||
);
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
echo $rendered_newsletter;
|
||||
exit;
|
||||
}
|
||||
|
||||
function verifySubscriber($subscriber_id, $subscriber_token) {
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
if(!$subscriber ||
|
||||
!Subscriber::verifyToken($subscriber->email, $subscriber_token)
|
||||
static function preProcessData($data) {
|
||||
$data = (object)$data;
|
||||
if(empty($data->subscriber_id) ||
|
||||
empty($data->subscriber_token) ||
|
||||
empty($data->newsletter_id)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return $subscriber;
|
||||
$data->newsletter = Newsletter::findOne($data->newsletter_id);
|
||||
$data->subscriber = Subscriber::findOne($data->subscriber_id);
|
||||
$data->queue = ($data->queue_id) ?
|
||||
SendingQueue::findOne($data->queue_id) :
|
||||
false;
|
||||
return $data;
|
||||
}
|
||||
|
||||
function getAndRenderNewsletter($newsletter, $subscriber, $queue) {
|
||||
if($queue) {
|
||||
$newsletter_body = json_decode($queue->newsletter_rendered_body, true);
|
||||
static function validateData($data) {
|
||||
if(!$data || !$data->subscriber || !$data->newsletter) return false;
|
||||
$subscriber_token_match =
|
||||
Subscriber::verifyToken($data->subscriber->email, $data->subscriber_token);
|
||||
if(!$subscriber_token_match) return false;
|
||||
// return if this is a WP user previewing the newsletter
|
||||
if($data->subscriber->isWPUser() && $data->preview) {
|
||||
return $data;
|
||||
}
|
||||
// if queue exists, check if the newsletter was sent to the subscriber
|
||||
if($data->queue && !$data->queue->isSubscriberProcessed($data->subscriber->id)) {
|
||||
$data = false;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
static function getAndRenderNewsletter($newsletter, $subscriber, $queue, $preview) {
|
||||
if($queue && $queue->newsletter_rendered_body) {
|
||||
$newsletter_body = $queue->getRenderedNewsletterBody();
|
||||
} else {
|
||||
$renderer = new Renderer($newsletter->asArray(), $preview = true);
|
||||
$renderer = new Renderer($newsletter, $preview);
|
||||
$newsletter_body = $renderer->render();
|
||||
}
|
||||
$shortcodes = new Shortcodes(
|
||||
@ -60,16 +72,16 @@ class ViewInBrowser {
|
||||
$rendered_newsletter = $shortcodes->replace($newsletter_body['html']);
|
||||
if($queue && (boolean)Setting::getValue('tracking.enabled')) {
|
||||
$rendered_newsletter = Links::replaceSubscriberData(
|
||||
$newsletter->id,
|
||||
$subscriber->id,
|
||||
$queue->id,
|
||||
$rendered_newsletter
|
||||
$rendered_newsletter,
|
||||
$preview
|
||||
);
|
||||
}
|
||||
return $rendered_newsletter;
|
||||
}
|
||||
|
||||
private function abort() {
|
||||
private static function abort() {
|
||||
status_header(404);
|
||||
exit;
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
<?php
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Statistics\Track\Clicks;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
|
||||
@ -12,12 +16,46 @@ class Track {
|
||||
const ACTION_OPEN = 'open';
|
||||
|
||||
static function click($data) {
|
||||
$clicks = new Clicks($data);
|
||||
$clicks->track();
|
||||
$click_event = new Clicks();
|
||||
return $click_event->track(self::_processTrackData($data));
|
||||
}
|
||||
|
||||
static function open($data) {
|
||||
$opens = new Opens($data);
|
||||
$opens->track();
|
||||
$open_event = new Opens();
|
||||
return $open_event->track(self::_processTrackData($data));
|
||||
}
|
||||
|
||||
static function _processTrackData($data) {
|
||||
$data = (object)$data;
|
||||
if(empty($data->queue_id) ||
|
||||
empty($data->subscriber_id) ||
|
||||
empty($data->subscriber_token)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$data->queue = SendingQueue::findOne($data->queue_id);
|
||||
$data->subscriber = Subscriber::findOne($data->subscriber_id);
|
||||
$data->newsletter = (!empty($data->queue->newsletter_id)) ?
|
||||
Newsletter::findOne($data->queue->newsletter_id) :
|
||||
false;
|
||||
if(!empty($data->link_hash)) {
|
||||
$data->link = NewsletterLink::getByHash($data->link_hash);
|
||||
}
|
||||
return self::_validateTrackData($data);
|
||||
}
|
||||
|
||||
static function _validateTrackData($data) {
|
||||
if(!$data->subscriber || !$data->queue || !$data->newsletter) return false;
|
||||
$subscriber_token_match =
|
||||
Subscriber::verifyToken($data->subscriber->email, $data->subscriber_token);
|
||||
if(!$subscriber_token_match) return false;
|
||||
// return if this is a WP user previewing the newsletter
|
||||
if($data->subscriber->isWPUser() && $data->preview) {
|
||||
return $data;
|
||||
}
|
||||
// check if the newsletter was sent to the subscriber
|
||||
return ($data->queue->isSubscriberProcessed($data->subscriber->id)) ?
|
||||
$data :
|
||||
false;
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ class ViewInBrowser {
|
||||
const ACTION_VIEW = 'view';
|
||||
|
||||
static function view($data) {
|
||||
$viewer = new NewsletterViewInBrowser($data);
|
||||
$viewer->view();
|
||||
NewsletterViewInBrowser::view($data);
|
||||
}
|
||||
}
|
@ -1,93 +1,52 @@
|
||||
<?php
|
||||
namespace MailPoet\Statistics\Track;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\StatisticsClicks;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Shortcodes\Categories\Link;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Clicks {
|
||||
public $data;
|
||||
|
||||
function __construct($data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function track($data = false) {
|
||||
$data = ($data) ? $data : $this->data;
|
||||
$newsletter = $this->getNewsletter($data['newsletter']);
|
||||
$subscriber = $this->getSubscriber($data['subscriber']);
|
||||
$queue = $this->getQueue($data['queue']);
|
||||
$link = $this->getLink($data['hash']);
|
||||
if(!$subscriber || !$newsletter || !$link || !$queue) {
|
||||
$this->abort();
|
||||
function track($data) {
|
||||
if(!$data || empty($data->link)) {
|
||||
return $this->abort();
|
||||
}
|
||||
$statistics = StatisticsClicks::where('link_id', $link['id'])
|
||||
->where('subscriber_id', $subscriber['id'])
|
||||
->where('newsletter_id', $newsletter['id'])
|
||||
->where('queue_id', $queue['id'])
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
// track open event in case it did not register
|
||||
$this->trackOpenEvent($data);
|
||||
$statistics = StatisticsClicks::create();
|
||||
$statistics->newsletter_id = $newsletter['id'];
|
||||
$statistics->link_id = $link['id'];
|
||||
$statistics->subscriber_id = $subscriber['id'];
|
||||
$statistics->queue_id = $queue['id'];
|
||||
$statistics->count = 1;
|
||||
$statistics->save();
|
||||
} else {
|
||||
$statistics->count++;
|
||||
$statistics->save();
|
||||
$subscriber = $data->subscriber;
|
||||
$queue = $data->queue;
|
||||
$newsletter = $data->newsletter;
|
||||
$link = $data->link;
|
||||
$wp_user_preview = ($data->preview && $subscriber->isWPUser());
|
||||
// log statistics only if the action did not come from
|
||||
// a WP user previewing the newsletter
|
||||
if(!$wp_user_preview) {
|
||||
StatisticsClicks::createOrUpdateClickCount(
|
||||
$link->id,
|
||||
$subscriber->id,
|
||||
$newsletter->id,
|
||||
$queue->id
|
||||
);
|
||||
// track open event
|
||||
$open_event = new Opens();
|
||||
$open_event->track($data, $display_image = false);
|
||||
}
|
||||
$url = $this->processUrl($link['url'], $newsletter, $subscriber, $queue);
|
||||
$url = $this->processUrl($link->url, $newsletter, $subscriber, $queue, $wp_user_preview);
|
||||
$this->redirectToUrl($url);
|
||||
}
|
||||
|
||||
function getNewsletter($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
return ($newsletter) ? $newsletter->asArray() : $newsletter;
|
||||
}
|
||||
|
||||
function getSubscriber($subscriber_id) {
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
return ($subscriber) ? $subscriber->asArray() : $subscriber;
|
||||
}
|
||||
|
||||
function getQueue($queue_id) {
|
||||
$queue = SendingQueue::findOne($queue_id);
|
||||
return ($queue) ? $queue->asArray() : $queue;
|
||||
}
|
||||
|
||||
function getLink($hash) {
|
||||
$link = NewsletterLink::where('hash', $hash)
|
||||
->findOne();
|
||||
return ($link) ? $link->asArray() : $link;
|
||||
}
|
||||
|
||||
function processUrl($url, $newsletter, $subscriber, $queue) {
|
||||
function processUrl($url, $newsletter, $subscriber, $queue, $wp_user_preview) {
|
||||
if(preg_match('/\[link:(?P<action>.*?)\]/', $url, $shortcode)) {
|
||||
if(!$shortcode['action']) $this->abort();
|
||||
$url = Link::processShortcodeAction(
|
||||
$shortcode['action'],
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$queue
|
||||
$queue,
|
||||
$wp_user_preview
|
||||
);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
function trackOpenEvent($data) {
|
||||
$open = new Opens($data, $display_image = false);
|
||||
return $open->track();
|
||||
}
|
||||
|
||||
function abort() {
|
||||
status_header(404);
|
||||
exit;
|
||||
|
@ -1,63 +1,33 @@
|
||||
<?php
|
||||
namespace MailPoet\Statistics\Track;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\StatisticsOpens;
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Opens {
|
||||
public $data;
|
||||
public $return_image;
|
||||
|
||||
function __construct($data, $return_image = true) {
|
||||
$this->data = $data;
|
||||
$this->return_image = $return_image;
|
||||
}
|
||||
|
||||
function track($data = false) {
|
||||
$data = ($data) ? $data : $this->data;
|
||||
$newsletter = $this->getNewsletter($data['newsletter']);
|
||||
$subscriber = $this->getSubscriber($data['subscriber']);
|
||||
$queue = $this->getQueue($data['queue']);
|
||||
if(!$subscriber || !$newsletter || !$queue) {
|
||||
return false;
|
||||
function track($data, $display_image = true) {
|
||||
if(!$data) {
|
||||
return $this->returnResponse($display_image);
|
||||
}
|
||||
$statistics = StatisticsOpens::where('subscriber_id', $data['subscriber'])
|
||||
->where('newsletter_id', $data['newsletter'])
|
||||
->where('queue_id', $data['queue'])
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = StatisticsOpens::create();
|
||||
$statistics->newsletter_id = $data['newsletter'];
|
||||
$statistics->subscriber_id = $data['subscriber'];
|
||||
$statistics->queue_id = $data['queue'];
|
||||
$statistics->save();
|
||||
$subscriber = $data->subscriber;
|
||||
$queue = $data->queue;
|
||||
$newsletter = $data->newsletter;
|
||||
$wp_user_preview = ($data->preview && $subscriber->isWPUser());
|
||||
// log statistics only if the action did not come from
|
||||
// a WP user previewing the newsletter
|
||||
if(!$wp_user_preview) {
|
||||
StatisticsOpens::getOrCreate(
|
||||
$subscriber->id,
|
||||
$newsletter->id,
|
||||
$queue->id
|
||||
);
|
||||
}
|
||||
if($this->return_image) {
|
||||
$this->returnImage();
|
||||
}
|
||||
return true;
|
||||
return $this->returnResponse($display_image);
|
||||
}
|
||||
|
||||
function getNewsletter($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
return ($newsletter) ? $newsletter->asArray() : $newsletter;
|
||||
}
|
||||
|
||||
function getSubscriber($subscriber_id) {
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
return ($subscriber) ? $subscriber->asArray() : $subscriber;
|
||||
}
|
||||
|
||||
function getQueue($queue_id) {
|
||||
$queue = SendingQueue::findOne($queue_id);
|
||||
return ($queue) ? $queue->asArray() : $queue;
|
||||
}
|
||||
|
||||
function returnImage() {
|
||||
function returnResponse($display_image) {
|
||||
if(!$display_image) return;
|
||||
// return 1x1 pixel transparent gif image
|
||||
header('Content-Type: image/gif');
|
||||
echo "\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
|
||||
|
@ -58,17 +58,11 @@ class Export {
|
||||
)
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage())
|
||||
);
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array(
|
||||
'totalExported' => $processed_subscribers,
|
||||
'exportFileURL' => $this->export_file_URL
|
||||
)
|
||||
'totalExported' => $processed_subscribers,
|
||||
'exportFileURL' => $this->export_file_URL
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscribers\ImportExport\Import;
|
||||
|
||||
use MailPoet\Form\Block\Date;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
@ -17,7 +19,6 @@ class Import {
|
||||
public $subscribers_count;
|
||||
public $created_at;
|
||||
public $updated_at;
|
||||
public $profiler_start;
|
||||
|
||||
public function __construct($data) {
|
||||
$this->subscribers_data = $this->transformSubscribersData(
|
||||
@ -32,16 +33,31 @@ class Import {
|
||||
$this->subscriber_custom_fields = $this->getCustomSubscriberFields(
|
||||
array_keys($data['columns'])
|
||||
);
|
||||
$this->subscriber_fields_validation_rules = $this->getSubscriberFieldsValidationRules(
|
||||
$data['columns']
|
||||
);
|
||||
$this->subscribers_count = count(reset($this->subscribers_data));
|
||||
$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->profiler_start = microtime(true);
|
||||
}
|
||||
|
||||
function getSubscriberFieldsValidationRules($subscriber_fields) {
|
||||
$validation_rules = array();
|
||||
foreach($subscriber_fields as $column => $field) {
|
||||
$validation_rules[$column] = (!empty($field['validation_rule'])) ?
|
||||
$field['validation_rule'] :
|
||||
false;
|
||||
}
|
||||
return $validation_rules;
|
||||
}
|
||||
|
||||
function process() {
|
||||
$subscriber_fields = $this->subscriber_fields;
|
||||
$subscriber_custom_fields = $this->subscriber_custom_fields;
|
||||
$subscribers_data = $this->subscribers_data;
|
||||
$subscribers_data = $this->validateSubscribersFields(
|
||||
$this->subscribers_data,
|
||||
$this->subscriber_fields_validation_rules
|
||||
);
|
||||
list ($subscribers_data, $subscriber_fields) =
|
||||
$this->filterSubscriberStatus($subscribers_data, $subscriber_fields);
|
||||
$this->deleteExistingTrashedSubscribers($subscribers_data);
|
||||
@ -74,10 +90,7 @@ class Import {
|
||||
}
|
||||
}
|
||||
} catch(\PDOException $e) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage())
|
||||
);
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
$import_factory = new ImportExportFactory('import');
|
||||
$segments = $import_factory->getSegments();
|
||||
@ -86,21 +99,47 @@ class Import {
|
||||
Newsletter::getWelcomeNotificationsForSegments($this->segments) :
|
||||
false;
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array(
|
||||
'created' => count($created_subscribers),
|
||||
'updated' => count($updated_subscribers),
|
||||
'segments' => $segments,
|
||||
'added_to_segment_with_welcome_notification' =>
|
||||
($welcome_notifications_in_segments) ? true : false
|
||||
),
|
||||
'profiler' => $this->timeExecution()
|
||||
'created' => count($created_subscribers),
|
||||
'updated' => count($updated_subscribers),
|
||||
'segments' => $segments,
|
||||
'added_to_segment_with_welcome_notification' =>
|
||||
($welcome_notifications_in_segments) ? true : false
|
||||
);
|
||||
}
|
||||
|
||||
function validateSubscribersFields($subscribers_data, $validation_rules) {
|
||||
$invalid_records = array();
|
||||
foreach($subscribers_data as $column => &$data) {
|
||||
$validation_rule = $validation_rules[$column];
|
||||
// if this is a custom column
|
||||
if(in_array($column, $this->subscriber_custom_fields)) {
|
||||
$custom_field = CustomField::findOne($column);
|
||||
// validate date type
|
||||
if($custom_field->type === 'date') {
|
||||
$data = array_map(
|
||||
function($index, $date) use($validation_rule, &$invalid_records) {
|
||||
if (empty($date)) return $date;
|
||||
$date = Date::convertDateToDatetime($date, $validation_rule);
|
||||
if(!$date) {
|
||||
$invalid_records[] = $index;
|
||||
}
|
||||
return $date;
|
||||
}, array_keys($data), $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($invalid_records) {
|
||||
foreach($subscribers_data as $column => &$data) {
|
||||
$data = array_diff_key($data, array_flip($invalid_records));
|
||||
$data = array_values($data);
|
||||
}
|
||||
}
|
||||
return $subscribers_data;
|
||||
}
|
||||
|
||||
function transformSubscribersData($subscribers, $columns) {
|
||||
foreach($columns as $column => $index) {
|
||||
$transformed_subscribers[$column] = Helpers::arrayColumn($subscribers, $index);
|
||||
foreach($columns as $column => $data) {
|
||||
$transformed_subscribers[$column] = Helpers::arrayColumn($subscribers, $data['index']);
|
||||
}
|
||||
return $transformed_subscribers;
|
||||
}
|
||||
@ -367,9 +406,4 @@ class Import {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function timeExecution() {
|
||||
$profiler_end = microtime(true);
|
||||
return ($profiler_end - $this->profiler_start) / 60;
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,13 @@ class MailChimp {
|
||||
|
||||
function getLists() {
|
||||
if(!$this->api_key || !$this->data_center) {
|
||||
return $this->processError('API');
|
||||
return $this->throwException('API');
|
||||
}
|
||||
|
||||
$connection = @fopen(sprintf($this->lists_url, $this->data_center, $this->api_key), 'r');
|
||||
|
||||
if(!$connection) {
|
||||
return $this->processError('connection');
|
||||
return $this->throwException('connection');
|
||||
} else {
|
||||
$response = '';
|
||||
while(!feof($connection)) {
|
||||
@ -35,7 +35,7 @@ class MailChimp {
|
||||
$response = json_decode($response);
|
||||
|
||||
if(!$response) {
|
||||
return $this->processError('API');
|
||||
return $this->throwException('API');
|
||||
}
|
||||
|
||||
foreach($response->data as $list) {
|
||||
@ -45,19 +45,16 @@ class MailChimp {
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => $lists
|
||||
);
|
||||
return $lists;
|
||||
}
|
||||
|
||||
function getSubscribers($lists = array()) {
|
||||
if(!$this->api_key || !$this->data_center) {
|
||||
return $this->processError('API');
|
||||
return $this->throwException('API');
|
||||
}
|
||||
|
||||
if(!$lists) {
|
||||
return $this->processError('lists');
|
||||
return $this->throwException('lists');
|
||||
}
|
||||
|
||||
$bytes_fetched = 0;
|
||||
@ -65,7 +62,7 @@ class MailChimp {
|
||||
$url = sprintf($this->export_url, $this->data_center, $this->api_key, $list);
|
||||
$connection = @fopen($url, 'r');
|
||||
if(!$connection) {
|
||||
return $this->processError('connection');
|
||||
return $this->throwException('connection');
|
||||
}
|
||||
$i = 0;
|
||||
$header = array();
|
||||
@ -76,13 +73,13 @@ class MailChimp {
|
||||
if($i === 0) {
|
||||
$header = $obj;
|
||||
if(is_object($header) && isset($header->error)) {
|
||||
return $this->processError('lists');
|
||||
return $this->throwException('lists');
|
||||
}
|
||||
if(!isset($header_hash)) {
|
||||
$header_hash = md5(implode(',', $header));
|
||||
} else {
|
||||
if(md5(implode(',', $header) !== $header_hash)) {
|
||||
return $this->processError('headers');
|
||||
return $this->throwException('headers');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -92,25 +89,22 @@ class MailChimp {
|
||||
}
|
||||
$bytes_fetched += strlen($buffer);
|
||||
if($bytes_fetched > $this->max_post_size) {
|
||||
return $this->processError('size');
|
||||
return $this->throwException('size');
|
||||
}
|
||||
}
|
||||
fclose($connection);
|
||||
}
|
||||
|
||||
if(!count($subscribers)) {
|
||||
return $this->processError('subscribers');
|
||||
return $this->throwException('subscribers');
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array(
|
||||
'subscribers' => $subscribers,
|
||||
'invalid' => false,
|
||||
'duplicate' => false,
|
||||
'header' => $header,
|
||||
'subscribersCount' => count($subscribers)
|
||||
)
|
||||
'subscribers' => $subscribers,
|
||||
'invalid' => false,
|
||||
'duplicate' => false,
|
||||
'header' => $header,
|
||||
'subscribersCount' => count($subscribers)
|
||||
);
|
||||
}
|
||||
|
||||
@ -125,16 +119,16 @@ class MailChimp {
|
||||
return (preg_match('/[a-zA-Z0-9]{32}-[a-zA-Z0-9]{3,}/', $APIKey)) ? $APIKey : false;
|
||||
}
|
||||
|
||||
function processError($error) {
|
||||
function throwException($error) {
|
||||
switch($error) {
|
||||
case 'API':
|
||||
$errorMessage = __('Invalid API Key.');
|
||||
break;
|
||||
case 'connection':
|
||||
$errorMessage = __('Could not connect to your MailChimp account');
|
||||
$errorMessage = __('Could not connect to your MailChimp account.');
|
||||
break;
|
||||
case 'headers':
|
||||
$errorMessage = __('The selected lists do not have matching columns (headers)');
|
||||
$errorMessage = __('The selected lists do not have matching columns (headers).');
|
||||
break;
|
||||
case 'size':
|
||||
$errorMessage = __('The information received from MailChimp is too large for processing. Please limit the number of lists!');
|
||||
@ -143,12 +137,9 @@ class MailChimp {
|
||||
$errorMessage = __('Did not find any active subscribers.');
|
||||
break;
|
||||
case 'lists':
|
||||
$errorMessage = __('Did not find any valid lists');
|
||||
$errorMessage = __('Did not find any valid lists.');
|
||||
break;
|
||||
}
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($errorMessage)
|
||||
);
|
||||
throw new \Exception($errorMessage);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ class ImportExportFactory {
|
||||
'id' => $field['id'],
|
||||
'name' => $field['name'],
|
||||
'type' => $field['type'],
|
||||
'params' => unserialize($field['params']),
|
||||
'custom' => true
|
||||
);
|
||||
}, $subscriber_custom_fields);
|
||||
|
@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
|
||||
use \MailPoet\Config\Initializer;
|
||||
/*
|
||||
* Plugin Name: MailPoet
|
||||
* Version: 0.0.40
|
||||
* Version: 0.0.41
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: MailPoet Newsletters.
|
||||
* Author: MailPoet
|
||||
@ -22,7 +22,7 @@ use \MailPoet\Config\Initializer;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
define('MAILPOET_VERSION', '0.0.40');
|
||||
define('MAILPOET_VERSION', '0.0.41');
|
||||
|
||||
$initializer = new Initializer(array(
|
||||
'file' => __FILE__,
|
||||
|
@ -351,7 +351,7 @@ define([
|
||||
|
||||
it('changes the model if post amount changes', function () {
|
||||
var newValue = '11';
|
||||
view.$('.mailpoet_automated_latest_content_show_amount').val(newValue).keyup();
|
||||
view.$('.mailpoet_automated_latest_content_show_amount').val(newValue).trigger('input');
|
||||
expect(model.get('amount')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -411,7 +411,7 @@ define([
|
||||
|
||||
it('changes the model if author preceded by changes', function () {
|
||||
var newValue = 'New author preceded by test';
|
||||
view.$('.mailpoet_automated_latest_content_author_preceded_by').val(newValue).keyup();
|
||||
view.$('.mailpoet_automated_latest_content_author_preceded_by').val(newValue).trigger('input');
|
||||
expect(model.get('authorPrecededBy')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -423,7 +423,7 @@ define([
|
||||
|
||||
it('changes the model if categories preceded by changes', function () {
|
||||
var newValue = 'New categories preceded by test';
|
||||
view.$('.mailpoet_automated_latest_content_categories').val(newValue).keyup();
|
||||
view.$('.mailpoet_automated_latest_content_categories').val(newValue).trigger('input');
|
||||
expect(model.get('categoriesPrecededBy')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -435,7 +435,7 @@ define([
|
||||
|
||||
it('changes the model if read more text changes', function () {
|
||||
var newValue = 'New read more text';
|
||||
view.$('.mailpoet_automated_latest_content_read_more_text').val(newValue).keyup();
|
||||
view.$('.mailpoet_automated_latest_content_read_more_text').val(newValue).trigger('input');
|
||||
expect(model.get('readMoreText')).to.equal(newValue);
|
||||
});
|
||||
|
||||
|
@ -16,7 +16,9 @@ define([
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
delete EditorApplication.getChannel;
|
||||
if(EditorApplication.getChannel) {
|
||||
delete EditorApplication.getChannel;
|
||||
}
|
||||
});
|
||||
|
||||
it("has a button type", function () {
|
||||
@ -247,6 +249,13 @@ define([
|
||||
it('has a specified font weight', function () {
|
||||
expect(view.$('.mailpoet_editor_button').css('font-weight')).to.equal(model.get('styles.block.fontWeight'));
|
||||
});
|
||||
|
||||
it('opens settings if clicked', function () {
|
||||
var mock = sinon.mock().once();
|
||||
model.on('startEditing', mock);
|
||||
view.$('.mailpoet_editor_button').click();
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -295,7 +304,7 @@ define([
|
||||
it('updates the model when text is changed', function () {
|
||||
var newValue = 'something else';
|
||||
|
||||
view.$('.mailpoet_field_button_text').val(newValue).keyup();
|
||||
view.$('.mailpoet_field_button_text').val(newValue).trigger('input');
|
||||
|
||||
expect(model.get('text')).to.equal(newValue);
|
||||
});
|
||||
@ -303,7 +312,7 @@ define([
|
||||
it('updates the model when link is changed', function () {
|
||||
var newValue = 'http://google.com/?q=123456';
|
||||
|
||||
view.$('.mailpoet_field_button_url').val(newValue).keyup();
|
||||
view.$('.mailpoet_field_button_url').val(newValue).trigger('input');
|
||||
|
||||
expect(model.get('url')).to.equal(newValue);
|
||||
});
|
||||
@ -357,7 +366,7 @@ define([
|
||||
expect(model.get('styles.block.borderWidth')).to.equal('3px');
|
||||
});
|
||||
it('updates the range slider when border width input changes', function () {
|
||||
view.$('.mailpoet_field_button_border_width_input').val('5').keyup();
|
||||
view.$('.mailpoet_field_button_border_width_input').val('5').trigger('input');
|
||||
expect(view.$('.mailpoet_field_button_border_width').val()).to.equal('5');
|
||||
});
|
||||
it('updates the input when border width range slider changes', function () {
|
||||
@ -370,7 +379,7 @@ define([
|
||||
expect(model.get('styles.block.borderRadius')).to.equal('7px');
|
||||
});
|
||||
it('updates the range slider when border radius input changes', function () {
|
||||
view.$('.mailpoet_field_button_border_radius_input').val('7').keyup();
|
||||
view.$('.mailpoet_field_button_border_radius_input').val('7').trigger('input');
|
||||
expect(view.$('.mailpoet_field_button_border_radius').val()).to.equal('7');
|
||||
});
|
||||
it('updates the input when border radius range slider changes', function () {
|
||||
@ -383,7 +392,7 @@ define([
|
||||
expect(model.get('styles.block.width')).to.equal('127px');
|
||||
});
|
||||
it('updates the range slider when width input changes', function () {
|
||||
view.$('.mailpoet_field_button_width_input').val('127').keyup();
|
||||
view.$('.mailpoet_field_button_width_input').val('127').trigger('input');
|
||||
expect(view.$('.mailpoet_field_button_width').val()).to.equal('127');
|
||||
});
|
||||
it('updates the input when width range slider changes', function () {
|
||||
@ -396,7 +405,7 @@ define([
|
||||
expect(model.get('styles.block.lineHeight')).to.equal('37px');
|
||||
});
|
||||
it('updates the range slider when line height input changes', function () {
|
||||
view.$('.mailpoet_field_button_line_height_input').val('37').keyup();
|
||||
view.$('.mailpoet_field_button_line_height_input').val('37').trigger('input');
|
||||
expect(view.$('.mailpoet_field_button_line_height').val()).to.equal('37');
|
||||
});
|
||||
it('updates the input when line height range slider changes', function () {
|
||||
|
@ -92,13 +92,13 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
var model = new (DividerBlock.DividerBlockModel)(),
|
||||
view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
model = new (DividerBlock.DividerBlockModel)();
|
||||
view = new (DividerBlock.DividerBlockView)({model: model});
|
||||
});
|
||||
|
||||
@ -114,6 +114,22 @@ define([
|
||||
|
||||
expect(view.$('.mailpoet_divider').css('border-top-style')).to.equal('inset');
|
||||
});
|
||||
|
||||
it('opens settings if clicked', function () {
|
||||
var mock = sinon.mock().once();
|
||||
model.on('startEditing', mock);
|
||||
view.render();
|
||||
view.$('.mailpoet_divider').click();
|
||||
mock.verify();
|
||||
});
|
||||
|
||||
it('does not open settings if clicked on the resize handle', function () {
|
||||
var mock = sinon.mock().never();
|
||||
model.on('startEditing', mock);
|
||||
view.render();
|
||||
view.$('.mailpoet_resize_handle').click();
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
@ -150,13 +166,13 @@ define([
|
||||
expect(model.get('styles.block.borderStyle')).to.equal('inset');
|
||||
});
|
||||
|
||||
it('updates the model when divider width changes', function () {
|
||||
it('updates the model when divider width slider changes', function () {
|
||||
view.$('.mailpoet_field_divider_border_width').val('17').change();
|
||||
expect(model.get('styles.block.borderWidth')).to.equal('17px');
|
||||
});
|
||||
|
||||
it('updates the range slider when divider width input changes', function () {
|
||||
view.$('.mailpoet_field_divider_border_width_input').val('19').keyup();
|
||||
view.$('.mailpoet_field_divider_border_width_input').val('19').trigger('input');
|
||||
expect(view.$('.mailpoet_field_divider_border_width').val()).to.equal('19');
|
||||
});
|
||||
|
||||
|
@ -116,16 +116,17 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model = new (ImageBlock.ImageBlockModel)({
|
||||
link: 'http://example.org/somepath',
|
||||
src: 'http://example.org/someimage.png',
|
||||
alt: 'some alt',
|
||||
}),
|
||||
view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
model = new (ImageBlock.ImageBlockModel)({
|
||||
link: 'http://example.org/somepath',
|
||||
src: 'http://example.org/someimage.png',
|
||||
alt: 'some alt',
|
||||
});
|
||||
view = new (ImageBlock.ImageBlockView)({model: model});
|
||||
view.render();
|
||||
});
|
||||
@ -142,6 +143,13 @@ define([
|
||||
model.set('src', newValue);
|
||||
expect(view.$('.mailpoet_content img').attr('src')).to.equal(newValue);
|
||||
});
|
||||
|
||||
it('opens settings if clicked on the image', function () {
|
||||
var mock = sinon.mock().once();
|
||||
model.on('startEditing', mock);
|
||||
view.$('img').click();
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -164,19 +172,19 @@ define([
|
||||
describe('once rendered', function () {
|
||||
it('updates the model when link changes', function () {
|
||||
var newValue = 'http://example.org/someNewLink';
|
||||
view.$('.mailpoet_field_image_link').val(newValue).keyup();
|
||||
view.$('.mailpoet_field_image_link').val(newValue).trigger('input');
|
||||
expect(model.get('link')).to.equal(newValue);
|
||||
});
|
||||
|
||||
it('updates the model when src changes', function () {
|
||||
var newValue = 'http://example.org/someNewImage.png';
|
||||
view.$('.mailpoet_field_image_address').val(newValue).keyup();
|
||||
view.$('.mailpoet_field_image_address').val(newValue).trigger('input');
|
||||
expect(model.get('src')).to.equal(newValue);
|
||||
});
|
||||
|
||||
it('updates the model when alt changes', function () {
|
||||
var newValue = 'Some new alt text';
|
||||
view.$('.mailpoet_field_image_alt_text').val(newValue).keyup();
|
||||
view.$('.mailpoet_field_image_alt_text').val(newValue).trigger('input');
|
||||
expect(model.get('alt')).to.equal(newValue);
|
||||
});
|
||||
|
||||
|
@ -282,7 +282,7 @@ define([
|
||||
|
||||
it('changes the model if search term changes', function () {
|
||||
var newValue = 'some New search term';
|
||||
view.$('.mailpoet_posts_search_term').val(newValue).keyup();
|
||||
view.$('.mailpoet_posts_search_term').val(newValue).trigger('input');
|
||||
expect(model.get('search')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -330,7 +330,7 @@ define([
|
||||
|
||||
it('changes the model if author preceded by changes', function () {
|
||||
var newValue = 'New author preceded by test';
|
||||
view.$('.mailpoet_posts_author_preceded_by').val(newValue).keyup();
|
||||
view.$('.mailpoet_posts_author_preceded_by').val(newValue).trigger('input');
|
||||
expect(model.get('authorPrecededBy')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -342,7 +342,7 @@ define([
|
||||
|
||||
it('changes the model if categories preceded by changes', function () {
|
||||
var newValue = 'New categories preceded by test';
|
||||
view.$('.mailpoet_posts_categories').val(newValue).keyup();
|
||||
view.$('.mailpoet_posts_categories').val(newValue).trigger('input');
|
||||
expect(model.get('categoriesPrecededBy')).to.equal(newValue);
|
||||
});
|
||||
|
||||
@ -354,7 +354,7 @@ define([
|
||||
|
||||
it('changes the model if read more text changes', function () {
|
||||
var newValue = 'New read more text';
|
||||
view.$('.mailpoet_posts_read_more_text').val(newValue).keyup();
|
||||
view.$('.mailpoet_posts_read_more_text').val(newValue).trigger('input');
|
||||
expect(model.get('readMoreText')).to.equal(newValue);
|
||||
});
|
||||
|
||||
|
@ -71,14 +71,14 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (SpacerBlock.SpacerBlockModel)(),
|
||||
view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
model = new (SpacerBlock.SpacerBlockModel)();
|
||||
view = new (SpacerBlock.SpacerBlockView)({model: model});
|
||||
});
|
||||
|
||||
@ -96,6 +96,22 @@ define([
|
||||
|
||||
expect(view.$('.mailpoet_spacer').css('height')).to.equal('71px');
|
||||
});
|
||||
|
||||
it('opens settings if clicked', function () {
|
||||
var mock = sinon.mock().once();
|
||||
model.on('startEditing', mock);
|
||||
view.render();
|
||||
view.$('.mailpoet_spacer').click();
|
||||
mock.verify();
|
||||
});
|
||||
|
||||
it('does not open settings if clicked on the resize handle', function () {
|
||||
var mock = sinon.mock().never();
|
||||
model.on('startEditing', mock);
|
||||
view.render();
|
||||
view.$('.mailpoet_resize_handle').click();
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use \MailPoet\API\Endpoints\CustomFields;
|
||||
use \MailPoet\API\Response as APIResponse;
|
||||
use \MailPoet\Models\CustomField;
|
||||
|
||||
class CustomFieldsTest extends MailPoetTest {
|
||||
@ -58,9 +59,10 @@ class CustomFieldsTest extends MailPoetTest {
|
||||
function testItCanGetAllCustomFields() {
|
||||
$router = new CustomFields();
|
||||
$response = $router->getAll();
|
||||
expect($response)->count(count($this->custom_fields));
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
expect($response->data)->count(count($this->custom_fields));
|
||||
|
||||
foreach($response as $custom_field) {
|
||||
foreach($response->data as $custom_field) {
|
||||
expect($custom_field['name'])->notEmpty();
|
||||
expect($custom_field['type'])->notEmpty();
|
||||
expect($custom_field['params'])->notEmpty();
|
||||
@ -72,14 +74,14 @@ class CustomFieldsTest extends MailPoetTest {
|
||||
$custom_field_id = $custom_field->id();
|
||||
|
||||
$router = new CustomFields();
|
||||
$response = $router->delete($custom_field_id);
|
||||
expect($response['result'])->true();
|
||||
$response = $router->delete(array('id' => $custom_field_id));
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
|
||||
$custom_field = CustomField::where('type', 'date')->findOne();
|
||||
expect($custom_field)->false();
|
||||
|
||||
$response = $router->delete($custom_field_id);
|
||||
expect($response['result'])->false();
|
||||
$response = $router->delete(array('id' => $custom_field_id));
|
||||
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
function testItCanSaveACustomField() {
|
||||
@ -90,37 +92,37 @@ class CustomFieldsTest extends MailPoetTest {
|
||||
|
||||
$router = new CustomFields();
|
||||
$response = $router->save($new_custom_field);
|
||||
expect($response['result'])->true();
|
||||
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||
|
||||
// missing type
|
||||
$response = $router->save(array('name' => 'New custom field'));
|
||||
expect($response['result'])->false();
|
||||
expect($response['errors'][0])->equals('Please specify a type');
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a type');
|
||||
|
||||
// missing name
|
||||
$response = $router->save(array('type' => 'text'));
|
||||
expect($response['result'])->false();
|
||||
expect($response['errors'][0])->equals('Please specify a name');
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
|
||||
// missing data
|
||||
$response = $router->save();
|
||||
expect($response['result'])->false();
|
||||
expect($response['errors'][0])->equals('Please specify a name');
|
||||
expect($response['errors'][1])->equals('Please specify a type');
|
||||
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||
expect($response->errors[0]['message'])->equals('Please specify a name');
|
||||
expect($response->errors[1]['message'])->equals('Please specify a type');
|
||||
}
|
||||
|
||||
function testItCanGetACustomField() {
|
||||
$custom_field = CustomField::where('name', 'CF: text')->findOne();
|
||||
|
||||
$router = new CustomFields();
|
||||
$response = $router->get($custom_field->id());
|
||||
expect($response)->notEmpty();
|
||||
expect($response['name'])->equals('CF: text');
|
||||
expect($response['type'])->equals('text');
|
||||
expect($response['params'])->notEmpty();
|
||||
$response = $router->get(array('id' => $custom_field->id()));
|
||||
|
||||
$response = $router->get('not_an_id');
|
||||
expect($response)->false();
|
||||
expect($response->data['name'])->equals('CF: text');
|
||||
expect($response->data['type'])->equals('text');
|
||||
expect($response->data['params'])->notEmpty();
|
||||
|
||||
$response = $router->get(array('id' => 'not_an_id'));
|
||||
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
|
57
tests/unit/Form/Block/DateTest.php
Normal file
57
tests/unit/Form/Block/DateTest.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Form\Block\Date;
|
||||
|
||||
class DateTest extends MailPoetTest {
|
||||
function testItCanConvertDateMonthYearFormatToDatetime() {
|
||||
$date = array(
|
||||
'MM/DD/YYYY' => '05/10/2016',
|
||||
'DD/MM/YYYY' => '10/05/2016',
|
||||
'YYYY/MM/DD' => '2016/05/10',
|
||||
'YYYY/DD/MM' => '2016/10/05'
|
||||
);
|
||||
foreach($date as $date_format => $date) {
|
||||
expect(Date::convertDateToDatetime($date, $date_format))
|
||||
->equals('2016-05-10 00:00:00');
|
||||
}
|
||||
}
|
||||
|
||||
function testItCanConvertMonthYearFormatToDatetime() {
|
||||
$date = array(
|
||||
'MM/YYYY' => '05/2016',
|
||||
'YYYY/MM' => '2016/05'
|
||||
);
|
||||
foreach($date as $date_format => $date) {
|
||||
expect(Date::convertDATEToDatetime($date, $date_format))
|
||||
->equals('2016-05-01 00:00:00');
|
||||
}
|
||||
}
|
||||
|
||||
function testItCanConvertMonthToDatetime() {
|
||||
expect(Date::convertDateToDatetime('05', 'MM'))
|
||||
->equals('2016-05-01 00:00:00');
|
||||
}
|
||||
|
||||
function testItCanConvertYearToDatetime() {
|
||||
expect(Date::convertDateToDatetime('2016', 'YYYY'))
|
||||
->equals('2016-01-01 00:00:00');
|
||||
}
|
||||
|
||||
function testItCanConvertDatetimeToDatetime() {
|
||||
expect(Date::convertDateToDatetime('2016-05-10 00:00:00', 'datetime'))
|
||||
->equals('2016-05-10 00:00:00');
|
||||
}
|
||||
|
||||
function testItCanClearDate() {
|
||||
expect(Date::convertDateToDatetime('0/10/5', 'YYYY/MM/DD'))
|
||||
->equals(date('Y') . '-10-05 00:00:00');
|
||||
expect(Date::convertDateToDatetime('0/0/5', 'YYYY/MM/DD'))
|
||||
->equals(date('Y') . '-' . date('m') . '-05 00:00:00');
|
||||
expect(Date::convertDateToDatetime('0/0/0', 'YYYY/MM/DD'))
|
||||
->equals('');
|
||||
expect(Date::convertDateToDatetime('0', 'YYYY'))
|
||||
->equals('');
|
||||
expect(Date::convertDateToDatetime('0', 'MM'))
|
||||
->equals('');
|
||||
}
|
||||
}
|
@ -169,7 +169,8 @@ class SubscriberTest extends MailPoetTest {
|
||||
'name' => 'Birthday',
|
||||
'type' => 'date',
|
||||
'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',
|
||||
'type' => 'date',
|
||||
'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->{'cf_'.$custom_field->id})->equals('Paris');
|
||||
// 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
|
||||
expect($subscriber->{'cf_'.$custom_field_3->id})->equals('2013-07');
|
||||
}
|
||||
|
120
tests/unit/Router/Endpoints/TrackTest.php
Normal file
120
tests/unit/Router/Endpoints/TrackTest.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Router\Endpoints\Track;
|
||||
|
||||
class TrackTest extends MailPoetTest {
|
||||
function _before() {
|
||||
// create newsletter
|
||||
$newsletter = Newsletter::create();
|
||||
$newsletter->type = 'type';
|
||||
$this->newsletter = $newsletter->save();
|
||||
// create subscriber
|
||||
$subscriber = Subscriber::create();
|
||||
$subscriber->email = 'test@example.com';
|
||||
$subscriber->first_name = 'First';
|
||||
$subscriber->last_name = 'Last';
|
||||
$this->subscriber = $subscriber->save();
|
||||
// create queue
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $newsletter->id;
|
||||
$queue->subscribers = array('processed' => array($subscriber->id));
|
||||
$this->queue = $queue->save();
|
||||
// create link
|
||||
$link = NewsletterLink::create();
|
||||
$link->hash = 'hash';
|
||||
$link->url = 'url';
|
||||
$link->newsletter_id = $newsletter->id;
|
||||
$link->queue_id = $queue->id;
|
||||
$this->link = $link->save();
|
||||
// build track data
|
||||
$this->track_data = array(
|
||||
'queue_id' => $queue->id,
|
||||
'subscriber_id' => $subscriber->id,
|
||||
'newsletter_id' => $newsletter->id,
|
||||
'subscriber_token' => Subscriber::generateToken($subscriber->email),
|
||||
'link_hash' => $link->hash,
|
||||
'preview' => false
|
||||
);
|
||||
}
|
||||
|
||||
function testItReturnsFalseWhenTrackDataIsMissing() {
|
||||
// queue ID is required
|
||||
$data = $this->track_data;
|
||||
unset($data['queue_id']);
|
||||
expect(Track::_processTrackData($data))->false();
|
||||
// subscriber ID is required
|
||||
$data = $this->track_data;
|
||||
unset($data['subscriber_id']);
|
||||
expect(Track::_processTrackData($data))->false();
|
||||
// subscriber token is required
|
||||
$data = $this->track_data;
|
||||
unset($data['subscriber_token']);
|
||||
expect(Track::_processTrackData($data))->false();
|
||||
}
|
||||
|
||||
function testItFailsWhenSubscriberTokenDoesNotMatch() {
|
||||
$data = (object)array_merge(
|
||||
$this->track_data,
|
||||
array(
|
||||
'queue' => $this->queue,
|
||||
'subscriber' => $this->subscriber,
|
||||
'newsletter' => $this->newsletter
|
||||
)
|
||||
);
|
||||
$data->subscriber->email = 'random@email.com';
|
||||
expect(Track::_validateTrackData($data))->false();
|
||||
}
|
||||
|
||||
function testItFailsWhenSubscriberIsNotOnProcessedList() {
|
||||
$data = (object)array_merge(
|
||||
$this->track_data,
|
||||
array(
|
||||
'queue' => $this->queue,
|
||||
'subscriber' => $this->subscriber,
|
||||
'newsletter' => $this->newsletter
|
||||
)
|
||||
);
|
||||
$data->subscriber->id = 99;
|
||||
expect(Track::_validateTrackData($data))->false();
|
||||
}
|
||||
|
||||
function testItDoesNotRequireWpUsersToBeOnProcessedListWhenPreviewIsEnabled() {
|
||||
$data = (object)array_merge(
|
||||
$this->track_data,
|
||||
array(
|
||||
'queue' => $this->queue,
|
||||
'subscriber' => $this->subscriber,
|
||||
'newsletter' => $this->newsletter
|
||||
)
|
||||
);
|
||||
$data->subscriber->wp_user_id = 99;
|
||||
$data->preview = true;
|
||||
expect(Track::_validateTrackData($data))->equals($data);
|
||||
}
|
||||
|
||||
function testItCanGetNewsletterFromQueue() {
|
||||
$data = $this->track_data;
|
||||
$data['newsletter_id'] = false;
|
||||
$processed_data = Track::_processTrackData($this->track_data);
|
||||
expect($processed_data->newsletter->id)->equals($this->newsletter->id);
|
||||
}
|
||||
|
||||
function testItCanProcessTrackData() {
|
||||
$processed_data = Track::_processTrackData($this->track_data);
|
||||
expect($processed_data->queue->id)->equals($this->queue->id);
|
||||
expect($processed_data->subscriber->id)->equals($this->subscriber->id);
|
||||
expect($processed_data->newsletter->id)->equals($this->newsletter->id);
|
||||
expect($processed_data->link->id)->equals($this->link->id);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . NewsletterLink::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ class ClicksTest extends MailPoetTest {
|
||||
// create queue
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $newsletter->id;
|
||||
$queue->subscribers = array('processed' => array($subscriber->id));
|
||||
$this->queue = $queue->save();
|
||||
// create link
|
||||
$link = NewsletterLink::create();
|
||||
@ -32,174 +33,117 @@ class ClicksTest extends MailPoetTest {
|
||||
$link->newsletter_id = $newsletter->id;
|
||||
$link->queue_id = $queue->id;
|
||||
$this->link = $link->save();
|
||||
// instantiate class
|
||||
$this->clicks = new Clicks(true);
|
||||
}
|
||||
|
||||
function testItCanConstruct() {
|
||||
$clicks = new Clicks('test');
|
||||
expect($clicks->data)->equals('test');
|
||||
}
|
||||
|
||||
function testItCanGetNewsletter() {
|
||||
$newsletter = $this->clicks->getNewsletter($this->newsletter->id);
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['id'])->equals($this->newsletter->id);
|
||||
}
|
||||
|
||||
function testItCanGetSubscriber() {
|
||||
$subscriber = $this->clicks->getSubscriber($this->subscriber->id);
|
||||
expect(is_array($subscriber))->true();
|
||||
expect($subscriber['id'])->equals($this->subscriber->id);
|
||||
}
|
||||
|
||||
function testItCanGetQueue() {
|
||||
$queue = $this->clicks->getQueue($this->queue->id);
|
||||
expect(is_array($queue))->true();
|
||||
expect($queue['id'])->equals($this->queue->id);
|
||||
}
|
||||
|
||||
function testItCanGetLink() {
|
||||
$link = $this->clicks->getLink($this->link->hash);
|
||||
expect(is_array($link))->true();
|
||||
expect($link['id'])->equals($this->link->id);
|
||||
}
|
||||
|
||||
function testItTreatsUrlAsUrl() {
|
||||
$link = $this->clicks->processUrl(
|
||||
'http://example.com',
|
||||
(array) $this->newsletter,
|
||||
(array) $this->subscriber,
|
||||
(array) $this->queue
|
||||
// build track data
|
||||
$this->track_data = (object)array(
|
||||
'queue' => $queue,
|
||||
'subscriber' => $subscriber,
|
||||
'newsletter' => $newsletter,
|
||||
'subscriber_token' => Subscriber::generateToken($subscriber->email),
|
||||
'link' => $link,
|
||||
'preview' => false
|
||||
);
|
||||
expect($link)->equals('http://example.com');
|
||||
// instantiate class
|
||||
$this->clicks = new Clicks();
|
||||
}
|
||||
|
||||
function testItConvertsShortcodeToUrl() {
|
||||
function testItAbortsWhenTrackDataIsEmptyOrMissingLink() {
|
||||
// abort function should be called twice:
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'abort' => Stub::exactly(2, function() { })
|
||||
), $this);
|
||||
$data = $this->track_data;
|
||||
// 1. when tracking data does not exist
|
||||
$clicks->track(false);
|
||||
// 2. when link model object is missing
|
||||
unset($data->link);
|
||||
$clicks->track($data);
|
||||
}
|
||||
|
||||
function testItDoesNotTrackEventsFromWpUserWhenPreviewIsEnabled() {
|
||||
$data = $this->track_data;
|
||||
$data->subscriber->wp_user_id = 99;
|
||||
$data->preview = true;
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
$clicks->track($data);
|
||||
expect(StatisticsClicks::findMany())->isEmpty();
|
||||
expect(StatisticsOpens::findMany())->isEmpty();
|
||||
}
|
||||
|
||||
function testItTracksClickAndOpenEvent() {
|
||||
$data = $this->track_data;
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
$clicks->track($data);
|
||||
expect(StatisticsClicks::findMany())->notEmpty();
|
||||
expect(StatisticsOpens::findMany())->notEmpty();
|
||||
}
|
||||
|
||||
function testItRedirectsToUrlAfterTracking() {
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'redirectToUrl' => Stub::exactly(1, function() { })
|
||||
), $this);
|
||||
$clicks->track($this->track_data);
|
||||
}
|
||||
|
||||
function testItIncrementsClickEventCount() {
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
$clicks->track($this->track_data);
|
||||
expect(StatisticsClicks::findMany()[0]->count)->equals(1);
|
||||
$clicks->track($this->track_data);
|
||||
expect(StatisticsClicks::findMany()[0]->count)->equals(2);
|
||||
}
|
||||
|
||||
function testItConvertsShortcodesToUrl() {
|
||||
$link = $this->clicks->processUrl(
|
||||
'[link:newsletter_view_in_browser_url]',
|
||||
(array) $this->newsletter,
|
||||
(array) $this->subscriber,
|
||||
(array) $this->queue
|
||||
$this->newsletter,
|
||||
$this->subscriber,
|
||||
$this->queue,
|
||||
$preview = false
|
||||
);
|
||||
expect($link)->contains('&endpoint=view_in_browser');
|
||||
}
|
||||
|
||||
function testItFailsToConvertsInvalidShortcodeToUrl() {
|
||||
$clicks = Stub::make(new Clicks(true), array(
|
||||
'abort' => Stub::exactly(1, function () { })
|
||||
$clicks = Stub::make($this->clicks, array(
|
||||
'abort' => Stub::exactly(1, function() { })
|
||||
), $this);
|
||||
// should call abort() method if shortcode action does not exist
|
||||
$link = $clicks->processUrl(
|
||||
'[link:]',
|
||||
(array) $this->newsletter,
|
||||
(array) $this->subscriber,
|
||||
(array) $this->queue
|
||||
$this->newsletter,
|
||||
$this->subscriber,
|
||||
$this->queue,
|
||||
$preview = false
|
||||
);
|
||||
}
|
||||
|
||||
function testItFailsToConvertsNonexistentShortcodeToUrl() {
|
||||
function testItDoesNotConvertNonexistentShortcodeToUrl() {
|
||||
$link = $this->clicks->processUrl(
|
||||
'[link:unknown_shortcode]',
|
||||
(array) $this->newsletter,
|
||||
(array) $this->subscriber,
|
||||
(array) $this->queue
|
||||
$this->newsletter,
|
||||
$this->subscriber,
|
||||
$this->queue,
|
||||
$preview = false
|
||||
);
|
||||
expect($link)->equals('[link:unknown_shortcode]');
|
||||
}
|
||||
|
||||
function testItAbortsWhenItCantFindData() {
|
||||
$clicks = Stub::make(new Clicks(true), array(
|
||||
'abort' => Stub::exactly(4, function () { }),
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
// should call abort() method when newsletter can't be found
|
||||
$data = array(
|
||||
'newsletter' => 999,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => $this->link->hash
|
||||
);
|
||||
$click = $clicks->track($data);
|
||||
// should call abort() method when subscriber can't be found
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => 999,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => $this->link->hash
|
||||
);
|
||||
$click = $clicks->track($data);
|
||||
// should call abort() method when queue can't be found
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => 999,
|
||||
'hash' => $this->link->hash
|
||||
);
|
||||
$click = $clicks->track($data);
|
||||
// should call abort() method when link can't be found
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => 999
|
||||
);
|
||||
$click = $clicks->track($data);
|
||||
}
|
||||
|
||||
function testItShouldAlwaysTrackOpenEvent() {
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => $this->link->hash
|
||||
function testItDoesNotConvertRegulaUrls() {
|
||||
$link = $this->clicks->processUrl(
|
||||
'http://example.com',
|
||||
$this->newsletter,
|
||||
$this->subscriber,
|
||||
$this->queue,
|
||||
$preview = false
|
||||
);
|
||||
$clicks = Stub::make(new Clicks(true), array(
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
$open_events = StatisticsOpens::findArray();
|
||||
expect(count($open_events))->equals(0);
|
||||
$click = $clicks->track($data);
|
||||
$open_events = StatisticsOpens::findArray();
|
||||
expect(count($open_events))->equals(1);
|
||||
}
|
||||
|
||||
function testItTracksUniqueAndRepeatClickEvent() {
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => $this->link->hash
|
||||
);
|
||||
$clicks = Stub::make(new Clicks(true), array(
|
||||
'redirectToUrl' => function() { }
|
||||
), $this);
|
||||
$click_events = StatisticsClicks::findArray();
|
||||
expect(count($click_events))->equals(0);
|
||||
// track unique click event
|
||||
$click = $clicks->track($data);
|
||||
$click_events = StatisticsClicks::findArray();
|
||||
expect(count($click_events))->equals(1);
|
||||
expect($click_events[0]['count'])->equals(1);
|
||||
// track repeat click event
|
||||
$click = $clicks->track($data);
|
||||
$click_events = StatisticsClicks::findArray();
|
||||
expect(count($click_events))->equals(1);
|
||||
expect($click_events[0]['count'])->equals(2);
|
||||
}
|
||||
|
||||
function testItRedirectsAfterTracking() {
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id,
|
||||
'hash' => $this->link->hash
|
||||
);
|
||||
$clicks = Stub::make(new Clicks(true), array(
|
||||
'redirectToUrl' => Stub::exactly(1, function() { })
|
||||
), $this);
|
||||
// should call redirectToUrl() method
|
||||
$click = $clicks->track($data);
|
||||
expect($link)->equals('http://example.com');
|
||||
}
|
||||
|
||||
function _after() {
|
||||
@ -210,4 +154,4 @@ class ClicksTest extends MailPoetTest {
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsOpens::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsClicks::$_table);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
use Codeception\Util\Stub;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\StatisticsClicks;
|
||||
use MailPoet\Models\StatisticsOpens;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
@ -22,94 +23,66 @@ class OpensTest extends MailPoetTest {
|
||||
// create queue
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $newsletter->id;
|
||||
$queue->subscribers = array('processed' => array($subscriber->id));
|
||||
$this->queue = $queue->save();
|
||||
// build track data
|
||||
$this->track_data = (object)array(
|
||||
'queue' => $queue,
|
||||
'subscriber' => $subscriber,
|
||||
'newsletter' => $newsletter,
|
||||
'subscriber_token' => Subscriber::generateToken($subscriber->email),
|
||||
'preview' => false
|
||||
);
|
||||
// instantiate class
|
||||
$this->opens = new Opens($data = true, $return_image = false);
|
||||
$this->opens = new Opens();
|
||||
}
|
||||
|
||||
function testItCanConstruct() {
|
||||
$opens = new Opens($data = 'test', $return_image = true);
|
||||
expect($opens->data)->equals('test');
|
||||
expect($opens->return_image)->true();
|
||||
}
|
||||
|
||||
function testItCanGetNewsletter() {
|
||||
$newsletter = $this->opens->getNewsletter($this->newsletter->id);
|
||||
expect(is_array($newsletter))->true();
|
||||
expect($newsletter['id'])->equals($this->newsletter->id);
|
||||
}
|
||||
|
||||
function testItCanGetSubscriber() {
|
||||
$subscriber = $this->opens->getSubscriber($this->subscriber->id);
|
||||
expect(is_array($subscriber))->true();
|
||||
expect($subscriber['id'])->equals($this->subscriber->id);
|
||||
}
|
||||
|
||||
function testItCanGetQueue() {
|
||||
$queue = $this->opens->getQueue($this->queue->id);
|
||||
expect(is_array($queue))->true();
|
||||
expect($queue['id'])->equals($this->queue->id);
|
||||
}
|
||||
|
||||
function testItReturnsWhenItCantFindData() {
|
||||
// should return false when newsletter can't be found
|
||||
$data = array(
|
||||
'newsletter' => 999,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id
|
||||
);
|
||||
expect($this->opens->track($data))->false();
|
||||
// should return false when subscriber can't be found
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => 999,
|
||||
'queue' => $this->queue->id
|
||||
);
|
||||
expect($this->opens->track($data))->false();
|
||||
// should return false when queue can't be found
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => 999
|
||||
);
|
||||
expect($this->opens->track($data))->false();
|
||||
}
|
||||
|
||||
function testItReturnsTrueOrImageUponCompletion() {
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id
|
||||
);
|
||||
$opens = Stub::make(new Opens(true), array(
|
||||
'returnImage' => Stub::exactly(1, function () { }),
|
||||
'data' => $data,
|
||||
'return_image' => true
|
||||
function testItReturnsImageWhenTrackDataIsEmpty() {
|
||||
$opens = Stub::make($this->opens, array(
|
||||
'returnResponse' => Stub::exactly(1, function() { })
|
||||
), $this);
|
||||
// it should run returnImage() method when $return_image is set to true
|
||||
$opens->track();
|
||||
$opens = Stub::make(new Opens(true), array(
|
||||
'returnImage' => Stub::exactly(0, function () { }),
|
||||
'data' => $data,
|
||||
'return_image' => false
|
||||
), $this);
|
||||
// it should return true when $return_image is set to false
|
||||
expect($opens->track())->true();
|
||||
$opens->track(false);
|
||||
expect(StatisticsOpens::findMany())->isEmpty();
|
||||
}
|
||||
|
||||
function testItTracksOnlyUniqueOpenEvent() {
|
||||
$data = array(
|
||||
'newsletter' => $this->newsletter->id,
|
||||
'subscriber' => $this->subscriber->id,
|
||||
'queue' => $this->queue->id
|
||||
);
|
||||
$open_events = StatisticsOpens::findArray();
|
||||
expect(count($open_events))->equals(0);
|
||||
// tracking twice the same event should only create 1 record
|
||||
$open = $this->opens->track($data);
|
||||
$open = $this->opens->track($data);
|
||||
$open_events = StatisticsOpens::findArray();
|
||||
expect(count($open_events))->equals(1);
|
||||
function testItDoesNotTrackOpenEventFromWpUserWhenPreviewIsEnabled() {
|
||||
$data = $this->track_data;
|
||||
$data->subscriber->wp_user_id = 99;
|
||||
$data->preview = true;
|
||||
$opens = Stub::make($this->opens, array(
|
||||
'returnResponse' => function() { }
|
||||
), $this);
|
||||
$opens->track($data);
|
||||
expect(StatisticsOpens::findMany())->isEmpty();
|
||||
}
|
||||
|
||||
function testItReturnsNothingWhenImageDisplayIsDisabled() {
|
||||
expect($this->opens->track($this->track_data, $display_image = false))->isEmpty();
|
||||
}
|
||||
|
||||
function testItTracksOpenEvent() {
|
||||
$opens = Stub::make($this->opens, array(
|
||||
'returnResponse' => function() { }
|
||||
), $this);
|
||||
$opens->track($this->track_data);
|
||||
expect(StatisticsOpens::findMany())->notEmpty();
|
||||
}
|
||||
|
||||
function testItDoesNotTrackRepeatedOpenEvents() {
|
||||
$opens = Stub::make($this->opens, array(
|
||||
'returnResponse' => function() { }
|
||||
), $this);
|
||||
for($count = 0; $count <= 2; $count++) {
|
||||
$opens->track($this->track_data);
|
||||
}
|
||||
expect(count(StatisticsOpens::findMany()))->equals(1);
|
||||
}
|
||||
|
||||
function testItReturnsImageAfterTracking() {
|
||||
$opens = Stub::make($this->opens, array(
|
||||
'returnResponse' => Stub::exactly(1, function() { })
|
||||
), $this);
|
||||
$opens->track($this->track_data);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
@ -117,5 +90,6 @@ class OpensTest extends MailPoetTest {
|
||||
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsOpens::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsClicks::$_table);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Codeception\Util\Stub;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\StatisticsOpens;
|
||||
use MailPoet\Models\StatisticsUnsubscribes;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
use MailPoet\Statistics\Track\Unsubscribes;
|
||||
|
||||
class UnsubscribesTest extends MailPoetTest {
|
||||
@ -24,27 +21,30 @@ class UnsubscribesTest extends MailPoetTest {
|
||||
// create queue
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $newsletter->id;
|
||||
$queue->subscribers = array('processed' => array($subscriber->id));
|
||||
$this->queue = $queue->save();
|
||||
// instantiate class
|
||||
$this->unsubscribes = new Unsubscribes();
|
||||
}
|
||||
|
||||
function testItCanUniqueTrack() {
|
||||
$unsubscribe_events = StatisticsUnsubscribes::findArray();
|
||||
expect(count($unsubscribe_events))->equals(0);
|
||||
// only 1 unique unsubscribe event should be recorded
|
||||
$unsubscribes = $this->unsubscribes->track(
|
||||
function testItTracksUnsubscribeEvent() {
|
||||
$this->unsubscribes->track(
|
||||
$this->newsletter->id,
|
||||
$this->subscriber->id,
|
||||
$this->queue->id
|
||||
);
|
||||
$unsubscribes = $this->unsubscribes->track(
|
||||
$this->newsletter->id,
|
||||
$this->subscriber->id,
|
||||
$this->queue->id
|
||||
);
|
||||
$unsubscribe_events = StatisticsUnsubscribes::findArray();
|
||||
expect(count($unsubscribe_events))->equals(1);
|
||||
expect(count(StatisticsUnsubscribes::findMany()))->equals(1);
|
||||
}
|
||||
|
||||
function testItDoesNotTrackRepeatedUnsubscribeEvents() {
|
||||
for($count = 0; $count <= 2; $count++) {
|
||||
$this->unsubscribes->track(
|
||||
$this->newsletter->id,
|
||||
$this->subscriber->id,
|
||||
$this->queue->id
|
||||
);
|
||||
}
|
||||
expect(count(StatisticsUnsubscribes::findMany()))->equals(1);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
@ -53,4 +53,4 @@ class UnsubscribesTest extends MailPoetTest {
|
||||
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . StatisticsUnsubscribes::$_table);
|
||||
}
|
||||
}
|
||||
}
|
@ -222,21 +222,36 @@ class ExportTest extends MailPoetTest {
|
||||
}
|
||||
|
||||
function testItRequiresWritableExportFile() {
|
||||
$this->export->export_path = '/fake_folder';
|
||||
$result = $this->export->process();
|
||||
expect($result['errors'][0])
|
||||
->equals("Couldn't save export file on the server");
|
||||
try {
|
||||
$this->export->export_path = '/fake_folder';
|
||||
$this->export->process();
|
||||
$this->fail('Export did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())
|
||||
->equals("Couldn't save export file on the server");
|
||||
}
|
||||
}
|
||||
|
||||
function testItCanProcess() {
|
||||
$this->export->export_file = $this->export->getExportFile('csv');
|
||||
$this->export->export_format_option = 'csv';
|
||||
$result = $this->export->process();
|
||||
expect($result['result'])->true();
|
||||
$this->export->export_file = $this->export->getExportFile('xlsx');
|
||||
$this->export->export_format_option = 'xlsx';
|
||||
$result = $this->export->process();
|
||||
expect($result['result'])->true();
|
||||
try {
|
||||
$this->export->export_file = $this->export->getExportFile('csv');
|
||||
$this->export->export_format_option = 'csv';
|
||||
$result = $this->export->process();
|
||||
} catch(\Exception $e) {
|
||||
$this->fail('Export to .csv process threw an exception');
|
||||
}
|
||||
expect($result['totalExported'])->equals(3);
|
||||
expect($result['exportFileURL'])->notEmpty();
|
||||
|
||||
try {
|
||||
$this->export->export_file = $this->export->getExportFile('xlsx');
|
||||
$this->export->export_format_option = 'xlsx';
|
||||
$result = $this->export->process();
|
||||
} catch(\Exception $e) {
|
||||
$this->fail('Export to .xlsx process threw an exception');
|
||||
}
|
||||
expect($result['totalExported'])->equals(3);
|
||||
expect($result['exportFileURL'])->notEmpty();
|
||||
}
|
||||
|
||||
function _after() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SubscriberCustomField;
|
||||
@ -9,6 +10,13 @@ use MailPoet\Util\Helpers;
|
||||
|
||||
class ImportTest extends MailPoetTest {
|
||||
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(
|
||||
'subscribers' => array(
|
||||
array(
|
||||
@ -25,13 +33,13 @@ class ImportTest extends MailPoetTest {
|
||||
)
|
||||
),
|
||||
'columns' => array(
|
||||
'first_name' => 0,
|
||||
'last_name' => 1,
|
||||
'email' => 2,
|
||||
777 => 3
|
||||
'first_name' => array('index' => 0),
|
||||
'last_name' => array('index' => 1),
|
||||
'email' => array('index' => 2),
|
||||
(string)$custom_field->id => array('index' => 3)
|
||||
),
|
||||
'segments' => array(
|
||||
195
|
||||
$this->segment_1->id
|
||||
),
|
||||
'timestamp' => time(),
|
||||
'updateSubscribers' => true
|
||||
@ -41,10 +49,6 @@ class ImportTest extends MailPoetTest {
|
||||
'last_name',
|
||||
'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->subscribers_data = $this->import->transformSubscribersData(
|
||||
$this->data['subscribers'],
|
||||
@ -63,13 +67,14 @@ class ImportTest extends MailPoetTest {
|
||||
}
|
||||
|
||||
function testItCanTransformSubscribers() {
|
||||
$custom_field = $this->subscriber_custom_fields[0];
|
||||
expect($this->import->subscribers_data['first_name'][0])
|
||||
->equals($this->data['subscribers'][0][0]);
|
||||
expect($this->import->subscribers_data['last_name'][0])
|
||||
->equals($this->data['subscribers'][0][1]);
|
||||
expect($this->import->subscribers_data['email'][0])
|
||||
->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]);
|
||||
}
|
||||
|
||||
@ -242,6 +247,7 @@ class ImportTest extends MailPoetTest {
|
||||
|
||||
function testItCanCreateOrUpdateCustomFields() {
|
||||
$subscribers_data = $this->subscribers_data;
|
||||
$custom_field = $this->subscriber_custom_fields[0];
|
||||
$this->import->createOrUpdateSubscribers(
|
||||
'create',
|
||||
$subscribers_data,
|
||||
@ -266,8 +272,8 @@ class ImportTest extends MailPoetTest {
|
||||
$subscriber_custom_fields = SubscriberCustomField::findArray();
|
||||
expect(count($subscriber_custom_fields))->equals(2);
|
||||
expect($subscriber_custom_fields[0]['value'])
|
||||
->equals($subscribers_data[777][0]);
|
||||
$subscribers_data[777][1] = 'Rio';
|
||||
->equals($subscribers_data[$custom_field][0]);
|
||||
$subscribers_data[$custom_field][1] = 'Rio';
|
||||
$this->import->createOrUpdateCustomFields(
|
||||
'update',
|
||||
$db_subscribers,
|
||||
@ -276,7 +282,7 @@ class ImportTest extends MailPoetTest {
|
||||
);
|
||||
$subscriber_custom_fields = SubscriberCustomField::findArray();
|
||||
expect($subscriber_custom_fields[1]['value'])
|
||||
->equals($subscribers_data[777][1]);
|
||||
->equals($subscribers_data[$custom_field][1]);
|
||||
}
|
||||
|
||||
|
||||
@ -320,17 +326,17 @@ class ImportTest extends MailPoetTest {
|
||||
|
||||
function testItCanUpdateSubscribers() {
|
||||
$result = $this->import->process();
|
||||
expect($result['data']['updated'])->equals(0);
|
||||
expect($result['updated'])->equals(0);
|
||||
$result = $this->import->process();
|
||||
expect($result['data']['updated'])->equals(2);
|
||||
expect($result['updated'])->equals(2);
|
||||
$this->import->update_subscribers = false;
|
||||
$result = $this->import->process();
|
||||
expect($result['data']['updated'])->equals(0);
|
||||
expect($result['updated'])->equals(0);
|
||||
}
|
||||
|
||||
function testItCanProcess() {
|
||||
$result = $this->import->process();
|
||||
expect($result['data']['created'])->equals(2);
|
||||
expect($result['created'])->equals(2);
|
||||
Subscriber::where('email', 'mary@jane.com')
|
||||
->findOne()
|
||||
->delete();
|
||||
@ -338,13 +344,14 @@ class ImportTest extends MailPoetTest {
|
||||
$this->import->created_at = date('Y-m-d H:i:s', $timestamp);
|
||||
$this->import->updated_at = date('Y-m-d H:i:s', $timestamp + 1);
|
||||
$result = $this->import->process();
|
||||
expect($result['data']['created'])->equals(1);
|
||||
expect($result['created'])->equals(1);
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . Segment::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . SubscriberSegment::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . CustomField::$_table);
|
||||
ORM::raw_execute('TRUNCATE ' . SubscriberCustomField::$_table);
|
||||
}
|
||||
}
|
@ -25,59 +25,86 @@ class MailChimpTest extends MailPoetTest {
|
||||
|
||||
function testItFailsWithIncorrectAPIKey() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$mailchimp = clone($this->mailchimp);
|
||||
$mailchimp->api_key = false;
|
||||
$lists = $mailchimp->getLists();
|
||||
expect($lists['result'])->false();
|
||||
expect($lists['errors'][0])->contains('API');
|
||||
$subscribers = $mailchimp->getLists();
|
||||
expect($subscribers['result'])->false();
|
||||
expect($subscribers['errors'][0])->contains('API');
|
||||
|
||||
try {
|
||||
$mailchimp = clone($this->mailchimp);
|
||||
$mailchimp->api_key = false;
|
||||
$lists = $mailchimp->getLists();
|
||||
$this->fail('MailChimp getLists() did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())->contains('Invalid API Key');
|
||||
}
|
||||
}
|
||||
|
||||
function testItCanGetLists() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$lists = $this->mailchimp->getLists();
|
||||
expect($lists['result'])->true();
|
||||
expect(count($lists['data']))->equals(2);
|
||||
expect(isset($lists['data'][0]['id']))->true();
|
||||
expect(isset($lists['data'][0]['name']))->true();
|
||||
try {
|
||||
$lists = $this->mailchimp->getLists();
|
||||
} catch(\Exception $e) {
|
||||
$this->fail('MailChimp getLists() threw an exception');
|
||||
}
|
||||
expect($lists)->count(2);
|
||||
expect($lists[0]['id'])->notEmpty();
|
||||
expect($lists[0]['name'])->notEmpty();
|
||||
}
|
||||
|
||||
function testItFailsWithIncorrectLists() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$subscribers = $this->mailchimp->getSubscribers();
|
||||
expect($subscribers['result'])->false();
|
||||
expect($subscribers['errors'][0])->contains('lists');
|
||||
$subscribers = $this->mailchimp->getSubscribers(array(12));
|
||||
expect($subscribers['result'])->false();
|
||||
expect($subscribers['errors'][0])->contains('lists');
|
||||
|
||||
try {
|
||||
$subscribers = $this->mailchimp->getSubscribers();
|
||||
$this->fail('MailChimp getSubscribers() did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())->contains('Did not find any valid lists');
|
||||
}
|
||||
|
||||
try {
|
||||
$subscribers = $this->mailchimp->getSubscribers(array(12));
|
||||
$this->fail('MailChimp getSubscribers() did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())->contains('Did not find any valid lists');
|
||||
}
|
||||
}
|
||||
|
||||
function testItCanGetSubscribers() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$subscribers = $this->mailchimp->getSubscribers(array($this->lists[0]));
|
||||
expect($subscribers['result'])->true();
|
||||
expect(isset($subscribers['data']['invalid']))->true();
|
||||
expect(isset($subscribers['data']['duplicate']))->true();
|
||||
expect(isset($subscribers['data']['header']))->true();
|
||||
expect(count($subscribers['data']['subscribers']))->equals(1);
|
||||
expect($subscribers['data']['subscribersCount'])->equals(1);
|
||||
|
||||
try {
|
||||
$subscribers = $this->mailchimp->getSubscribers(array($this->lists[0]));
|
||||
} catch(\Exception $e) {
|
||||
$this->fail('MailChimp getSubscribers() threw an exception');
|
||||
}
|
||||
|
||||
expect($subscribers)->hasKey('invalid');
|
||||
expect($subscribers)->hasKey('duplicate');
|
||||
expect($subscribers['header'])->notEmpty();
|
||||
expect($subscribers['subscribers'])->count(1);
|
||||
expect($subscribers['subscribersCount'])->equals(1);
|
||||
}
|
||||
|
||||
function testItFailsWhenListHeadersDontMatch() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$subscribers = $this->mailchimp->getSubscribers($this->lists);
|
||||
expect($subscribers['result'])->false();
|
||||
expect($subscribers['errors'][0])->contains('header');
|
||||
|
||||
try {
|
||||
$subscribers = $this->mailchimp->getSubscribers($this->lists);
|
||||
$this->fail('MailChimp getSubscribers() did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())
|
||||
->contains('The selected lists do not have matching columns (headers)');
|
||||
}
|
||||
}
|
||||
|
||||
function testItFailsWhenSubscribersDataTooLarge() {
|
||||
if(getenv('WP_TEST_ENABLE_NETWORK_TESTS') !== 'true') return;
|
||||
$mailchimp = clone($this->mailchimp);
|
||||
$mailchimp->max_post_size = 10;
|
||||
$subscribers = $mailchimp->getSubscribers($this->lists);
|
||||
expect($subscribers['result'])->false();
|
||||
expect($subscribers['errors'][0])->contains('large');
|
||||
|
||||
try {
|
||||
$subscribers = $mailchimp->getSubscribers($this->lists);
|
||||
$this->fail('MailChimp getSubscribers() did not throw an exception');
|
||||
} catch(\Exception $e) {
|
||||
expect($e->getMessage())
|
||||
->contains('The information received from MailChimp is too large for processing');
|
||||
}
|
||||
}
|
||||
}
|
102
views/form/custom_fields.html
Normal file
102
views/form/custom_fields.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!-- date settings and block templates -->
|
||||
<%= partial('form_template_date_years',
|
||||
'form/templates/blocks/date_years.hbs',
|
||||
'_settings_date_years'
|
||||
) %>
|
||||
<%= partial('form_template_date_months',
|
||||
'form/templates/blocks/date_months.hbs',
|
||||
'_settings_date_months'
|
||||
) %>
|
||||
<%= partial('form_template_date_days',
|
||||
'form/templates/blocks/date_days.hbs',
|
||||
'_settings_date_days'
|
||||
) %>
|
||||
<%= partial('form_template_date', 'form/templates/blocks/date.hbs') %>
|
||||
|
||||
<!-- field settings -->
|
||||
<%= partial('form_template_field_settings', 'form/templates/settings/field.hbs') %>
|
||||
|
||||
<%= partial('field_settings_label',
|
||||
'form/templates/settings/label.hbs',
|
||||
'_settings_label'
|
||||
) %>
|
||||
<%= partial('field_settings_label_within',
|
||||
'form/templates/settings/label_within.hbs',
|
||||
'_settings_label_within'
|
||||
) %>
|
||||
<%= partial('field_settings_required',
|
||||
'form/templates/settings/required.hbs',
|
||||
'_settings_required'
|
||||
) %>
|
||||
<%= partial('field_settings_validate',
|
||||
'form/templates/settings/validate.hbs',
|
||||
'_settings_validate'
|
||||
) %>
|
||||
<%= partial('field_settings_values',
|
||||
'form/templates/settings/values.hbs',
|
||||
'_settings_values'
|
||||
) %>
|
||||
<%= partial('field_settings_date_default',
|
||||
'form/templates/settings/date_default.hbs',
|
||||
'_settings_date_default'
|
||||
) %>
|
||||
<%= partial('field_settings_submit',
|
||||
'form/templates/settings/submit.hbs',
|
||||
'_settings_submit'
|
||||
) %>
|
||||
|
||||
<%= partial('field_settings_values_item',
|
||||
'form/templates/settings/values_item.hbs') %>
|
||||
<%= partial(
|
||||
'field_settings_date_format',
|
||||
'form/templates/settings/date_formats.hbs',
|
||||
'_settings_date_format'
|
||||
) %>
|
||||
<%= partial(
|
||||
'field_settings_date_type',
|
||||
'form/templates/settings/date_types.hbs',
|
||||
'_settings_date_type'
|
||||
) %>
|
||||
<%= partial('field_settings_segment_selection_item',
|
||||
'form/templates/settings/segment_selection_item.hbs'
|
||||
) %>
|
||||
<%= partial('field_settings_segment_selection',
|
||||
'form/templates/settings/segment_selection.hbs',
|
||||
'_settings_segment_selection'
|
||||
) %>
|
||||
|
||||
<!-- custom field: new -->
|
||||
<%= partial('form_template_field_form',
|
||||
'form/templates/settings/field_form.hbs'
|
||||
) %>
|
||||
|
||||
<!-- field settings depending on field type -->
|
||||
<script id="form_template_field_text" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_validate }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_textarea" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_validate }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_radio" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_checkbox" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_select" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_date" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_date_type }}
|
||||
</script>
|
@ -282,9 +282,7 @@
|
||||
endpoint: 'customFields',
|
||||
action: 'getAll',
|
||||
}).done(function(response) {
|
||||
if(response !== false) {
|
||||
data.fields = $.merge(response, data.fields);
|
||||
}
|
||||
data.fields = $.merge(response.data, data.fields);
|
||||
|
||||
// render toolbar
|
||||
jQuery('#mailpoet_toolbar_fields').html(template(data));
|
||||
@ -489,18 +487,6 @@
|
||||
action: 'saveEditor',
|
||||
data: form
|
||||
}).done(function(response) {
|
||||
if(response.result === false) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(response.errors.join('<br />'));
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
"<%= __('An error occurred. Please reload the page and try again.') %>"
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(callback !== false) {
|
||||
var message = null;
|
||||
|
||||
@ -523,6 +509,13 @@
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -579,14 +572,21 @@
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'customFields',
|
||||
action: 'get',
|
||||
data: id
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result !== false) {
|
||||
MailPoet.Modal.popup({
|
||||
title: "<%= __('Edit field') %>",
|
||||
template: $('#form_template_field_form').html(),
|
||||
data: response
|
||||
});
|
||||
MailPoet.Modal.popup({
|
||||
title: "<%= __('Edit field') %>",
|
||||
template: $('#form_template_field_form').html(),
|
||||
data: response.data
|
||||
});
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -603,22 +603,20 @@
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'customFields',
|
||||
action: 'delete',
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
item.remove();
|
||||
|
||||
if(response.field !== undefined) {
|
||||
WysijaForm.removeBlock(response.field, function() {
|
||||
mailpoet_form_save(false);
|
||||
});
|
||||
}
|
||||
|
||||
mailpoet_form_fields();
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Removed custom field “"+name+"“') %>"
|
||||
);
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done(function(response) {
|
||||
item.remove();
|
||||
|
||||
WysijaForm.removeBlock(id, function() {
|
||||
mailpoet_form_save(false);
|
||||
});
|
||||
|
||||
mailpoet_form_fields();
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Removed custom field “"+name+"“') %>"
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -685,110 +683,12 @@
|
||||
<%= partial('form_template_checkbox', 'form/templates/blocks/checkbox.hbs') %>
|
||||
<%= partial('form_template_textarea', 'form/templates/blocks/textarea.hbs') %>
|
||||
<%= partial('form_template_html', 'form/templates/blocks/html.hbs') %>
|
||||
<%= partial('form_template_date_years',
|
||||
'form/templates/blocks/date_years.hbs',
|
||||
'_settings_date_years'
|
||||
) %>
|
||||
<%= partial('form_template_date_months',
|
||||
'form/templates/blocks/date_months.hbs',
|
||||
'_settings_date_months'
|
||||
) %>
|
||||
<%= partial('form_template_date_days',
|
||||
'form/templates/blocks/date_days.hbs',
|
||||
'_settings_date_days'
|
||||
) %>
|
||||
<%= partial('form_template_date', 'form/templates/blocks/date.hbs') %>
|
||||
|
||||
<!-- field settings -->
|
||||
<%= partial('form_template_field_settings', 'form/templates/settings/field.hbs') %>
|
||||
|
||||
<%= partial('field_settings_label',
|
||||
'form/templates/settings/label.hbs',
|
||||
'_settings_label'
|
||||
) %>
|
||||
<%= partial('field_settings_label_within',
|
||||
'form/templates/settings/label_within.hbs',
|
||||
'_settings_label_within'
|
||||
) %>
|
||||
<%= partial('field_settings_required',
|
||||
'form/templates/settings/required.hbs',
|
||||
'_settings_required'
|
||||
) %>
|
||||
<%= partial('field_settings_validate',
|
||||
'form/templates/settings/validate.hbs',
|
||||
'_settings_validate'
|
||||
) %>
|
||||
<%= partial('field_settings_values',
|
||||
'form/templates/settings/values.hbs',
|
||||
'_settings_values'
|
||||
) %>
|
||||
<%= partial('field_settings_date_default',
|
||||
'form/templates/settings/date_default.hbs',
|
||||
'_settings_date_default'
|
||||
) %>
|
||||
<%= partial('field_settings_submit',
|
||||
'form/templates/settings/submit.hbs',
|
||||
'_settings_submit'
|
||||
) %>
|
||||
|
||||
<%= partial('field_settings_values_item',
|
||||
'form/templates/settings/values_item.hbs') %>
|
||||
<%= partial(
|
||||
'field_settings_date_format',
|
||||
'form/templates/settings/date_formats.hbs',
|
||||
'_settings_date_format'
|
||||
) %>
|
||||
<%= partial(
|
||||
'field_settings_date_type',
|
||||
'form/templates/settings/date_types.hbs',
|
||||
'_settings_date_type'
|
||||
) %>
|
||||
<%= partial('field_settings_segment_selection_item',
|
||||
'form/templates/settings/segment_selection_item.hbs'
|
||||
) %>
|
||||
<%= partial('field_settings_segment_selection',
|
||||
'form/templates/settings/segment_selection.hbs',
|
||||
'_settings_segment_selection'
|
||||
) %>
|
||||
|
||||
<!-- custom field: new -->
|
||||
<%= partial('form_template_field_form',
|
||||
'form/templates/settings/field_form.hbs'
|
||||
) %>
|
||||
<!-- custom field settings and templates -->
|
||||
<% include 'form/custom_fields.html' %>
|
||||
|
||||
<!-- form preview -->
|
||||
<%= partial('mailpoet_form_preview_template',
|
||||
'form/templates/preview.hbs'
|
||||
) %>
|
||||
|
||||
<!-- field settings depending on field type -->
|
||||
<script id="form_template_field_text" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_validate }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_textarea" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_validate }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_radio" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_checkbox" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_select" type="text/x-handlebars-template">
|
||||
{{> _settings_values }}
|
||||
{{> _settings_required }}
|
||||
</script>
|
||||
|
||||
<script id="form_template_field_date" type="text/x-handlebars-template">
|
||||
{{> _settings_required }}
|
||||
{{> _settings_date_type }}
|
||||
</script>
|
||||
<% endblock %>
|
@ -9,17 +9,17 @@
|
||||
{{> _settings_date_days }}
|
||||
{{> _settings_date_years }}
|
||||
{{/unless}}
|
||||
{{#ifCond params.date_format "==" "mm/dd/yyyy"}}
|
||||
{{#ifCond params.date_format "==" "MM/DD/YYYY"}}
|
||||
{{> _settings_date_months }}
|
||||
{{> _settings_date_days }}
|
||||
{{> _settings_date_years }}
|
||||
{{/ifCond}}
|
||||
{{#ifCond params.date_format "==" "dd/mm/yyyy"}}
|
||||
{{#ifCond params.date_format "==" "DD/MM/YYYY"}}
|
||||
{{> _settings_date_days }}
|
||||
{{> _settings_date_months }}
|
||||
{{> _settings_date_years }}
|
||||
{{/ifCond}}
|
||||
{{#ifCond params.date_format "==" "yyyy/mm/dd"}}
|
||||
{{#ifCond params.date_format "==" "YYYY/MM/DD"}}
|
||||
{{> _settings_date_years }}
|
||||
{{> _settings_date_months }}
|
||||
{{> _settings_date_days }}
|
||||
@ -31,11 +31,11 @@
|
||||
{{> _settings_date_months }}
|
||||
{{> _settings_date_years }}
|
||||
{{/unless}}
|
||||
{{#ifCond params.date_format "==" "mm/yyyy"}}
|
||||
{{#ifCond params.date_format "==" "MM/YYYY"}}
|
||||
{{> _settings_date_months }}
|
||||
{{> _settings_date_years }}
|
||||
{{/ifCond}}
|
||||
{{#ifCond params.date_format "==" "yyyy/mm"}}
|
||||
{{#ifCond params.date_format "==" "YYYY/MM"}}
|
||||
{{> _settings_date_years }}
|
||||
{{> _settings_date_months }}
|
||||
{{/ifCond}}
|
||||
|
@ -22,5 +22,7 @@
|
||||
.find('option:selected')
|
||||
.data('format'));
|
||||
});
|
||||
// set default format
|
||||
$('select[name="params[date_type]"]').trigger('change');
|
||||
});
|
||||
<{{!}}/script>
|
@ -43,8 +43,9 @@
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<label><%= __("Field name:") %></label>
|
||||
<label for="field_name"><%= __("Field name:") %></label>
|
||||
<input
|
||||
id="field_name"
|
||||
type="text"
|
||||
name="name"
|
||||
value="{{ name }}"
|
||||
@ -77,32 +78,31 @@
|
||||
action: 'save',
|
||||
data: data
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
// close popup
|
||||
MailPoet.Modal.close();
|
||||
// close popup
|
||||
MailPoet.Modal.close();
|
||||
|
||||
if(WysijaForm.updateBlock(response.field) === true) {
|
||||
// trigger save, if a block has been updated
|
||||
mailpoet_form_save(false);
|
||||
}
|
||||
if(WysijaForm.updateBlock(response.data) === true) {
|
||||
// trigger save, if a block has been updated
|
||||
mailpoet_form_save(false);
|
||||
}
|
||||
|
||||
mailpoet_form_fields();
|
||||
mailpoet_form_fields();
|
||||
|
||||
if(data.id) {
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Updated custom field “"+data.name+"“') %>"
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Added custom field “"+data.name+"“') %>"
|
||||
);
|
||||
}
|
||||
if(data.id) {
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Updated custom field “"+data.name+"“') %>"
|
||||
);
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
$(response.errors).each(function(i, error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Added custom field “"+data.name+"“') %>"
|
||||
);
|
||||
}
|
||||
}).fail(function(response) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ positionAfter: '#field_name' }
|
||||
);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
|
@ -197,6 +197,10 @@
|
||||
'newsletter_editor_template_styles',
|
||||
'newsletter/templates/components/styles.hbs'
|
||||
) %>
|
||||
<%= partial(
|
||||
'newsletter_editor_template_newsletter_preview',
|
||||
'newsletter/templates/components/newsletterPreview.hbs'
|
||||
) %>
|
||||
<%= partial(
|
||||
'newsletter_editor_template_sidebar',
|
||||
'newsletter/templates/components/sidebar/sidebar.hbs'
|
||||
@ -329,6 +333,8 @@
|
||||
'templateSaveFailed': __('Template has not been saved, please try again'),
|
||||
'categoriesAndTags': __('Categories & tags'),
|
||||
'noPostsToDisplay': __('There is no content to display'),
|
||||
'previewShouldOpenInNewTab': __('Your preview should open in a new tab. Please ensure your browser is not blocking popups from this page.'),
|
||||
'newsletterPreview': __('Newsletter Preview'),
|
||||
}) %>
|
||||
<% endblock %>
|
||||
|
||||
@ -376,6 +382,9 @@
|
||||
sidebarPreview: Handlebars.compile(
|
||||
jQuery('#newsletter_editor_template_sidebar_preview').html()
|
||||
),
|
||||
newsletterPreview: Handlebars.compile(
|
||||
jQuery('#newsletter_editor_template_newsletter_preview').html()
|
||||
),
|
||||
|
||||
genericBlockTools: Handlebars.compile(
|
||||
jQuery('#newsletter_editor_template_tools_generic').html()
|
||||
@ -1170,6 +1179,10 @@
|
||||
},
|
||||
shortcodes: <%= json_encode(shortcodes) %>,
|
||||
sidepanelWidth: '331px',
|
||||
newsletterPreview: {
|
||||
width: '1024px',
|
||||
height: '768px'
|
||||
},
|
||||
validation: {
|
||||
validateUnsubscribeLinkPresent: true, // TODO: Add validation based on whether Mailpoet MTA is used or not
|
||||
},
|
||||
|
@ -1,3 +1,3 @@
|
||||
<div class="mailpoet_tools"></div>
|
||||
<div class="mailpoet_social"></div>
|
||||
<div class="mailpoet_content mailpoet_social"></div>
|
||||
<div class="mailpoet_block_highlight"></div>
|
||||
|
@ -0,0 +1 @@
|
||||
<iframe src="{{ previewUrl }}" width="{{ width }}" height="{{ height }}"></iframe>
|
@ -47,6 +47,7 @@
|
||||
'showDetails': __('Show more details'),
|
||||
'segmentSelectionRequired': __('Please select at least one list'),
|
||||
'addNewList': __('Add new list'),
|
||||
'addNewField': __('Add new field'),
|
||||
'addNewColumuserColumnsn': __('Add new list'),
|
||||
'userColumns': __('User fields'),
|
||||
'selectedValueAlreadyMatched': __('The selected value is already matched to another field'),
|
||||
@ -65,7 +66,7 @@
|
||||
'november': __('November'),
|
||||
'december': __('December'),
|
||||
'noDateFieldMatch': __("Do not match as a 'date field' if most of the rows for that field return the same error"),
|
||||
'emptyDate': __('Date cannot be empty'),
|
||||
'emptyFirstRowDate': __('First row date cannot be empty'),
|
||||
'verifyDateMatch': __('Verify that the date in blue matches the original date'),
|
||||
'pm': __('PM'),
|
||||
'am': __('AM'),
|
||||
|
@ -92,7 +92,7 @@
|
||||
{{#show_and_match_columns .}}
|
||||
{{#.}}
|
||||
<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>
|
||||
{{/.}}
|
||||
{{/show_and_match_columns}}
|
||||
@ -157,57 +157,7 @@
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<!-- New column template -->
|
||||
<script id="new_column_template" type="text/x-handlebars-template">
|
||||
<p>
|
||||
<label><%= __('Field type') %>:</label>
|
||||
<select id="new_column_type" name="type">
|
||||
<option value="">--</option>
|
||||
<option value="input">
|
||||
<%= __('Text Input') %>
|
||||
</option>
|
||||
<option value="textarea">
|
||||
<%= __('Text Area') %>
|
||||
</option>
|
||||
<option value="radio">
|
||||
<%= __('Radio buttons') %>
|
||||
</option>
|
||||
<option value="checkbox">
|
||||
<%= __('Checkbox') %>
|
||||
</option>
|
||||
<option value="select">
|
||||
<%= __('Select') %>
|
||||
</option>
|
||||
<option value="date">
|
||||
<%= __('Date') %>
|
||||
</option>
|
||||
</select>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="type_required">
|
||||
<%= __('Please select a type') %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label><%= __('Field name') %>:</label>
|
||||
<input id="new_column_name" type="text" name="name" value="{{ name }}"/>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="name_required">
|
||||
<%= __('Please specify a name') %>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="name_not_unique">
|
||||
<%= __('This name is already taken') %>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p class="mailpoet_align_right">
|
||||
<input type="submit" value="<%= __('Done') %>" id="new_column_process"
|
||||
class="button-primary "/>
|
||||
<input type="submit" value="<%= __('Cancel') %>" id="new_column_cancel"
|
||||
class="button-primary"/>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</script>
|
||||
<!-- New custom field logic -->
|
||||
<% include 'form/custom_fields.html' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -150,6 +150,7 @@ config.push(_.extend({}, baseConfig, {
|
||||
'newsletter_editor/behaviors/HighlightEditingBehavior.js',
|
||||
'newsletter_editor/behaviors/ResizableBehavior.js',
|
||||
'newsletter_editor/behaviors/SortableBehavior.js',
|
||||
'newsletter_editor/behaviors/ShowSettingsBehavior.js',
|
||||
'newsletter_editor/blocks/base.js',
|
||||
'newsletter_editor/blocks/container.js',
|
||||
'newsletter_editor/blocks/button.js',
|
||||
@ -226,6 +227,7 @@ config.push(_.extend({}, baseConfig, {
|
||||
'newsletter_editor/behaviors/HighlightEditingBehavior.js',
|
||||
'newsletter_editor/behaviors/ResizableBehavior.js',
|
||||
'newsletter_editor/behaviors/SortableBehavior.js',
|
||||
'newsletter_editor/behaviors/ShowSettingsBehavior.js',
|
||||
'newsletter_editor/blocks/base.js',
|
||||
'newsletter_editor/blocks/container.js',
|
||||
'newsletter_editor/blocks/button.js',
|
||||
|
Reference in New Issue
Block a user