Compare commits
154 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 | |||
1b40f02715 | |||
c5a02c6136 | |||
492cd8c96b | |||
7f091d7188 | |||
1c081623b9 | |||
87332037c2 | |||
62023397f4 | |||
37ec6dc1a6 | |||
81c277ca93 | |||
f8fea75130 | |||
a4457649f7 | |||
1d6a09f010 | |||
faec553521 | |||
37fcf3a234 | |||
68a56aada8 | |||
f744305834 | |||
7a9402f5b5 | |||
de6d7e0cae | |||
a3c56b84ce | |||
3d4defd563 | |||
52da08abb2 | |||
b9637b52e9 | |||
0369a23fe8 | |||
f690e1a095 | |||
22e8e34213 | |||
12b46736c5 | |||
4950e47297 | |||
d7c5c8c3e7 | |||
46b0fcf37b | |||
b07c4d0e6e | |||
eb107799a7 | |||
4eec0a42f9 | |||
9a5a3a08c6 | |||
151683c632 | |||
fd2103d1aa | |||
7696b6ec5d | |||
d972b96255 | |||
35ccfb8bcf | |||
7ff036b1e9 | |||
983d56c29b | |||
a2528939ba | |||
c136d91dd2 | |||
bf00e82596 | |||
0e10f6c820 | |||
c056e95249 | |||
1be7fda1cf | |||
0b0c0f5759 | |||
59a4428965 | |||
3f5c36d2d4 | |||
3cc5812c1d | |||
3e616201ad | |||
5558ebad45 | |||
63bd093f35 | |||
ec6559b8be | |||
3421406dc7 | |||
a2917c08f6 | |||
5fa9b5a8dd | |||
41ad86ba1f | |||
067b3ff3e6 | |||
9b9cb1455a | |||
a5569a6a55 | |||
71c1026729 | |||
f102e847bf | |||
3158e2c460 | |||
a438f13bb0 | |||
5ed0a5819c | |||
6dd3c6acda | |||
ca2c1c2e6f | |||
1305a10ee0 | |||
5e36eb818b | |||
cfde82ff5f | |||
af98ade650 | |||
598432466e | |||
9469ce83f1 | |||
5624f4c7a0 | |||
82a001dc05 | |||
a9b424fb79 | |||
d31af9d71c | |||
ff7a24590f | |||
ea87a7acf8 | |||
9d36a17261 | |||
9c3cb5a509 | |||
4dd7f32f3a | |||
1c6fca7f83 | |||
c5b376bd21 | |||
5d2800bc25 | |||
6675d5a20d | |||
28c39d301c | |||
afa0d3af63 | |||
b05344b1d3 | |||
2e88d7cce0 | |||
cb558ce2ab | |||
ed30d8f639 | |||
9410d4f10a | |||
354d249e1d | |||
008fdb94c5 | |||
d0fb94b3f8 | |||
a451f00ed3 | |||
0e0c371b28 | |||
2e52f3bb92 | |||
a3a5016278 | |||
cb5d7cb9a0 | |||
a44d4ed0b5 | |||
7bd23288f6 | |||
08c663759c | |||
c46ee07674 | |||
18398a3bfb | |||
88d9315f8b | |||
8bc95db0c9 | |||
c05a20cff9 | |||
08cb994252 | |||
543ad81e28 | |||
641ba04685 | |||
8e4d07c658 | |||
420650f37f | |||
775f7faee4 | |||
13b91ad051 | |||
2d3ec13473 | |||
3094cfc076 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,7 +12,7 @@ npm-debug.log
|
||||
/views/cache/**
|
||||
temp
|
||||
.idea
|
||||
wysija-newsletters.zip
|
||||
mailpoet.zip
|
||||
tests/javascript/testBundles
|
||||
assets/css/*.css
|
||||
assets/js/*.js
|
||||
|
@ -141,8 +141,13 @@ class RoboFile extends \Robo\Tasks {
|
||||
$this->_exec('vendor/bin/codecept run -g failed');
|
||||
}
|
||||
|
||||
function qa() {
|
||||
$this->qaLint();
|
||||
$this->qaCodeSniffer('all');
|
||||
}
|
||||
|
||||
function qaLint() {
|
||||
$this->_exec('./tasks/php_lint.sh lib/ tests/');
|
||||
$this->_exec('./tasks/php_lint.sh lib/ tests/ mailpoet.php');
|
||||
}
|
||||
|
||||
function qaCodeSniffer($severity='errors') {
|
||||
|
@ -65,11 +65,10 @@
|
||||
overflow: hidden
|
||||
|
||||
.mailpoet_boxes .mailpoet_description h3
|
||||
margin: 0 0 1em 0
|
||||
margin: 0 0 0.7em 0
|
||||
overflow: hidden
|
||||
white-space: nowrap
|
||||
text-overflow: ellipsis
|
||||
max-width: 220px
|
||||
max-width: 210px
|
||||
line-height: 1.4em
|
||||
|
||||
.mailpoet_boxes .mailpoet_actions
|
||||
position: absolute
|
||||
|
BIN
assets/img/blank_templates/fake-logo.png
Normal file
BIN
assets/img/blank_templates/fake-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -8,19 +8,11 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
|
||||
endpoint: null,
|
||||
action: null,
|
||||
token: null,
|
||||
data: {},
|
||||
onSuccess: function(data, textStatus, xhr) {},
|
||||
onError: function(xhr, textStatus, errorThrown) {}
|
||||
},
|
||||
get: function(options) {
|
||||
return this.request('get', options);
|
||||
data: {}
|
||||
},
|
||||
post: function(options) {
|
||||
return this.request('post', options);
|
||||
},
|
||||
delete: function(options) {
|
||||
return this.request('delete', options);
|
||||
},
|
||||
init: function(options) {
|
||||
// merge options
|
||||
this.options = jQuery.extend({}, this.defaults, options);
|
||||
@ -50,7 +42,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
|
||||
|
||||
// set request params
|
||||
var params = this.getParams();
|
||||
var jqXHR;
|
||||
var deferred = jQuery.Deferred();
|
||||
|
||||
// remove null values from the data object
|
||||
if (_.isObject(params.data)) {
|
||||
@ -59,29 +51,22 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
|
||||
})
|
||||
}
|
||||
|
||||
// make ajax request depending on method
|
||||
if(method === 'get') {
|
||||
jqXHR = jQuery.get(
|
||||
this.options.url,
|
||||
params,
|
||||
this.options.onSuccess,
|
||||
'json'
|
||||
);
|
||||
} else {
|
||||
jqXHR = jQuery.ajax({
|
||||
url: this.options.url,
|
||||
type : 'post',
|
||||
data: params,
|
||||
dataType: 'json',
|
||||
success : this.options.onSuccess,
|
||||
error : this.options.onError
|
||||
});
|
||||
}
|
||||
// ajax request
|
||||
deferred = jQuery.post(
|
||||
this.options.url,
|
||||
params,
|
||||
null,
|
||||
'json'
|
||||
).then(function(data) {
|
||||
return data;
|
||||
}, function(xhr) {
|
||||
return xhr.responseJSON;
|
||||
});
|
||||
|
||||
// clear options
|
||||
this.options = {};
|
||||
|
||||
return jqXHR;
|
||||
return deferred;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -19,16 +19,15 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'getStatus'
|
||||
})
|
||||
.done(function(response) {
|
||||
jQuery('.button-primary')
|
||||
.removeClass('disabled');
|
||||
if(response.status !== undefined) {
|
||||
this.setState(response);
|
||||
} else {
|
||||
this.replaceState();
|
||||
}
|
||||
}.bind(this));
|
||||
}).done((response) => {
|
||||
this.setState({
|
||||
status: response.data.status
|
||||
});
|
||||
}).fail((response) => {
|
||||
this.setState({
|
||||
status: false
|
||||
});
|
||||
});
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
@ -36,56 +35,29 @@ define(
|
||||
setInterval(this.getCronData, 5000);
|
||||
}
|
||||
},
|
||||
controlCron: function(action) {
|
||||
if(jQuery('.button-primary').hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
jQuery('.button-primary')
|
||||
.addClass('disabled');
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: action,
|
||||
})
|
||||
.done(function(response) {
|
||||
if(!response.result) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('daemonControlError'));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
render: function() {
|
||||
if(this.state.status === 'loading') {
|
||||
return(<div>{MailPoet.I18n.t('loadingDaemonStatus')}</div>);
|
||||
}
|
||||
let status;
|
||||
|
||||
switch(this.state.status) {
|
||||
case 'started':
|
||||
return(
|
||||
<div>
|
||||
{MailPoet.I18n.t('cronDaemonIsRunning')}
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>{MailPoet.I18n.t('stop')}</a>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case 'starting':
|
||||
case false:
|
||||
case 'stopping':
|
||||
return(
|
||||
<div>
|
||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case 'stopped':
|
||||
return(
|
||||
<div>
|
||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
||||
<br />
|
||||
<br />
|
||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>{MailPoet.I18n.t('start')}</a>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
status = MailPoet.I18n.t('cronDaemonIsNotRunning');
|
||||
break;
|
||||
case 'starting':
|
||||
case 'started':
|
||||
status = MailPoet.I18n.t('cronDaemonIsRunning');
|
||||
break;
|
||||
case 'loading':
|
||||
status = MailPoet.I18n.t('loadingDaemonStatus');
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ status }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -97,4 +69,4 @@ define(
|
||||
container
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
@ -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",
|
||||
};
|
||||
@ -217,8 +217,10 @@ define([
|
||||
};
|
||||
},
|
||||
transport: function(options, success, failure) {
|
||||
var taxonomies,
|
||||
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||
var taxonomies;
|
||||
var promise = CommunicationComponent.getTaxonomies(
|
||||
that.model.get('contentType')
|
||||
).then(function(tax) {
|
||||
taxonomies = tax;
|
||||
// Fetch available terms based on the list of taxonomies already fetched
|
||||
var promise = CommunicationComponent.getTerms({
|
||||
@ -227,7 +229,7 @@ define([
|
||||
}).then(function(terms) {
|
||||
return {
|
||||
taxonomies: taxonomies,
|
||||
terms: terms,
|
||||
terms: terms
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
|
@ -19,7 +19,7 @@ define([
|
||||
return this._getDefaults({
|
||||
type: 'button',
|
||||
text: 'Button',
|
||||
url: 'http://google.com',
|
||||
url: '',
|
||||
styles: {
|
||||
block: {
|
||||
backgroundColor: '#ff0000',
|
||||
@ -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"),
|
||||
|
@ -17,8 +17,8 @@ define([
|
||||
defaults: function() {
|
||||
return this._getDefaults({
|
||||
type: 'image',
|
||||
link: 'http://example.org',
|
||||
src: 'no-image.png',
|
||||
link: '',
|
||||
src: '',
|
||||
alt: 'An image of...',
|
||||
fullWidth: true, // true | false
|
||||
width: '64px',
|
||||
@ -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() {
|
||||
@ -302,8 +302,10 @@ define([
|
||||
};
|
||||
},
|
||||
transport: function(options, success, failure) {
|
||||
var taxonomies,
|
||||
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||
var taxonomies;
|
||||
var promise = CommunicationComponent.getTaxonomies(
|
||||
that.model.get('contentType')
|
||||
).then(function(tax) {
|
||||
taxonomies = tax;
|
||||
// Fetch available terms based on the list of taxonomies already fetched
|
||||
var promise = CommunicationComponent.getTerms({
|
||||
@ -312,7 +314,7 @@ define([
|
||||
}).then(function(terms) {
|
||||
return {
|
||||
taxonomies: taxonomies,
|
||||
terms: terms,
|
||||
terms: terms
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
@ -412,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"),
|
||||
};
|
||||
},
|
||||
|
@ -93,6 +93,7 @@ define([
|
||||
return {
|
||||
model: this.model.toJSON(),
|
||||
allIconSets: allIconSets.toJSON(),
|
||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -140,6 +141,7 @@ define([
|
||||
},
|
||||
},
|
||||
HighlightEditingBehavior: {},
|
||||
ShowSettingsBehavior: {},
|
||||
},
|
||||
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
|
||||
constructor: function() {
|
||||
@ -148,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;
|
||||
},
|
||||
@ -175,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();
|
||||
@ -274,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: {
|
||||
@ -383,7 +389,7 @@ define([
|
||||
{
|
||||
type: 'socialIcon',
|
||||
iconType: 'facebook',
|
||||
link: 'http://example.com',
|
||||
link: 'http://www.facebook.com',
|
||||
image: App.getAvailableStyles().get('socialIconSets.default.facebook'),
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
@ -392,7 +398,7 @@ define([
|
||||
{
|
||||
type: 'socialIcon',
|
||||
iconType: 'twitter',
|
||||
link: 'http://example.com',
|
||||
link: 'http://www.twitter.com',
|
||||
image: App.getAvailableStyles().get('socialIconSets.default.twitter'),
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
|
@ -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; },
|
||||
|
@ -27,8 +27,8 @@ define([
|
||||
return Module._cachedQuery({
|
||||
action: 'getPostTypes',
|
||||
options: {},
|
||||
}).then(function(types) {
|
||||
return _.values(types);
|
||||
}).then(function(response) {
|
||||
return _.values(response.data);
|
||||
});
|
||||
};
|
||||
|
||||
@ -36,36 +36,46 @@ define([
|
||||
return Module._cachedQuery({
|
||||
action: 'getTaxonomies',
|
||||
options: {
|
||||
postType: postType,
|
||||
},
|
||||
postType: postType
|
||||
}
|
||||
}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
Module.getTerms = function(options) {
|
||||
return Module._cachedQuery({
|
||||
action: 'getTerms',
|
||||
options: options,
|
||||
options: options
|
||||
}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
Module.getPosts = function(options) {
|
||||
return Module._cachedQuery({
|
||||
action: 'getPosts',
|
||||
options: options,
|
||||
options: options
|
||||
}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
Module.getTransformedPosts = function(options) {
|
||||
return Module._cachedQuery({
|
||||
action: 'getTransformedPosts',
|
||||
options: options,
|
||||
options: options
|
||||
}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
Module.getBulkTransformedPosts = function(options) {
|
||||
return Module._query({
|
||||
action: 'getBulkTransformedPosts',
|
||||
options: options,
|
||||
options: options
|
||||
}).then(function(response) {
|
||||
return response.data;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -104,7 +104,7 @@ define([
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: data,
|
||||
data: data
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -65,10 +65,6 @@ define([
|
||||
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
||||
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||
|
||||
if ($openRegion.get(0) === $targetRegion.get(0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$openRegion.find('.mailpoet_region_content').velocity(
|
||||
'slideUp',
|
||||
{
|
||||
@ -79,16 +75,19 @@ define([
|
||||
}.bind(this)
|
||||
}
|
||||
);
|
||||
$targetRegion.find('.mailpoet_region_content').velocity(
|
||||
'slideDown',
|
||||
{
|
||||
duration: 250,
|
||||
easing: "easeIn",
|
||||
complete: function() {
|
||||
$targetRegion.removeClass('closed');
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if ($openRegion.get(0) !== $targetRegion.get(0)) {
|
||||
$targetRegion.find('.mailpoet_region_content').velocity(
|
||||
'slideDown',
|
||||
{
|
||||
duration: 250,
|
||||
easing: "easeIn",
|
||||
complete: function() {
|
||||
$targetRegion.removeClass('closed');
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
initialize: function(options) {
|
||||
@ -233,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();
|
||||
|
||||
@ -247,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() {
|
||||
@ -309,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;
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
@ -8,20 +8,38 @@ const _QueueMixin = {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'pause',
|
||||
data: newsletter.id
|
||||
data: {
|
||||
newsletter_id: newsletter.id
|
||||
}
|
||||
}).done(function() {
|
||||
jQuery('#resume_'+newsletter.id).show();
|
||||
jQuery('#pause_'+newsletter.id).hide();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
resumeSending: function(newsletter) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'resume',
|
||||
data: newsletter.id
|
||||
data: {
|
||||
newsletter_id: newsletter.id
|
||||
}
|
||||
}).done(function() {
|
||||
jQuery('#pause_'+newsletter.id).show();
|
||||
jQuery('#resume_'+newsletter.id).hide();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
renderQueueStatus: function(newsletter) {
|
||||
|
@ -158,20 +158,18 @@ const NewsletterListNotification = React.createClass({
|
||||
id: ~~(e.target.getAttribute('data-id')),
|
||||
status: e.target.value
|
||||
}
|
||||
}).done(function(response) {
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('postNotificationActivationFailed'));
|
||||
|
||||
// reset value to actual newsletter's status
|
||||
e.target.value = response.status;
|
||||
} else {
|
||||
if (response.status === 'active') {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('postNotificationActivated'));
|
||||
}
|
||||
// force refresh of listing so that groups are updated
|
||||
this.forceUpdate();
|
||||
}).done((response) => {
|
||||
if (response.data.status === 'active') {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('postNotificationActivated'));
|
||||
}
|
||||
}.bind(this));
|
||||
// force refresh of listing so that groups are updated
|
||||
this.forceUpdate();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('postNotificationActivationFailed'));
|
||||
|
||||
// reset value to actual newsletter's status
|
||||
e.target.value = response.status;
|
||||
});
|
||||
},
|
||||
renderStatus: function(newsletter) {
|
||||
return (
|
||||
|
@ -156,20 +156,18 @@ const NewsletterListWelcome = React.createClass({
|
||||
id: ~~(e.target.getAttribute('data-id')),
|
||||
status: e.target.value
|
||||
}
|
||||
}).done(function(response) {
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('welcomeEmailActivationFailed'));
|
||||
|
||||
// reset value to actual newsletter's status
|
||||
e.target.value = response.status;
|
||||
} else {
|
||||
if (response.status === 'active') {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('welcomeEmailActivated'));
|
||||
}
|
||||
// force refresh of listing so that groups are updated
|
||||
this.forceUpdate();
|
||||
}).done((response) => {
|
||||
if (response.data.status === 'active') {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('welcomeEmailActivated'));
|
||||
}
|
||||
}.bind(this));
|
||||
// force refresh of listing so that groups are updated
|
||||
this.forceUpdate();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('welcomeEmailActivationFailed'));
|
||||
|
||||
// reset value to actual newsletter's status
|
||||
e.target.value = response.status;
|
||||
});
|
||||
},
|
||||
renderStatus: function(newsletter) {
|
||||
let total_sent;
|
||||
|
@ -90,78 +90,110 @@ define(
|
||||
if(!this.isValid()) {
|
||||
jQuery('#mailpoet_newsletter').parsley().validate();
|
||||
} else {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: this.state.item,
|
||||
}).then((response) => {
|
||||
if (response.result === true) {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: _.extend({}, this.state.item, {
|
||||
newsletter_id: this.props.params.id,
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
this._save(e).done(() => {
|
||||
this.setState({ loading: true });
|
||||
}).done((response) => {
|
||||
this.setState({ loading: false });
|
||||
switch (response.data.type) {
|
||||
case 'notification':
|
||||
case 'welcome':
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'setStatus',
|
||||
data: {
|
||||
id: this.props.params.id,
|
||||
status: 'active'
|
||||
}
|
||||
}).done((response) => {
|
||||
// redirect to listing based on newsletter type
|
||||
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||
|
||||
if(response.result === true) {
|
||||
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||
MailPoet.Notice.success(response.data.message);
|
||||
} else {
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('newsletterSendingError').replace("%$1s", '?page=mailpoet-settings')
|
||||
);
|
||||
}
|
||||
// display success message depending on newsletter type
|
||||
if (response.data.type === 'welcome') {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('welcomeEmailActivated')
|
||||
);
|
||||
} else if (response.data.type === 'notification') {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('postNotificationActivated')
|
||||
);
|
||||
}
|
||||
}).fail(this._showError);
|
||||
default:
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id
|
||||
}
|
||||
}).done((response) => {
|
||||
// redirect to listing based on newsletter type
|
||||
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||
|
||||
if (response.data.status === 'scheduled') {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterHasBeenScheduled')
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterBeingSent')
|
||||
);
|
||||
}
|
||||
}).fail(this._showError);
|
||||
}
|
||||
}).fail(this._showError).always(() => {
|
||||
this.setState({ loading: false });
|
||||
});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleSave: function(e) {
|
||||
e.preventDefault();
|
||||
this._save(e).done(() => {
|
||||
|
||||
this._save(e).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
}).done(() => {
|
||||
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||
});
|
||||
}).fail(this._showError);
|
||||
},
|
||||
handleRedirectToDesign: function(e) {
|
||||
e.preventDefault();
|
||||
var redirectTo = e.target.href;
|
||||
|
||||
this._save(e).done(() => {
|
||||
this._save(e).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
}).done(() => {
|
||||
window.location = redirectTo;
|
||||
});
|
||||
}).fail(this._showError);
|
||||
},
|
||||
_save: function(e) {
|
||||
var data = this.state.item;
|
||||
this.setState({ loading: true });
|
||||
|
||||
// Ensure that body is JSON encoded
|
||||
if (!_.isUndefined(data.body)) {
|
||||
data.body = JSON.stringify(data.body);
|
||||
}
|
||||
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: this.state.item,
|
||||
}).done((response) => {
|
||||
data: data,
|
||||
}).always(() => {
|
||||
this.setState({ loading: false });
|
||||
|
||||
if(response.result === true) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
} else {
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
_showError: (response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
},
|
||||
handleFormChange: function(e) {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
|
@ -30,33 +30,35 @@ define(
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: template
|
||||
}).done(function(response) {
|
||||
}).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(response.result === true) {
|
||||
this.props.onImport(template);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}).done((response) => {
|
||||
this.props.onImport(response.data);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (_.size(this.refs.templateFile.files) <= 0) return false;
|
||||
|
||||
var file = _.first(this.refs.templateFile.files),
|
||||
reader = new FileReader(),
|
||||
saveTemplate = this.saveTemplate;
|
||||
var file = _.first(this.refs.templateFile.files);
|
||||
var reader = new FileReader();
|
||||
var saveTemplate = this.saveTemplate;
|
||||
|
||||
reader.onload = function(e) {
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
saveTemplate(JSON.parse(e.target.result));
|
||||
} catch (err) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('templateFileMalformedError'));
|
||||
}
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
},
|
||||
@ -97,12 +99,12 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'getAll',
|
||||
}).done(function(response) {
|
||||
}).always(() => {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(this.isMounted()) {
|
||||
|
||||
if(response.length === 0) {
|
||||
response = [
|
||||
}).done((response) => {
|
||||
if (this.isMounted()) {
|
||||
if (response.data.length === 0) {
|
||||
response.data = [
|
||||
{
|
||||
name:
|
||||
MailPoet.I18n.t('mailpoetGuideTemplateTitle'),
|
||||
@ -110,14 +112,14 @@ define(
|
||||
MailPoet.I18n.t('mailpoetGuideTemplateDescription'),
|
||||
readonly: "1"
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
this.setState({
|
||||
templates: response,
|
||||
templates: response.data,
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleSelectTemplate: function(template) {
|
||||
var body = template.body;
|
||||
@ -134,19 +136,17 @@ define(
|
||||
id: this.props.params.id,
|
||||
body: body
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
// TODO: Move this URL elsewhere
|
||||
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + this.props.params.id;
|
||||
} else {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}).done((response) => {
|
||||
// TODO: Move this URL elsewhere
|
||||
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + response.data.id;
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
handlePreviewTemplate: function(template) {
|
||||
console.log('preview template #'+template.id);
|
||||
});
|
||||
},
|
||||
handleDeleteTemplate: function(template) {
|
||||
this.setState({ loading: true });
|
||||
@ -160,10 +160,12 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'delete',
|
||||
data: template.id
|
||||
}).done(function(response) {
|
||||
data: {
|
||||
id: template.id
|
||||
}
|
||||
}).done((response) => {
|
||||
this.getTemplates();
|
||||
}.bind(this));
|
||||
});
|
||||
} else {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
@ -172,7 +174,7 @@ define(
|
||||
MailPoet.Modal.popup({
|
||||
title: template.name,
|
||||
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||
data: template,
|
||||
data: template
|
||||
});
|
||||
},
|
||||
handleTemplateImport: function() {
|
||||
@ -213,20 +215,19 @@ define(
|
||||
</div>
|
||||
|
||||
<div className="mailpoet_actions">
|
||||
<a
|
||||
className="button button-secondary"
|
||||
onClick={ this.handleShowTemplate.bind(null, template) }
|
||||
>
|
||||
{MailPoet.I18n.t('preview')}
|
||||
</a>
|
||||
|
||||
<a
|
||||
className="button button-primary"
|
||||
onClick={ this.handleSelectTemplate.bind(null, template) }
|
||||
>
|
||||
{MailPoet.I18n.t('select')}
|
||||
</a>
|
||||
|
||||
<a
|
||||
style={ { display: 'none' }}
|
||||
className="button button-secondary"
|
||||
onClick={ this.handlePreviewTemplate.bind(null, template) }
|
||||
>
|
||||
{MailPoet.I18n.t('preview')}
|
||||
</a>
|
||||
</div>
|
||||
{ (template.readonly === "1") ? false : deleteLink }
|
||||
</li>
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
3
build.sh
3
build.sh
@ -16,6 +16,9 @@ npm install
|
||||
# Production libraries.
|
||||
./composer.phar install --no-dev
|
||||
|
||||
# Translations
|
||||
./do makepot
|
||||
|
||||
# Copy release folders.
|
||||
cp -Rf lang $plugin_name
|
||||
cp -RfL assets $plugin_name
|
||||
|
264
composer.lock
generated
264
composer.lock
generated
@ -407,12 +407,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mailpoet/html2text.git",
|
||||
"reference": "6e6c48d07a542f4b4ae24341cc6ab92335c32922"
|
||||
"reference": "5ba872ab9a96c7b74fdaffbb42c78ee8dc12745a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mailpoet/html2text/zipball/6e6c48d07a542f4b4ae24341cc6ab92335c32922",
|
||||
"reference": "6e6c48d07a542f4b4ae24341cc6ab92335c32922",
|
||||
"url": "https://api.github.com/repos/mailpoet/html2text/zipball/5ba872ab9a96c7b74fdaffbb42c78ee8dc12745a",
|
||||
"reference": "5ba872ab9a96c7b74fdaffbb42c78ee8dc12745a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -452,7 +452,7 @@
|
||||
"email": "support@jevon.org",
|
||||
"source": "https://github.com/mailpoet/html2text/tree/master"
|
||||
},
|
||||
"time": "2016-06-13 18:24:35"
|
||||
"time": "2016-07-28 01:09:53"
|
||||
},
|
||||
{
|
||||
"name": "sunra/php-simple-html-dom-parser",
|
||||
@ -499,23 +499,23 @@
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v5.4.2",
|
||||
"version": "v5.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swiftmailer/swiftmailer.git",
|
||||
"reference": "d8db871a54619458a805229a057ea2af33c753e8"
|
||||
"reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/d8db871a54619458a805229a057ea2af33c753e8",
|
||||
"reference": "d8db871a54619458a805229a057ea2af33c753e8",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/4cc92842069c2bbc1f28daaaf1d2576ec4dfe153",
|
||||
"reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9.1,<0.9.4"
|
||||
"mockery/mockery": "~0.9.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -548,7 +548,7 @@
|
||||
"mail",
|
||||
"mailer"
|
||||
],
|
||||
"time": "2016-05-01 08:45:47"
|
||||
"time": "2016-07-08 11:51:25"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
@ -611,16 +611,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "8a1648d2e165ba87c759ba57d7f4c13d95fdf4a1"
|
||||
"reference": "00334ef0b9317e5d7c7641a2b56671a1df23b7a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/8a1648d2e165ba87c759ba57d7f4c13d95fdf4a1",
|
||||
"reference": "8a1648d2e165ba87c759ba57d7f4c13d95fdf4a1",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/00334ef0b9317e5d7c7641a2b56671a1df23b7a0",
|
||||
"reference": "00334ef0b9317e5d7c7641a2b56671a1df23b7a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -671,7 +671,7 @@
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:11:27"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "tburry/pquery",
|
||||
@ -848,16 +848,16 @@
|
||||
},
|
||||
{
|
||||
"name": "codeception/codeception",
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Codeception.git",
|
||||
"reference": "8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6"
|
||||
"reference": "34c268ae5872105c0c218296487650ab08e3991b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6",
|
||||
"reference": "8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/34c268ae5872105c0c218296487650ab08e3991b",
|
||||
"reference": "34c268ae5872105c0c218296487650ab08e3991b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -935,20 +935,20 @@
|
||||
"functional testing",
|
||||
"unit testing"
|
||||
],
|
||||
"time": "2016-06-29 00:59:28"
|
||||
"time": "2016-07-24 19:31:22"
|
||||
},
|
||||
{
|
||||
"name": "codeception/verify",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Verify.git",
|
||||
"reference": "d3721cfc668d96b41acbda3ecd01d3499381db64"
|
||||
"reference": "dc19c8722f3756341e5b0ce0590f09fda1d63719"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Verify/zipball/d3721cfc668d96b41acbda3ecd01d3499381db64",
|
||||
"reference": "d3721cfc668d96b41acbda3ecd01d3499381db64",
|
||||
"url": "https://api.github.com/repos/Codeception/Verify/zipball/dc19c8722f3756341e5b0ce0590f09fda1d63719",
|
||||
"reference": "dc19c8722f3756341e5b0ce0590f09fda1d63719",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
@ -968,7 +968,7 @@
|
||||
}
|
||||
],
|
||||
"description": "BDD assertion library for PHPUnit",
|
||||
"time": "2015-11-26 23:23:25"
|
||||
"time": "2016-07-13 09:34:15"
|
||||
},
|
||||
{
|
||||
"name": "codegyre/robo",
|
||||
@ -1125,27 +1125,27 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.2.0",
|
||||
"version": "6.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "d094e337976dff9d8e2424e8485872194e768662"
|
||||
"reference": "3f808fba627f2c5b69e2501217bf31af349c1427"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
|
||||
"reference": "d094e337976dff9d8e2424e8485872194e768662",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427",
|
||||
"reference": "3f808fba627f2c5b69e2501217bf31af349c1427",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/promises": "~1.0",
|
||||
"guzzlehttp/psr7": "~1.1",
|
||||
"php": ">=5.5.0"
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.3.1",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"psr/log": "~1.0"
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@ -1183,7 +1183,7 @@
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2016-03-21 20:02:09"
|
||||
"time": "2016-07-15 17:22:37"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
@ -1605,16 +1605,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "900370c81280cc0d942ffbc5912d80464eaee7e9"
|
||||
"reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/900370c81280cc0d942ffbc5912d80464eaee7e9",
|
||||
"reference": "900370c81280cc0d942ffbc5912d80464eaee7e9",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3",
|
||||
"reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1623,7 +1623,7 @@
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-token-stream": "^1.4.2",
|
||||
"sebastian/code-unit-reverse-lookup": "~1.0",
|
||||
"sebastian/environment": "^1.3.2",
|
||||
"sebastian/environment": "^1.3.2 || ^2.0",
|
||||
"sebastian/version": "~1.0|~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -1664,7 +1664,7 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2016-06-03 05:03:56"
|
||||
"time": "2016-07-26 14:39:29"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -1849,16 +1849,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "5.4.6",
|
||||
"version": "5.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59"
|
||||
"reference": "3132365e1430c091f208e120b8845d39c25f20e6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2f1fc94b77ea6418bd6a06c64a1dac0645fbce59",
|
||||
"reference": "2f1fc94b77ea6418bd6a06c64a1dac0645fbce59",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3132365e1430c091f208e120b8845d39c25f20e6",
|
||||
"reference": "3132365e1430c091f208e120b8845d39c25f20e6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1870,7 +1870,7 @@
|
||||
"myclabs/deep-copy": "~1.3",
|
||||
"php": "^5.6 || ^7.0",
|
||||
"phpspec/prophecy": "^1.3.1",
|
||||
"phpunit/php-code-coverage": "^4.0",
|
||||
"phpunit/php-code-coverage": "^4.0.1",
|
||||
"phpunit/php-file-iterator": "~1.4",
|
||||
"phpunit/php-text-template": "~1.2",
|
||||
"phpunit/php-timer": "^1.0.6",
|
||||
@ -1923,7 +1923,7 @@
|
||||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2016-06-16 06:01:15"
|
||||
"time": "2016-07-26 14:48:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit-mock-objects",
|
||||
@ -2599,16 +2599,16 @@
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
|
||||
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d"
|
||||
"reference": "4edb770cb853def6e60c93abb088ad5ac2010c83"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
|
||||
"reference": "fb72ed32f8418db5e7770be1653e62e0d6f5dd3d",
|
||||
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4edb770cb853def6e60c93abb088ad5ac2010c83",
|
||||
"reference": "4edb770cb853def6e60c93abb088ad5ac2010c83",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2673,20 +2673,20 @@
|
||||
"phpcs",
|
||||
"standards"
|
||||
],
|
||||
"time": "2016-05-30 22:24:32"
|
||||
"time": "2016-07-13 23:29:13"
|
||||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/browser-kit.git",
|
||||
"reference": "b645a9b23d6c0eeba5ac823fa87bf010db9aff22"
|
||||
"reference": "dcf41ed026b0499254385b5c88f03247b2ba010b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/b645a9b23d6c0eeba5ac823fa87bf010db9aff22",
|
||||
"reference": "b645a9b23d6c0eeba5ac823fa87bf010db9aff22",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/dcf41ed026b0499254385b5c88f03247b2ba010b",
|
||||
"reference": "dcf41ed026b0499254385b5c88f03247b2ba010b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2730,20 +2730,20 @@
|
||||
],
|
||||
"description": "Symfony BrowserKit Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-03-04 07:56:56"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05"
|
||||
"reference": "0926e69411eba491803dbafb9f1f233e2ced58d0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/a2edd59c2163c65747fc3f35d132b5a39266bd05",
|
||||
"reference": "a2edd59c2163c65747fc3f35d132b5a39266bd05",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/0926e69411eba491803dbafb9f1f233e2ced58d0",
|
||||
"reference": "0926e69411eba491803dbafb9f1f233e2ced58d0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2783,20 +2783,20 @@
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:11:27"
|
||||
"time": "2016-06-29 05:31:50"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "64a4d43b045f07055bb197650159769604cb2a92"
|
||||
"reference": "747154aa69b0f83cd02fc9aa554836dee417631a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/64a4d43b045f07055bb197650159769604cb2a92",
|
||||
"reference": "64a4d43b045f07055bb197650159769604cb2a92",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/747154aa69b0f83cd02fc9aa554836dee417631a",
|
||||
"reference": "747154aa69b0f83cd02fc9aa554836dee417631a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2843,20 +2843,20 @@
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-14 11:18:07"
|
||||
"time": "2016-06-29 07:02:31"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "c526d7b3cb4fe1673c6a34e13be2ff63f519df99"
|
||||
"reference": "2851e1932d77ce727776154d659b232d061e816a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/c526d7b3cb4fe1673c6a34e13be2ff63f519df99",
|
||||
"reference": "c526d7b3cb4fe1673c6a34e13be2ff63f519df99",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/2851e1932d77ce727776154d659b232d061e816a",
|
||||
"reference": "2851e1932d77ce727776154d659b232d061e816a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2896,20 +2896,20 @@
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:42:41"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "12aa63fd41b060d2bee9a34623d29eda70bc8fe3"
|
||||
"reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/12aa63fd41b060d2bee9a34623d29eda70bc8fe3",
|
||||
"reference": "12aa63fd41b060d2bee9a34623d29eda70bc8fe3",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0",
|
||||
"reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2952,20 +2952,20 @@
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-05-13 15:49:09"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "2a6b8713f8bdb582058cfda463527f195b066110"
|
||||
"reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110",
|
||||
"reference": "2a6b8713f8bdb582058cfda463527f195b066110",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9",
|
||||
"reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3012,20 +3012,20 @@
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:11:27"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "dee379131dceed90a429e951546b33edfe7dccbb"
|
||||
"reference": "7258ddd6f987053f21fa43d03430580ba54e6096"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/dee379131dceed90a429e951546b33edfe7dccbb",
|
||||
"reference": "dee379131dceed90a429e951546b33edfe7dccbb",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7258ddd6f987053f21fa43d03430580ba54e6096",
|
||||
"reference": "7258ddd6f987053f21fa43d03430580ba54e6096",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3061,20 +3061,20 @@
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-04-12 18:01:21"
|
||||
"time": "2016-06-29 05:31:50"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219"
|
||||
"reference": "8201978de88a9fa0923e18601bb17f1df9c721e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/40d17ed287bf51a2f884c4619ce8ff2a1c5cd219",
|
||||
"reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/8201978de88a9fa0923e18601bb17f1df9c721e7",
|
||||
"reference": "8201978de88a9fa0923e18601bb17f1df9c721e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3110,20 +3110,20 @@
|
||||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-05-13 18:06:41"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "symfony/form",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/form.git",
|
||||
"reference": "edfb109ac1ebb755ad0ce964f32e43ddbddae7bb"
|
||||
"reference": "fd24c42112a3c434a083c498b9550331bb96eaa3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/form/zipball/edfb109ac1ebb755ad0ce964f32e43ddbddae7bb",
|
||||
"reference": "edfb109ac1ebb755ad0ce964f32e43ddbddae7bb",
|
||||
"url": "https://api.github.com/repos/symfony/form/zipball/fd24c42112a3c434a083c498b9550331bb96eaa3",
|
||||
"reference": "fd24c42112a3c434a083c498b9550331bb96eaa3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3184,20 +3184,20 @@
|
||||
],
|
||||
"description": "Symfony Form Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:11:27"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "symfony/intl",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/intl.git",
|
||||
"reference": "96ce72abb3538c4256585ce278cf30ceb1e86f16"
|
||||
"reference": "330c95b92989c1a515794bb87aabfe7492148f61"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/96ce72abb3538c4256585ce278cf30ceb1e86f16",
|
||||
"reference": "96ce72abb3538c4256585ce278cf30ceb1e86f16",
|
||||
"url": "https://api.github.com/repos/symfony/intl/zipball/330c95b92989c1a515794bb87aabfe7492148f61",
|
||||
"reference": "330c95b92989c1a515794bb87aabfe7492148f61",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3259,20 +3259,20 @@
|
||||
"l10n",
|
||||
"localization"
|
||||
],
|
||||
"time": "2016-05-13 18:03:36"
|
||||
"time": "2016-06-29 05:40:45"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "ddad0be20d6f2cb266cded8c349e046731df09b8"
|
||||
"reference": "b6f982782a0624d37b5416c2c96fb99ce5ab74d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/ddad0be20d6f2cb266cded8c349e046731df09b8",
|
||||
"reference": "ddad0be20d6f2cb266cded8c349e046731df09b8",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/b6f982782a0624d37b5416c2c96fb99ce5ab74d5",
|
||||
"reference": "b6f982782a0624d37b5416c2c96fb99ce5ab74d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3313,7 +3313,7 @@
|
||||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"time": "2016-05-24 10:00:02"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-icu",
|
||||
@ -3375,16 +3375,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "6350e63ed9c232da50e00f00a7e0330f066387a2"
|
||||
"reference": "5c11a1a4d4016662eeaf0f8757958c7de069f9a0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/6350e63ed9c232da50e00f00a7e0330f066387a2",
|
||||
"reference": "6350e63ed9c232da50e00f00a7e0330f066387a2",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/5c11a1a4d4016662eeaf0f8757958c7de069f9a0",
|
||||
"reference": "5c11a1a4d4016662eeaf0f8757958c7de069f9a0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3420,20 +3420,20 @@
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:42:41"
|
||||
"time": "2016-06-29 05:42:25"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-access",
|
||||
"version": "v3.0.7",
|
||||
"version": "v3.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-access.git",
|
||||
"reference": "6a958de831366005603432ef438c22cd93fad1ef"
|
||||
"reference": "dedc1109b7c4f0454dffb00b7caa449a39a3c5dd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/6a958de831366005603432ef438c22cd93fad1ef",
|
||||
"reference": "6a958de831366005603432ef438c22cd93fad1ef",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/dedc1109b7c4f0454dffb00b7caa449a39a3c5dd",
|
||||
"reference": "dedc1109b7c4f0454dffb00b7caa449a39a3c5dd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3480,20 +3480,20 @@
|
||||
"property path",
|
||||
"reflection"
|
||||
],
|
||||
"time": "2016-05-29 09:50:11"
|
||||
"time": "2016-06-29 05:40:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/routing",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/routing.git",
|
||||
"reference": "4cbc81aa378869445fbd2d18c8c8b4a056c632a0"
|
||||
"reference": "cdd298b1d45b9882de0905856e89171bf487c6d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/4cbc81aa378869445fbd2d18c8c8b4a056c632a0",
|
||||
"reference": "4cbc81aa378869445fbd2d18c8c8b4a056c632a0",
|
||||
"url": "https://api.github.com/repos/symfony/routing/zipball/cdd298b1d45b9882de0905856e89171bf487c6d5",
|
||||
"reference": "cdd298b1d45b9882de0905856e89171bf487c6d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3555,20 +3555,20 @@
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2016-05-30 06:57:11"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "symfony/twig-bridge",
|
||||
"version": "v2.8.7",
|
||||
"version": "v2.8.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/twig-bridge.git",
|
||||
"reference": "360f3330e1df67edde1bb5d72fe5aa7c1bc74b9d"
|
||||
"reference": "b2db0187b7b805bb349ffe2714fbc846124c71ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/360f3330e1df67edde1bb5d72fe5aa7c1bc74b9d",
|
||||
"reference": "360f3330e1df67edde1bb5d72fe5aa7c1bc74b9d",
|
||||
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/b2db0187b7b805bb349ffe2714fbc846124c71ba",
|
||||
"reference": "b2db0187b7b805bb349ffe2714fbc846124c71ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3636,20 +3636,20 @@
|
||||
],
|
||||
"description": "Symfony Twig Bridge",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-06 11:11:27"
|
||||
"time": "2016-06-29 05:29:29"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v3.1.1",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623"
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/c5a7e7fc273c758b92b85dcb9c46149ccda89623",
|
||||
"reference": "c5a7e7fc273c758b92b85dcb9c46149ccda89623",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -3685,7 +3685,7 @@
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2016-06-14 11:18:07"
|
||||
"time": "2016-06-29 05:41:56"
|
||||
},
|
||||
{
|
||||
"name": "twig/extensions",
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,199 +0,0 @@
|
||||
# Copyright (C) 2015
|
||||
# This file is distributed under the same license as the package.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
|
||||
"POT-Creation-Date: 2015-07-29 16:59:53+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"PO-Revision-Date: 2015-07-29 19:00+0100\n"
|
||||
"Last-Translator: MailPoet i18n (https://www.transifex.com/organization/wysija)\n"
|
||||
"Language-Team: MailPoet i18n <https://www.transifex.com/organization/wysija>\n"
|
||||
"X-Generator: Poedit 1.7.4\n"
|
||||
"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-Basepath: ../\n"
|
||||
"X-Textdomain-Support: yes\n"
|
||||
"Language: en\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#: lib/form/renderer.php:91
|
||||
msgid "Year, month, day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:92
|
||||
msgid "Year, month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:93
|
||||
msgid "Month (January, February,...)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:94 lib/form/renderer.php:519
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:108
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:109
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:110
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:111
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:112
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:113
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:114
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:115
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:116
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:117
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:118
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:119
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:509
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:514
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:11
|
||||
msgid "MailPoet Subscription Form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:13
|
||||
msgid "Newsletter subscription form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:36
|
||||
msgid "Subscribe to our Newsletter"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:56
|
||||
msgid "Title:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:76
|
||||
msgid "Create a new form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:109
|
||||
msgid "Newsletter"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:4 views/form/editor.html:26
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:5
|
||||
msgid "Translatable string with a link %shere%s"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:6
|
||||
msgid "deleted one message"
|
||||
msgid_plural "deleted %d messages"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: views/form/editor.html:34
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:42
|
||||
msgid "This form adds subscribers to these lists:"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:44
|
||||
msgid "Choose a list"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:57
|
||||
msgid "You have to select at least 1 list"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:63
|
||||
msgid "After submit..."
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:65
|
||||
msgid "Show message"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:69
|
||||
msgid "Go to page"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:76
|
||||
msgid "Check your inbox now to confirm your subscription."
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:98
|
||||
msgid "Shortcodes"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:103
|
||||
msgid "You can easily add this form to your theme's in the"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:103
|
||||
msgid "Widgets areas"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:126
|
||||
msgid "[link_html]HTML[/link_html]"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:138
|
||||
msgid "Fields"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:144
|
||||
msgid "Add New Field"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:153
|
||||
msgid "Styles"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:157
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: views/index.html:4
|
||||
msgid "monvier"
|
||||
msgstr ""
|
Binary file not shown.
@ -1,215 +0,0 @@
|
||||
# Copyright (C) 2015
|
||||
# This file is distributed under the same license as the package.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: http://support.mailpoet.com/\n"
|
||||
"POT-Creation-Date: 2015-07-30 14:08:29+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"PO-Revision-Date: 2015-07-30 16:19+0100\n"
|
||||
"Last-Translator: MailPoet i18n (https://www.transifex.com/organization/wysija)\n"
|
||||
"Language-Team: MailPoet i18n <https://www.transifex.com/organization/wysija>\n"
|
||||
"X-Generator: Poedit 1.7.4\n"
|
||||
"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-Basepath: ../\n"
|
||||
"X-Textdomain-Support: yes\n"
|
||||
"Language: fr\n"
|
||||
"X-Poedit-SearchPath-0: .\n"
|
||||
|
||||
#: lib/config/initializer.php:259
|
||||
msgid "New form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/config/initializer.php:264
|
||||
msgid "Check your inbox or spam folder now to confirm your subscription."
|
||||
msgstr ""
|
||||
|
||||
#: lib/config/initializer.php:270 lib/config/initializer.php:275
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/config/initializer.php:280
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: lib/config/initializer.php:285
|
||||
msgid "Subscribe!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:91
|
||||
msgid "Year, month, day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:92
|
||||
msgid "Year, month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:93
|
||||
msgid "Month (January, February,...)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:94 lib/form/renderer.php:519
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:108
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:109
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:110
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:111
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:112
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:113
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:114
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:115
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:116
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:117
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:118
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:119
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:509
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/renderer.php:514
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:11
|
||||
msgid "MailPoet Subscription Form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:13
|
||||
msgid "Newsletter subscription form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:36
|
||||
msgid "Subscribe to our Newsletter"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:56
|
||||
msgid "Title:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:76
|
||||
msgid "Create a new form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/form/widget.php:109
|
||||
msgid "Newsletter"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:8
|
||||
msgid "Edit name' "
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:23
|
||||
msgid "Save"
|
||||
msgstr "Sauvegarder"
|
||||
|
||||
#: views/form/editor.html:31
|
||||
msgid "Settings"
|
||||
msgstr "Réglages"
|
||||
|
||||
#: views/form/editor.html:39
|
||||
msgid "This form adds subscribers to these lists:"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:41
|
||||
msgid "Choose a list"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:46
|
||||
msgid "You have to select at least 1 list"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:52
|
||||
msgid "After submit..."
|
||||
msgstr "Après l'inscription"
|
||||
|
||||
#: views/form/editor.html:54
|
||||
msgid "Show message"
|
||||
msgstr "Afficher le message"
|
||||
|
||||
#: views/form/editor.html:58
|
||||
msgid "Go to page"
|
||||
msgstr "Aller à la page"
|
||||
|
||||
#: views/form/editor.html:65
|
||||
msgid "Check your inbox now to confirm your subscription."
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:85
|
||||
msgid "Shortcodes"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:90
|
||||
msgid "You can easily add this form to your theme's in the %sWidgets area%s"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:96
|
||||
msgid "%sHTML%s"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:119
|
||||
msgid "Fields"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:125
|
||||
msgid "Add New Field"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:134
|
||||
msgid "Styles"
|
||||
msgstr ""
|
||||
|
||||
#: views/form/editor.html:138
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#: views/index.html:5
|
||||
msgid "Translatable string with a link %shere%s"
|
||||
msgstr ""
|
||||
|
||||
#: views/index.html:6 views/index.html:7
|
||||
msgid "deleted one message"
|
||||
msgid_plural "deleted %d messages"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
191
lib/API/API.php
191
lib/API/API.php
@ -1,90 +1,135 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
use MailPoet\Util\Helpers;
|
||||
use \MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class API {
|
||||
public $api_request;
|
||||
public $endpoint;
|
||||
public $action;
|
||||
public $data;
|
||||
const NAME = 'mailpoet_api';
|
||||
const ENDPOINT_NAMESPACE = '\MailPoet\API\Endpoints\\';
|
||||
const RESPONSE_ERROR = 404;
|
||||
|
||||
function __construct($api_data = false) {
|
||||
$api_data = ($api_data) ? $api_data : $_GET;
|
||||
$this->api_request = isset($api_data[self::NAME]);
|
||||
$this->endpoint = isset($api_data['endpoint']) ?
|
||||
Helpers::underscoreToCamelCase($api_data['endpoint']) :
|
||||
false;
|
||||
$this->action = isset($api_data['action']) ?
|
||||
Helpers::underscoreToCamelCase($api_data['action']) :
|
||||
false;
|
||||
$this->data = isset($api_data['data']) ?
|
||||
self::decodeRequestData($api_data['data']) :
|
||||
false;
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
$endpoint = self::ENDPOINT_NAMESPACE . ucfirst($this->endpoint);
|
||||
if(!$this->api_request) return;
|
||||
if(!$this->endpoint || !class_exists($endpoint)) {
|
||||
self::terminateRequest(self::RESPONSE_ERROR, __('Invalid API endpoint.'));
|
||||
}
|
||||
$this->callEndpoint(
|
||||
$endpoint,
|
||||
$this->action,
|
||||
$this->data
|
||||
// security token
|
||||
add_action(
|
||||
'admin_head',
|
||||
array($this, 'setToken')
|
||||
);
|
||||
|
||||
// Admin API (Ajax only)
|
||||
add_action(
|
||||
'wp_ajax_mailpoet',
|
||||
array($this, 'setupAdmin')
|
||||
);
|
||||
|
||||
// Public API (Ajax)
|
||||
add_action(
|
||||
'wp_ajax_nopriv_mailpoet',
|
||||
array($this, 'setupPublic')
|
||||
);
|
||||
// Public API (Post)
|
||||
add_action(
|
||||
'admin_post_nopriv_mailpoet',
|
||||
array($this, 'setupPublic')
|
||||
);
|
||||
}
|
||||
|
||||
function callEndpoint($endpoint, $action, $data) {
|
||||
if(!method_exists($endpoint, $action)) {
|
||||
self::terminateRequest(self::RESPONSE_ERROR, __('Invalid API action.'));
|
||||
function setupAdmin() {
|
||||
if($this->checkToken() === false) {
|
||||
(new ErrorResponse(
|
||||
array(
|
||||
Error::UNAUTHORIZED => __('You need to specify a valid API token.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_UNAUTHORIZED
|
||||
))->send();
|
||||
}
|
||||
call_user_func(
|
||||
array(
|
||||
$endpoint,
|
||||
$action
|
||||
),
|
||||
$data
|
||||
|
||||
if($this->checkPermissions() === false) {
|
||||
(new ErrorResponse(
|
||||
array(
|
||||
Error::FORBIDDEN => __('You do not have the required permissions.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_FORBIDDEN
|
||||
))->send();
|
||||
}
|
||||
|
||||
$this->processRoute();
|
||||
}
|
||||
|
||||
function setupPublic() {
|
||||
if($this->checkToken() === false) {
|
||||
(new ErrorResponse(
|
||||
array(
|
||||
Error::UNAUTHORIZED => __('You need to specify a valid API token.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_UNAUTHORIZED
|
||||
))->send();
|
||||
}
|
||||
|
||||
$this->processRoute();
|
||||
}
|
||||
|
||||
function processRoute() {
|
||||
$class = ucfirst($_POST['endpoint']);
|
||||
$endpoint = __NAMESPACE__ . "\\Endpoints\\" . $class;
|
||||
$method = $_POST['method'];
|
||||
|
||||
$doing_ajax = (bool)(defined('DOING_AJAX') && DOING_AJAX);
|
||||
|
||||
if($doing_ajax) {
|
||||
$data = isset($_POST['data']) ? stripslashes_deep($_POST['data']) : array();
|
||||
} else {
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
if(is_array($data) && !empty($data)) {
|
||||
// filter out reserved keywords from data
|
||||
$reserved_keywords = array(
|
||||
'token',
|
||||
'endpoint',
|
||||
'method',
|
||||
'mailpoet_redirect'
|
||||
);
|
||||
$data = array_diff_key($data, array_flip($reserved_keywords));
|
||||
}
|
||||
|
||||
try {
|
||||
$endpoint = new $endpoint();
|
||||
$response = $endpoint->$method($data);
|
||||
|
||||
// TODO: remove this condition once the API unification is complete
|
||||
if(is_object($response)) {
|
||||
$response->send();
|
||||
} else {
|
||||
// LEGACY API
|
||||
wp_send_json($response);
|
||||
}
|
||||
} catch(\Exception $e) {
|
||||
(new ErrorResponse(
|
||||
array($e->getCode() => $e->getMessage())
|
||||
))->send();
|
||||
}
|
||||
}
|
||||
|
||||
function setToken() {
|
||||
$global = '<script type="text/javascript">';
|
||||
$global .= 'var mailpoet_token = "'.Security::generateToken().'";';
|
||||
$global .= '</script>';
|
||||
echo $global;
|
||||
}
|
||||
|
||||
function checkPermissions() {
|
||||
return current_user_can('manage_options');
|
||||
}
|
||||
|
||||
function checkToken() {
|
||||
return (
|
||||
isset($_POST['token'])
|
||||
&&
|
||||
wp_verify_nonce($_POST['token'], 'mailpoet_token')
|
||||
);
|
||||
}
|
||||
|
||||
static function decodeRequestData($data) {
|
||||
$data = base64_decode($data);
|
||||
|
||||
if(is_serialized($data)) {
|
||||
$data = unserialize($data);
|
||||
}
|
||||
|
||||
if(!is_array($data)) {
|
||||
$data = array();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
static function encodeRequestData($data) {
|
||||
return rtrim(base64_encode(serialize($data)), '=');
|
||||
}
|
||||
|
||||
static function buildRequest($endpoint, $action, $data) {
|
||||
$data = self::encodeRequestData($data);
|
||||
$params = array(
|
||||
self::NAME => '',
|
||||
'endpoint' => $endpoint,
|
||||
'action' => $action,
|
||||
'data' => $data
|
||||
);
|
||||
return add_query_arg($params, home_url());
|
||||
}
|
||||
|
||||
static function terminateRequest($code, $message) {
|
||||
status_header($code, $message);
|
||||
exit;
|
||||
}
|
||||
}
|
33
lib/API/Endpoint.php
Normal file
33
lib/API/Endpoint.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
abstract class Endpoint {
|
||||
|
||||
function successResponse(
|
||||
$data = array(), $meta = array(), $status = Response::STATUS_OK
|
||||
) {
|
||||
return new SuccessResponse($data, $meta, $status);
|
||||
}
|
||||
|
||||
function errorResponse(
|
||||
$errors = array(), $meta = array(), $status = Response::STATUS_NOT_FOUND
|
||||
) {
|
||||
if(empty($errors)) {
|
||||
$errors = array(
|
||||
Error::UNKNOWN => __('An unknown error occurred.')
|
||||
);
|
||||
}
|
||||
return new ErrorResponse($errors, $meta, $status);
|
||||
}
|
||||
|
||||
function badRequest($errors = array(), $meta = array()) {
|
||||
if(empty($errors)) {
|
||||
$errors = array(
|
||||
Error::BAD_REQUEST => __('Invalid request parameters.')
|
||||
);
|
||||
}
|
||||
return new ErrorResponse($errors, $meta, Response::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
77
lib/API/Endpoints/AutomatedLatestContent.php
Normal file
77
lib/API/Endpoints/AutomatedLatestContent.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class AutomatedLatestContent extends APIEndpoint {
|
||||
public $ALC;
|
||||
|
||||
function __construct() {
|
||||
$this->ALC = new \MailPoet\Newsletter\AutomatedLatestContent();
|
||||
}
|
||||
|
||||
function getPostTypes() {
|
||||
return $this->successResponse(
|
||||
get_post_types(array(), 'objects')
|
||||
);
|
||||
}
|
||||
|
||||
function getTaxonomies($data = array()) {
|
||||
$post_type = (isset($data['postType'])) ? $data['postType'] : 'post';
|
||||
return $this->successResponse(
|
||||
get_object_taxonomies($post_type, 'objects')
|
||||
);
|
||||
}
|
||||
|
||||
function getTerms($data = array()) {
|
||||
$taxonomies = (isset($data['taxonomies'])) ? $data['taxonomies'] : array();
|
||||
$search = (isset($data['search'])) ? $data['search'] : '';
|
||||
$limit = (isset($data['limit'])) ? (int)$data['limit'] : 10;
|
||||
$page = (isset($data['page'])) ? (int)$data['page'] : 1;
|
||||
|
||||
return $this->successResponse(
|
||||
get_terms(
|
||||
$taxonomies,
|
||||
array(
|
||||
'hide_empty' => false,
|
||||
'search' => $search,
|
||||
'number' => $limit,
|
||||
'offset' => $limit * ($page - 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getPosts($data = array()) {
|
||||
return $this->successResponse(
|
||||
$this->ALC->getPosts($data)
|
||||
);
|
||||
}
|
||||
|
||||
function getTransformedPosts($data = array()) {
|
||||
$posts = $this->ALC->getPosts($data);
|
||||
return $this->successResponse(
|
||||
$this->ALC->transformPosts($data, $posts)
|
||||
);
|
||||
}
|
||||
|
||||
function getBulkTransformedPosts($data = array()) {
|
||||
$alc = new \MailPoet\Newsletter\AutomatedLatestContent();
|
||||
|
||||
$used_posts = array();
|
||||
$rendered_posts = array();
|
||||
|
||||
foreach($data['blocks'] as $block) {
|
||||
$posts = $alc->getPosts($block, $used_posts);
|
||||
$rendered_posts[] = $alc->transformPosts($block, $posts);
|
||||
|
||||
foreach($posts as $post) {
|
||||
$used_posts[] = $post->ID;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->successResponse($rendered_posts);
|
||||
}
|
||||
}
|
23
lib/API/Endpoints/Cron.php
Normal file
23
lib/API/Endpoints/Cron.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Cron extends APIEndpoint {
|
||||
function getStatus() {
|
||||
$daemon = Setting::getValue(CronHelper::DAEMON_SETTING, false);
|
||||
|
||||
if($daemon === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('Cron daemon is not running.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse($daemon);
|
||||
}
|
||||
}
|
||||
}
|
57
lib/API/Endpoints/CustomFields.php
Normal file
57
lib/API/Endpoints/CustomFields.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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 extends APIEndpoint {
|
||||
function getAll() {
|
||||
$collection = CustomField::findMany();
|
||||
$custom_fields = array_map(function($custom_field) {
|
||||
return $custom_field->asArray();
|
||||
}, $collection);
|
||||
|
||||
return $this->successResponse($custom_fields);
|
||||
}
|
||||
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
$custom_field->delete();
|
||||
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$custom_field = CustomField::createOrUpdate($data);
|
||||
$errors = $custom_field->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
CustomField::findOne($custom_field->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Models\StatisticsForms;
|
||||
use \MailPoet\Form\Renderer as FormRenderer;
|
77
lib/API/Endpoints/ImportExport.php
Normal file
77
lib/API/Endpoints/ImportExport.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?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;
|
||||
use MailPoet\Models\Segment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class ImportExport extends APIEndpoint {
|
||||
function getMailChimpLists($data) {
|
||||
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) {
|
||||
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);
|
||||
$errors = $segment->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function processImport($data) {
|
||||
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) {
|
||||
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()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
31
lib/API/Endpoints/Mailer.php
Normal file
31
lib/API/Endpoints/Mailer.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer extends APIEndpoint {
|
||||
function send($data = array()) {
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
(isset($data['mailer'])) ? $data['mailer'] : false,
|
||||
(isset($data['sender'])) ? $data['sender'] : false,
|
||||
(isset($data['reply_to'])) ? $data['reply_to'] : false
|
||||
);
|
||||
$result = $mailer->send($data['newsletter'], $data['subscriber']);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
if($result === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::BAD_REQUEST => __("The email could not be sent. Please check your settings.")
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse(null);
|
||||
}
|
||||
}
|
||||
}
|
59
lib/API/Endpoints/NewsletterTemplates.php
Normal file
59
lib/API/Endpoints/NewsletterTemplates.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Models\NewsletterTemplate;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterTemplates extends APIEndpoint {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$template = NewsletterTemplate::findOne($id);
|
||||
if($template === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This template does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
$template->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = NewsletterTemplate::findMany();
|
||||
$templates = array_map(function($item) {
|
||||
return $item->asArray();
|
||||
}, $collection);
|
||||
|
||||
return $this->successResponse($templates);
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$template = NewsletterTemplate::createOrUpdate($data);
|
||||
$errors = $template->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
NewsletterTemplate::findOne($template->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$template = NewsletterTemplate::findOne($id);
|
||||
if($template === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This template does not exist.')
|
||||
));
|
||||
} else {
|
||||
$template->delete();
|
||||
return $this->successResponse(null, array('count' => 1));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
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;
|
||||
@ -18,10 +21,7 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
class Newsletters {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
class Newsletters extends APIEndpoint {
|
||||
function get($id = false) {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter === false) {
|
||||
@ -55,10 +55,7 @@ class Newsletters {
|
||||
$errors = $newsletter->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
if(!empty($segment_ids)) {
|
||||
NewsletterSegment::where('newsletter_id', $newsletter->id)
|
||||
@ -92,32 +89,39 @@ class Newsletters {
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => true
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($newsletter->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : null;
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
$status = (isset($data['status']) ? $data['status'] : null);
|
||||
|
||||
$result = false;
|
||||
$errors = array();
|
||||
|
||||
if($newsletter !== false && $status !== null) {
|
||||
$newsletter->setStatus($status);
|
||||
|
||||
$result = (
|
||||
$newsletter->getErrors() === false && $newsletter->status === $status
|
||||
);
|
||||
if(!$status) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST => __('You need to specify a status.')
|
||||
));
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => $result,
|
||||
'status' => $newsletter->status
|
||||
);
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
}
|
||||
|
||||
$newsletter->setStatus($status);
|
||||
$errors = $newsletter->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
$newsletter->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
@ -178,11 +182,10 @@ class Newsletters {
|
||||
}
|
||||
$newsletter->body = $data['body'];
|
||||
$newsletter->save();
|
||||
$wp_user = wp_get_current_user();
|
||||
$subscriber = Subscriber::where('email', $wp_user->data->user_email)
|
||||
->findOne();
|
||||
$subscriber = ($subscriber) ? $subscriber->asArray() : $subscriber;
|
||||
$preview_url = NewsletterUrl::getViewInBrowserUrl($data, $subscriber);
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
$data, $subscriber, $queue = false, $preview = true
|
||||
);
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array('url' => $preview_url)
|
||||
@ -190,7 +193,7 @@ class Newsletters {
|
||||
}
|
||||
|
||||
function sendPreview($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : null;
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
@ -207,15 +210,14 @@ class Newsletters {
|
||||
|
||||
$newsletter = $newsletter->asArray();
|
||||
|
||||
$renderer = new Renderer($newsletter);
|
||||
$renderer = new Renderer($newsletter, $preview = true);
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$data_for_shortcodes =
|
||||
array_merge(array($newsletter['subject']), $rendered_newsletter);
|
||||
$body = implode($divider, $data_for_shortcodes);
|
||||
|
||||
$wp_user = wp_get_current_user();
|
||||
$subscriber = Subscriber::findOne($wp_user->data->user_email);
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$subscriber = ($subscriber) ? $subscriber->asArray() : false;
|
||||
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
@ -251,8 +253,10 @@ class Newsletters {
|
||||
$data
|
||||
);
|
||||
$listing_data = $listing->get();
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
|
||||
foreach($listing_data['items'] as $key => $newsletter) {
|
||||
$queue = false;
|
||||
|
||||
if($newsletter->type === Newsletter::TYPE_STANDARD) {
|
||||
$newsletter
|
||||
@ -276,8 +280,15 @@ class Newsletters {
|
||||
->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();
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Models\SegmentFilter;
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
@ -14,63 +16,41 @@ use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue {
|
||||
function add($data) {
|
||||
class SendingQueue extends APIEndpoint {
|
||||
function add($data = array()) {
|
||||
$newsletter_id = (isset($data['newsletter_id'])
|
||||
? (int)$data['newsletter_id']
|
||||
: false
|
||||
);
|
||||
|
||||
// check that the newsletter exists
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->findOne($newsletter_id);
|
||||
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
}
|
||||
|
||||
// check that the sending method has been configured properly
|
||||
try {
|
||||
new Mailer(false);
|
||||
} catch(\Exception $e) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
// check that the newsletter exists
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->findOne($data['newsletter_id']);
|
||||
|
||||
if($newsletter === false) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('This newsletter does not exist'))
|
||||
);
|
||||
}
|
||||
|
||||
if($newsletter->type === Newsletter::TYPE_WELCOME ||
|
||||
$newsletter->type === Newsletter::TYPE_NOTIFICATION
|
||||
) {
|
||||
// set newsletter status to active
|
||||
$result = $newsletter->setStatus(Newsletter::STATUS_ACTIVE);
|
||||
$errors = $result->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$message = ($newsletter->type === Newsletter::TYPE_WELCOME) ?
|
||||
__('Your welcome email has been activated') :
|
||||
__('Your post notification has been activated');
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array(
|
||||
'message' => $message
|
||||
)
|
||||
);
|
||||
}
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
// add newsletter to the sending queue
|
||||
$queue = SendingQueueModel::whereNull('status')
|
||||
->where('newsletter_id', $newsletter->id)
|
||||
->findOne();
|
||||
->where('newsletter_id', $newsletter->id)
|
||||
->findOne();
|
||||
|
||||
if(!empty($queue)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('This newsletter is already being sent'))
|
||||
);
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter is already being sent.')
|
||||
));
|
||||
}
|
||||
|
||||
$queue = SendingQueueModel::where('newsletter_id', $newsletter->id)
|
||||
@ -92,8 +72,6 @@ class SendingQueue {
|
||||
);
|
||||
$queue->subscribers = null;
|
||||
$queue->count_total = $queue->count_to_process = 0;
|
||||
|
||||
$message = __('The newsletter has been scheduled');
|
||||
} else {
|
||||
$segments = $newsletter->segments()->findArray();
|
||||
$segment_ids = array_map(function($segment) {
|
||||
@ -104,10 +82,9 @@ class SendingQueue {
|
||||
$subscribers = Helpers::arrayColumn($subscribers, 'subscriber_id');
|
||||
$subscribers = array_unique($subscribers);
|
||||
if(!count($subscribers)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('There are no subscribers'))
|
||||
);
|
||||
return $this->errorResponse(array(
|
||||
APIError::UNKNOWN => __('There are no subscribers in that list!')
|
||||
));
|
||||
}
|
||||
$queue->status = null;
|
||||
$queue->scheduled_at = null;
|
||||
@ -120,58 +97,69 @@ class SendingQueue {
|
||||
|
||||
// set newsletter status
|
||||
$newsletter->setStatus(Newsletter::STATUS_SENDING);
|
||||
|
||||
$message = __('The newsletter is being sent...');
|
||||
}
|
||||
$queue->save();
|
||||
|
||||
$errors = $queue->getErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array(
|
||||
'message' => $message
|
||||
)
|
||||
return $this->successResponse(
|
||||
$newsletter->getQueue()->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function pause($newsletter_id) {
|
||||
function pause($data = array()) {
|
||||
$newsletter_id = (isset($data['newsletter_id'])
|
||||
? (int)$data['newsletter_id']
|
||||
: false
|
||||
);
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$queue = $newsletter->getQueue();
|
||||
|
||||
if($queue !== false) {
|
||||
$result = $queue->pause();
|
||||
if($queue === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::UNKNOWN => __('This newsletter has not been sent yet.')
|
||||
));
|
||||
} else {
|
||||
$queue->pause();
|
||||
return $this->successResponse(
|
||||
$newsletter->getQueue()->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => $result
|
||||
);
|
||||
}
|
||||
|
||||
function resume($newsletter_id) {
|
||||
function resume($data = array()) {
|
||||
$newsletter_id = (isset($data['newsletter_id'])
|
||||
? (int)$data['newsletter_id']
|
||||
: false
|
||||
);
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$queue = $newsletter->getQueue();
|
||||
|
||||
if($queue !== false) {
|
||||
$result = $queue->resume();
|
||||
if($queue === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::UNKNOWN => __('This newsletter has not been sent yet.')
|
||||
));
|
||||
} else {
|
||||
$queue->resume();
|
||||
return $this->successResponse(
|
||||
$newsletter->getQueue()->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => $result
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
27
lib/API/Endpoints/Settings.php
Normal file
27
lib/API/Endpoints/Settings.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Settings extends APIEndpoint {
|
||||
function get() {
|
||||
return $this->successResponse(Setting::getAll());
|
||||
}
|
||||
|
||||
function set($settings = array()) {
|
||||
if(empty($settings)) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST =>
|
||||
__("You have not specified any settings to be saved.")
|
||||
));
|
||||
} else {
|
||||
foreach($settings as $name => $value) {
|
||||
Setting::setValue($name, $value);
|
||||
}
|
||||
return $this->successResponse(Setting::getAll());
|
||||
}
|
||||
}
|
||||
}
|
21
lib/API/Endpoints/Setup.php
Normal file
21
lib/API/Endpoints/Setup.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\Config\Activator;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Setup extends APIEndpoint {
|
||||
function reset() {
|
||||
try {
|
||||
$activator = new Activator();
|
||||
$activator->deactivate();
|
||||
$activator->activate();
|
||||
return $this->successResponse();
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Subscriber;
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use MailPoet\Statistics\Track\Clicks;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Track {
|
||||
const ENDPOINT = 'track';
|
||||
const ACTION_CLICK = 'click';
|
||||
const ACTION_OPEN = 'open';
|
||||
|
||||
static function click($data) {
|
||||
$clicks = new Clicks($data);
|
||||
$clicks->track();
|
||||
}
|
||||
|
||||
static function open($data) {
|
||||
$opens = new Opens($data);
|
||||
$opens->track();
|
||||
}
|
||||
}
|
16
lib/API/Error.php
Normal file
16
lib/API/Error.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
final class Error {
|
||||
const UNKNOWN = 'unknown';
|
||||
const BAD_REQUEST = 'bad_request';
|
||||
const UNAUTHORIZED = 'unauthorized';
|
||||
const FORBIDDEN = 'forbidden';
|
||||
const NOT_FOUND = 'not_found';
|
||||
|
||||
private function __construct() {
|
||||
|
||||
}
|
||||
}
|
34
lib/API/ErrorResponse.php
Normal file
34
lib/API/ErrorResponse.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class ErrorResponse extends Response {
|
||||
public $errors;
|
||||
|
||||
function __construct($errors = array(), $meta = array(), $status = self::STATUS_NOT_FOUND) {
|
||||
parent::__construct($status, $meta);
|
||||
$this->errors = $this->formatErrors($errors);
|
||||
}
|
||||
|
||||
function getData() {
|
||||
if(empty($this->errors)) {
|
||||
return null;
|
||||
} else {
|
||||
return array(
|
||||
'errors' => $this->errors
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function formatErrors($errors = array()) {
|
||||
$formatted_errors = array();
|
||||
foreach($errors as $error => $message) {
|
||||
$formatted_errors[] = array(
|
||||
'error' => $error,
|
||||
'message' => $message
|
||||
);
|
||||
}
|
||||
return $formatted_errors;
|
||||
}
|
||||
}
|
42
lib/API/Response.php
Normal file
42
lib/API/Response.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
abstract class Response {
|
||||
const STATUS_OK = 200;
|
||||
const STATUS_BAD_REQUEST = 400;
|
||||
const STATUS_UNAUTHORIZED = 401;
|
||||
const STATUS_FORBIDDEN = 403;
|
||||
const STATUS_NOT_FOUND = 404;
|
||||
|
||||
public $status;
|
||||
public $meta;
|
||||
|
||||
function __construct($status, $meta = array()) {
|
||||
$this->status = $status;
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
function send() {
|
||||
status_header($this->status);
|
||||
|
||||
$data = $this->getData();
|
||||
$response = array();
|
||||
|
||||
if(!empty($this->meta)) {
|
||||
$response['meta'] = $this->meta;
|
||||
}
|
||||
if($data !== null) {
|
||||
$response = array_merge($response, $data);
|
||||
}
|
||||
|
||||
if(empty($response)) {
|
||||
die();
|
||||
} else {
|
||||
wp_send_json($response);
|
||||
}
|
||||
}
|
||||
|
||||
abstract function getData();
|
||||
}
|
21
lib/API/SuccessResponse.php
Normal file
21
lib/API/SuccessResponse.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace MailPoet\API;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SuccessResponse extends Response {
|
||||
public $data;
|
||||
|
||||
function __construct($data = array(), $meta = array(), $status = self::STATUS_OK) {
|
||||
parent::__construct($status, $meta);
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
function getData() {
|
||||
if($this->data === null) return null;
|
||||
|
||||
return array(
|
||||
'data' => $this->data
|
||||
);
|
||||
}
|
||||
}
|
@ -2,14 +2,19 @@
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Models;
|
||||
use MailPoet\Cron\Supervisor;
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use MailPoet\Router;
|
||||
use MailPoet\API;
|
||||
use MailPoet\WP\Notice as WPNotice;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||
|
||||
class Initializer {
|
||||
|
||||
protected $plugin_initialized = false;
|
||||
|
||||
function __construct($params = array(
|
||||
'file' => '',
|
||||
'version' => '1.0.0'
|
||||
@ -28,30 +33,6 @@ class Initializer {
|
||||
add_action('widgets_init', array($this, 'setupWidget'));
|
||||
}
|
||||
|
||||
function setup() {
|
||||
try {
|
||||
$this->setupRenderer();
|
||||
$this->setupLocalizer();
|
||||
$this->setupMenu();
|
||||
$this->setupAnalytics();
|
||||
$this->setupChangelog();
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupImages();
|
||||
$this->runQueueSupervisor();
|
||||
} catch(\Exception $e) {
|
||||
// if anything goes wrong during init
|
||||
// automatically deactivate the plugin
|
||||
deactivate_plugins(Env::$file);
|
||||
}
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
$this->setupRouter();
|
||||
$this->setupAPI();
|
||||
$this->setupPages();
|
||||
}
|
||||
|
||||
function setupDB() {
|
||||
\ORM::configure(Env::$db_source_name);
|
||||
\ORM::configure('username', Env::$db_username);
|
||||
@ -116,6 +97,51 @@ class Initializer {
|
||||
$populator->up();
|
||||
}
|
||||
|
||||
function setup() {
|
||||
try {
|
||||
$this->setupRenderer();
|
||||
$this->setupLocalizer();
|
||||
$this->setupMenu();
|
||||
$this->setupAnalytics();
|
||||
$this->setupChangelog();
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupImages();
|
||||
$this->setupCronTrigger();
|
||||
|
||||
$this->plugin_initialized = true;
|
||||
} catch(\Exception $e) {
|
||||
$this->handleFailedInitialization($e);
|
||||
}
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
if(!$this->plugin_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->setupAPI();
|
||||
$this->setupFrontRouter();
|
||||
$this->setupPages();
|
||||
} catch(\Exception $e) {
|
||||
$this->handleFailedInitialization($e);
|
||||
}
|
||||
}
|
||||
|
||||
function setupWidget() {
|
||||
if(!$this->plugin_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$widget = new Widget($this->renderer);
|
||||
$widget->init();
|
||||
} catch(\Exception $e) {
|
||||
$this->handleFailedInitialization($e);
|
||||
}
|
||||
}
|
||||
|
||||
function setupRenderer() {
|
||||
$renderer = new Renderer();
|
||||
$this->renderer = $renderer->init();
|
||||
@ -131,19 +157,9 @@ class Initializer {
|
||||
$menu->init();
|
||||
}
|
||||
|
||||
function setupRouter() {
|
||||
$router = new Router\Router();
|
||||
$router->init();
|
||||
}
|
||||
|
||||
function setupWidget() {
|
||||
$widget = new Widget($this->renderer);
|
||||
$widget->init();
|
||||
}
|
||||
|
||||
function setupAnalytics() {
|
||||
$widget = new Analytics();
|
||||
$widget->init();
|
||||
$analytics = new Analytics();
|
||||
$analytics->init();
|
||||
}
|
||||
|
||||
function setupChangelog() {
|
||||
@ -167,21 +183,25 @@ class Initializer {
|
||||
}
|
||||
|
||||
function setupAPI() {
|
||||
$API = new \MailPoet\API\API();
|
||||
$API->init();
|
||||
$api = new API\API();
|
||||
$api->init();
|
||||
}
|
||||
|
||||
function runQueueSupervisor() {
|
||||
if(php_sapi_name() === 'cli') return;
|
||||
try {
|
||||
$supervisor = new Supervisor();
|
||||
$supervisor->checkDaemon();
|
||||
} catch(\Exception $e) {
|
||||
// Prevent Daemon exceptions from breaking out and breaking UI
|
||||
}
|
||||
function setupFrontRouter() {
|
||||
$router = new Router\Front();
|
||||
$router->init();
|
||||
}
|
||||
|
||||
function setupCronTrigger() {
|
||||
$cron_trigger = new CronTrigger();
|
||||
$cron_trigger->init();
|
||||
}
|
||||
|
||||
function setupImages() {
|
||||
add_image_size('mailpoet_newsletter_max', 1320);
|
||||
}
|
||||
|
||||
function handleFailedInitialization($message) {
|
||||
return WPNotice::displayError($message);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use MailPoet\Form\Block;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Models\CustomField;
|
||||
@ -105,8 +106,8 @@ class Menu {
|
||||
|
||||
$segments_page = add_submenu_page(
|
||||
$main_page_slug,
|
||||
$this->setPageTitle(__('Segments')),
|
||||
__('Segments'),
|
||||
$this->setPageTitle(__('Lists')),
|
||||
__('Lists'),
|
||||
'manage_options',
|
||||
'mailpoet-segments',
|
||||
array($this, 'segments')
|
||||
@ -169,8 +170,8 @@ class Menu {
|
||||
|
||||
add_submenu_page(
|
||||
true,
|
||||
$this->setPageTitle(__('Form')),
|
||||
__('Form editor'),
|
||||
$this->setPageTitle(__('Form Editor')),
|
||||
__('Form Editor'),
|
||||
'manage_options',
|
||||
'mailpoet-form-editor',
|
||||
array($this, 'formEditor')
|
||||
@ -255,6 +256,7 @@ class Menu {
|
||||
$data = array(
|
||||
'settings' => $settings,
|
||||
'segments' => Segment::getPublic()->findArray(),
|
||||
'cron_trigger' => CronTrigger::getAvailableMethods(),
|
||||
'pages' => Pages::getAll(),
|
||||
'flags' => $flags,
|
||||
'current_user' => wp_get_current_user(),
|
||||
@ -377,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);
|
||||
}
|
||||
|
||||
@ -433,4 +440,4 @@ class Menu {
|
||||
? (int)$listing_per_page
|
||||
: Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,15 @@
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Config\PopulatorData\Templates\FranksRoastHouseTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\BlankTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\WelcomeTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlankTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank12Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank121Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank13Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank12Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\SimpleText;
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Segments\WP;
|
||||
use \MailPoet\Models\Setting;
|
||||
@ -69,10 +75,10 @@ class Populator {
|
||||
private function createDefaultSettings() {
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
if(!Setting::getValue('task_scheduler')) {
|
||||
if(!Setting::getValue(CronTrigger::SETTING_NAME)) {
|
||||
// disable task scheduler (cron) be default
|
||||
Setting::setValue('task_scheduler', array(
|
||||
'method' => 'WordPress'
|
||||
Setting::setValue(CronTrigger::SETTING_NAME, array(
|
||||
'method' => CronTrigger::DEFAULT_METHOD
|
||||
));
|
||||
}
|
||||
|
||||
@ -180,9 +186,14 @@ class Populator {
|
||||
private function newsletterTemplates() {
|
||||
return array(
|
||||
(new FranksRoastHouseTemplate(Env::$assets_url))->get(),
|
||||
(new BlankTemplate(Env::$assets_url))->get(),
|
||||
(new WelcomeTemplate(Env::$assets_url))->get(),
|
||||
(new PostNotificationsBlankTemplate(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank1Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank12Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank121Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank13Column(Env::$assets_url))->get(),
|
||||
(new PostNotificationsBlank1Column(Env::$assets_url))->get(),
|
||||
(new WelcomeBlank1Column(Env::$assets_url))->get(),
|
||||
(new WelcomeBlank12Column(Env::$assets_url))->get(),
|
||||
(new SimpleText(Env::$assets_url))->get(),
|
||||
);
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
378
lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php
Normal file
378
lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php
Normal file
File diff suppressed because one or more lines are too long
318
lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php
Normal file
318
lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php
Normal file
File diff suppressed because one or more lines are too long
341
lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php
Normal file
341
lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php
Normal file
File diff suppressed because one or more lines are too long
256
lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php
Normal file
256
lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
200
lib/Config/PopulatorData/Templates/SimpleText.php
Normal file
200
lib/Config/PopulatorData/Templates/SimpleText.php
Normal file
File diff suppressed because one or more lines are too long
346
lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php
Normal file
346
lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php
Normal file
File diff suppressed because one or more lines are too long
255
lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php
Normal file
255
lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -67,17 +67,16 @@ class Shortcodes {
|
||||
}
|
||||
|
||||
function getArchive($params) {
|
||||
$segment_ids = array();
|
||||
if(!empty($params['segments'])) {
|
||||
$segment_ids = array_map(function($segment_id) {
|
||||
return (int)trim($segment_id);
|
||||
}, explode(',', $params['segments']));
|
||||
}
|
||||
|
||||
$newsletters = array();
|
||||
$html = '';
|
||||
|
||||
// TODO: needs more advanced newsletters in order to finish
|
||||
$newsletters = Newsletter::limit(10)->orderByDesc('created_at')->findMany();
|
||||
$newsletters = Newsletter::getArchives($segment_ids);
|
||||
|
||||
if(empty($newsletters)) {
|
||||
return apply_filters(
|
||||
@ -109,7 +108,7 @@ class Shortcodes {
|
||||
function renderArchiveDate($newsletter) {
|
||||
return date_i18n(
|
||||
get_option('date_format'),
|
||||
strtotime($newsletter->created_at)
|
||||
strtotime($newsletter->processed_at)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\API\API;
|
||||
use MailPoet\API\Endpoints\Queue as QueueAPI;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Router\Endpoints\Queue as QueueEndpoint;
|
||||
use MailPoet\Router\Front as FrontRouter;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
@ -12,6 +12,7 @@ class CronHelper {
|
||||
const DAEMON_EXECUTION_LIMIT = 20;
|
||||
const DAEMON_EXECUTION_TIMEOUT = 35;
|
||||
const DAEMON_REQUEST_TIMEOUT = 2;
|
||||
const DAEMON_SETTING = 'cron_daemon';
|
||||
|
||||
static function createDaemon($token) {
|
||||
$daemon = array(
|
||||
@ -22,30 +23,46 @@ class CronHelper {
|
||||
return $daemon;
|
||||
}
|
||||
|
||||
static function restartDaemon($token) {
|
||||
return self::createDaemon($token);
|
||||
}
|
||||
|
||||
static function getDaemon() {
|
||||
return Setting::getValue('cron_daemon');
|
||||
return Setting::getValue(self::DAEMON_SETTING);
|
||||
}
|
||||
|
||||
static function saveDaemon($daemon) {
|
||||
$daemon['updated_at'] = time();
|
||||
return Setting::setValue(
|
||||
'cron_daemon',
|
||||
self::DAEMON_SETTING,
|
||||
$daemon
|
||||
);
|
||||
}
|
||||
|
||||
static function stopDaemon() {
|
||||
$daemon = self::getDaemon();
|
||||
$daemon['status'] = Daemon::STATUS_STOPPED;
|
||||
return self::saveDaemon($daemon);
|
||||
}
|
||||
|
||||
static function deleteDaemon() {
|
||||
return Setting::deleteValue(self::DAEMON_SETTING);
|
||||
}
|
||||
|
||||
static function createToken() {
|
||||
return Security::generateRandomString();
|
||||
}
|
||||
|
||||
static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) {
|
||||
$data = array('token' => $token);
|
||||
$url = API::buildRequest(
|
||||
QueueAPI::ENDPOINT,
|
||||
QueueAPI::ACTION_RUN,
|
||||
$url = FrontRouter::buildRequest(
|
||||
QueueEndpoint::ENDPOINT,
|
||||
QueueEndpoint::ACTION_RUN,
|
||||
$data
|
||||
);
|
||||
$args = array(
|
||||
'blocking' => false,
|
||||
'sslverify' => false,
|
||||
'timeout' => $timeout,
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||
);
|
||||
@ -70,7 +87,7 @@ class CronHelper {
|
||||
throw new \Exception(__('Site URL is unreachable.'));
|
||||
}
|
||||
|
||||
static function checkExecutionTimer($timer) {
|
||||
static function enforceExecutionLimit($timer) {
|
||||
$elapsed_time = microtime(true) - $timer;
|
||||
if($elapsed_time >= self::DAEMON_EXECUTION_LIMIT) {
|
||||
throw new \Exception(__('Maximum execution time has been reached.'));
|
||||
|
41
lib/Cron/CronTrigger.php
Normal file
41
lib/Cron/CronTrigger.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CronTrigger {
|
||||
public $current_method;
|
||||
public static $available_methods = array(
|
||||
'mailpoet' => 'MailPoet',
|
||||
'wordpress' => 'WordPress'
|
||||
);
|
||||
const DEFAULT_METHOD = 'WordPress';
|
||||
const SETTING_NAME = 'cron_trigger';
|
||||
|
||||
function __construct() {
|
||||
$this->current_method = self::getCurrentMethod();
|
||||
}
|
||||
|
||||
function init() {
|
||||
try {
|
||||
// configure cron trigger only outside of cli environment
|
||||
if(php_sapi_name() === 'cli') return;
|
||||
$trigger_class = __NAMESPACE__ . '\Triggers\\' . $this->current_method;
|
||||
return (class_exists($trigger_class)) ?
|
||||
$trigger_class::run() :
|
||||
false;
|
||||
} catch(\Exception $e) {
|
||||
// cron exceptions should not prevent the rest of the site from loading
|
||||
}
|
||||
}
|
||||
|
||||
static function getAvailableMethods() {
|
||||
return self::$available_methods;
|
||||
}
|
||||
|
||||
static function getCurrentMethod() {
|
||||
return Setting::getValue(self::SETTING_NAME . '.method');
|
||||
}
|
||||
}
|
@ -78,15 +78,16 @@ class Daemon {
|
||||
}
|
||||
}
|
||||
|
||||
function abortWithError($message) {
|
||||
exit('[mailpoet_cron_error:' . base64_encode($message) . ']');
|
||||
}
|
||||
|
||||
function callSelf() {
|
||||
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
|
||||
$this->terminateRequest();
|
||||
}
|
||||
|
||||
function abortWithError($message) {
|
||||
status_header(404, $message);
|
||||
exit;
|
||||
}
|
||||
|
||||
function terminateRequest() {
|
||||
exit;
|
||||
}
|
||||
|
@ -6,87 +6,35 @@ if(!defined('ABSPATH')) exit;
|
||||
class Supervisor {
|
||||
public $daemon;
|
||||
public $token;
|
||||
public $force_run;
|
||||
|
||||
function __construct($force_run = false) {
|
||||
$this->daemon = CronHelper::getDaemon();
|
||||
function __construct() {
|
||||
$this->token = CronHelper::createToken();
|
||||
$this->force_run = $force_run;
|
||||
$this->daemon = $this->getDaemon();
|
||||
}
|
||||
|
||||
function checkDaemon() {
|
||||
$daemon = $this->daemon;
|
||||
if(!$daemon) {
|
||||
$daemon = CronHelper::createDaemon($this->token);
|
||||
return $this->runDaemon($daemon);
|
||||
$execution_timeout_exceeded =
|
||||
(time() - (int)$daemon['updated_at']) > CronHelper::DAEMON_EXECUTION_TIMEOUT;
|
||||
if($execution_timeout_exceeded) {
|
||||
CronHelper::restartDaemon($this->token);
|
||||
return $this->runDaemon();
|
||||
}
|
||||
// if the daemon is stopped, return its status and do nothing
|
||||
if(!$this->force_run &&
|
||||
isset($daemon['status']) &&
|
||||
$daemon['status'] === Daemon::STATUS_STOPPED
|
||||
) {
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
}
|
||||
$elapsed_time = time() - (int)$daemon['updated_at'];
|
||||
// if it's been less than 40 seconds since last execution and we're not
|
||||
// force-running the daemon, return its status and do nothing
|
||||
if($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT && !$this->force_run) {
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
} elseif($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT &&
|
||||
$this->force_run &&
|
||||
in_array($daemon['status'], array(
|
||||
Daemon::STATUS_STOPPING,
|
||||
Daemon::STATUS_STARTING
|
||||
))
|
||||
) {
|
||||
// if it's been less than 40 seconds since last execution, we are
|
||||
// force-running the daemon and it's either being started or stopped,
|
||||
// return its status and do nothing
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
}
|
||||
// re-create (restart) daemon
|
||||
CronHelper::createDaemon($this->token);
|
||||
return $this->runDaemon();
|
||||
return $daemon;
|
||||
}
|
||||
|
||||
function runDaemon() {
|
||||
$request = CronHelper::accessDaemon($this->token);
|
||||
preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
|
||||
CronHelper::accessDaemon($this->token);
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!empty($status) || !$daemon) {
|
||||
if(!$daemon) {
|
||||
$message = __('Daemon failed to run.');
|
||||
} else {
|
||||
list(, $message) = explode(':', $status[0]);
|
||||
$message = base64_decode($message);
|
||||
}
|
||||
return $this->formatResultMessage(
|
||||
false,
|
||||
$message
|
||||
);
|
||||
}
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
return $daemon;
|
||||
}
|
||||
|
||||
private function formatDaemonStatusMessage($status) {
|
||||
return $this->formatResultMessage(
|
||||
true,
|
||||
sprintf(
|
||||
__('Daemon is currently %s.'),
|
||||
__($status)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function formatResultMessage($result, $message) {
|
||||
$formattedResult = array(
|
||||
'result' => $result
|
||||
);
|
||||
if(!$result) {
|
||||
$formattedResult['errors'] = array($message);
|
||||
} else {
|
||||
$formattedResult['message'] = $message;
|
||||
function getDaemon() {
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!$daemon) {
|
||||
CronHelper::createDaemon($this->token);
|
||||
return $this->runDaemon();
|
||||
}
|
||||
return $formattedResult;
|
||||
return $daemon;
|
||||
}
|
||||
}
|
||||
}
|
13
lib/Cron/Triggers/MailPoet.php
Normal file
13
lib/Cron/Triggers/MailPoet.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Triggers;
|
||||
|
||||
use MailPoet\Cron\Supervisor;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MailPoet {
|
||||
static function run() {
|
||||
$supervisor = new Supervisor();
|
||||
return $supervisor->checkDaemon();
|
||||
}
|
||||
}
|
31
lib/Cron/Triggers/WordPress.php
Normal file
31
lib/Cron/Triggers/WordPress.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Triggers;
|
||||
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
||||
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
||||
use MailPoet\Mailer\MailerLog;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class WordPress {
|
||||
static function run() {
|
||||
return (self::checkExecutionRequirements()) ?
|
||||
MailPoet::run() :
|
||||
self::cleanup();
|
||||
}
|
||||
|
||||
static function checkExecutionRequirements() {
|
||||
$scheduled_queues = SchedulerWorker::getScheduledQueues();
|
||||
$running_queues = SendingQueueWorker::getRunningQueues();
|
||||
$sending_limit_reached = MailerLog::isSendingLimitReached();
|
||||
return (($scheduled_queues || $running_queues) && !$sending_limit_reached);
|
||||
}
|
||||
|
||||
static function cleanup() {
|
||||
$cron_daemon = CronHelper::getDaemon();
|
||||
if($cron_daemon) {
|
||||
CronHelper::deleteDaemon();
|
||||
}
|
||||
}
|
||||
}
|
@ -20,13 +20,12 @@ class Scheduler {
|
||||
|
||||
function __construct($timer = false) {
|
||||
$this->timer = ($timer) ? $timer : microtime(true);
|
||||
CronHelper::checkExecutionTimer($this->timer);
|
||||
// abort if execution limit is reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
|
||||
function process() {
|
||||
$scheduled_queues = SendingQueue::where('status', 'scheduled')
|
||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->findMany();
|
||||
$scheduled_queues = self::getScheduledQueues();
|
||||
if(!count($scheduled_queues)) return;
|
||||
foreach($scheduled_queues as $i => $queue) {
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
@ -40,7 +39,7 @@ class Scheduler {
|
||||
} elseif($newsletter->type === 'standard') {
|
||||
$this->processScheduledStandardNewsletter($newsletter, $queue);
|
||||
}
|
||||
CronHelper::checkExecutionTimer($this->timer);
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,4 +184,10 @@ class Scheduler {
|
||||
$notification_history :
|
||||
false;
|
||||
}
|
||||
|
||||
static function getScheduledQueues() {
|
||||
return SendingQueue::where('status', 'scheduled')
|
||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
->findMany();
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
|
||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
|
||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Subscribers as SubscribersTask;
|
||||
use MailPoet\Models\Newsletter as NewsletterModel;
|
||||
use MailPoet\Mailer\MailerLog;
|
||||
use MailPoet\Models\SendingQueue as SendingQueueModel;
|
||||
use MailPoet\Models\StatisticsNewsletters as StatisticsNewslettersModel;
|
||||
use MailPoet\Models\Subscriber as SubscriberModel;
|
||||
@ -23,11 +23,14 @@ class SendingQueue {
|
||||
$this->mailer_task = new MailerTask();
|
||||
$this->newsletter_task = new NewsletterTask();
|
||||
$this->timer = ($timer) ? $timer : microtime(true);
|
||||
// abort if execution or sending limit are reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
|
||||
function process() {
|
||||
$this->mailer_task->checkSendingLimit();
|
||||
foreach($this->getQueues() as $queue) {
|
||||
foreach(self::getRunningQueues() as $queue) {
|
||||
// abort if sending limit is reached
|
||||
MailerLog::enforceSendingLimit();
|
||||
// get and pre-process newsletter (render, replace shortcodes/links, etc.)
|
||||
$newsletter = $this->newsletter_task->getAndPreProcess($queue->asArray());
|
||||
if(!$newsletter) {
|
||||
@ -67,6 +70,11 @@ class SendingQueue {
|
||||
$newsletter,
|
||||
$found_subscribers
|
||||
);
|
||||
if($queue->status === SendingQueueModel::STATUS_COMPLETED) {
|
||||
$this->newsletter_task->markNewsletterAsSent($queue->newsletter_id);
|
||||
}
|
||||
// abort if execution limit is reached
|
||||
CronHelper::enforceExecutionLimit($this->timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,6 +149,7 @@ class SendingQueue {
|
||||
$prepared_subscribers_ids,
|
||||
$queue->subscribers
|
||||
);
|
||||
$queue = $this->updateQueue($queue);
|
||||
} else {
|
||||
// update processed/to process list
|
||||
$queue->subscribers = SubscribersTask::updateProcessedList(
|
||||
@ -149,19 +158,18 @@ class SendingQueue {
|
||||
);
|
||||
// log statistics
|
||||
StatisticsNewslettersModel::createMultiple($statistics);
|
||||
// keep track of sent items
|
||||
$this->mailer_task->updateMailerLog();
|
||||
$subscribers_to_process_count = count($queue->subscribers['to_process']);
|
||||
// update the sent count
|
||||
$this->mailer_task->updateSentCount();
|
||||
$queue = $this->updateQueue($queue);
|
||||
// enforce sending limit if there are still subscribers left to process
|
||||
if($queue->count_to_process) {
|
||||
MailerLog::enforceSendingLimit();
|
||||
}
|
||||
}
|
||||
$queue = $this->updateQueue($queue);
|
||||
if($subscribers_to_process_count) {
|
||||
$this->mailer_task->checkSendingLimit();
|
||||
}
|
||||
CronHelper::checkExecutionTimer($this->timer);
|
||||
return $queue;
|
||||
}
|
||||
|
||||
function getQueues() {
|
||||
static function getRunningQueues() {
|
||||
return SendingQueueModel::orderByDesc('priority')
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
@ -178,13 +186,6 @@ class SendingQueue {
|
||||
if(!$queue->count_to_process) {
|
||||
$queue->processed_at = current_time('mysql');
|
||||
$queue->status = SendingQueueModel::STATUS_COMPLETED;
|
||||
// if it's a standard or post notificaiton newsletter, update its status to sent
|
||||
$newsletter = NewsletterModel::findOne($queue->newsletter_id);
|
||||
if($newsletter->type === NewsletterModel::TYPE_STANDARD ||
|
||||
$newsletter->type === NewsletterModel::TYPE_NOTIFICATION_HISTORY
|
||||
) {
|
||||
$newsletter->setStatus(NewsletterModel::STATUS_SENT);
|
||||
}
|
||||
}
|
||||
return $queue->save();
|
||||
}
|
||||
|
@ -2,18 +2,14 @@
|
||||
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
||||
|
||||
use MailPoet\Mailer\Mailer as MailerFactory;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Mailer\MailerLog;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
public $mta_config;
|
||||
public $mta_log;
|
||||
public $mailer;
|
||||
|
||||
function __construct() {
|
||||
$this->mta_config = $this->getMailerConfig();
|
||||
$this->mta_log = $this->getMailerLog();
|
||||
$this->mailer = $this->configureMailer();
|
||||
}
|
||||
|
||||
@ -40,33 +36,16 @@ class Mailer {
|
||||
return $this->mailer;
|
||||
}
|
||||
|
||||
function getMailerConfig() {
|
||||
$mta_config = Setting::getValue('mta');
|
||||
if(!$mta_config) {
|
||||
throw new \Exception(__('Mailer is not configured'));
|
||||
}
|
||||
return $mta_config;
|
||||
}
|
||||
|
||||
function getMailerLog() {
|
||||
$mta_log = Setting::getValue('mta_log');
|
||||
if(!$mta_log) {
|
||||
$mta_log = array(
|
||||
'sent' => 0,
|
||||
'started' => time()
|
||||
);
|
||||
Setting::setValue('mta_log', $mta_log);
|
||||
}
|
||||
return $mta_log;
|
||||
return MailerLog::getMailerLog();
|
||||
}
|
||||
|
||||
function updateMailerLog() {
|
||||
$this->mta_log['sent']++;
|
||||
Setting::setValue('mta_log', $this->mta_log);
|
||||
function updateSentCount() {
|
||||
return MailerLog::incrementSentCount();
|
||||
}
|
||||
|
||||
function getProcessingMethod() {
|
||||
return ($this->mta_config['method'] === 'MailPoet') ?
|
||||
return ($this->mailer->mailer_config['method'] === MailerFactory::METHOD_MAILPOET) ?
|
||||
'bulk' :
|
||||
'individual';
|
||||
}
|
||||
@ -81,23 +60,4 @@ class Mailer {
|
||||
$prepared_subscribers
|
||||
);
|
||||
}
|
||||
|
||||
function checkSendingLimit() {
|
||||
if($this->mta_config['method'] === 'MailPoet') return;
|
||||
$frequency_interval = (int)$this->mta_config['frequency']['interval'] * 60;
|
||||
$frequency_limit = (int)$this->mta_config['frequency']['emails'];
|
||||
$elapsed_time = time() - (int)$this->mta_log['started'];
|
||||
if($this->mta_log['sent'] === $frequency_limit &&
|
||||
$elapsed_time <= $frequency_interval
|
||||
) {
|
||||
throw new \Exception(__('Sending frequency limit has been reached'));
|
||||
}
|
||||
if($elapsed_time > $frequency_interval) {
|
||||
$this->mta_log = array(
|
||||
'sent' => 0,
|
||||
'started' => time()
|
||||
);
|
||||
Setting::setValue('mta_log', $this->mta_log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -62,7 +62,7 @@ class Newsletter {
|
||||
return $newsletter;
|
||||
}
|
||||
|
||||
function render($newsletter) {
|
||||
function render(array $newsletter) {
|
||||
$renderer = new Renderer($newsletter);
|
||||
$newsletter['rendered_body'] = $renderer->render();
|
||||
return $newsletter;
|
||||
@ -88,7 +88,6 @@ class Newsletter {
|
||||
);
|
||||
if($this->tracking_enabled) {
|
||||
$prepared_newsletter = NewsletterLinks::replaceSubscriberData(
|
||||
$newsletter['id'],
|
||||
$subscriber['id'],
|
||||
$queue['id'],
|
||||
$prepared_newsletter
|
||||
@ -103,4 +102,12 @@ class Newsletter {
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function markNewsletterAsSent($newsletter_id) {
|
||||
$newsletter = NewsletterModel::findOne($newsletter_id);
|
||||
// if it's a standard newsletter, update its status
|
||||
if($newsletter->type === NewsletterModel::TYPE_STANDARD) {
|
||||
$newsletter->setStatus(NewsletterModel::STATUS_SENT);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Newsletter as NewsletterModel;
|
||||
use MailPoet\Models\NewsletterPost;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
@ -19,7 +19,7 @@ class Posts {
|
||||
if(!count($matched_posts_ids)) {
|
||||
return $newsletter;
|
||||
}
|
||||
$newsletter_id = ($newsletter['type'] === Newsletter::TYPE_NOTIFICATION_HISTORY) ?
|
||||
$newsletter_id = ($newsletter['type'] === NewsletterModel::TYPE_NOTIFICATION_HISTORY) ?
|
||||
$newsletter['parent_id'] :
|
||||
$newsletter['id'];
|
||||
foreach($matched_posts_ids as $post_id) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -8,13 +8,22 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
public $mailer;
|
||||
public $mailer_config;
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $mailer_instance;
|
||||
const MAILER_CONFIG = 'mta';
|
||||
const SENDING_LIMIT_INTERVAL_MULTIPLIER = 60;
|
||||
const METHOD_MAILPOET = 'MailPoet';
|
||||
const METHOD_MAILGUN = 'MailGun';
|
||||
const METHOD_ELASTICEMAIL = 'ElasticEmail';
|
||||
const METHOD_AMAZONSES = 'AmazonSES';
|
||||
const METHOD_SENDGRID = 'SendGrid';
|
||||
const METHOD_PHPMAIL = 'PHPMail';
|
||||
const METHOD_SMTP = 'SMTP';
|
||||
|
||||
function __construct($mailer = false, $sender = false, $reply_to = false) {
|
||||
$this->mailer = $this->getMailer($mailer);
|
||||
$this->mailer_config = self::getMailerConfig($mailer);
|
||||
$this->sender = $this->getSender($sender);
|
||||
$this->reply_to = $this->getReplyTo($reply_to);
|
||||
$this->mailer_instance = $this->buildMailer();
|
||||
@ -26,59 +35,59 @@ class Mailer {
|
||||
}
|
||||
|
||||
function buildMailer() {
|
||||
switch($this->mailer['method']) {
|
||||
case 'AmazonSES':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['region'],
|
||||
$this->mailer['access_key'],
|
||||
$this->mailer['secret_key'],
|
||||
switch($this->mailer_config['method']) {
|
||||
case self::METHOD_AMAZONSES:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['region'],
|
||||
$this->mailer_config['access_key'],
|
||||
$this->mailer_config['secret_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
case self::METHOD_ELASTICEMAIL:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['domain'],
|
||||
$this->mailer['api_key'],
|
||||
case self::METHOD_MAILGUN:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['domain'],
|
||||
$this->mailer_config['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['mailpoet_api_key'],
|
||||
case self::METHOD_MAILPOET:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['mailpoet_api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
case self::METHOD_SENDGRID:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'PHPMail':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
case self::METHOD_PHPMAIL:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'SMTP':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['host'],
|
||||
$this->mailer['port'],
|
||||
$this->mailer['authentication'],
|
||||
$this->mailer['login'],
|
||||
$this->mailer['password'],
|
||||
$this->mailer['encryption'],
|
||||
case self::METHOD_SMTP:
|
||||
$mailer_instance = new $this->mailer_config['class'](
|
||||
$this->mailer_config['host'],
|
||||
$this->mailer_config['port'],
|
||||
$this->mailer_config['authentication'],
|
||||
$this->mailer_config['login'],
|
||||
$this->mailer_config['password'],
|
||||
$this->mailer_config['encryption'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
@ -89,12 +98,20 @@ class Mailer {
|
||||
return $mailer_instance;
|
||||
}
|
||||
|
||||
function getMailer($mailer = false) {
|
||||
static function getMailerConfig($mailer = false) {
|
||||
if(!$mailer) {
|
||||
$mailer = Setting::getValue('mta');
|
||||
$mailer = Setting::getValue(self::MAILER_CONFIG);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured'));
|
||||
}
|
||||
if(empty($mailer['frequency'])) {
|
||||
$default_settings = Setting::getDefaults();
|
||||
$mailer['frequency'] = $default_settings['mta']['frequency'];
|
||||
}
|
||||
// add additional variables to the mailer object
|
||||
$mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method'];
|
||||
$mailer['frequency_interval'] =
|
||||
(int)$mailer['frequency']['interval'] * self::SENDING_LIMIT_INTERVAL_MULTIPLIER;
|
||||
$mailer['frequency_limit'] = (int)$mailer['frequency']['emails'];
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
@ -140,4 +157,4 @@ class Mailer {
|
||||
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
|
||||
return $subscriber;
|
||||
}
|
||||
}
|
||||
}
|
60
lib/Mailer/MailerLog.php
Normal file
60
lib/Mailer/MailerLog.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class MailerLog {
|
||||
const SETTING_NAME = 'mta_log';
|
||||
|
||||
static function getMailerLog() {
|
||||
$mailer_log = Setting::getValue(self::SETTING_NAME);
|
||||
if(!$mailer_log) {
|
||||
$mailer_log = self::createMailerLog();
|
||||
}
|
||||
return $mailer_log;
|
||||
}
|
||||
|
||||
static function createMailerLog() {
|
||||
$mailer_log = array(
|
||||
'sent' => 0,
|
||||
'started' => time()
|
||||
);
|
||||
Setting::setValue(self::SETTING_NAME, $mailer_log);
|
||||
return $mailer_log;
|
||||
}
|
||||
|
||||
static function resetMailerLog() {
|
||||
return self::createMailerLog();
|
||||
}
|
||||
|
||||
static function updateMailerLog($mailer_log) {
|
||||
Setting::setValue(self::SETTING_NAME, $mailer_log);
|
||||
return $mailer_log;
|
||||
}
|
||||
|
||||
static function incrementSentCount($mailer_log = false) {
|
||||
$mailer_log = ($mailer_log) ? $mailer_log : self::getMailerLog();
|
||||
(int)$mailer_log['sent']++;
|
||||
return self::updateMailerLog($mailer_log);
|
||||
}
|
||||
|
||||
static function isSendingLimitReached() {
|
||||
$mailer_config = Mailer::getMailerConfig();
|
||||
$mailer_log = self::getMailerLog();
|
||||
$elapsed_time = time() - (int)$mailer_log['started'];
|
||||
if($mailer_log['sent'] === $mailer_config['frequency_limit']) {
|
||||
if($elapsed_time <= $mailer_config['frequency_interval']) return true;
|
||||
// reset mailer log if enough time has passed since the limit was reached
|
||||
self::resetMailerLog();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static function enforceSendingLimit() {
|
||||
if(self::isSendingLimitReached()) {
|
||||
throw new \Exception(__('Sending frequency limit has been reached'));
|
||||
}
|
||||
}
|
||||
}
|
@ -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');
|
||||
}
|
||||
}
|
||||
}
|
@ -126,6 +126,11 @@ class Newsletter extends Model {
|
||||
$notification_history = self::create();
|
||||
$notification_history->hydrate($data);
|
||||
|
||||
// reset timestamps
|
||||
$notification_history->set_expr('created_at', 'NOW()');
|
||||
$notification_history->set_expr('updated_at', 'NOW()');
|
||||
$notification_history->set_expr('deleted_at', 'NULL');
|
||||
|
||||
$notification_history->save();
|
||||
|
||||
if($notification_history->getErrors() === false) {
|
||||
@ -611,4 +616,31 @@ class Newsletter extends Model {
|
||||
->whereIn('options.value', $segments)
|
||||
->findMany();
|
||||
}
|
||||
}
|
||||
|
||||
static function getArchives($segment_ids = array()) {
|
||||
$orm = self::table_alias('newsletters')
|
||||
->distinct()->select('newsletters.*')
|
||||
->whereIn('newsletters.type', array(
|
||||
self::TYPE_STANDARD,
|
||||
self::TYPE_NOTIFICATION_HISTORY
|
||||
))
|
||||
->join(
|
||||
MP_SENDING_QUEUES_TABLE,
|
||||
'queues.newsletter_id = newsletters.id',
|
||||
'queues'
|
||||
)
|
||||
->where('queues.status', SendingQueue::STATUS_COMPLETED)
|
||||
->select('queues.processed_at')
|
||||
->orderByDesc('queues.processed_at');
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
$orm->join(
|
||||
MP_NEWSLETTER_SEGMENT_TABLE,
|
||||
'newsletter_segments.newsletter_id = newsletters.id',
|
||||
'newsletter_segments'
|
||||
)
|
||||
->whereIn('newsletter_segments.segment_id', $segment_ids);
|
||||
}
|
||||
return $orm->findMany();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,10 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterPost extends Model {
|
||||
public static $_table = MP_NEWSLETTER_POSTS_TABLE;
|
||||
|
||||
static function getNewestNewsletterPost($newsletter_id) {
|
||||
return self::where('newsletter_id', $newsletter_id)
|
||||
->orderByDesc('created_at')
|
||||
->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))
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Setting extends Model {
|
||||
@ -38,6 +40,9 @@ class Setting extends Model {
|
||||
'interval' => self::DEFAULT_SENDING_FREQUENCY_INTERVAL
|
||||
)
|
||||
),
|
||||
CronTrigger::SETTING_NAME => array(
|
||||
'method' => CronTrigger::DEFAULT_METHOD
|
||||
),
|
||||
'signup_confirmation' => array(
|
||||
'enabled' => true,
|
||||
'subject' => sprintf(__('Confirm your subscription to %1$s'), get_option('blogname')),
|
||||
@ -157,4 +162,9 @@ class Setting extends Model {
|
||||
|
||||
return $setting->save();
|
||||
}
|
||||
}
|
||||
|
||||
public static function deleteValue($value) {
|
||||
$value = self::where('name', $value)->findOne();
|
||||
return ($value) ? $value->delete() : false;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,11 @@ class Subscriber extends Model {
|
||||
return ($this->wp_user_id !== null);
|
||||
}
|
||||
|
||||
static function getCurrentWPUser() {
|
||||
$wp_user = wp_get_current_user();
|
||||
return self::where('wp_user_id', $wp_user->ID)->findOne();
|
||||
}
|
||||
|
||||
function sendConfirmationEmail() {
|
||||
if($this->status === self::STATUS_UNCONFIRMED) {
|
||||
$signup_confirmation = Setting::getValue('signup_confirmation');
|
||||
@ -212,13 +217,13 @@ class Subscriber extends Model {
|
||||
$segments = Segment::orderByAsc('name')->findMany();
|
||||
$segment_list = array();
|
||||
$segment_list[] = array(
|
||||
'label' => __('All segments'),
|
||||
'label' => __('All Lists'),
|
||||
'value' => ''
|
||||
);
|
||||
|
||||
$subscribers_without_segment = self::filter('withoutSegments')->count();
|
||||
$subscribers_without_segment_label = sprintf(
|
||||
__('Subscribers without a segment (%s)'),
|
||||
__('Subscribers without a list (%s)'),
|
||||
number_format($subscribers_without_segment)
|
||||
);
|
||||
|
||||
|
@ -9,8 +9,12 @@ if(!defined('ABSPATH')) exit;
|
||||
class AutomatedLatestContent {
|
||||
const DEFAULT_POSTS_PER_PAGE = 10;
|
||||
|
||||
function __construct($newsletter_id = false) {
|
||||
private $newsletter_id;
|
||||
private $newer_than_timestamp;
|
||||
|
||||
function __construct($newsletter_id = false, $newer_than_timestamp = false) {
|
||||
$this->newsletter_id = $newsletter_id;
|
||||
$this->newer_than_timestamp = $newer_than_timestamp;
|
||||
|
||||
$this->_attachSentPostsFilter();
|
||||
}
|
||||
@ -59,6 +63,15 @@ class AutomatedLatestContent {
|
||||
// the query.
|
||||
$parameters['suppress_filters'] = false;
|
||||
|
||||
if($this->newer_than_timestamp) {
|
||||
$parameters['date_query'] = array(
|
||||
array(
|
||||
'column' => 'post_date',
|
||||
'after' => $this->newer_than_timestamp
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return get_posts($parameters);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Links;
|
||||
|
||||
use MailPoet\API\API;
|
||||
use MailPoet\API\Endpoints\Track as TrackAPI;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Router\Front as FrontRouter;
|
||||
use MailPoet\Router\Endpoints\Track as TrackEndpoint;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
use MailPoet\Util\Security;
|
||||
@ -80,7 +81,7 @@ class Links {
|
||||
// i.e., <a href="http://google.com">(http://google.com)</a> => [(http://google.com)](http://tracked_link)
|
||||
$regex_escaped_extracted_link = preg_quote($extracted_link['link'], '/');
|
||||
$content = preg_replace(
|
||||
'/\[(' . $regex_escaped_extracted_link . ')\](\(' . $regex_escaped_extracted_link . '\))/',
|
||||
'/\[(.*?)\](\(' . $regex_escaped_extracted_link . '\))/',
|
||||
'[$1](' . $tracked_link . ')',
|
||||
$content
|
||||
);
|
||||
@ -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,17 +112,18 @@ 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
|
||||
);
|
||||
$API_action = ($matches[2][$index] === self::DATA_TAG_CLICK) ?
|
||||
TrackAPI::ACTION_CLICK :
|
||||
TrackAPI::ACTION_OPEN;
|
||||
$link = API::buildRequest(
|
||||
TrackAPI::ENDPOINT,
|
||||
$API_action,
|
||||
$router_action = ($matches[2][$index] === self::DATA_TAG_CLICK) ?
|
||||
TrackEndpoint::ACTION_CLICK :
|
||||
TrackEndpoint::ACTION_OPEN;
|
||||
$link = FrontRouter::buildRequest(
|
||||
TrackEndpoint::ENDPOINT,
|
||||
$router_action,
|
||||
$data
|
||||
);
|
||||
$content = str_replace($match, $link, $content);
|
||||
@ -130,7 +133,7 @@ class Links {
|
||||
|
||||
static function save(array $links, $newsletter_id, $queue_id) {
|
||||
foreach($links as $link) {
|
||||
if(empty($link['hash'] || empty($link['url']))) continue;
|
||||
if(empty($link['hash']) || empty($link['url'])) continue;
|
||||
$newsletter_link = NewsletterLink::create();
|
||||
$newsletter_link->newsletter_id = $newsletter_id;
|
||||
$newsletter_link->queue_id = $queue_id;
|
||||
|
@ -6,6 +6,10 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
|
||||
class Image {
|
||||
static function render($element, $column_count) {
|
||||
if(empty($element['src'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$element['width'] = (int)$element['width'];
|
||||
$element['height'] = (int)$element['height'];
|
||||
$element = self::adjustImageDimensions($element, $column_count);
|
||||
|
@ -2,19 +2,38 @@
|
||||
namespace MailPoet\Newsletter\Renderer\Blocks;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterPost;
|
||||
use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
|
||||
class Renderer {
|
||||
public $newsletter;
|
||||
public $posts;
|
||||
public $ALC;
|
||||
|
||||
function __construct(array $newsletter, $posts = false) {
|
||||
function __construct(array $newsletter, $preview) {
|
||||
$this->newsletter = $newsletter;
|
||||
$this->posts = array();
|
||||
$newsletter_id = ($newsletter['type'] === Newsletter::TYPE_NOTIFICATION_HISTORY) ?
|
||||
$newsletter['parent_id'] :
|
||||
$newsletter['id'];
|
||||
$this->ALC = new \MailPoet\Newsletter\AutomatedLatestContent($newsletter_id);
|
||||
if($newsletter['type'] === Newsletter::TYPE_NOTIFICATION_HISTORY) {
|
||||
$newsletter_id = $newsletter['parent_id'];
|
||||
|
||||
$last_post = NewsletterPost::getNewestNewsletterPost($newsletter_id);
|
||||
if($last_post) {
|
||||
$newer_than_timestamp = $last_post->created_at;
|
||||
} else {
|
||||
$parent = Newsletter::findOne($newsletter_id);
|
||||
$newer_than_timestamp = $parent->created_at;
|
||||
}
|
||||
} else if($preview) {
|
||||
$newsletter_id = false;
|
||||
$newer_than_timestamp = false;
|
||||
} else {
|
||||
$newsletter_id = $newsletter['id'];
|
||||
$newer_than_timestamp = false;
|
||||
}
|
||||
$this->ALC = new \MailPoet\Newsletter\AutomatedLatestContent(
|
||||
$newsletter_id,
|
||||
$newer_than_timestamp
|
||||
);
|
||||
}
|
||||
|
||||
function render($data, $column_count) {
|
||||
|
@ -6,11 +6,17 @@ class Social {
|
||||
$icons_block = '';
|
||||
if(is_array($element['icons'])) {
|
||||
foreach($element['icons'] as $index => $icon) {
|
||||
if(empty($icon['image'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$icons_block .= '
|
||||
<a href="' . $icon['link'] . '" style="text-decoration:none!important;">
|
||||
<img src="' . $icon['image'] . '" width="' . (int)$icon['width'] . '" height="' . (int)$icon['height'] . '" style="width:' . $icon['width'] . ';height:' . $icon['width'] . ';-ms-interpolation-mode:bicubic;border:0;display:inline;outline:none;" alt="' . $icon['iconType'] . '">
|
||||
</a>';
|
||||
}
|
||||
}
|
||||
if(!empty($icons_block)) {
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_padded_side mailpoet_padded_bottom" valign="top" align="center">
|
||||
@ -20,4 +26,4 @@ class Social {
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user