Compare commits
112 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6088497433 | ||
|
57f0b88299 | ||
|
f874ffc19c | ||
|
d11badf3ce | ||
|
3006c982cb | ||
|
b29e31fdd6 | ||
|
bc42c8e280 | ||
|
409697ee64 | ||
|
cfb4265971 | ||
|
13d78aac05 | ||
|
6f176f4e6c | ||
|
9b584296a5 | ||
|
5ea87c5eed | ||
|
7522084ccb | ||
|
214aa60d0e | ||
|
7a049ce1b7 | ||
|
94d293deb7 | ||
|
bd2d38d757 | ||
|
abec524daa | ||
|
cac6beb4ac | ||
|
cac995e15b | ||
|
b26380fd10 | ||
|
6c6a4070be | ||
|
8b001d820b | ||
|
2ae3d8ebdf | ||
|
459ec21f9d | ||
|
9c7790d07e | ||
|
f9c5b99e46 | ||
|
95b0b39366 | ||
|
4b6fa0e760 | ||
|
67a3440ced | ||
|
0de372344a | ||
|
7a04eeb650 | ||
|
8dbfe82922 | ||
|
7322f2151c | ||
|
c43d2f240d | ||
|
bbcd267b6f | ||
|
bbc4acb2a4 | ||
|
c89cc5a919 | ||
|
33075940de | ||
|
51c09b8360 | ||
|
2fbf85f371 | ||
|
24cb614adb | ||
|
55f851208b | ||
|
990dac7727 | ||
|
233020ca20 | ||
|
0c419cde16 | ||
|
35f9530d8e | ||
|
992fe2a6e9 | ||
|
c2cb88f995 | ||
|
ba69d659ab | ||
|
397d988eb1 | ||
|
d85f2341ec | ||
|
2b3c288b5f | ||
|
8ec28a23a7 | ||
|
12c9623e2f | ||
|
8ba9fdccbc | ||
|
a2ef62302f | ||
|
24ecc879d3 | ||
|
a1104a7f90 | ||
|
aa959810e9 | ||
|
45b7a79277 | ||
|
41c8c0dae5 | ||
|
2aeab7aaff | ||
|
4fd0c4b484 | ||
|
d4623cf763 | ||
|
181c4fed08 | ||
|
7884dd8389 | ||
|
b577d33414 | ||
|
70de0a01bf | ||
|
3b7f77d9af | ||
|
21847ca875 | ||
|
6153316047 | ||
|
32f8f07602 | ||
|
70a04d9bf6 | ||
|
bb1cc997cc | ||
|
24f96d9d7d | ||
|
46c7332da2 | ||
|
2f42f643ab | ||
|
63c87f3746 | ||
|
d4d575cda4 | ||
|
2cf03ec0a3 | ||
|
72ad98a77f | ||
|
b5094f568c | ||
|
7d224274fc | ||
|
f3b9f7be92 | ||
|
6e74f82ace | ||
|
831eb6af44 | ||
|
1e8e5aecee | ||
|
c0f98c9ba6 | ||
|
746c19d6ed | ||
|
894a9e8c90 | ||
|
8fea917337 | ||
|
c60425afb2 | ||
|
0776e9ad73 | ||
|
91981cc324 | ||
|
1906fafacb | ||
|
c11d95b402 | ||
|
b4c8fe6f45 | ||
|
d0e770e0fc | ||
|
3d6d1a4282 | ||
|
dc3b47db00 | ||
|
900d6694e2 | ||
|
e8074a61a5 | ||
|
64501a914a | ||
|
de70e855ad | ||
|
03e3b5a94b | ||
|
3331bed31c | ||
|
8c5a33a0fe | ||
|
01eb6c7a98 | ||
|
f502e0b677 | ||
|
a6b64a1c5d |
16
.env.sample
16
.env.sample
@@ -1,2 +1,16 @@
|
||||
WP_TEST_PATH="/var/www/wordpress"
|
||||
|
||||
WP_TEST_ENABLE_NETWORK_TESTS="true"
|
||||
WP_TEST_IMPORT_MAILCHIMP_API=""
|
||||
WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma)
|
||||
WP_TEST_MAILER_ENABLE_SENDING="true"
|
||||
WP_TEST_MAILER_AMAZON_ACCESS=""
|
||||
WP_TEST_MAILER_AMAZON_SECRET=""
|
||||
WP_TEST_MAILER_AMAZON_REGION=""
|
||||
WP_TEST_MAILER_ELASTICEMAIL_API=""
|
||||
WP_TEST_MAILER_MAILGUN_API=""
|
||||
WP_TEST_MAILER_MAILGUN_DOMAIN=""
|
||||
WP_TEST_MAILER_MAILPOET_API=""
|
||||
WP_TEST_MAILER_SENDGRID_API=""
|
||||
WP_TEST_MAILER_SMTP_HOST=""
|
||||
WP_TEST_MAILER_SMTP_LOGIN=""
|
||||
WP_TEST_MAILER_SMTP_PASSWORD=""
|
13
RoboFile.php
13
RoboFile.php
@@ -105,7 +105,18 @@ class RoboFile extends \Robo\Tasks {
|
||||
function testUnit($file = null) {
|
||||
$this->loadEnv();
|
||||
$this->_exec('vendor/bin/codecept build');
|
||||
$this->_exec('vendor/bin/codecept run unit '.(($file) ? $file : ''));
|
||||
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
||||
}
|
||||
|
||||
function testCoverage($file = null) {
|
||||
$this->loadEnv();
|
||||
$this->_exec('vendor/bin/codecept build');
|
||||
$this->_exec(join(' ', array(
|
||||
'vendor/bin/codecept run',
|
||||
(($file) ? $file : ''),
|
||||
'--coverage',
|
||||
'--coverage-html'
|
||||
)));
|
||||
}
|
||||
|
||||
function testJavascript() {
|
||||
|
@@ -120,7 +120,7 @@ function(
|
||||
<select
|
||||
id={ this.props.field.id || this.props.field.name }
|
||||
ref="select"
|
||||
placeholder={ this.props.field.placeholder }
|
||||
data-placeholder={ this.props.field.placeholder }
|
||||
multiple={ this.props.field.multiple }
|
||||
defaultValue={ default_value }
|
||||
{...this.props.field.validation}
|
||||
|
@@ -48,7 +48,7 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'get',
|
||||
data: { id: id }
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
if(response === false) {
|
||||
this.setState({
|
||||
|
@@ -25,58 +25,49 @@ const columns = [
|
||||
|
||||
const messages = {
|
||||
onTrash: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 form was moved to the trash.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d forms were moved to the trash.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 form was moved to the trash.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d forms were moved to the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 form was permanently deleted.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d forms were permanently deleted.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 form was permanently deleted.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d forms were permanently deleted.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 form has been restored from the trash.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d forms have been restored from the trash.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 form has been restored from the trash.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d forms have been restored from the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -125,8 +116,8 @@ const FormList = React.createClass({
|
||||
endpoint: 'forms',
|
||||
action: 'create'
|
||||
}).done(function(response) {
|
||||
if(response !== false) {
|
||||
window.location = response;
|
||||
if(response.result && response.form_id) {
|
||||
window.location = mailpoet_form_edit_url + response.form_id;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -14,6 +14,9 @@ function(
|
||||
})
|
||||
return this.props.onSelectFilter(filters);
|
||||
},
|
||||
handleEmptyTrash: function() {
|
||||
return this.props.onEmptyTrash();
|
||||
},
|
||||
getAvailableFilters: function() {
|
||||
let filters = this.props.filters;
|
||||
|
||||
@@ -34,7 +37,7 @@ function(
|
||||
const available_filters = this.getAvailableFilters()
|
||||
.map(function(filter, i) {
|
||||
let default_value = false;
|
||||
if(selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||
default_value = selected_filters[filter]
|
||||
} else {
|
||||
jQuery(`select[name="${filter}"]`).val('');
|
||||
@@ -60,9 +63,10 @@ function(
|
||||
|
||||
let button = false;
|
||||
|
||||
if(available_filters.length > 0) {
|
||||
if (available_filters.length > 0) {
|
||||
button = (
|
||||
<input
|
||||
id="post-query-submit"
|
||||
onClick={ this.handleFilterAction }
|
||||
type="submit"
|
||||
defaultValue="Filter"
|
||||
@@ -70,10 +74,23 @@ function(
|
||||
);
|
||||
}
|
||||
|
||||
let empty_trash = false;
|
||||
if (this.props.group === 'trash') {
|
||||
empty_trash = (
|
||||
<input
|
||||
onClick={ this.handleEmptyTrash }
|
||||
type="submit"
|
||||
value="Empty Trash"
|
||||
className="button"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="alignleft actions actions">
|
||||
{ available_filters }
|
||||
{ button }
|
||||
{ empty_trash }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -504,10 +504,21 @@ define(
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
},
|
||||
handleEmptyTrash: function() {
|
||||
this.handleBulkAction('all', {
|
||||
action: 'delete',
|
||||
group: 'trash'
|
||||
}, function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoetI18n.permanentlyDeleted.replace('%d', response)
|
||||
);
|
||||
});
|
||||
},
|
||||
handleBulkAction: function(selected_ids, params, callback) {
|
||||
if(
|
||||
this.state.selection === false
|
||||
&& this.state.selected_ids.length === 0
|
||||
&& selected_ids !== 'all'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -520,8 +531,10 @@ define(
|
||||
limit: 0,
|
||||
filter: this.state.filter,
|
||||
group: this.state.group,
|
||||
search: this.state.search,
|
||||
selection: selected_ids
|
||||
search: this.state.search
|
||||
}
|
||||
if(selected_ids !== 'all') {
|
||||
data.listing.selection = selected_ids;
|
||||
}
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
@@ -715,7 +728,10 @@ define(
|
||||
<ListingFilters
|
||||
filters={ this.state.filters }
|
||||
filter={ this.state.filter }
|
||||
onSelectFilter={ this.handleFilter } />
|
||||
group={ this.state.group }
|
||||
onSelectFilter={ this.handleFilter }
|
||||
onEmptyTrash={ this.handleEmptyTrash }
|
||||
/>
|
||||
<ListingPages
|
||||
count={ this.state.count }
|
||||
page={ this.state.page }
|
||||
|
@@ -7,7 +7,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
}
|
||||
},
|
||||
setPage: function(page) {
|
||||
this.props.onSetPage(page);
|
||||
this.setState({
|
||||
page: null
|
||||
}, function () {
|
||||
this.props.onSetPage(this.constrainPage(page));
|
||||
}.bind(this));
|
||||
},
|
||||
setFirstPage: function() {
|
||||
this.setPage(1);
|
||||
@@ -16,10 +20,14 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
this.setPage(this.getLastPage());
|
||||
},
|
||||
setPreviousPage: function() {
|
||||
this.setPage(this.constrainPage(this.props.page - 1));
|
||||
this.setPage(this.constrainPage(
|
||||
parseInt(this.props.page, 10) - 1)
|
||||
);
|
||||
},
|
||||
setNextPage: function() {
|
||||
this.setPage(this.constrainPage(this.props.page + 1));
|
||||
this.setPage(this.constrainPage(
|
||||
parseInt(this.props.page, 10) + 1)
|
||||
);
|
||||
},
|
||||
constrainPage: function(page) {
|
||||
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
|
||||
@@ -27,14 +35,16 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
handleSetManualPage: function(e) {
|
||||
if(e.which === 13) {
|
||||
this.setPage(this.state.page);
|
||||
this.setState({ page: null });
|
||||
}
|
||||
},
|
||||
handleChangeManualPage: function(e) {
|
||||
this.setState({
|
||||
page: this.constrainPage(e.target.value)
|
||||
page: e.target.value
|
||||
});
|
||||
},
|
||||
handleBlurManualPage: function(e) {
|
||||
this.setPage(e.target.value);
|
||||
},
|
||||
getLastPage: function() {
|
||||
return Math.ceil(this.props.count / this.props.limit);
|
||||
},
|
||||
@@ -101,6 +111,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
);
|
||||
}
|
||||
|
||||
let pageValue = this.props.page;
|
||||
if(this.state.page !== null) {
|
||||
pageValue = this.state.page;
|
||||
}
|
||||
|
||||
pagination = (
|
||||
<span className="pagination-links">
|
||||
{firstPage}
|
||||
@@ -115,10 +130,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
type="text"
|
||||
onChange={ this.handleChangeManualPage }
|
||||
onKeyUp={ this.handleSetManualPage }
|
||||
onBlur={ this.handleBlurManualPage }
|
||||
aria-describedby="table-paging"
|
||||
size="1"
|
||||
ref="page"
|
||||
value={ this.state.page || this.props.page }
|
||||
value={ pageValue }
|
||||
name="paged"
|
||||
id="current-page-selector"
|
||||
className="current-page" />
|
||||
|
@@ -35,7 +35,7 @@ define([
|
||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||
titleIsLink: false, // false|true
|
||||
imagePadded: true, // true|false
|
||||
imageFullWidth: false, // true|false
|
||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||
authorPrecededBy: 'Author:',
|
||||
@@ -63,7 +63,7 @@ define([
|
||||
initialize: function() {
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
this.fetchPosts();
|
||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
||||
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
|
||||
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
|
||||
},
|
||||
@@ -144,7 +144,7 @@ define([
|
||||
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
|
||||
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_automated_latest_content_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
||||
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
|
@@ -20,7 +20,7 @@ define([
|
||||
link: 'http://example.org',
|
||||
src: 'no-image.png',
|
||||
alt: 'An image of...',
|
||||
padded: true, // true | false - Padded or full width
|
||||
fullWidth: true, // true | false
|
||||
width: '64px',
|
||||
height: '64px',
|
||||
styles: {
|
||||
@@ -45,10 +45,10 @@ define([
|
||||
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
||||
this.toolsRegion.show(this.toolsView);
|
||||
|
||||
if (this.model.get('padded')) {
|
||||
this.$el.removeClass('mailpoet_full_image');
|
||||
} else {
|
||||
if (this.model.get('fullWidth')) {
|
||||
this.$el.addClass('mailpoet_full_image');
|
||||
} else {
|
||||
this.$el.removeClass('mailpoet_full_image');
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -64,7 +64,7 @@ define([
|
||||
"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"),
|
||||
"change .mailpoet_field_image_padded": _.partial(this.changeBoolCheckboxField, "padded"),
|
||||
"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",
|
||||
"click .mailpoet_done_editing": "close",
|
||||
|
@@ -46,7 +46,7 @@ define([
|
||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||
titleIsLink: false, // false|true
|
||||
imagePadded: true, // true|false
|
||||
imageFullWidth: false, // true|false
|
||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||
authorPrecededBy: 'Author:',
|
||||
@@ -88,7 +88,7 @@ define([
|
||||
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
||||
|
||||
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
||||
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
||||
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
||||
this.listenTo(this.get('readMoreButton'), 'change', refreshTransformedPosts);
|
||||
this.listenTo(this.get('divider'), 'change', refreshTransformedPosts);
|
||||
|
||||
@@ -396,7 +396,7 @@ define([
|
||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
|
||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_posts_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
||||
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
|
@@ -9,7 +9,7 @@ define([
|
||||
|
||||
Module._query = function(args) {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'wordpress',
|
||||
endpoint: 'automatedLatestContent',
|
||||
action: args.action,
|
||||
data: args.options || {},
|
||||
});
|
||||
|
@@ -11,7 +11,7 @@ define([
|
||||
// Does not hold newsletter content nor newsletter styles, those are
|
||||
// handled by other components.
|
||||
Module.NewsletterModel = SuperModel.extend({
|
||||
stale: ['body'],
|
||||
stale: ['body', 'created_at', 'deleted_at', 'updated_at'],
|
||||
initialize: function(options) {
|
||||
this.on('change', function() {
|
||||
App.getChannel().trigger('autoSave');
|
||||
|
@@ -225,6 +225,11 @@ define([
|
||||
showPreview: function() {
|
||||
var json = App.toJSON();
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(json.body)) {
|
||||
json.body = JSON.stringify(json.body);
|
||||
}
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'render',
|
||||
|
@@ -43,58 +43,49 @@ define(
|
||||
|
||||
var messages = {
|
||||
onTrash: function(response) {
|
||||
var count = ~~response.newsletters;
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(count === 1 || response === true) {
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 newsletter was moved to the trash.'
|
||||
);
|
||||
} else if(count > 1) {
|
||||
} else {
|
||||
message = (
|
||||
'%$1d newsletters were moved to the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
var count = ~~response.newsletters;
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(count === 1 || response === true) {
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 newsletter was permanently deleted.'
|
||||
);
|
||||
} else if(count > 1) {
|
||||
} else {
|
||||
message = (
|
||||
'%$1d newsletters were permanently deleted.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
var count = ~~response.newsletters;
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(count === 1 || response === true) {
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 newsletter has been restored from the trash.'
|
||||
);
|
||||
} else if(count > 1) {
|
||||
} else {
|
||||
message = (
|
||||
'%$1d newsletters have been restored from the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -145,14 +145,6 @@ define(
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
}
|
||||
},
|
||||
isValid: function() {
|
||||
return (jQuery('#mailpoet_newsletter').parsley().validate());
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
@@ -166,8 +158,7 @@ define(
|
||||
fields={ fields }
|
||||
params={ this.props.params }
|
||||
messages={ messages }
|
||||
isValid={ this.isValid }>
|
||||
|
||||
>
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
|
@@ -29,7 +29,7 @@ define(
|
||||
action: 'save',
|
||||
data: template
|
||||
}).done(function(response) {
|
||||
if(response === true) {
|
||||
if(response.result === true) {
|
||||
this.props.onImport(template);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
|
@@ -29,12 +29,14 @@ define(
|
||||
subject: 'Draft newsletter',
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.id !== undefined) {
|
||||
this.history.pushState(null, `/template/${response.id}`);
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.history.pushState(null, `/template/${response.newsletter.id}`);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
@@ -138,12 +138,14 @@ define(
|
||||
options: this.state,
|
||||
},
|
||||
}).done(function(response) {
|
||||
if(response.id !== undefined) {
|
||||
this.showTemplateSelection(response.id);
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
@@ -32,12 +32,15 @@ define(
|
||||
type: 'standard',
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.id !== undefined) {
|
||||
this.showTemplateSelection(response.id);
|
||||
console.log(response);
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
@@ -111,12 +111,14 @@ define(
|
||||
options: this.state,
|
||||
},
|
||||
}).done(function(response) {
|
||||
if(response.id !== undefined) {
|
||||
this.showTemplateSelection(response.id);
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
response.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
@@ -192,21 +192,28 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
error: function(message, options) {
|
||||
this.show(jQuery.extend({}, {
|
||||
type: 'error',
|
||||
message: '<p>'+message+'</p>'
|
||||
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||
}, options));
|
||||
},
|
||||
success: function(message, options) {
|
||||
this.show(jQuery.extend({}, {
|
||||
type: 'success',
|
||||
message: '<p>'+message+'</p>'
|
||||
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||
}, options));
|
||||
},
|
||||
system: function(message, options) {
|
||||
this.show(jQuery.extend({}, {
|
||||
type: 'system',
|
||||
static: true,
|
||||
message: message
|
||||
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||
}, options));
|
||||
},
|
||||
formatMessage: function(message) {
|
||||
if(Array.isArray(message)) {
|
||||
return message.join('<br />');
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@@ -42,58 +42,49 @@ var columns = [
|
||||
|
||||
const messages = {
|
||||
onTrash: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 segment was moved to the trash.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d segments were moved to the trash.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 segment was moved to the trash.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d segments were moved to the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 segment was permanently deleted.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d segments were permanently deleted.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 segment was permanently deleted.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d segments were permanently deleted.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
if(response) {
|
||||
let message = null;
|
||||
if(~~response === 1) {
|
||||
message = (
|
||||
'1 segment has been restored from the trash.'
|
||||
);
|
||||
} else if(~~response > 1) {
|
||||
message = (
|
||||
'%$1d segments have been restored from the trash.'
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if(count === 1) {
|
||||
message = (
|
||||
'1 segment has been restored from the trash.'
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
'%$1d segments have been restored from the trash.'
|
||||
).replace('%$1d', count);
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -53,10 +53,6 @@ define(
|
||||
|
||||
var custom_fields = window.mailpoet_custom_fields || [];
|
||||
custom_fields.map(custom_field => {
|
||||
if(custom_field.type === 'input') {
|
||||
custom_field.type = 'text';
|
||||
}
|
||||
|
||||
let field = {
|
||||
name: 'cf_' + custom_field.id,
|
||||
label: custom_field.name,
|
||||
|
@@ -193,7 +193,7 @@ define(
|
||||
}).done(function (response) {
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(response.error, {
|
||||
MailPoet.Notice.error(response.errors, {
|
||||
timeout: 3000,
|
||||
});
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
@@ -245,7 +245,7 @@ define(
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice(response.message, {
|
||||
MailPoet.Notice.error(response.errors, {
|
||||
timeout: 3000,
|
||||
});
|
||||
}
|
||||
@@ -1082,7 +1082,7 @@ define(
|
||||
}).done(function (response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.error(response.error, {
|
||||
MailPoet.Notice.error(response.errors, {
|
||||
timeout: 3000,
|
||||
});
|
||||
} else {
|
||||
|
@@ -19,3 +19,12 @@ modules:
|
||||
user: ''
|
||||
password: ''
|
||||
dump: tests/_data/dump.sql
|
||||
coverage:
|
||||
enabled: true
|
||||
whitelist:
|
||||
include:
|
||||
- lib/*
|
||||
exclude:
|
||||
blacklist:
|
||||
include:
|
||||
exclude:
|
@@ -10,7 +10,8 @@
|
||||
"swiftmailer/swiftmailer": "^5.4",
|
||||
"phpseclib/phpseclib": "*",
|
||||
"mtdowling/cron-expression": "^1.0",
|
||||
"nesbot/carbon": "^1.21"
|
||||
"nesbot/carbon": "^1.21",
|
||||
"soundasleep/html2text": "^0.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "*",
|
||||
|
64
composer.lock
generated
64
composer.lock
generated
@@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "4720dce62e4a6a7bf4d3ba3944b9c2b9",
|
||||
"content-hash": "748470f0803c52a798a4ecd1bb8a93b9",
|
||||
"hash": "db2edea5fb720fcb8013ac470e924c19",
|
||||
"content-hash": "85119d1ccd5193b6b08fda305a2427e7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "cerdic/css-tidy",
|
||||
@@ -399,6 +399,56 @@
|
||||
],
|
||||
"time": "2016-01-18 17:07:21"
|
||||
},
|
||||
{
|
||||
"name": "soundasleep/html2text",
|
||||
"version": "0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/soundasleep/html2text.git",
|
||||
"reference": "55be17ddbb7234650722f66816ba2b10f66e565f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/soundasleep/html2text/zipball/55be17ddbb7234650722f66816ba2b10f66e565f",
|
||||
"reference": "55be17ddbb7234650722f66816ba2b10f66e565f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.0",
|
||||
"soundasleep/component-tests": "dev-master"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Html2Text\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"EPL-1.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jevon Wright",
|
||||
"homepage": "https://jevon.org",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A PHP script to convert HTML into a plain text format",
|
||||
"homepage": "https://github.com/soundasleep/html2text",
|
||||
"keywords": [
|
||||
"email",
|
||||
"html",
|
||||
"php",
|
||||
"text"
|
||||
],
|
||||
"time": "2015-12-18 02:30:26"
|
||||
},
|
||||
{
|
||||
"name": "sunra/php-simple-html-dom-parser",
|
||||
"version": "v1.5.0",
|
||||
@@ -1110,16 +1160,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982"
|
||||
"reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982",
|
||||
"reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5d04bdd2881ac89abde1fb78cc234bce24327bb",
|
||||
"reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1164,7 +1214,7 @@
|
||||
"stream",
|
||||
"uri"
|
||||
],
|
||||
"time": "2015-11-03 01:34:55"
|
||||
"time": "2016-01-23 01:23:02"
|
||||
},
|
||||
{
|
||||
"name": "henrikbjorn/lurker",
|
||||
|
@@ -9,13 +9,6 @@ class Activator {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
register_activation_hook(
|
||||
Env::$file,
|
||||
array($this, 'activate')
|
||||
);
|
||||
}
|
||||
|
||||
function activate() {
|
||||
$migrator = new Migrator();
|
||||
$migrator->up();
|
||||
|
@@ -36,8 +36,9 @@ class Env {
|
||||
self::$views_path = self::$path . '/views';
|
||||
self::$assets_path = self::$path . '/assets';
|
||||
self::$assets_url = plugins_url('/assets', $file);
|
||||
self::$temp_path = wp_upload_dir()['path'];
|
||||
self::$temp_URL = wp_upload_dir()['url'];
|
||||
$wp_upload_dir = wp_upload_dir();
|
||||
self::$temp_path = $wp_upload_dir['path'];
|
||||
self::$temp_URL = $wp_upload_dir['url'];
|
||||
self::$languages_path = self::$path . '/lang';
|
||||
self::$lib_path = self::$path . '/lib';
|
||||
self::$plugin_prefix = 'mailpoet_';
|
||||
@@ -72,19 +73,4 @@ class Env {
|
||||
);
|
||||
return implode('', $source_name);
|
||||
}
|
||||
|
||||
static function isPluginActivated() {
|
||||
$activatesPlugins = get_option('active_plugins');
|
||||
$isActivated = (
|
||||
in_array(
|
||||
sprintf('%s/%s.php', basename(self::$path), self::$plugin_name),
|
||||
$activatesPlugins
|
||||
) ||
|
||||
in_array(
|
||||
sprintf('%s/%s.php', explode('/', plugin_basename(__FILE__))[0], self::$plugin_name),
|
||||
$activatesPlugins
|
||||
)
|
||||
);
|
||||
return ($isActivated) ? true : false;
|
||||
}
|
||||
}
|
@@ -9,10 +9,17 @@ class Hooks {
|
||||
function init() {
|
||||
// Subscribe in comments
|
||||
if((bool)Setting::getValue('subscribe.on_comment.enabled')) {
|
||||
add_action(
|
||||
'comment_form_after_fields',
|
||||
'\MailPoet\Subscription\Comment::extendForm'
|
||||
);
|
||||
if(is_user_logged_in()) {
|
||||
add_action(
|
||||
'comment_form_field_comment',
|
||||
'\MailPoet\Subscription\Comment::extendLoggedInForm'
|
||||
);
|
||||
} else {
|
||||
add_action(
|
||||
'comment_form_after_fields',
|
||||
'\MailPoet\Subscription\Comment::extendLoggedOutForm'
|
||||
);
|
||||
}
|
||||
|
||||
add_action(
|
||||
'comment_post',
|
||||
|
@@ -9,6 +9,8 @@ use MailPoet\Settings\Pages;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||
|
||||
class Initializer {
|
||||
function __construct($params = array(
|
||||
'file' => '',
|
||||
@@ -19,21 +21,34 @@ class Initializer {
|
||||
|
||||
function init() {
|
||||
$this->setupDB();
|
||||
$this->setupActivator();
|
||||
$this->setupRenderer();
|
||||
$this->setupLocalizer();
|
||||
$this->setupMenu();
|
||||
$this->setupRouter();
|
||||
$this->setupWidget();
|
||||
$this->setupAnalytics();
|
||||
$this->setupPermissions();
|
||||
$this->setupChangelog();
|
||||
$this->setupPublicAPI();
|
||||
$this->runQueueSupervisor();
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupPages();
|
||||
$this->setupImages();
|
||||
|
||||
register_activation_hook(Env::$file, array($this, 'runMigrator'));
|
||||
register_activation_hook(Env::$file, array($this, 'runPopulator'));
|
||||
|
||||
add_action('plugins_loaded', array($this, 'setup'));
|
||||
add_action('widgets_init', array($this, 'setupWidget'));
|
||||
}
|
||||
|
||||
function setup() {
|
||||
try {
|
||||
$this->setupRenderer();
|
||||
$this->setupLocalizer();
|
||||
$this->setupMenu();
|
||||
$this->setupRouter();
|
||||
$this->setupPermissions();
|
||||
$this->setupPublicAPI();
|
||||
$this->setupAnalytics();
|
||||
$this->setupChangelog();
|
||||
$this->runQueueSupervisor();
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupPages();
|
||||
$this->setupImages();
|
||||
} catch(\Exception $e) {
|
||||
// if anything goes wrong during init
|
||||
// automatically deactivate the plugin
|
||||
deactivate_plugins(Env::$file);
|
||||
}
|
||||
}
|
||||
|
||||
function setupDB() {
|
||||
@@ -51,8 +66,6 @@ class Initializer {
|
||||
$newsletters = Env::$db_prefix . 'newsletters';
|
||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||
$segments = Env::$db_prefix . 'segments';
|
||||
$filters = Env::$db_prefix . 'filters';
|
||||
$segment_filter = Env::$db_prefix . 'segment_filter';
|
||||
$forms = Env::$db_prefix . 'forms';
|
||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||
@@ -67,8 +80,6 @@ class Initializer {
|
||||
define('MP_SETTINGS_TABLE', $settings);
|
||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||
define('MP_SEGMENTS_TABLE', $segments);
|
||||
define('MP_FILTERS_TABLE', $filters);
|
||||
define('MP_SEGMENT_FILTER_TABLE', $segment_filter);
|
||||
define('MP_FORMS_TABLE', $forms);
|
||||
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
||||
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
||||
@@ -81,9 +92,14 @@ class Initializer {
|
||||
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||
}
|
||||
|
||||
function setupActivator() {
|
||||
$activator = new Activator();
|
||||
$activator->init();
|
||||
function runMigrator() {
|
||||
$migrator = new Migrator();
|
||||
$migrator->up();
|
||||
}
|
||||
|
||||
function runPopulator() {
|
||||
$populator = new Populator();
|
||||
$populator->up();
|
||||
}
|
||||
|
||||
function setupRenderer() {
|
||||
@@ -97,10 +113,7 @@ class Initializer {
|
||||
}
|
||||
|
||||
function setupMenu() {
|
||||
$menu = new Menu(
|
||||
$this->renderer,
|
||||
Env::$assets_url
|
||||
);
|
||||
$menu = new Menu($this->renderer, Env::$assets_url);
|
||||
$menu->init();
|
||||
}
|
||||
|
||||
@@ -138,6 +151,7 @@ class Initializer {
|
||||
$shortcodes = new Shortcodes();
|
||||
$shortcodes->init();
|
||||
}
|
||||
|
||||
function setupHooks() {
|
||||
$hooks = new Hooks();
|
||||
$hooks->init();
|
||||
@@ -153,7 +167,7 @@ class Initializer {
|
||||
try {
|
||||
$supervisor = new Supervisor();
|
||||
$supervisor->checkDaemon();
|
||||
} catch (\Exception $e) {
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,8 +11,7 @@ class Localizer {
|
||||
function init() {
|
||||
add_action(
|
||||
'init',
|
||||
array($this, 'setup'),
|
||||
0
|
||||
array($this, 'setup')
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
|
||||
@@ -236,10 +236,7 @@ class Migrator {
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'queue_id mediumint(9) NOT NULL,',
|
||||
'sent_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id)',
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
|
@@ -68,7 +68,7 @@ class FranksRoastHouseTemplate {
|
||||
"link" => "http://www.example.com",
|
||||
"src" => $this->template_image_url . "/header-v2.jpg",
|
||||
"alt" => __("Frank's Roast House"),
|
||||
"padded" => false,
|
||||
"fullWidth" => true,
|
||||
"width" => "600px",
|
||||
"height" => "220px",
|
||||
"styles" => array(
|
||||
@@ -95,7 +95,7 @@ class FranksRoastHouseTemplate {
|
||||
"link" => "http://example.org",
|
||||
"src" => $this->template_image_url . "/coffee-grain.jpg",
|
||||
"alt" => __("coffee-grain-3-1329675-1599x941"),
|
||||
"padded" => true,
|
||||
"fullWidth" => false,
|
||||
"width" => "1599px",
|
||||
"height" => "777px",
|
||||
"styles" => array(
|
||||
@@ -139,7 +139,7 @@ class FranksRoastHouseTemplate {
|
||||
"link" => "http://example.org",
|
||||
"src" => $this->template_image_url . "/sandwich.jpg",
|
||||
"alt" => "sandwich",
|
||||
"padded" => true,
|
||||
"fullWidth" => false,
|
||||
"width" => "640px",
|
||||
"height" => "344px",
|
||||
"styles" => array(
|
||||
@@ -238,7 +238,7 @@ class FranksRoastHouseTemplate {
|
||||
"link" => "http://example.org",
|
||||
"src" => $this->template_image_url . "/map-v2.jpg",
|
||||
"alt" => __("map-v2"),
|
||||
"padded" => true,
|
||||
"fullWidth" => false,
|
||||
"width" => "636px",
|
||||
"height" => "342px",
|
||||
"styles" => array(
|
||||
@@ -279,19 +279,19 @@ class FranksRoastHouseTemplate {
|
||||
"blocks" => array(
|
||||
array(
|
||||
"type" => "footer",
|
||||
"text" => __("<p><span style=\"color: #000000;\"><a href=\"[unsubscribeUrl]\" style=\"color: #000000;\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\" style=\"color: #000000;\">Manage subscription</a></span><br /><span style=\"color: #000000;\">12345 MailPoet Drive, EmailVille, 76543</span></p>"),
|
||||
"text" => __("<p><a href=\"[unsubscribeUrl]\">Unsubscribe</a> | <a href=\"[manageSubscriptionUrl]\">Manage subscription</a><br />12345 MailPoet Drive, EmailVille, 76543</p>"),
|
||||
"styles" => array(
|
||||
"block" => array(
|
||||
"backgroundColor" => "#a9a7a7"
|
||||
),
|
||||
"text" => array(
|
||||
"fontColor" => "#ffffff",
|
||||
"fontColor" => "#000000",
|
||||
"fontFamily" => "Arial",
|
||||
"fontSize" => "12px",
|
||||
"textAlign" => "center"
|
||||
),
|
||||
"link" => array(
|
||||
"fontColor" => "#ffffff",
|
||||
"fontColor" => "#000000",
|
||||
"textDecoration" => "underline"
|
||||
)
|
||||
)
|
||||
|
@@ -90,7 +90,7 @@ class PostNotificationsBlankTemplate {
|
||||
"link" => "http://example.org",
|
||||
"src" => $this->template_image_url . "/ALC-widget-icon.png",
|
||||
"alt" => __("ALC-widget-icon"),
|
||||
"padded" => true,
|
||||
"fullWidth" => false,
|
||||
"width" => "200px",
|
||||
"height" => "134px",
|
||||
"styles" => array(
|
||||
|
@@ -68,7 +68,7 @@ class WelcomeTemplate {
|
||||
"link" => "http://example.org",
|
||||
"src" => $this->template_image_url . "/logo-header.gif",
|
||||
"alt" => "logo-header",
|
||||
"padded" => true,
|
||||
"fullWidth" => false,
|
||||
"width" => "233px",
|
||||
"height" => "118px",
|
||||
"styles" => array(
|
||||
|
@@ -20,7 +20,7 @@ class PublicAPI {
|
||||
Helpers::underscoreToCamelCase($_GET['action']) :
|
||||
false;
|
||||
$this->request_payload = isset($_GET['request_payload']) ?
|
||||
json_decode(urldecode($_GET['request_payload']), true) :
|
||||
unserialize(base64_decode($_GET['request_payload'])) :
|
||||
false;
|
||||
}
|
||||
|
||||
|
@@ -9,13 +9,12 @@ class Widget {
|
||||
}
|
||||
|
||||
function init() {
|
||||
add_action('widgets_init', array($this, 'registerWidget'));
|
||||
$this->registerWidget();
|
||||
|
||||
if(!is_admin()) {
|
||||
//$this->setupActions();
|
||||
add_action('widgets_init', array($this, 'setupDependencies'));
|
||||
$this->setupDependencies();
|
||||
} else {
|
||||
add_action('widgets_init', array($this, 'setupAdminDependencies'));
|
||||
$this->setupAdminDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +68,9 @@ class Widget {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: extract this method into an Initializer
|
||||
// - the "ajax" part might probably be useless
|
||||
// - the "post" (non-ajax) part needs to be redone properly
|
||||
function setupActions() {
|
||||
// ajax requests
|
||||
add_action(
|
||||
|
71
lib/Cron/CronHelper.php
Normal file
71
lib/Cron/CronHelper.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CronHelper {
|
||||
const daemon_execution_limit = 20;
|
||||
const daemon_execution_timeout = 35;
|
||||
const daemon_request_timeout = 2;
|
||||
|
||||
static function createDaemon($token) {
|
||||
$daemon = array(
|
||||
'status' => 'starting',
|
||||
'counter' => 0,
|
||||
'token' => $token
|
||||
);
|
||||
self::saveDaemon($daemon);
|
||||
return $daemon;
|
||||
}
|
||||
|
||||
static function getDaemon() {
|
||||
return Setting::getValue('cron_daemon');
|
||||
}
|
||||
|
||||
static function saveDaemon($daemon) {
|
||||
$daemon['updated_at'] = time();
|
||||
return Setting::setValue(
|
||||
'cron_daemon',
|
||||
$daemon
|
||||
);
|
||||
}
|
||||
|
||||
static function createToken() {
|
||||
return Security::generateRandomString();
|
||||
}
|
||||
|
||||
static function accessDaemon($token, $timeout = self::daemon_request_timeout) {
|
||||
$payload = serialize(array('token' => $token));
|
||||
$url = '/?mailpoet-api§ion=queue&action=run&request_payload=' .
|
||||
base64_encode($payload);
|
||||
$args = array(
|
||||
'timeout' => $timeout,
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||
);
|
||||
$result = wp_remote_get(
|
||||
self::getSiteUrl() . $url,
|
||||
$args
|
||||
);
|
||||
return wp_remote_retrieve_body($result);
|
||||
}
|
||||
|
||||
private static function getSiteUrl() {
|
||||
// additional check for some sites running on a virtual machine or behind
|
||||
// proxy where there could be different ports (e.g., host:8080 => guest:80)
|
||||
|
||||
// if the site URL does not contain a port, return the URL
|
||||
if(!preg_match('!^https?://.*?:\d+!', site_url())) return site_url();
|
||||
preg_match('!://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
||||
// connect to the URL with port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
if($fp) return site_url();
|
||||
// connect to the URL without port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
if($fp) return preg_replace('!(?=:\d+):\d+!', '$1', site_url());
|
||||
// throw an error if all connection attempts failed
|
||||
throw new \Exception(__('Site URL is unreachable.'));
|
||||
}
|
||||
}
|
@@ -2,8 +2,6 @@
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Cron\Workers\SendingQueue;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
@@ -13,132 +11,69 @@ class Daemon {
|
||||
public $daemon;
|
||||
public $request_payload;
|
||||
public $refreshed_token;
|
||||
public $timer;
|
||||
const daemon_request_timeout = 5;
|
||||
private $timer;
|
||||
|
||||
function __construct($request_payload = array()) {
|
||||
set_time_limit(0);
|
||||
ignore_user_abort();
|
||||
$this->daemon = $this->getDaemon();
|
||||
$this->refreshed_token = $this->refreshToken();
|
||||
$this->daemon = CronHelper::getDaemon();
|
||||
$this->token = CronHelper::createToken();
|
||||
$this->request_payload = $request_payload;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
function start() {
|
||||
if(!isset($this->request_payload['session'])) {
|
||||
$this->abortWithError(__('Missing session ID.'));
|
||||
}
|
||||
$this->manageSession('start');
|
||||
function run() {
|
||||
$daemon = $this->daemon;
|
||||
if(!$daemon) {
|
||||
$this->saveDaemon(
|
||||
array(
|
||||
'status' => 'starting',
|
||||
'counter' => 0
|
||||
)
|
||||
);
|
||||
}
|
||||
if($daemon['status'] === 'started') {
|
||||
$_SESSION['cron_daemon'] = array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Daemon already running.'))
|
||||
);
|
||||
}
|
||||
if($daemon['status'] === 'starting') {
|
||||
$_SESSION['cron_daemon'] = 'started';
|
||||
$_SESSION['cron_daemon'] = array('result' => true);
|
||||
$this->manageSession('end');
|
||||
$daemon['status'] = 'started';
|
||||
$daemon['token'] = $this->refreshed_token;
|
||||
$this->saveDaemon($daemon);
|
||||
$this->callSelf();
|
||||
}
|
||||
$this->manageSession('end');
|
||||
}
|
||||
|
||||
function run() {
|
||||
$allowed_statuses = array(
|
||||
'stopping',
|
||||
'starting',
|
||||
'started'
|
||||
);
|
||||
if(!$this->daemon || !in_array($this->daemon['status'], $allowed_statuses)) {
|
||||
$this->abortWithError(__('Invalid daemon status.'));
|
||||
$this->abortWithError(__('Daemon does not exist.'));
|
||||
}
|
||||
if(!isset($this->request_payload['token']) ||
|
||||
$this->request_payload['token'] !== $this->daemon['token']
|
||||
$this->request_payload['token'] !== $daemon['token']
|
||||
) {
|
||||
$this->abortWithError('Invalid token.');
|
||||
$this->abortWithError(__('Invalid or missing token.'));
|
||||
}
|
||||
$this->abortIfStopped($daemon);
|
||||
try {
|
||||
$sending_queue = new SendingQueue($this->timer);
|
||||
$sending_queue->process();
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
$elapsed_time = microtime(true) - $this->timer;
|
||||
if($elapsed_time < 30) {
|
||||
sleep(30 - $elapsed_time);
|
||||
if($elapsed_time < CronHelper::daemon_execution_limit) {
|
||||
sleep(CronHelper::daemon_execution_limit - $elapsed_time);
|
||||
}
|
||||
// after each execution, re-read daemon data in case it was deleted or
|
||||
// its status has changed
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!$daemon || $daemon['token'] !== $this->request_payload['token']) {
|
||||
exit;
|
||||
}
|
||||
// after each execution, read daemon in case its status was modified
|
||||
$daemon = $this->getDaemon();
|
||||
|
||||
if($daemon['status'] === 'stopping') $daemon['status'] = 'stopped';
|
||||
if($daemon['status'] === 'starting') $daemon['status'] = 'started';
|
||||
|
||||
$daemon['token'] = $this->refreshed_token;
|
||||
$daemon['counter']++;
|
||||
|
||||
$this->saveDaemon($daemon);
|
||||
|
||||
if($daemon['status'] === 'started') $this->callSelf();
|
||||
}
|
||||
|
||||
function getDaemon() {
|
||||
return Setting::getValue('cron_daemon');
|
||||
}
|
||||
|
||||
function saveDaemon($daemon_data) {
|
||||
$daemon_data['updated_at'] = time();
|
||||
|
||||
return Setting::setValue(
|
||||
'cron_daemon',
|
||||
$daemon_data
|
||||
);
|
||||
}
|
||||
|
||||
function refreshToken() {
|
||||
return Security::generateRandomString();
|
||||
}
|
||||
|
||||
function manageSession($action) {
|
||||
switch($action) {
|
||||
case 'start':
|
||||
if(session_id()) {
|
||||
session_write_close();
|
||||
}
|
||||
session_id($this->request_payload['session']);
|
||||
session_start();
|
||||
break;
|
||||
case 'end':
|
||||
session_write_close();
|
||||
break;
|
||||
$this->abortIfStopped($daemon);
|
||||
if($daemon['status'] === 'starting') {
|
||||
$daemon['status'] = 'started';
|
||||
}
|
||||
$daemon['token'] = $this->token;
|
||||
CronHelper::saveDaemon($daemon);
|
||||
$this->callSelf();
|
||||
}
|
||||
|
||||
function abortIfStopped($daemon) {
|
||||
if($daemon['status'] === 'stopped') exit;
|
||||
if($daemon['status'] === 'stopping') {
|
||||
$daemon['status'] = 'stopped';
|
||||
CronHelper::saveDaemon($daemon);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function abortWithError($message) {
|
||||
exit('[mailpoet_cron_error:' . base64_encode($message) . ']');
|
||||
}
|
||||
|
||||
function callSelf() {
|
||||
$payload = json_encode(array('token' => $this->refreshed_token));
|
||||
Supervisor::accessRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=run&request_payload=' . urlencode($payload)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
function abortWithError($error) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array($error)
|
||||
));
|
||||
CronHelper::accessDaemon($this->token, self::daemon_request_timeout);
|
||||
exit;
|
||||
}
|
||||
}
|
@@ -1,104 +1,94 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Config\Env;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Supervisor {
|
||||
public $daemon;
|
||||
public $token;
|
||||
public $force_run;
|
||||
|
||||
function __construct($force_start = false) {
|
||||
$this->force_start = $force_start;
|
||||
if(!Env::isPluginActivated()) {
|
||||
throw new \Exception(__('MailPoet is not activated.'));
|
||||
}
|
||||
$this->daemon = $this->getDaemon();
|
||||
function __construct($force_run = false) {
|
||||
$this->daemon = CronHelper::getDaemon();
|
||||
$this->token = CronHelper::createToken();
|
||||
$this->force_run = $force_run;
|
||||
}
|
||||
|
||||
function checkDaemon() {
|
||||
if(!$this->daemon) {
|
||||
return $this->startDaemon();
|
||||
$daemon = $this->daemon;
|
||||
if(!$daemon) {
|
||||
$daemon = CronHelper::createDaemon($this->token);
|
||||
return $this->runDaemon($daemon);
|
||||
}
|
||||
if(
|
||||
!$this->force_start
|
||||
&& isset($this->daemon['status'])
|
||||
&& in_array($this->daemon['status'], array('stopped', 'stopping'))
|
||||
// if the daemon is stopped, return its status and do nothing
|
||||
if(!$this->force_run &&
|
||||
isset($daemon['status']) &&
|
||||
$daemon['status'] === 'stopped'
|
||||
) {
|
||||
return $this->daemon['status'];
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
|
||||
}
|
||||
|
||||
$elapsed_time = time() - (int)$this->daemon['updated_at'];
|
||||
|
||||
if($elapsed_time < 40) {
|
||||
if(!$this->force_start) {
|
||||
return;
|
||||
}
|
||||
if($this->daemon['status'] === 'stopping' ||
|
||||
$this->daemon['status'] === 'starting'
|
||||
) {
|
||||
return $this->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']);
|
||||
}
|
||||
$this->daemon['status'] = 'starting';
|
||||
$this->saveDaemon($this->daemon);
|
||||
return $this->startDaemon();
|
||||
// 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
|
||||
elseif($elapsed_time < CronHelper::daemon_execution_timeout &&
|
||||
$this->force_run &&
|
||||
in_array($daemon['status'], array(
|
||||
'stopping',
|
||||
'starting'
|
||||
))
|
||||
) {
|
||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
||||
}
|
||||
// re-create (restart) daemon
|
||||
CronHelper::createDaemon($this->token);
|
||||
return $this->runDaemon();
|
||||
}
|
||||
|
||||
function startDaemon() {
|
||||
if(!session_id()) session_start();
|
||||
$sessionId = session_id();
|
||||
session_write_close();
|
||||
$_SESSION['cron_daemon'] = null;
|
||||
$requestPayload = json_encode(array('session' => $sessionId));
|
||||
self::accessRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=start&request_payload=' .
|
||||
urlencode($requestPayload)
|
||||
);
|
||||
session_start();
|
||||
$daemonStatus = $_SESSION['cron_daemon'];
|
||||
unset($_SESSION['daemon']);
|
||||
session_write_close();
|
||||
return $daemonStatus;
|
||||
function runDaemon() {
|
||||
$request = CronHelper::accessDaemon($this->token);
|
||||
preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
|
||||
$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']);
|
||||
}
|
||||
|
||||
function getDaemon() {
|
||||
return Setting::getValue('cron_daemon');
|
||||
}
|
||||
|
||||
function saveDaemon($daemon_data) {
|
||||
return Setting::setValue(
|
||||
'cron_daemon',
|
||||
$daemon_data
|
||||
private function formatDaemonStatusMessage($status) {
|
||||
return $this->formatResultMessage(
|
||||
true,
|
||||
sprintf(
|
||||
__('Daemon is currently %s.'),
|
||||
__($status)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static function accessRemoteUrl($url) {
|
||||
$args = array(
|
||||
'timeout' => 1,
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||
private function formatResultMessage($result, $message) {
|
||||
$formattedResult = array(
|
||||
'result' => $result
|
||||
);
|
||||
wp_remote_get(
|
||||
self::getSiteUrl() . $url,
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
static function getSiteUrl() {
|
||||
// additional check for some sites running on a virtual machine or behind
|
||||
// proxy where there could be different ports (e.g., host:8080 => guest:80)
|
||||
|
||||
// if the site URL does not contain a port, return the URL
|
||||
if(!preg_match('!^https?://.*?:\d+!', site_url())) return site_url();
|
||||
preg_match('!://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
||||
// connect to the URL with port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
if($fp) return site_url();
|
||||
// connect to the URL without port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
if($fp) return preg_replace('!(?=:\d+):\d+!', '$1', site_url());
|
||||
// throw an error if all connections fail
|
||||
throw new \Exception(__('Site URL is unreachable.'));
|
||||
if(!$result) {
|
||||
$formattedResult['errors'] = array($message);
|
||||
} else {
|
||||
$formattedResult['message'] = $message;
|
||||
}
|
||||
return $formattedResult;
|
||||
}
|
||||
}
|
@@ -1,123 +1,190 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers;
|
||||
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterStatistics;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue {
|
||||
public $timer;
|
||||
public $mta_config;
|
||||
public $mta_log;
|
||||
public $processing_method;
|
||||
private $timer;
|
||||
const batch_size = 50;
|
||||
|
||||
function __construct($timer = false) {
|
||||
$this->mta_config = $this->getMailerConfig();
|
||||
$this->mta_log = $this->getMailerLog();
|
||||
$this->processing_method = ($this->mta_config['method'] === 'MailPoet') ?
|
||||
'processBulkSubscribers' :
|
||||
'processIndividualSubscriber';
|
||||
$this->timer = ($timer) ? $timer : microtime(true);
|
||||
}
|
||||
|
||||
function process() {
|
||||
// TODO: implement mailer sending frequency limits
|
||||
foreach($this->getQueues() as $queue) {
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id)
|
||||
->asArray();
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id);
|
||||
if(!$newsletter) {
|
||||
continue;
|
||||
};
|
||||
$mailer = $this->configureMailerForNewsletter($newsletter);
|
||||
$newsletter = $this->renderNewsletter($newsletter);
|
||||
$subscribers = json_decode($queue->subscribers, true);
|
||||
$subscribers_to_process = $subscribers['to_process'];
|
||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
||||
foreach(array_chunk($subscribers_to_process, 200) as $subscriber_ids) {
|
||||
$db_subscribers = Subscriber::whereIn('id', $subscriber_ids)
|
||||
}
|
||||
$queue->subscribers = (object) unserialize($queue->subscribers);
|
||||
if(!isset($queue->subscribers->processed)) {
|
||||
$queue->subscribers->processed = array();
|
||||
}
|
||||
if(!isset($queue->subscribers->failed)) {
|
||||
$queue->subscribers->failed = array();
|
||||
}
|
||||
$newsletter = $newsletter->asArray();
|
||||
$newsletter['body'] = $this->renderNewsletter($newsletter);
|
||||
$mailer = $this->configureMailer($newsletter);
|
||||
foreach(array_chunk($queue->subscribers->to_process, self::batch_size) as
|
||||
$subscribers_ids) {
|
||||
$subscribers = Subscriber::whereIn('id', $subscribers_ids)
|
||||
->findArray();
|
||||
foreach($db_subscribers as $db_subscriber) {
|
||||
$this->checkExecutionTimer();
|
||||
$result = $this->sendNewsletter(
|
||||
$queue->subscribers = call_user_func_array(
|
||||
array(
|
||||
$this,
|
||||
$this->processing_method
|
||||
),
|
||||
array(
|
||||
$mailer,
|
||||
$this->processNewsletter($newsletter),
|
||||
$db_subscriber);
|
||||
if($result) {
|
||||
$this->updateStatistics($newsletter['id'], $db_subscriber['id'], $queue->id);
|
||||
$subscribers['processed'][] = $db_subscriber['id'];
|
||||
} else {
|
||||
$subscribers['failed'][] = $db_subscriber['id'];
|
||||
}
|
||||
$this->updateQueue($queue, $subscribers);
|
||||
}
|
||||
$newsletter,
|
||||
$subscribers,
|
||||
$queue
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processNewsletter($newsletter) {
|
||||
// TODO: replace shortcodes, etc..
|
||||
function processBulkSubscribers($mailer, $newsletter, $subscribers, $queue) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
$processed_newsletters[] =
|
||||
$this->processNewsletter($newsletter, $subscriber);
|
||||
$transformed_subscribers[] =
|
||||
$mailer->transformSubscriber($subscriber);
|
||||
}
|
||||
$result = $this->sendNewsletter(
|
||||
$mailer,
|
||||
$processed_newsletters,
|
||||
$transformed_subscribers
|
||||
);
|
||||
$subscribers_ids = Helpers::arrayColumn($subscribers, 'id');
|
||||
if(!$result) {
|
||||
$queue->subscribers->failed = array_merge(
|
||||
$queue->subscribers->failed,
|
||||
$subscribers_ids
|
||||
);
|
||||
} else {
|
||||
$newsletter_statistics =
|
||||
array_map(function ($data) use ($newsletter, $subscribers_ids, $queue) {
|
||||
return array(
|
||||
$newsletter['id'],
|
||||
$subscribers_ids[$data],
|
||||
$queue->id
|
||||
);
|
||||
}, range(0, count($transformed_subscribers) - 1));
|
||||
$newsletter_statistics = Helpers::flattenArray($newsletter_statistics);
|
||||
$this->updateMailerLog();
|
||||
$this->updateNewsletterStatistics($newsletter_statistics);
|
||||
$queue->subscribers->processed = array_merge(
|
||||
$queue->subscribers->processed,
|
||||
$subscribers_ids
|
||||
);
|
||||
}
|
||||
$this->updateQueue($queue);
|
||||
$this->checkSendingLimit();
|
||||
$this->checkExecutionTimer();
|
||||
return $queue->subscribers;
|
||||
}
|
||||
|
||||
function processIndividualSubscriber($mailer, $newsletter, $subscribers, $queue) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
$this->checkSendingLimit();
|
||||
$processed_newsletter = $this->processNewsletter($newsletter, $subscriber);
|
||||
$transformed_subscriber = $mailer->transformSubscriber($subscriber);
|
||||
$result = $this->sendNewsletter(
|
||||
$mailer,
|
||||
$processed_newsletter,
|
||||
$transformed_subscriber
|
||||
);
|
||||
if(!$result) {
|
||||
$queue->subscribers->failed[] = $subscriber['id'];;
|
||||
} else {
|
||||
$queue->subscribers->processed[] = $subscriber['id'];
|
||||
$newsletter_statistics = array(
|
||||
$newsletter['id'],
|
||||
$subscriber['id'],
|
||||
$queue->id
|
||||
);
|
||||
$this->updateMailerLog();
|
||||
$this->updateNewsletterStatistics($newsletter_statistics);
|
||||
}
|
||||
$this->updateQueue($queue);
|
||||
$this->checkExecutionTimer();
|
||||
}
|
||||
return $queue->subscribers;
|
||||
}
|
||||
|
||||
function updateNewsletterStatistics($data) {
|
||||
return NewsletterStatistics::createMultiple($data);
|
||||
}
|
||||
|
||||
function renderNewsletter($newsletter) {
|
||||
$renderer = new Renderer($newsletter);
|
||||
return $renderer->render();
|
||||
}
|
||||
|
||||
function processNewsletter($newsletter, $subscriber = false) {
|
||||
$divider = '***MailPoet***';
|
||||
$shortcodes = new Shortcodes(
|
||||
implode($divider, $newsletter['body']),
|
||||
$newsletter,
|
||||
$subscriber
|
||||
);
|
||||
list($newsletter['body']['html'], $newsletter['body']['text']) =
|
||||
explode($divider, $shortcodes->replace());
|
||||
return $newsletter;
|
||||
}
|
||||
|
||||
function sendNewsletter($mailer, $newsletter, $subscriber) {
|
||||
return $mailer->mailer_instance->send(
|
||||
$newsletter,
|
||||
$mailer->transformSubscriber($subscriber)
|
||||
$subscriber
|
||||
);
|
||||
}
|
||||
|
||||
function updateStatistics($newsletter_id, $subscriber_id, $queue_id) {
|
||||
$newsletter_statistic = NewsletterStatistics::create();
|
||||
$newsletter_statistic->subscriber_id = $newsletter_id;
|
||||
$newsletter_statistic->newsletter_id = $subscriber_id;
|
||||
$newsletter_statistic->queue_id = $queue_id;
|
||||
$newsletter_statistic->save();
|
||||
}
|
||||
|
||||
function updateQueue($queue, $subscribers) {
|
||||
$subscribers['to_process'] = array_values(
|
||||
array_diff(
|
||||
$subscribers['to_process'],
|
||||
array_merge($subscribers['processed'], $subscribers['failed'])
|
||||
)
|
||||
);
|
||||
$queue->count_processed =
|
||||
count($subscribers['processed']) + count($subscribers['failed']);
|
||||
$queue->count_to_process = count($subscribers['to_process']);
|
||||
$queue->count_failed = count($subscribers['failed']);
|
||||
$queue->count_total =
|
||||
$queue->count_processed + $queue->count_to_process;
|
||||
if(!$queue->count_to_process) {
|
||||
$queue->processed_at = date('Y-m-d H:i:s');
|
||||
$queue->status = 'completed';
|
||||
}
|
||||
$queue->subscribers = json_encode($subscribers);
|
||||
$queue->save();
|
||||
}
|
||||
|
||||
function configureMailerForNewsletter($newsletter) {
|
||||
if(!empty($newsletter['sender_address']) && !empty($newsletter['sender_name'])) {
|
||||
$sender = array(
|
||||
'name' => $newsletter['sender_name'],
|
||||
'address' => $newsletter['sender_address']
|
||||
);
|
||||
} else {
|
||||
function configureMailer($newsletter) {
|
||||
$sender['address'] = (!empty($newsletter['sender_address'])) ?
|
||||
$newsletter['sender_address'] :
|
||||
false;
|
||||
$sender['name'] = (!empty($newsletter['sender_name'])) ?
|
||||
$newsletter['sender_name'] :
|
||||
false;
|
||||
$reply_to['address'] = (!empty($newsletter['reply_to_address'])) ?
|
||||
$newsletter['reply_to_address'] :
|
||||
false;
|
||||
$reply_to['name'] = (!empty($newsletter['reply_to_name'])) ?
|
||||
$newsletter['reply_to_name'] :
|
||||
false;
|
||||
if(!$sender['address']) {
|
||||
$sender = false;
|
||||
}
|
||||
if(!empty($newsletter['reply_to_address']) && !empty($newsletter['reply_to_name'])) {
|
||||
$reply_to = array(
|
||||
'name' => $newsletter['reply_to_name'],
|
||||
'address' => $newsletter['reply_to_address']
|
||||
);
|
||||
} else {
|
||||
if(!$reply_to['address']) {
|
||||
$reply_to = false;
|
||||
}
|
||||
$mailer = new Mailer($method = false, $sender, $reply_to);
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
function checkExecutionTimer() {
|
||||
$elapsed_time = microtime(true) - $this->timer;
|
||||
if($elapsed_time >= 30) throw new \Exception('Maximum execution time reached.');
|
||||
}
|
||||
|
||||
function getQueues() {
|
||||
return \MailPoet\Models\SendingQueue::orderByDesc('priority')
|
||||
->whereNull('deleted_at')
|
||||
@@ -125,10 +192,78 @@ class SendingQueue {
|
||||
->findResultSet();
|
||||
}
|
||||
|
||||
function renderNewsletter($newsletter) {
|
||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
||||
// TODO: update once text rendering is implemented/enderer returns an array
|
||||
$newsletter['body'] = array('html' => $renderer->render(), 'text' => '');
|
||||
return $newsletter;
|
||||
function updateQueue($queue) {
|
||||
$queue = clone($queue);
|
||||
$queue->subscribers->to_process = array_diff(
|
||||
$queue->subscribers->to_process,
|
||||
array_merge(
|
||||
$queue->subscribers->processed,
|
||||
$queue->subscribers->failed
|
||||
)
|
||||
);
|
||||
$queue->subscribers->to_process = array_values($queue->subscribers->to_process);
|
||||
$queue->count_processed =
|
||||
count($queue->subscribers->processed) + count($queue->subscribers->failed);
|
||||
$queue->count_to_process = count($queue->subscribers->to_process);
|
||||
$queue->count_failed = count($queue->subscribers->failed);
|
||||
$queue->count_total =
|
||||
$queue->count_processed + $queue->count_to_process;
|
||||
if(!$queue->count_to_process) {
|
||||
$queue->processed_at = date('Y-m-d H:i:s');
|
||||
$queue->status = 'completed';
|
||||
}
|
||||
$queue->subscribers = serialize((array) $queue->subscribers);
|
||||
$queue->save();
|
||||
}
|
||||
|
||||
function updateMailerLog() {
|
||||
$this->mta_log['sent']++;
|
||||
return Setting::setValue('mta_log', $this->mta_log);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function checkSendingLimit() {
|
||||
$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 reached.'));
|
||||
}
|
||||
if($elapsed_time > $frequency_interval) {
|
||||
$this->mta_log = array(
|
||||
'sent' => 0,
|
||||
'started' => time()
|
||||
);
|
||||
Setting::setValue('mta_log', $this->mta_log);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function checkExecutionTimer() {
|
||||
$elapsed_time = microtime(true) - $this->timer;
|
||||
if($elapsed_time >= CronHelper::daemon_execution_limit) {
|
||||
throw new \Exception(__('Maximum execution time reached.'));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Form\Block;
|
||||
|
||||
class Input extends Base {
|
||||
class Text extends Base {
|
||||
|
||||
static function render($block) {
|
||||
$type = 'text';
|
||||
@@ -15,7 +15,7 @@ class Input extends Base {
|
||||
|
||||
$html .= static::renderLabel($block);
|
||||
|
||||
$html .= '<input type="'.$type.'" class="mailpoet_input" ';
|
||||
$html .= '<input type="'.$type.'" class="mailpoet_text" ';
|
||||
|
||||
$html .= 'name="'.static::getFieldName($block).'" ';
|
||||
|
@@ -49,7 +49,7 @@ class Renderer {
|
||||
|
||||
private static function renderBlock($block = array()) {
|
||||
$html = '';
|
||||
switch ($block['type']) {
|
||||
switch($block['type']) {
|
||||
case 'html':
|
||||
$html .= Block\Html::render($block);
|
||||
break;
|
||||
@@ -78,8 +78,8 @@ class Renderer {
|
||||
$html .= Block\Select::render($block);
|
||||
break;
|
||||
|
||||
case 'input':
|
||||
$html .= Block\Input::render($block);
|
||||
case 'text':
|
||||
$html .= Block\Text::render($block);
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
|
@@ -65,6 +65,8 @@ class Widget extends \WP_Widget {
|
||||
)
|
||||
);
|
||||
|
||||
$form_edit_url = admin_url('admin.php?page=mailpoet-form-editor&id=');
|
||||
|
||||
// set title
|
||||
$title = isset($instance['title']) ? strip_tags($instance['title']) : '';
|
||||
|
||||
@@ -102,8 +104,9 @@ class Widget extends \WP_Widget {
|
||||
endpoint: 'forms',
|
||||
action: 'create'
|
||||
}).done(function(response) {
|
||||
if(response !== false) {
|
||||
window.location = response;
|
||||
if(response.result && response.form_id) {
|
||||
window.location =
|
||||
"<?php echo $form_edit_url; ?>" + response.form_id;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
|
@@ -19,82 +19,77 @@ class Mailer {
|
||||
$this->reply_to = $this->getReplyTo($reply_to);
|
||||
$this->mailer_instance = $this->buildMailer();
|
||||
}
|
||||
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$subscriber = $this->transformSubscriber($subscriber);
|
||||
return $this->mailer_instance->send($newsletter, $subscriber);
|
||||
}
|
||||
|
||||
|
||||
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'],
|
||||
$this->sender['from_name_email']
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['domain'],
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['from_name_email']
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['mailpoet_api_key'],
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
break;
|
||||
case 'Mandrill':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
break;
|
||||
case 'WPMail':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
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'],
|
||||
$this->sender['from_email'],
|
||||
$this->sender['from_name']
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(__('Mailing method does not exist.'));
|
||||
break;
|
||||
case 'AmazonSES':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['region'],
|
||||
$this->mailer['access_key'],
|
||||
$this->mailer['secret_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['domain'],
|
||||
$this->mailer['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['mailpoet_api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailer_instance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
case 'PHPMail':
|
||||
$mailer_instance = new $this->mailer['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'],
|
||||
$this->sender,
|
||||
$this->reply_to
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(__('Mailing method does not exist.'));
|
||||
break;
|
||||
}
|
||||
return $mailer_instance;
|
||||
}
|
||||
|
||||
|
||||
function getMailer($mailer = false) {
|
||||
if(!$mailer) {
|
||||
$mailer = Setting::getValue('mta', null);
|
||||
@@ -107,7 +102,7 @@ class Mailer {
|
||||
function getSender($sender = false) {
|
||||
if(!$sender) {
|
||||
$sender = Setting::getValue('sender', null);
|
||||
if(!$sender) throw new \Exception(__('Sender name and email are not configured.'));
|
||||
if(!$sender['address']) throw new \Exception(__('Sender name and email are not configured.'));
|
||||
}
|
||||
return array(
|
||||
'from_name' => $sender['name'],
|
||||
@@ -126,6 +121,9 @@ class Mailer {
|
||||
);
|
||||
}
|
||||
}
|
||||
if(!$reply_to['address']) {
|
||||
$reply_to['address'] = $this->sender['from_email'];
|
||||
}
|
||||
return array(
|
||||
'reply_to_name' => $reply_to['name'],
|
||||
'reply_to_email' => $reply_to['address'],
|
||||
|
@@ -13,25 +13,27 @@ class AmazonSES {
|
||||
public $aws_termination_string;
|
||||
public $hash_algorithm;
|
||||
public $url;
|
||||
public $from;
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $date;
|
||||
public $date_without_time;
|
||||
|
||||
function __construct($region, $access_key, $secret_key, $from) {
|
||||
|
||||
function __construct($region, $access_key, $secret_key, $sender, $reply_to) {
|
||||
$this->aws_access_key = $access_key;
|
||||
$this->aws_secret_key = $secret_key;
|
||||
$this->aws_region = $region;
|
||||
$this->aws_endpoint = sprintf('email.%s.amazonaws.com', $region);
|
||||
$this->aws_endpoint = sprintf('email.%s.amazonaws.com', $this->aws_region);
|
||||
$this->aws_signing_algorithm = 'AWS4-HMAC-SHA256';
|
||||
$this->aws_service = 'ses';
|
||||
$this->aws_termination_string = 'aws4_request';
|
||||
$this->hash_algorithm = 'sha256';
|
||||
$this->url = 'https://' . $this->aws_endpoint;
|
||||
$this->from = $from;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
$this->date = gmdate('Ymd\THis\Z');
|
||||
$this->date_without_time = gmdate('Ymd');
|
||||
}
|
||||
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
@@ -42,15 +44,16 @@ class AmazonSES {
|
||||
wp_remote_retrieve_response_code($result) === 200
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'Action' => 'SendEmail',
|
||||
'Version' => '2010-12-01',
|
||||
'Source' => $this->from,
|
||||
'Destination.ToAddresses.member.1' => $subscriber,
|
||||
'Source' => $this->sender['from_name_email'],
|
||||
'ReplyToAddresses.member.1' => $this->reply_to['reply_to_name_email'],
|
||||
'Message.Subject.Data' => $newsletter['subject'],
|
||||
'ReturnPath' => $this->from
|
||||
'ReturnPath' => $this->sender['from_name_email'],
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['Message.Body.Html.Data'] = $newsletter['body']['html'];
|
||||
@@ -60,7 +63,7 @@ class AmazonSES {
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
$body = $this->getBody($newsletter, $subscriber);
|
||||
return array(
|
||||
@@ -75,7 +78,7 @@ class AmazonSES {
|
||||
'body' => urldecode(http_build_query($body))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function signRequest($body) {
|
||||
$string_to_sign = $this->createStringToSign(
|
||||
$this->getCredentialScope(),
|
||||
@@ -86,7 +89,7 @@ class AmazonSES {
|
||||
$string_to_sign,
|
||||
$this->getSigningKey()
|
||||
);
|
||||
|
||||
|
||||
return sprintf(
|
||||
'%s Credential=%s/%s, SignedHeaders=host;x-amz-date, Signature=%s',
|
||||
$this->aws_signing_algorithm,
|
||||
@@ -94,7 +97,7 @@ class AmazonSES {
|
||||
$this->getCredentialScope(),
|
||||
$signature);
|
||||
}
|
||||
|
||||
|
||||
function getCredentialScope() {
|
||||
return sprintf(
|
||||
'%s/%s/%s/%s',
|
||||
@@ -103,7 +106,7 @@ class AmazonSES {
|
||||
$this->aws_service,
|
||||
$this->aws_termination_string);
|
||||
}
|
||||
|
||||
|
||||
function getCanonicalRequest($body) {
|
||||
return implode("\n", array(
|
||||
'POST',
|
||||
@@ -116,7 +119,7 @@ class AmazonSES {
|
||||
hash($this->hash_algorithm, urldecode(http_build_query($body)))
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
function createStringToSign($credential_scope, $canonical_request) {
|
||||
return implode("\n", array(
|
||||
$this->aws_signing_algorithm,
|
||||
@@ -125,7 +128,7 @@ class AmazonSES {
|
||||
hash($this->hash_algorithm, $canonical_request)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
function getSigningKey() {
|
||||
$date_key = hash_hmac(
|
||||
$this->hash_algorithm,
|
||||
|
@@ -6,13 +6,13 @@ if(!defined('ABSPATH')) exit;
|
||||
class ElasticEmail {
|
||||
public $url = 'https://api.elasticemail.com/mailer/send';
|
||||
public $api_key;
|
||||
public $from_email;
|
||||
public $from_name;
|
||||
|
||||
function __construct($api_key, $from_email, $from_name) {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
|
||||
function __construct($api_key, $sender, $reply_to) {
|
||||
$this->api_key = $api_key;
|
||||
$this->from_email = $from_email;
|
||||
$this->from_name = $from_name;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
@@ -28,9 +28,11 @@ class ElasticEmail {
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'api_key' => $this->api_key,
|
||||
'from' => $this->from_email,
|
||||
'from_name' => $this->from_name,
|
||||
'to' => $subscriber,
|
||||
'from' => $this->sender['from_email'],
|
||||
'from_name' => $this->sender['from_name'],
|
||||
'reply_to' => $this->reply_to['reply_to_email'],
|
||||
'reply_to_name' => $this->reply_to['reply_to_name'],
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
|
@@ -6,12 +6,14 @@ if(!defined('ABSPATH')) exit;
|
||||
class MailGun {
|
||||
public $url;
|
||||
public $api_key;
|
||||
public $from;
|
||||
|
||||
function __construct($domain, $api_key, $from) {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
|
||||
function __construct($domain, $api_key, $sender, $reply_to) {
|
||||
$this->url = sprintf('https://api.mailgun.net/v3/%s/messages', $domain);
|
||||
$this->api_key = $api_key;
|
||||
$this->from = $from;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
@@ -27,8 +29,9 @@ class MailGun {
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'from' => $this->from,
|
||||
'to' => $subscriber,
|
||||
'from' => $this->sender['from_name_email'],
|
||||
'h:Reply-To' => $this->reply_to['reply_to_name_email'],
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
|
@@ -6,26 +6,27 @@ if(!defined('ABSPATH')) exit;
|
||||
class MailPoet {
|
||||
public $url = 'https://bridge.mailpoet.com/api/messages';
|
||||
public $api_key;
|
||||
public $from_email;
|
||||
public $from_name;
|
||||
|
||||
function __construct($api_key, $from_email, $from_name) {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
|
||||
function __construct($api_key, $sender, $reply_to) {
|
||||
$this->api_key = $api_key;
|
||||
$this->from_email = $from_email;
|
||||
$this->from_name = $from_name;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
}
|
||||
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$message_body = $this->getBody($newsletter, $subscriber);
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($newsletter, $this->processSubscriber($subscriber))
|
||||
$this->request($message_body)
|
||||
);
|
||||
return (
|
||||
!is_wp_error($result) === true &&
|
||||
wp_remote_retrieve_response_code($result) === 201
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||
if(!isset($subscriber_data['email'])) {
|
||||
@@ -38,34 +39,51 @@ class MailPoet {
|
||||
'name' => (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'to' => (array(
|
||||
'address' => $subscriber['email'],
|
||||
'name' => $subscriber['name']
|
||||
)),
|
||||
'from' => (array(
|
||||
'address' => $this->from_email,
|
||||
'name' => $this->from_name
|
||||
)),
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['text'] = $newsletter['body']['text'];
|
||||
$composeBody = function ($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'to' => (array(
|
||||
'address' => $subscriber['email'],
|
||||
'name' => $subscriber['name']
|
||||
)),
|
||||
'from' => (array(
|
||||
'address' => $this->sender['from_email'],
|
||||
'name' => $this->sender['from_name']
|
||||
)),
|
||||
'reply_to' => (array(
|
||||
'address' => $this->reply_to['reply_to_email'],
|
||||
'name' => $this->reply_to['reply_to_name']
|
||||
)),
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
};
|
||||
if(is_array($newsletter) && is_array($subscriber)) {
|
||||
$body = array();
|
||||
for($record = 0; $record < count($newsletter); $record++) {
|
||||
$body[] = $composeBody(
|
||||
$newsletter[$record],
|
||||
$this->processSubscriber($subscriber[$record])
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$body[] = $composeBody($newsletter, $this->processSubscriber($subscriber));
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
||||
function auth() {
|
||||
return 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
$body = array($this->getBody($newsletter, $subscriber));
|
||||
|
||||
function request($body) {
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.0',
|
||||
@@ -74,7 +92,7 @@ class MailPoet {
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $this->auth()
|
||||
),
|
||||
'body' => $body
|
||||
'body' => json_encode($body)
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mandrill {
|
||||
public $url = 'https://mandrillapp.com/api/1.0/messages/send.json';
|
||||
public $api_key;
|
||||
public $from_email;
|
||||
public $from_name;
|
||||
|
||||
function __construct($api_key, $from_email, $from_name) {
|
||||
$this->api_key = $api_key;
|
||||
$this->from_name = $from_name;
|
||||
$this->from_email = $from_email;
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$result = wp_remote_post(
|
||||
$this->url,
|
||||
$this->request($newsletter, $this->processSubscriber($subscriber))
|
||||
);
|
||||
return (
|
||||
!is_wp_error($result) === true &&
|
||||
!preg_match('!invalid!', $result['body']) === true &&
|
||||
wp_remote_retrieve_response_code($result) === 200
|
||||
);
|
||||
}
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||
if(!isset($subscriber_data['email'])) {
|
||||
$subscriber_data = array(
|
||||
'email' => $subscriber,
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'email' => $subscriber_data['email'],
|
||||
'name' => (isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||
);
|
||||
}
|
||||
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'key' => $this->api_key,
|
||||
'message' => array(
|
||||
'from_email' => $this->from_email,
|
||||
'from_name' => $this->from_name,
|
||||
'to' => array($subscriber),
|
||||
'subject' => $newsletter['subject']
|
||||
),
|
||||
'async' => false,
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$body['message']['html'] = $newsletter['body']['html'];
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$body['message']['text'] = $newsletter['body']['text'];
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
function request($newsletter, $subscriber) {
|
||||
$body = $this->getBody($newsletter, $subscriber);
|
||||
return array(
|
||||
'timeout' => 10,
|
||||
'httpversion' => '1.0',
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json'
|
||||
),
|
||||
'body' => json_encode($body)
|
||||
);
|
||||
}
|
||||
}
|
64
lib/Mailer/Methods/PHPMail.php
Normal file
64
lib/Mailer/Methods/PHPMail.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class PHPMail {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $mailer;
|
||||
|
||||
function __construct($sender, $reply_to) {
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
$this->mailer = $this->buildMailer();
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
try {
|
||||
$message = $this->createMessage($newsletter, $subscriber);
|
||||
$result = $this->mailer->send($message);
|
||||
} catch(\Exception $e) {
|
||||
$result = false;
|
||||
}
|
||||
return ($result === 1);
|
||||
}
|
||||
|
||||
function buildMailer() {
|
||||
$transport = \Swift_SmtpTransport::newInstance();
|
||||
$transport->setTimeout(10);
|
||||
return \Swift_Mailer::newInstance($transport);
|
||||
}
|
||||
|
||||
function createMessage($newsletter, $subscriber) {
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setFrom(array(
|
||||
$this->sender['from_email'] => $this->sender['from_name']
|
||||
))
|
||||
->setReplyTo(array(
|
||||
$this->reply_to['reply_to_email'] => $this->reply_to['reply_to_name']
|
||||
))
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||
}
|
||||
if(!empty($newsletter['body']['text'])) {
|
||||
$message = $message->addPart($newsletter['body']['text'], 'text/plain');
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
function processSubscriber($subscriber) {
|
||||
preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriber_data);
|
||||
if(!isset($subscriber_data['email'])) {
|
||||
$subscriber_data = array(
|
||||
'email' => $subscriber,
|
||||
);
|
||||
}
|
||||
return array(
|
||||
$subscriber_data['email'] =>
|
||||
(isset($subscriber_data['name'])) ? $subscriber_data['name'] : ''
|
||||
);
|
||||
}
|
||||
}
|
@@ -10,21 +10,21 @@ class SMTP {
|
||||
public $login;
|
||||
public $password;
|
||||
public $encryption;
|
||||
public $from_name;
|
||||
public $from_email;
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $mailer;
|
||||
|
||||
|
||||
function __construct(
|
||||
$host, $port, $authentication, $login = null, $password = null, $encryption,
|
||||
$from_email, $from_name) {
|
||||
$sender, $reply_to) {
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->authentication = $authentication;
|
||||
$this->login = $login;
|
||||
$this->password = $password;
|
||||
$this->encryption = $encryption;
|
||||
$this->from_name = $from_name;
|
||||
$this->from_email = $from_email;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
$this->mailer = $this->buildMailer();
|
||||
}
|
||||
|
||||
@@ -50,11 +50,15 @@ class SMTP {
|
||||
return \Swift_Mailer::newInstance($transport);
|
||||
}
|
||||
|
||||
|
||||
function createMessage($newsletter, $subscriber) {
|
||||
$message = \Swift_Message::newInstance()
|
||||
->setFrom(array($this->from_email => $this->from_name))
|
||||
->setTo($this->processSubscriber($subscriber))
|
||||
->setFrom(array(
|
||||
$this->sender['from_email'] => $this->sender['from_name']
|
||||
))
|
||||
->setReplyTo(array(
|
||||
$this->reply_to['reply_to_email'] => $this->reply_to['reply_to_name']
|
||||
))
|
||||
->setSubject($newsletter['subject']);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
$message = $message->setBody($newsletter['body']['html'], 'text/html');
|
||||
|
@@ -6,13 +6,13 @@ if(!defined('ABSPATH')) exit;
|
||||
class SendGrid {
|
||||
public $url = 'https://api.sendgrid.com/api/mail.send.json';
|
||||
public $api_key;
|
||||
public $from_email;
|
||||
public $from_name;
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
|
||||
function __construct($api_key, $from_email, $from_name) {
|
||||
function __construct($api_key, $sender, $reply_to) {
|
||||
$this->api_key = $api_key;
|
||||
$this->from_email = $from_email;
|
||||
$this->from_name = $from_name;
|
||||
$this->sender = $sender;
|
||||
$this->reply_to = $reply_to;
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
@@ -20,10 +20,11 @@ class SendGrid {
|
||||
$this->url,
|
||||
$this->request($newsletter, $subscriber)
|
||||
);
|
||||
$result_body = json_decode($result['body'], true);
|
||||
return (
|
||||
!is_wp_error($result) === true &&
|
||||
!preg_match('!invalid!', $result['body']) === true &&
|
||||
!isset(json_decode($result['body'], true)['errors']) === true &&
|
||||
!isset($result_body['errors']) === true &&
|
||||
wp_remote_retrieve_response_code($result) === 200
|
||||
);
|
||||
}
|
||||
@@ -31,8 +32,9 @@ class SendGrid {
|
||||
function getBody($newsletter, $subscriber) {
|
||||
$body = array(
|
||||
'to' => $subscriber,
|
||||
'from' => $this->from_email,
|
||||
'from_name' => $this->from_name,
|
||||
'from' => $this->sender['from_email'],
|
||||
'fromname' => $this->sender['from_name'],
|
||||
'replyto' => $this->reply_to['reply_to_email'],
|
||||
'subject' => $newsletter['subject']
|
||||
);
|
||||
if(!empty($newsletter['body']['html'])) {
|
||||
@@ -57,7 +59,7 @@ class SendGrid {
|
||||
'headers' => array(
|
||||
'Authorization' => $this->auth()
|
||||
),
|
||||
'body' => urldecode(http_build_query($body))
|
||||
'body' => http_build_query($body)
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class WPMail {
|
||||
public $from_email;
|
||||
public $from_name;
|
||||
public $filters = array(
|
||||
'wp_mail_from' => 'setFromEmail',
|
||||
'wp_mail_from_name' => 'setFromName',
|
||||
'wp_mail_content_type' => 'setContentType'
|
||||
);
|
||||
|
||||
function __construct($from_email, $from_name) {
|
||||
$this->from_email = $from_email;
|
||||
$this->from_name = $from_name;
|
||||
}
|
||||
|
||||
function addFilters() {
|
||||
foreach($this->filters as $filter => $method) {
|
||||
add_filter($filter, array(
|
||||
$this,
|
||||
$method
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function removeFilters() {
|
||||
foreach($this->filters as $filter => $method) {
|
||||
remove_filter($filter, array(
|
||||
$this,
|
||||
$method
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function setFromEmail() {
|
||||
return $this->from_email;
|
||||
}
|
||||
|
||||
function setFromName() {
|
||||
return $this->from_name;
|
||||
}
|
||||
|
||||
function setContentType() {
|
||||
return 'text/html';
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$this->addFilters();
|
||||
$result = wp_mail(
|
||||
$subscriber, $newsletter['subject'],
|
||||
(!empty($newsletter['body']['html'])) ?
|
||||
$newsletter['body']['html'] :
|
||||
$newsletter['body']['text']
|
||||
);
|
||||
$this->removeFilters();
|
||||
return ($result === true);
|
||||
}
|
||||
}
|
@@ -19,20 +19,22 @@ class CustomField extends Model {
|
||||
function asArray() {
|
||||
$model = parent::asArray();
|
||||
|
||||
$model['params'] = (
|
||||
is_serialized($this->params)
|
||||
? unserialize($this->params)
|
||||
: $this->params
|
||||
);
|
||||
|
||||
if(isset($model['params'])) {
|
||||
$model['params'] = (is_array($this->params))
|
||||
? $this->params
|
||||
: unserialize($this->params);
|
||||
}
|
||||
return $model;
|
||||
}
|
||||
|
||||
function save() {
|
||||
if(is_null($this->params)) {
|
||||
$this->params = array();
|
||||
}
|
||||
$this->set('params', (
|
||||
is_serialized($this->params)
|
||||
? $this->params
|
||||
: serialize($this->params)
|
||||
is_array($this->params)
|
||||
? serialize($this->params)
|
||||
: $this->params
|
||||
));
|
||||
return parent::save();
|
||||
}
|
||||
@@ -54,7 +56,7 @@ class CustomField extends Model {
|
||||
}
|
||||
|
||||
// set name as label by default
|
||||
if(empty($data['params']['label'])) {
|
||||
if(empty($data['params']['label']) && isset($data['name'])) {
|
||||
$data['params']['label'] = $data['name'];
|
||||
}
|
||||
|
||||
@@ -66,12 +68,6 @@ class CustomField extends Model {
|
||||
$custom_field->set($data);
|
||||
}
|
||||
|
||||
try {
|
||||
$custom_field->save();
|
||||
return $custom_field;
|
||||
} catch(Exception $e) {
|
||||
return $custom_field->getValidationErrors();
|
||||
}
|
||||
return false;
|
||||
return $custom_field->save();
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
<?php namespace MailPoet\Models;
|
||||
|
||||
class CustomValidator {
|
||||
function __construct() {
|
||||
$this->validator = new \Sudzy\Engine();
|
||||
}
|
||||
|
||||
function init() {
|
||||
$this->validator
|
||||
->addValidator('isString', function ($val) {
|
||||
return is_string($val);
|
||||
});
|
||||
|
||||
return $this->validator;
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Filter extends Model {
|
||||
static $_table = MP_FILTERS_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => __('You need to specify a name.')
|
||||
));
|
||||
}
|
||||
|
||||
function delete() {
|
||||
// delete all relations to subscribers
|
||||
SegmentFilter::where('filter_id', $this->id)->deleteMany();
|
||||
return parent::delete();
|
||||
}
|
||||
|
||||
function segments() {
|
||||
return $this->has_many_through(
|
||||
__NAMESPACE__.'\Segment',
|
||||
__NAMESPACE__.'\SegmentFilter',
|
||||
'filter_id',
|
||||
'segment_id'
|
||||
);
|
||||
}
|
||||
|
||||
static function createOrUpdate($data = array()) {
|
||||
$filter = false;
|
||||
|
||||
if(isset($data['id']) && (int)$data['id'] > 0) {
|
||||
$filter = self::findOne((int)$data['id']);
|
||||
}
|
||||
|
||||
if($filter === false) {
|
||||
$filter = self::create();
|
||||
$filter->hydrate($data);
|
||||
} else {
|
||||
unset($data['id']);
|
||||
$filter->set($data);
|
||||
}
|
||||
|
||||
$filter->save();
|
||||
return $filter;
|
||||
}
|
||||
}
|
@@ -17,36 +17,30 @@ class Form extends Model {
|
||||
function asArray() {
|
||||
$model = parent::asArray();
|
||||
|
||||
$model['body'] = (
|
||||
is_serialized($this->body)
|
||||
$model['body'] = (is_serialized($this->body))
|
||||
? unserialize($this->body)
|
||||
: $this->body
|
||||
);
|
||||
$model['settings'] = (
|
||||
is_serialized($this->settings)
|
||||
: $this->body;
|
||||
$model['settings'] = (is_serialized($this->settings))
|
||||
? unserialize($this->settings)
|
||||
: $this->settings
|
||||
);
|
||||
: $this->settings;
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
function save() {
|
||||
$this->set('body', (
|
||||
is_serialized($this->body)
|
||||
$this->set('body', (is_serialized($this->body))
|
||||
? $this->body
|
||||
: serialize($this->body)
|
||||
));
|
||||
$this->set('settings', (
|
||||
is_serialized($this->settings)
|
||||
);
|
||||
$this->set('settings', (is_serialized($this->settings))
|
||||
? $this->settings
|
||||
: serialize($this->settings)
|
||||
));
|
||||
);
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
return $orm->where_like('name', '%'.$search.'%');
|
||||
return $orm->whereLike('name', '%'.$search.'%');
|
||||
}
|
||||
|
||||
static function groups() {
|
||||
@@ -67,9 +61,8 @@ class Form extends Model {
|
||||
static function groupBy($orm, $group = null) {
|
||||
if($group === 'trash') {
|
||||
return $orm->whereNotNull('deleted_at');
|
||||
} else {
|
||||
$orm = $orm->whereNull('deleted_at');
|
||||
}
|
||||
return $orm->whereNull('deleted_at');
|
||||
}
|
||||
|
||||
static function createOrUpdate($data = array()) {
|
||||
@@ -87,7 +80,6 @@ class Form extends Model {
|
||||
$form->set($data);
|
||||
}
|
||||
|
||||
$form->save();
|
||||
return $form;
|
||||
return $form->save();
|
||||
}
|
||||
}
|
||||
|
@@ -4,25 +4,48 @@ namespace MailPoet\Models;
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Model extends \Sudzy\ValidModel {
|
||||
protected $_errors;
|
||||
|
||||
function __construct() {
|
||||
$customValidators = new CustomValidator();
|
||||
parent::__construct($customValidators->init());
|
||||
$this->_errors = array();
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
static function create() {
|
||||
return parent::create();
|
||||
}
|
||||
|
||||
function getErrors() {
|
||||
if(empty($this->_errors)) {
|
||||
return false;
|
||||
} else {
|
||||
return $this->_errors;
|
||||
}
|
||||
}
|
||||
|
||||
function setError($error = '') {
|
||||
if(!empty($error)) {
|
||||
if(is_array($error)) {
|
||||
$this->_errors = array_merge($this->_errors, $error);
|
||||
$this->_errors = array_unique($this->_errors);
|
||||
} else {
|
||||
$this->_errors[] = $error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function save() {
|
||||
$this->setTimestamp();
|
||||
try {
|
||||
parent::save();
|
||||
return true;
|
||||
} catch (\Sudzy\ValidationException $e) {
|
||||
return array_unique($e->getValidationErrors());
|
||||
} catch (\PDOException $e) {
|
||||
return $e->getMessage();
|
||||
} catch(\Sudzy\ValidationException $e) {
|
||||
$this->setError($e->getValidationErrors());
|
||||
} catch(\PDOException $e) {
|
||||
$this->setError($e->getMessage());
|
||||
} catch(\Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
function trash() {
|
||||
|
@@ -8,6 +8,10 @@ class Newsletter extends Model {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('type', array(
|
||||
'required' => __('You need to specify a type.')
|
||||
));
|
||||
}
|
||||
|
||||
function save() {
|
||||
@@ -15,9 +19,23 @@ class Newsletter extends Model {
|
||||
$this->set_expr('deleted_at', 'NULL');
|
||||
}
|
||||
|
||||
$this->set('body',
|
||||
is_array($this->body)
|
||||
? json_encode($this->body)
|
||||
: $this->body
|
||||
);
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
function asArray() {
|
||||
$model = parent::asArray();
|
||||
|
||||
if(isset($model['body'])) {
|
||||
$model['body'] = json_decode($model['body'], true);
|
||||
}
|
||||
return $model;
|
||||
}
|
||||
|
||||
function delete() {
|
||||
// delete all relations to segments
|
||||
NewsletterSegment::where('newsletter_id', $this->id)->deleteMany();
|
||||
@@ -79,14 +97,13 @@ class Newsletter extends Model {
|
||||
}
|
||||
|
||||
static function filterBy($orm, $filters = null) {
|
||||
if(empty($filters)) {
|
||||
return $orm;
|
||||
}
|
||||
foreach($filters as $key => $value) {
|
||||
if($key === 'segment') {
|
||||
$segment = Segment::findOne($value);
|
||||
if($segment !== false) {
|
||||
$orm = $segment->newsletters();
|
||||
if(!empty($filters)) {
|
||||
foreach($filters as $key => $value) {
|
||||
if($key === 'segment') {
|
||||
$segment = Segment::findOne($value);
|
||||
if($segment !== false) {
|
||||
$orm = $segment->newsletters();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,4 +9,16 @@ class NewsletterStatistics extends Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
static function createMultiple($data) {
|
||||
return self::rawExecute(
|
||||
'INSERT INTO `' . NewsletterStatistics::$_table . '` ' .
|
||||
'(newsletter_id, subscriber_id, queue_id) ' .
|
||||
'VALUES ' . rtrim(
|
||||
str_repeat('(?,?,?), ', count($data)/3),
|
||||
', '
|
||||
),
|
||||
$data
|
||||
);
|
||||
}
|
||||
}
|
@@ -17,6 +17,14 @@ class NewsletterTemplate extends Model {
|
||||
));
|
||||
}
|
||||
|
||||
function asArray() {
|
||||
$template = parent::asArray();
|
||||
if(isset($template['body'])) {
|
||||
$template['body'] = json_decode($template['body'], true);
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
|
||||
static function createOrUpdate($data = array()) {
|
||||
$template = false;
|
||||
|
||||
@@ -32,16 +40,7 @@ class NewsletterTemplate extends Model {
|
||||
$template->set($data);
|
||||
}
|
||||
|
||||
$saved = $template->save();
|
||||
|
||||
if($saved === true) {
|
||||
return true;
|
||||
} else {
|
||||
$errors = $template->getValidationErrors();
|
||||
if(!empty($errors)) {
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
$template->save();
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
@@ -164,8 +164,7 @@ class Segment extends Model {
|
||||
$segment->set($data);
|
||||
}
|
||||
|
||||
$segment->save();
|
||||
return $segment;
|
||||
return $segment->save();
|
||||
}
|
||||
|
||||
static function getPublic() {
|
||||
|
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SegmentFilter extends Model {
|
||||
public static $_table = MP_SEGMENT_FILTER_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
@@ -15,7 +15,8 @@ class SendingQueue extends Model {
|
||||
return false;
|
||||
} else {
|
||||
$this->set('status', 'paused');
|
||||
return $this->save();
|
||||
$this->save();
|
||||
return ($this->getErrors() === false && $this->id() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +25,14 @@ class SendingQueue extends Model {
|
||||
return $this->complete();
|
||||
} else {
|
||||
$this->set_expr('status', 'NULL');
|
||||
return $this->save();
|
||||
$this->save();
|
||||
return ($this->getErrors() === false && $this->id() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
function complete() {
|
||||
$this->set('status', 'completed');
|
||||
return $this->save();
|
||||
$this->save();
|
||||
return ($this->getErrors() === false && $this->id() > 0);
|
||||
}
|
||||
}
|
@@ -10,8 +10,7 @@ class Setting extends Model {
|
||||
parent::__construct();
|
||||
|
||||
$this->addValidations('name', array(
|
||||
'required' => 'name_is_blank',
|
||||
'isString' => 'name_is_not_string'
|
||||
'required' => __('You need to specify a name.')
|
||||
));
|
||||
}
|
||||
|
||||
@@ -36,6 +35,9 @@ class Setting extends Model {
|
||||
|
||||
if($setting !== $default) {
|
||||
for($i = 0, $count = count($keys); $i < $count; $i++) {
|
||||
if(!is_array($setting)) {
|
||||
$setting = array();
|
||||
}
|
||||
if(array_key_exists($keys[$i], $setting)) {
|
||||
$setting = $setting[$keys[$i]];
|
||||
} else {
|
||||
@@ -55,10 +57,11 @@ class Setting extends Model {
|
||||
$value = serialize($value);
|
||||
}
|
||||
|
||||
return Setting::createOrUpdate(array(
|
||||
$setting = Setting::createOrUpdate(array(
|
||||
'name' => $key,
|
||||
'value' => $value
|
||||
));
|
||||
return ($setting->id() > 0 && $setting->getErrors() === false);
|
||||
} else {
|
||||
$main_key = array_shift($keys);
|
||||
|
||||
@@ -67,13 +70,6 @@ class Setting extends Model {
|
||||
$last_key = array_pop($keys);
|
||||
|
||||
foreach($keys as $key) {
|
||||
if(!is_array($current_value)) {
|
||||
$current_value = array();
|
||||
}
|
||||
|
||||
if(!array_key_exists($key, $current_value)) {
|
||||
$current_value = array($key => array());
|
||||
}
|
||||
$current_value =& $current_value[$key];
|
||||
}
|
||||
if(is_scalar($current_value)) {
|
||||
@@ -100,17 +96,20 @@ class Setting extends Model {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public static function createOrUpdate($model) {
|
||||
$exists = self::where('name', $model['name'])
|
||||
->find_one();
|
||||
public static function createOrUpdate($data = array()) {
|
||||
$setting = false;
|
||||
|
||||
if($exists === false) {
|
||||
$new_model = self::create();
|
||||
$new_model->hydrate($model);
|
||||
return $new_model->save();
|
||||
if(isset($data['name'])) {
|
||||
$setting = self::where('name', $data['name'])->findOne();
|
||||
}
|
||||
|
||||
$exists->value = $model['value'];
|
||||
return $exists->save();
|
||||
if($setting === false) {
|
||||
$setting = self::create();
|
||||
$setting->hydrate($data);
|
||||
} else {
|
||||
$setting->value = $data['value'];
|
||||
}
|
||||
|
||||
return $setting->save();
|
||||
}
|
||||
}
|
||||
|
@@ -33,12 +33,17 @@ class Subscriber extends Model {
|
||||
}
|
||||
|
||||
function addToSegments(array $segment_ids = array()) {
|
||||
$segments = Segment::whereIn('id', $segment_ids)->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $this->id;
|
||||
$association->segment_id = $segment->id;
|
||||
$association->save();
|
||||
// delete all relations to segments
|
||||
SubscriberSegment::where('subscriber_id', $this->id)->deleteMany();
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
$segments = Segment::whereIn('id', $segment_ids)->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $this->id;
|
||||
$association->segment_id = $segment->id;
|
||||
$association->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +58,7 @@ class Subscriber extends Model {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subscriber = static::createOrUpdate($subscriber_data);
|
||||
$subscriber = self::createOrUpdate($subscriber_data);
|
||||
|
||||
if($subscriber !== false && $subscriber->id() > 0) {
|
||||
// restore deleted subscriber
|
||||
@@ -92,20 +97,25 @@ class Subscriber extends Model {
|
||||
$segments = Segment::orderByAsc('name')->findMany();
|
||||
$segment_list = array();
|
||||
$segment_list[] = array(
|
||||
'label' => __('All lists'),
|
||||
'label' => __('All segments'),
|
||||
'value' => ''
|
||||
);
|
||||
$segment_list[] = array(
|
||||
'label' => sprintf(
|
||||
__('Subscribers without a segment (%d)'),
|
||||
self::filter('withoutSegments')->count()
|
||||
),
|
||||
'value' => 'none'
|
||||
);
|
||||
|
||||
foreach($segments as $segment) {
|
||||
$subscribers_count = $segment->subscribers()
|
||||
->whereNull('deleted_at')
|
||||
->count();
|
||||
if($subscribers_count > 0) {
|
||||
$segment_list[] = array(
|
||||
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
|
||||
'value' => $segment->id()
|
||||
);
|
||||
}
|
||||
$segment_list[] = array(
|
||||
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
|
||||
'value' => $segment->id()
|
||||
);
|
||||
}
|
||||
|
||||
$filters = array(
|
||||
@@ -121,9 +131,13 @@ class Subscriber extends Model {
|
||||
}
|
||||
foreach($filters as $key => $value) {
|
||||
if($key === 'segment') {
|
||||
$segment = Segment::findOne($value);
|
||||
if($segment !== false) {
|
||||
return $segment->subscribers();
|
||||
if($value === 'none') {
|
||||
return self::filter('withoutSegments');
|
||||
} else {
|
||||
$segment = Segment::findOne($value);
|
||||
if($segment !== false) {
|
||||
return $segment->subscribers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,27 +149,27 @@ class Subscriber extends Model {
|
||||
array(
|
||||
'name' => 'all',
|
||||
'label' => __('All'),
|
||||
'count' => Subscriber::getPublished()->count()
|
||||
'count' => self::getPublished()->count()
|
||||
),
|
||||
array(
|
||||
'name' => 'subscribed',
|
||||
'label' => __('Subscribed'),
|
||||
'count' => Subscriber::filter('subscribed')->count()
|
||||
'count' => self::filter('subscribed')->count()
|
||||
),
|
||||
array(
|
||||
'name' => 'unconfirmed',
|
||||
'label' => __('Unconfirmed'),
|
||||
'count' => Subscriber::filter('unconfirmed')->count()
|
||||
'count' => self::filter('unconfirmed')->count()
|
||||
),
|
||||
array(
|
||||
'name' => 'unsubscribed',
|
||||
'label' => __('Unsubscribed'),
|
||||
'count' => Subscriber::filter('unsubscribed')->count()
|
||||
'count' => self::filter('unsubscribed')->count()
|
||||
),
|
||||
array(
|
||||
'name' => 'trash',
|
||||
'label' => __('Trash'),
|
||||
'count' => Subscriber::getTrashed()->count()
|
||||
'count' => self::getTrashed()->count()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -226,17 +240,25 @@ class Subscriber extends Model {
|
||||
$subscriber = false;
|
||||
|
||||
if(isset($data['id']) && (int)$data['id'] > 0) {
|
||||
$subscriber = static::findOne((int)$data['id']);
|
||||
$subscriber = self::findOne((int)$data['id']);
|
||||
unset($data['id']);
|
||||
}
|
||||
|
||||
if($subscriber === false && !empty($data['email'])) {
|
||||
$subscriber = static::where('email', $data['email'])->findOne();
|
||||
$subscriber = self::where('email', $data['email'])->findOne();
|
||||
if($subscriber !== false) {
|
||||
unset($data['email']);
|
||||
}
|
||||
}
|
||||
|
||||
// segments
|
||||
$segment_ids = array();
|
||||
|
||||
if(isset($data['segments'])) {
|
||||
$segment_ids = (array)$data['segments'];
|
||||
unset($data['segments']);
|
||||
}
|
||||
|
||||
// custom fields
|
||||
$custom_fields = array();
|
||||
|
||||
@@ -248,7 +270,7 @@ class Subscriber extends Model {
|
||||
}
|
||||
|
||||
if($subscriber === false) {
|
||||
$subscriber = static::create();
|
||||
$subscriber = self::create();
|
||||
$subscriber->hydrate($data);
|
||||
} else {
|
||||
$subscriber->set($data);
|
||||
@@ -260,6 +282,7 @@ class Subscriber extends Model {
|
||||
$subscriber->setCustomField($custom_field_id, $value);
|
||||
}
|
||||
}
|
||||
$subscriber->addToSegments($segment_ids);
|
||||
}
|
||||
return $subscriber;
|
||||
}
|
||||
@@ -430,6 +453,19 @@ class Subscriber extends Model {
|
||||
->where('status', 'unconfirmed');
|
||||
}
|
||||
|
||||
static function withoutSegments($orm) {
|
||||
return $orm->select(MP_SUBSCRIBERS_TABLE.'.*')
|
||||
->leftOuterJoin(
|
||||
MP_SUBSCRIBER_SEGMENT_TABLE,
|
||||
array(
|
||||
MP_SUBSCRIBERS_TABLE.'.id',
|
||||
'=',
|
||||
MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id'
|
||||
)
|
||||
)
|
||||
->whereNull(MP_SUBSCRIBER_SEGMENT_TABLE.'.subscriber_id');
|
||||
}
|
||||
|
||||
static function createMultiple($columns, $values) {
|
||||
return self::rawExecute(
|
||||
'INSERT INTO `' . self::$_table . '` ' .
|
||||
|
69
lib/Newsletter/AutomatedLatestContent.php
Normal file
69
lib/Newsletter/AutomatedLatestContent.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter;
|
||||
|
||||
use MailPoet\Newsletter\Editor\Transformer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class AutomatedLatestContent {
|
||||
function getPosts($args) {
|
||||
$parameters = array(
|
||||
'posts_per_page' => (isset($args['amount'])) ? (int) $args['amount'] : 10,
|
||||
'post_type' => (isset($args['contentType'])) ? $args['contentType'] : 'post',
|
||||
'post_status' => (isset($args['postStatus'])) ? $args['postStatus'] : 'publish',
|
||||
'orderby' => 'date',
|
||||
'order' => ($args['sortBy'] === 'newest') ? 'DESC' : 'ASC',
|
||||
);
|
||||
if(isset($args['search'])) {
|
||||
$parameters['s'] = $args['search'];
|
||||
}
|
||||
if(isset($args['posts']) && is_array($args['posts'])) {
|
||||
$parameters['post__in'] = $args['posts'];
|
||||
}
|
||||
$parameters['tax_query'] = $this->constructTaxonomiesQuery($args);
|
||||
return get_posts($parameters);
|
||||
}
|
||||
|
||||
function transformPosts($args, $posts) {
|
||||
$transformer = new Transformer($args);
|
||||
return $transformer->transform($posts);
|
||||
}
|
||||
|
||||
function constructTaxonomiesQuery($args) {
|
||||
$taxonomies_query = array();
|
||||
if(isset($args['terms']) && is_array($args['terms'])) {
|
||||
// Add filtering by tags and categories
|
||||
$tags = array();
|
||||
$categories = array();
|
||||
foreach($args['terms'] as $term) {
|
||||
if($term['taxonomy'] === 'category') {
|
||||
$categories[] = $term['id'];
|
||||
} else if($term['taxonomy'] === 'post_tag') $tags[] = $term['id'];
|
||||
}
|
||||
$taxonomies = array(
|
||||
'post_tag' => $tags,
|
||||
'category' => $categories
|
||||
);
|
||||
foreach($taxonomies as $taxonomy => $terms) {
|
||||
if(!empty($terms)) {
|
||||
$tax = array(
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'id',
|
||||
'terms' => $terms,
|
||||
);
|
||||
if($args['inclusionType'] === 'exclude') $tax['operator'] = 'NOT IN';
|
||||
$taxonomies_query[] = $tax;
|
||||
}
|
||||
}
|
||||
if(!empty($taxonomies_query)) {
|
||||
// With exclusion we want to use 'AND', because we want posts that
|
||||
// don't have excluded tags/categories. But with inclusion we want to
|
||||
// use 'OR', because we want posts that have any of the included
|
||||
// tags/categories
|
||||
$taxonomies_query['relation'] = ($args['inclusionType'] === 'exclude') ? 'AND' : 'OR';
|
||||
return $taxonomies_query;
|
||||
}
|
||||
}
|
||||
return $taxonomies_query;
|
||||
}
|
||||
}
|
@@ -22,12 +22,12 @@ class PostTransformer {
|
||||
$content = $content_manager->filterContent($content);
|
||||
|
||||
$structure_transformer = new StructureTransformer();
|
||||
$structure = $structure_transformer->transform($content, $this->args['imagePadded'] === 'true');
|
||||
$structure = $structure_transformer->transform($content, $this->args['imageFullWidth'] === 'true');
|
||||
|
||||
$structure = $this->appendFeaturedImage(
|
||||
$post,
|
||||
$this->args['displayType'],
|
||||
$this->args['imagePadded'] === 'true',
|
||||
$this->args['imageFullWidth'] === 'true',
|
||||
$structure
|
||||
);
|
||||
$structure = $this->appendPostTitle($post, $structure);
|
||||
@@ -36,7 +36,7 @@ class PostTransformer {
|
||||
return $structure;
|
||||
}
|
||||
|
||||
private function appendFeaturedImage($post, $display_type, $image_padded, $structure) {
|
||||
private function appendFeaturedImage($post, $display_type, $image_full_width, $structure) {
|
||||
if ($display_type === 'full') {
|
||||
// No featured images for full posts
|
||||
return $structure;
|
||||
@@ -45,7 +45,7 @@ class PostTransformer {
|
||||
$featured_image = $this->getFeaturedImage(
|
||||
$post->ID,
|
||||
$post->post_title,
|
||||
(bool)$image_padded
|
||||
(bool)$image_full_width
|
||||
);
|
||||
|
||||
if (is_array($featured_image)) {
|
||||
@@ -55,14 +55,14 @@ class PostTransformer {
|
||||
return $structure;
|
||||
}
|
||||
|
||||
private function getFeaturedImage($post_id, $post_title, $image_padded) {
|
||||
private function getFeaturedImage($post_id, $post_title, $image_full_width) {
|
||||
if(has_post_thumbnail($post_id)) {
|
||||
$thumbnail_id = get_post_thumbnail_id($post_id);
|
||||
|
||||
// get attachment data (src, width, height)
|
||||
$image_info = wp_get_attachment_image_src(
|
||||
$thumbnail_id,
|
||||
'single-post-thumbnail'
|
||||
'mailpoet_newsletter_max'
|
||||
);
|
||||
|
||||
// get alt text
|
||||
@@ -81,7 +81,7 @@ class PostTransformer {
|
||||
'link' => get_permalink($post_id),
|
||||
'src' => $image_info[0],
|
||||
'alt' => $alt_text,
|
||||
'padded' => $image_padded,
|
||||
'fullWidth' => $image_full_width,
|
||||
'width' => $image_info[1],
|
||||
'height' => $image_info[2],
|
||||
'styles' => array(
|
||||
|
@@ -7,11 +7,11 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StructureTransformer {
|
||||
|
||||
function transform($content, $image_padded) {
|
||||
function transform($content, $image_full_width) {
|
||||
$root = pQuery::parseStr($content);
|
||||
|
||||
$this->hoistImagesToRoot($root);
|
||||
$structure = $this->transformTagsToBlocks($root, $image_padded);
|
||||
$structure = $this->transformTagsToBlocks($root, $image_full_width);
|
||||
$structure = $this->mergeNeighboringBlocks($structure);
|
||||
return $structure;
|
||||
}
|
||||
@@ -44,8 +44,8 @@ class StructureTransformer {
|
||||
* Transforms HTML tags into their respective JSON objects,
|
||||
* turns other root children into text blocks
|
||||
*/
|
||||
private function transformTagsToBlocks($root, $image_padded) {
|
||||
return array_map(function($item) use ($image_padded) {
|
||||
private function transformTagsToBlocks($root, $image_full_width) {
|
||||
return array_map(function($item) use ($image_full_width) {
|
||||
if ($item->tag === 'img' || $item->tag === 'a' && $item->query('img')) {
|
||||
if ($item->tag === 'a') {
|
||||
$link = $item->getAttribute('href');
|
||||
@@ -60,7 +60,7 @@ class StructureTransformer {
|
||||
'link' => $link,
|
||||
'src' => $image->getAttribute('src'),
|
||||
'alt' => $image->getAttribute('alt'),
|
||||
'padded' => $image_padded,
|
||||
'fullWidth' => $image_full_width,
|
||||
'width' => $image->getAttribute('width'),
|
||||
'height' => $image->getAttribute('height'),
|
||||
'styles' => array(
|
||||
|
12
lib/Newsletter/Renderer/Blocks/AutomatedLatestContent.php
Normal file
12
lib/Newsletter/Renderer/Blocks/AutomatedLatestContent.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Renderer\Blocks;
|
||||
|
||||
class AutomatedLatestContent {
|
||||
static function render($element, $column_count) {
|
||||
$ALC = new \MailPoet\Newsletter\AutomatedLatestContent();
|
||||
$posts = $ALC->getPosts($element);
|
||||
$transformed_posts = array('blocks' => $ALC->transformPosts($element, $posts));
|
||||
$renderer = new Renderer();
|
||||
return $renderer->render($transformed_posts, $column_count);
|
||||
}
|
||||
}
|
@@ -5,21 +5,23 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
|
||||
class Footer {
|
||||
static function render($element) {
|
||||
if(isset($element['styles']['link'])) {
|
||||
$element['text'] = str_replace(
|
||||
'<a',
|
||||
'<a style="'
|
||||
. StylesHelper::getStyles($element['styles'], 'link')
|
||||
. '"', $element['text']
|
||||
);
|
||||
}
|
||||
$element['text'] = preg_replace('/\n/', '<br /><br />', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p>)/', '', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p.*?>)/i', '', $element['text']);
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($element['text']);
|
||||
if(isset($element['styles']['link'])) {
|
||||
$links = $DOM->query('a');
|
||||
if($links->count()) {
|
||||
foreach($links as $link) {
|
||||
$link->style = StylesHelper::getStyles($element['styles'], 'link');
|
||||
}
|
||||
}
|
||||
}
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_padded_header_footer mailpoet_footer" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
||||
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
' . $element['text'] . '
|
||||
' . $DOM->html() . '
|
||||
</td>
|
||||
</tr>';
|
||||
return $template;
|
||||
|
@@ -5,21 +5,23 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
|
||||
class Header {
|
||||
static function render($element) {
|
||||
if(isset($element['styles']['link'])) {
|
||||
$element['text'] = str_replace(
|
||||
'<a',
|
||||
'<a style="'
|
||||
. StylesHelper::getStyles($element['styles'], 'link')
|
||||
. '"', $element['text']
|
||||
);
|
||||
}
|
||||
$element['text'] = preg_replace('/\n/', '<br /><br />', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p>)/', '', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p.*?>)/', '', $element['text']);
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($element['text']);
|
||||
if(isset($element['styles']['link'])) {
|
||||
$links = $DOM->query('a');
|
||||
if($links->count()) {
|
||||
foreach($links as $link) {
|
||||
$link->style = StylesHelper::getStyles($element['styles'], 'link');
|
||||
}
|
||||
}
|
||||
}
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_padded_header_footer mailpoet_header" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
||||
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
' . $element['text'] . '
|
||||
' . $DOM->html() . '
|
||||
</td>
|
||||
</tr>';
|
||||
return $template;
|
||||
|
@@ -6,10 +6,12 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
|
||||
class Image {
|
||||
static function render($element, $columnCount) {
|
||||
$element = self::getImageDimensions($element, $columnCount);
|
||||
$element['width'] = (int) $element['width'];
|
||||
$element['height'] = (int) $element['height'];
|
||||
$element = self::adjustImageDimensions($element, $columnCount);
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_image ' . $element['paddedClass'] . '" align="center" valign="top">
|
||||
<td class="mailpoet_image ' . (($element['fullWidth'] === false) ? 'mailpoet_padded' : '') . '" align="center" valign="top">
|
||||
<img style="max-width:' . $element['width'] . 'px;" src="' . $element['src'] . '"
|
||||
width="' . $element['width'] . '" height="' . $element['height'] . '" alt="' . $element['alt'] . '"/>
|
||||
</td>
|
||||
@@ -17,25 +19,22 @@ class Image {
|
||||
return $template;
|
||||
}
|
||||
|
||||
static function getImageDimensions($element, $column_count) {
|
||||
static function adjustImageDimensions($element, $column_count) {
|
||||
$column_width = ColumnsHelper::columnWidth($column_count);
|
||||
$padded_width = StylesHelper::$padding_width * 2;
|
||||
// resize image if it's wider than the column width
|
||||
if((int) $element['width'] >= $column_width) {
|
||||
$ratio = (int) $element['width'] / $column_width;
|
||||
// scale image to fit column width
|
||||
if($element['width'] > $column_width ||
|
||||
($element['width'] < $column_width && $element['fullWidth'] === true)
|
||||
) {
|
||||
$ratio = $element['width'] / $column_width;
|
||||
$element['width'] = $column_width;
|
||||
$element['height'] = ceil((int) $element['height'] / $ratio);
|
||||
$element['height'] = ceil($element['height'] / $ratio);
|
||||
}
|
||||
if($element['padded'] == "true" && $element['width'] >= $column_width) {
|
||||
// resize image if the padded option is on
|
||||
$ratio = (int) $element['width'] / ((int) $element['width'] - $padded_width);
|
||||
$element['width'] = (int) $element['width'] - $padded_width;
|
||||
$element['height'] = ceil((int) $element['height'] / $ratio);
|
||||
$element['paddedClass'] = 'mailpoet_padded';
|
||||
} else {
|
||||
$element['width'] = (int) $element['width'];
|
||||
$element['height'] = (int) $element['height'];
|
||||
$element['paddedClass'] = '';
|
||||
// resize image if the image is padded and wider than column width
|
||||
if($element['fullWidth'] === false && $element['width'] >= $column_width) {
|
||||
$ratio = $element['width'] / ($element['width'] - $padded_width);
|
||||
$element['width'] = $element['width'] - $padded_width;
|
||||
$element['height'] = ceil($element['height'] / $ratio);
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
@@ -6,10 +6,9 @@ class Text {
|
||||
$html = $element['text'];
|
||||
$html = self::convertBlockquotesToTables($html);
|
||||
$html = self::convertParagraphsToTables($html);
|
||||
$html = self::addLineBreakAfterTags($html);
|
||||
$html = self::styleLists($html);
|
||||
$html = self::styleHeadings($html);
|
||||
$html = self::removeLastElementBreakLine($html);
|
||||
$html = self::addLineBreakAfterTags($html);
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_text mailpoet_padded" valign="top" style="word-break:break-word;word-wrap:break-word;">
|
||||
@@ -19,42 +18,26 @@ class Text {
|
||||
return $template;
|
||||
}
|
||||
|
||||
static function convertParagraphsToTables($html) {
|
||||
$html = preg_replace('/<p>(.*?)<\/p>/', '
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0">
|
||||
<tr>
|
||||
<td class="mailpoet_paragraph" style="word-break:break-word;word-wrap:break-word;">
|
||||
$1
|
||||
<br /><br />
|
||||
</td>
|
||||
</tr>
|
||||
</table>'
|
||||
, $html);
|
||||
$html = preg_replace('/<p style=\"(.*)\">(.*?)<\/p>/', '
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0">
|
||||
<tr>
|
||||
<td class="mailpoet_paragraph" style="word-break:break-word;word-wrap:break-word;$1">
|
||||
$2
|
||||
<br /><br />
|
||||
</td>
|
||||
</tr>
|
||||
</table>'
|
||||
, $html);
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
static function removeLastElementBreakLine($html) {
|
||||
return preg_replace('/<br\/>([^<br\/>]*)$/s', '', $html);
|
||||
}
|
||||
|
||||
static function addLineBreakAfterTags($html) {
|
||||
return preg_replace('/(<\/(ul|ol|h\d)>)/', '$1<br />', $html);
|
||||
}
|
||||
|
||||
static function convertBlockquotesToTables($html) {
|
||||
$template = '
|
||||
<table width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$blockquotes = $DOM->query('blockquote');
|
||||
if(!$blockquotes->count()) return $html;
|
||||
foreach($blockquotes as $blockquote) {
|
||||
$paragraphs = $blockquote->query('p', 0);
|
||||
foreach($paragraphs as $index => $paragraph) {
|
||||
$contents[] = $paragraph->html();
|
||||
if($index + 1 < $paragraphs->count()) $contents[] = '<br />';
|
||||
$paragraph->remove();
|
||||
}
|
||||
$paragraph->remove();
|
||||
$blockquote->setTag('table');
|
||||
$blockquote->addClass('mailpoet_blockquote');
|
||||
$blockquote->width = '100%';
|
||||
$blockquote->spacing = 0;
|
||||
$blockquote->border = 0;
|
||||
$blockquote->cellpadding = 0;
|
||||
$blockquote->html('
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="2" bgcolor="#565656"></td>
|
||||
@@ -63,48 +46,90 @@ class Text {
|
||||
<table style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0">
|
||||
<tr>
|
||||
<td class="mailpoet_blockquote">
|
||||
$1
|
||||
' . implode('', $contents) . '
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br/>';
|
||||
preg_match('/<blockquote>.*?<\/blockquote>/s', $html, $blockquotes);
|
||||
foreach($blockquotes as $index => $blockquote) {
|
||||
$blockquote = preg_replace('/<\/p>\n<p>/', '<br/><br/>', $blockquote);
|
||||
$blockquote = preg_replace('/<\/?p>/', '', $blockquote);
|
||||
$blockquote = preg_replace(
|
||||
'/<blockquote>(.*?)<\/blockquote>/s',
|
||||
$template,
|
||||
$blockquote
|
||||
);
|
||||
$html = preg_replace(
|
||||
'/' . preg_quote($blockquotes[$index], '/') . '/',
|
||||
$blockquote,
|
||||
$html
|
||||
</tbody>'
|
||||
);
|
||||
}
|
||||
return $html;
|
||||
return $DOM->__toString();
|
||||
}
|
||||
|
||||
static function styleHeadings($html) {
|
||||
return preg_replace(
|
||||
'/<(h[1-6])(?:.+style=\"(.*)?\")?>/',
|
||||
'<$1 style="margin:0;font-style:normal;font-weight:normal;$2">',
|
||||
$html
|
||||
);
|
||||
static function convertParagraphsToTables($html) {
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$paragraphs = $DOM->query('p');
|
||||
if(!$paragraphs->count()) return $html;
|
||||
foreach($paragraphs as $paragraph) {
|
||||
// remove empty paragraphs
|
||||
if(!trim($paragraph->html())) {
|
||||
$paragraph->remove();
|
||||
continue;
|
||||
}
|
||||
$style = $paragraph->style;
|
||||
$contents = $paragraph->html();
|
||||
$paragraph->setTag('table');
|
||||
$paragraph->style = 'border-spacing:0;mso-table-lspace:0;mso-table-rspace:0;';
|
||||
$paragraph->width = '100%';
|
||||
$paragraph->cellpadding = 0;
|
||||
$paragraph->html('
|
||||
<tr>
|
||||
<td class="mailpoet_paragraph" style="word-break:break-word;word-wrap:break-word;' . $style . '">
|
||||
' . $contents . '
|
||||
<br /><br />
|
||||
</td>
|
||||
</tr>'
|
||||
);
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
|
||||
static function styleLists($html) {
|
||||
$html = preg_replace(
|
||||
'/<(ul|ol)>/',
|
||||
'<$1 class="mailpoet_paragraph" style="padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;">',
|
||||
$html
|
||||
);
|
||||
$html = preg_replace('/<li>/', '<li class="mailpoet_paragraph">', $html);
|
||||
return $html;
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$lists = $DOM->query('ol, ul, li');
|
||||
if(!$lists->count()) return $html;
|
||||
foreach($lists as $list) {
|
||||
if($list->tag === 'li') {
|
||||
$list->class = 'mailpoet_paragraph';
|
||||
} else {
|
||||
$list->class = 'mailpoet_paragraph';
|
||||
$list->style .= 'padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;';
|
||||
}
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
|
||||
static function styleHeadings($html) {
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$headings = $DOM->query('h1, h2, h3, h4');
|
||||
if(!$headings->count()) return $html;
|
||||
foreach($headings as $heading) {
|
||||
$heading->style .= 'margin:0;font-style:normal;font-weight:normal;';
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
|
||||
static function addLineBreakAfterTags($html) {
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$tags = $DOM->query('ul, ol, h1, h2, h3, h4, table.mailpoet_blockquote');
|
||||
if(!$tags->count()) return $html;
|
||||
foreach($tags as $tag) {
|
||||
$tag->parent->insertChild(
|
||||
array(
|
||||
'tag_name' => 'br',
|
||||
'self_close' => true,
|
||||
'attributes' => array()
|
||||
),
|
||||
$tag->index() + 1
|
||||
);
|
||||
}
|
||||
// remove last line break
|
||||
return preg_replace('/(^)?(<br.*?\/?>)+$/i', '', $DOM->__toString());
|
||||
}
|
||||
}
|
@@ -35,7 +35,11 @@ class Renderer {
|
||||
$newsletter_body
|
||||
));
|
||||
$template = $this->inlineCSSStyles($template);
|
||||
return $this->postProcessTemplate($template);
|
||||
$template = $this->postProcessTemplate($template);
|
||||
return array(
|
||||
'html' => $template,
|
||||
'text' => $this->renderTextVersion($template)
|
||||
);
|
||||
}
|
||||
|
||||
function renderBody($content) {
|
||||
@@ -65,7 +69,7 @@ class Renderer {
|
||||
$selector = 'h3';
|
||||
break;
|
||||
case 'text':
|
||||
$selector = '.mailpoet_paragraph, .mailpoet_blockquote';
|
||||
$selector = '.mailpoet_paragraph, td.mailpoet_blockquote';
|
||||
break;
|
||||
case 'body':
|
||||
$selector = 'body, .mailpoet-wrapper';
|
||||
@@ -107,8 +111,8 @@ class Renderer {
|
||||
}
|
||||
|
||||
function renderTextVersion($template) {
|
||||
// TODO: add text rendering
|
||||
return $template;
|
||||
$template = mb_convert_encoding($template, 'HTML-ENTITIES', 'UTF-8');
|
||||
return \Html2Text\Html2Text::convert($template);
|
||||
}
|
||||
|
||||
function postProcessTemplate($template) {
|
||||
@@ -118,7 +122,6 @@ class Renderer {
|
||||
$template->html(
|
||||
str_replace('!important', '', $template->html())
|
||||
);
|
||||
// TODO: return array with html and text body
|
||||
return $DOM->__toString();
|
||||
}
|
||||
}
|
43
lib/Newsletter/Shortcodes/Categories/Date.php
Normal file
43
lib/Newsletter/Shortcodes/Categories/Date.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes\Categories;
|
||||
|
||||
class Date {
|
||||
/*
|
||||
{
|
||||
text: '<%= __('Current day of the month number') %>',
|
||||
shortcode: 'date:d',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Current day of the month in ordinal, ie. 2nd, 3rd, etc.') %>',
|
||||
shortcode: 'date:dordinal',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Full name of current day') %>',
|
||||
shortcode: 'date:dtext',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Current month number') %>',
|
||||
shortcode: 'date:m',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Full name of current month') %>',
|
||||
shortcode: 'date:mtext',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Year') %>',
|
||||
shortcode: 'date:y',
|
||||
}
|
||||
*/
|
||||
static function process($action) {
|
||||
$date = new \DateTime('now');
|
||||
$actions = array(
|
||||
'd' => $date->format('d'),
|
||||
'dordinal' => $date->format('dS'),
|
||||
'dtext' => $date->format('D'),
|
||||
'm' => $date->format('m'),
|
||||
'mtext' => $date->format('F'),
|
||||
'y' => $date->format('Y')
|
||||
);
|
||||
return (isset($actions[$action])) ? $actions[$action] : false;
|
||||
}
|
||||
}
|
30
lib/Newsletter/Shortcodes/Categories/Link.php
Normal file
30
lib/Newsletter/Shortcodes/Categories/Link.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes\Categories;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
class Link {
|
||||
/*
|
||||
{
|
||||
text: '<%= __('Unsubscribe link') %>',
|
||||
shortcode: 'global:unsubscribe',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Edit subscription page link') %>',
|
||||
shortcode: 'global:manage',
|
||||
},
|
||||
{
|
||||
text: '<%= __('View in browser link') %>',
|
||||
shortcode: 'global:browser',
|
||||
}
|
||||
*/
|
||||
static function process($action) {
|
||||
// TODO: implement
|
||||
$actions = array(
|
||||
'unsubscribe' => '',
|
||||
'manage' => '',
|
||||
'browser' => ''
|
||||
);
|
||||
return (isset($actions[$action])) ? $actions[$action] : false;
|
||||
}
|
||||
}
|
43
lib/Newsletter/Shortcodes/Categories/Newsletter.php
Normal file
43
lib/Newsletter/Shortcodes/Categories/Newsletter.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes\Categories;
|
||||
|
||||
class Newsletter {
|
||||
/*
|
||||
{
|
||||
text: '<%= __('Newsletter Subject') %>',-
|
||||
shortcode: 'newsletter:subject',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Total number of posts or pages') %>',
|
||||
shortcode: 'newsletter:total',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Latest post title') %>',
|
||||
shortcode: 'newsletter:post_title',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Issue number') %>',
|
||||
shortcode: 'newsletter:number',
|
||||
}
|
||||
*/
|
||||
static function process($action, $default_value = false, $newsletter) {
|
||||
if(is_object($newsletter)) {
|
||||
$newsletter = $newsletter->asArray();
|
||||
}
|
||||
switch($action) {
|
||||
case 'subject':
|
||||
return ($newsletter) ? $newsletter['subject'] : false;
|
||||
case 'total':
|
||||
$posts = wp_count_posts();
|
||||
return $posts->publish;
|
||||
case 'post_title':
|
||||
$post = wp_get_recent_posts(array('numberposts' => 1));
|
||||
return (isset($post[0])) ? $post[0]['post_title'] : false;
|
||||
case 'number':
|
||||
// TODO: implement
|
||||
return;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
54
lib/Newsletter/Shortcodes/Categories/User.php
Normal file
54
lib/Newsletter/Shortcodes/Categories/User.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes\Categories;
|
||||
|
||||
use MailPoet\Models\Subscriber;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
class User {
|
||||
/*
|
||||
{
|
||||
text: '<%= __('First Name') %>',
|
||||
shortcode: 'user:firstname | default:reader',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Last Name') %>',
|
||||
shortcode: 'user:lastname | default:reader',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Email Address') %>',
|
||||
shortcode: 'user:email',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Wordpress user display name') %>',
|
||||
shortcode: 'user:displayname | default:member',
|
||||
},
|
||||
{
|
||||
text: '<%= __('Total of subscribers') %>',
|
||||
shortcode: 'user:count',
|
||||
}
|
||||
*/
|
||||
static function process($action, $default_value, $newsletter = false, $subscriber) {
|
||||
if(is_object($subscriber)) {
|
||||
$subscriber = $subscriber->asArray();
|
||||
}
|
||||
switch($action) {
|
||||
case 'firstname':
|
||||
return ($subscriber) ? $subscriber['first_name'] : $default_value;
|
||||
case 'lastname':
|
||||
return ($subscriber) ? $subscriber['last_name'] : $default_value;
|
||||
case 'email':
|
||||
return ($subscriber) ? $subscriber['email'] : false;
|
||||
case 'displayname':
|
||||
if($subscriber && $subscriber['wp_user_id']) {
|
||||
$wp_user = get_userdata($subscriber['wp_user_id']);
|
||||
return $wp_user->user_login;
|
||||
};
|
||||
return $default_value;
|
||||
case 'count':
|
||||
return Subscriber::count();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
53
lib/Newsletter/Shortcodes/Shortcodes.php
Normal file
53
lib/Newsletter/Shortcodes/Shortcodes.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes;
|
||||
|
||||
class Shortcodes {
|
||||
public $rendered_newsletter;
|
||||
public $newsletter;
|
||||
public $subscriber;
|
||||
|
||||
function __construct(
|
||||
$rendered_newsletter,
|
||||
$newsletter = false,
|
||||
$subscriber = false) {
|
||||
$this->rendered_newsletter = $rendered_newsletter;
|
||||
$this->newsletter = $newsletter;
|
||||
$this->subscriber = $subscriber;
|
||||
}
|
||||
|
||||
function extract() {
|
||||
preg_match_all('/\[(?:\w+):.*?\]/', $this->rendered_newsletter, $shortcodes);
|
||||
return array_unique($shortcodes[0]);
|
||||
}
|
||||
|
||||
function process($shortcodes) {
|
||||
$processed_shortcodes = array_map(
|
||||
function ($shortcode) {
|
||||
// TODO: discuss renaming "global". It is a reserved name in PHP.
|
||||
if($shortcode === 'global') $shortcode = 'link';
|
||||
preg_match(
|
||||
'/\[(?P<type>\w+):(?P<action>\w+)(?:.*?default:(?P<default>.*?))?\]/',
|
||||
$shortcode,
|
||||
$shortcode_details
|
||||
);
|
||||
$shortcode_class =
|
||||
__NAMESPACE__ . '\\Categories\\' . ucfirst($shortcode_details['type']);
|
||||
if(!class_exists($shortcode_class)) return false;
|
||||
return $shortcode_class::process(
|
||||
$shortcode_details['action'],
|
||||
isset($shortcode_details['default'])
|
||||
? $shortcode_details['default'] : false,
|
||||
$this->newsletter,
|
||||
$this->subscriber
|
||||
);
|
||||
}, $shortcodes);
|
||||
return array_filter($processed_shortcodes);
|
||||
}
|
||||
|
||||
function replace() {
|
||||
$shortcodes = $this->extract($this->rendered_newsletter);
|
||||
$processed_shortcodes = $this->process($shortcodes);
|
||||
$shortcodes = array_intersect_key($shortcodes, $processed_shortcodes);
|
||||
return str_replace($shortcodes, $processed_shortcodes, $this->rendered_newsletter);
|
||||
}
|
||||
}
|
46
lib/Router/AutomatedLatestContent.php
Normal file
46
lib/Router/AutomatedLatestContent.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class AutomatedLatestContent {
|
||||
public $ALC;
|
||||
|
||||
function __construct() {
|
||||
$this->ALC = new \MailPoet\Newsletter\AutomatedLatestContent();
|
||||
}
|
||||
|
||||
function getPostTypes() {
|
||||
return get_post_types(array(), 'objects');
|
||||
}
|
||||
|
||||
function getTaxonomies($args) {
|
||||
$post_type = (isset($args['postType'])) ? $args['postType'] : 'post';
|
||||
return get_object_taxonomies($post_type, 'objects');
|
||||
}
|
||||
|
||||
function getTerms($args) {
|
||||
$taxonomies = (isset($args['taxonomies'])) ? $args['taxonomies'] : array();
|
||||
$search = (isset($args['search'])) ? $args['search'] : '';
|
||||
$limit = (isset($args['limit'])) ? (int)$args['limit'] : 10;
|
||||
$page = (isset($args['page'])) ? (int)$args['page'] : 1;
|
||||
return get_terms(
|
||||
$taxonomies,
|
||||
array(
|
||||
'hide_empty' => false,
|
||||
'search' => $search,
|
||||
'number' => $limit,
|
||||
'offset' => $limit * ($page - 1)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getPosts($args) {
|
||||
return $this->ALC->getPosts($args);
|
||||
}
|
||||
|
||||
function getTransformedPosts($args) {
|
||||
$posts = $this->ALC->getPosts($args);
|
||||
return $this->ALC->transformPosts($args, $posts);
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\Cron\Daemon;
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Cron\Supervisor;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
@@ -10,35 +10,27 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Cron {
|
||||
function start() {
|
||||
$supervisor = new Supervisor($forceStart = true);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $supervisor->checkDaemon() ? true : false
|
||||
)
|
||||
);
|
||||
$supervisor = new Supervisor($force_run = true);
|
||||
return $supervisor->checkDaemon();
|
||||
}
|
||||
|
||||
function stop() {
|
||||
$daemon = new Daemon();
|
||||
if(!$daemon->daemon ||
|
||||
$daemon->daemon['status'] !== 'started'
|
||||
) {
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!$daemon || $daemon['status'] !== 'started') {
|
||||
$result = false;
|
||||
} else {
|
||||
$daemon->daemon['status'] = 'stopping';
|
||||
$result = $daemon->saveDaemon($daemon->daemon);
|
||||
$daemon['status'] = 'stopping';
|
||||
$result = CronHelper::saveDaemon($daemon);
|
||||
}
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $result
|
||||
)
|
||||
return array(
|
||||
'result' => $result
|
||||
);
|
||||
}
|
||||
|
||||
function getStatus() {
|
||||
$daemon = Setting::where('name', 'cron_daemon')
|
||||
->findOne();
|
||||
wp_send_json(
|
||||
return (
|
||||
($daemon) ?
|
||||
array_merge(
|
||||
array(
|
||||
|
@@ -14,60 +14,46 @@ class CustomFields {
|
||||
return $custom_field->asArray();
|
||||
}, $collection);
|
||||
|
||||
wp_send_json($custom_fields);
|
||||
return $custom_fields;
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false or !$custom_field->id()) {
|
||||
wp_send_json(array(
|
||||
'result' => false
|
||||
));
|
||||
return array('result' => false);
|
||||
} else {
|
||||
$custom_field->delete();
|
||||
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$custom_field = CustomField::createOrUpdate($data);
|
||||
$errors = $custom_field->getErrors();
|
||||
|
||||
if($custom_field === false) {
|
||||
$result = array(
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(
|
||||
__('The custom field could not be created.')
|
||||
)
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$errors = $custom_field->getValidationErrors();
|
||||
if(!empty($errors)) {
|
||||
$result = array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$result = array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
);
|
||||
}
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
}
|
||||
|
||||
function get($id) {
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
$custom_field = $custom_field->asArray();
|
||||
wp_send_json($custom_field);
|
||||
return $custom_field->asArray();
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,15 +11,12 @@ class Forms {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : 0);
|
||||
|
||||
function get($id = false) {
|
||||
$form = Form::findOne($id);
|
||||
if($form === false) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
$form = $form->asArray();
|
||||
wp_send_json($form);
|
||||
return $form->asArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,12 +44,7 @@ class Forms {
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json($listing_data);
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = Form::findArray();
|
||||
wp_send_json($collection);
|
||||
return $listing_data;
|
||||
}
|
||||
|
||||
function create() {
|
||||
@@ -63,7 +55,7 @@ class Forms {
|
||||
array(
|
||||
'id' => 'email',
|
||||
'name' => __('Email'),
|
||||
'type' => 'input',
|
||||
'type' => 'text',
|
||||
'static' => true,
|
||||
'params' => array(
|
||||
'label' => __('Email'),
|
||||
@@ -88,24 +80,23 @@ class Forms {
|
||||
)
|
||||
);
|
||||
|
||||
$form = Form::createOrUpdate($form_data);
|
||||
|
||||
if($form !== false && $form->id()) {
|
||||
wp_send_json(
|
||||
admin_url('admin.php?page=mailpoet-form-editor&id='.$form->id())
|
||||
);
|
||||
} else {
|
||||
wp_send_json(false);
|
||||
}
|
||||
return $this->save($form_data);
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$form = Form::createOrUpdate($data);
|
||||
$errors = $form->getErrors();
|
||||
|
||||
if($form !== false && $form->id()) {
|
||||
wp_send_json($form->id());
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
wp_send_json($form);
|
||||
return array(
|
||||
'result' => true,
|
||||
'form_id' => $form->id()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,10 +110,10 @@ class Forms {
|
||||
// styles
|
||||
$css = new Util\Styles(FormRenderer::getStyles($data));
|
||||
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'html' => $html,
|
||||
'css' => $css->render()
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
function exportsEditor($id) {
|
||||
@@ -134,19 +125,19 @@ class Forms {
|
||||
$exports = Util\Export::getAll($form->asArray());
|
||||
}
|
||||
|
||||
wp_send_json($exports);
|
||||
return $exports;
|
||||
}
|
||||
|
||||
function saveEditor($data = array()) {
|
||||
$form_id = (isset($data['id']) ? (int)$data['id'] : 0);
|
||||
$name = (isset($data['name']) ? $data['name'] : array());
|
||||
$name = (isset($data['name']) ? $data['name'] : __('New form'));
|
||||
$body = (isset($data['body']) ? $data['body'] : array());
|
||||
$settings = (isset($data['settings']) ? $data['settings'] : array());
|
||||
$styles = (isset($data['styles']) ? $data['styles'] : array());
|
||||
$styles = (isset($data['styles']) ? $data['styles'] : '');
|
||||
|
||||
if(empty($body) || empty($settings)) {
|
||||
// error
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
// check if the form is used as a widget
|
||||
$is_widget = false;
|
||||
@@ -178,7 +169,7 @@ class Forms {
|
||||
}
|
||||
}
|
||||
|
||||
// check list selectio
|
||||
// check list selection
|
||||
if($has_segment_selection === true) {
|
||||
$settings['segments_selected_by'] = 'user';
|
||||
} else {
|
||||
@@ -194,45 +185,42 @@ class Forms {
|
||||
'styles' => $styles
|
||||
));
|
||||
|
||||
// response
|
||||
wp_send_json(array(
|
||||
'result' => ($form !== false),
|
||||
'is_widget' => $is_widget
|
||||
));
|
||||
if($form->getErrors() === false) {
|
||||
return array(
|
||||
'result' => true,
|
||||
'is_widget' => $is_widget
|
||||
);
|
||||
} else {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $form->getErrors()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
$result = false;
|
||||
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
$result = $form->restore();
|
||||
$form->restore();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($form->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
$result = false;
|
||||
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
$result = $form->trash();
|
||||
$form->trash();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($form->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$result = false;
|
||||
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
$form->delete();
|
||||
$result = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id) {
|
||||
@@ -246,7 +234,7 @@ class Forms {
|
||||
$result = $form->duplicate($data)->asArray();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
@@ -255,6 +243,6 @@ class Forms {
|
||||
$data
|
||||
);
|
||||
|
||||
wp_send_json($bulk_action->apply());
|
||||
return $bulk_action->apply();
|
||||
}
|
||||
}
|
||||
|
@@ -10,17 +10,17 @@ if(!defined('ABSPATH')) exit;
|
||||
class ImportExport {
|
||||
function getMailChimpLists($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
wp_send_json($mailChimp->getLists());
|
||||
return $mailChimp->getLists();
|
||||
}
|
||||
|
||||
function getMailChimpSubscribers($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
wp_send_json($mailChimp->getSubscribers($data['lists']));
|
||||
return $mailChimp->getSubscribers($data['lists']);
|
||||
}
|
||||
|
||||
function addSegment($data) {
|
||||
$segment = Segment::createOrUpdate($data);
|
||||
wp_send_json(
|
||||
return (
|
||||
($segment->id) ?
|
||||
array(
|
||||
'result' => true,
|
||||
@@ -36,7 +36,7 @@ class ImportExport {
|
||||
$customField = CustomField::create();
|
||||
$customField->hydrate($data);
|
||||
$result = $customField->save();
|
||||
wp_send_json(
|
||||
return (
|
||||
($result) ?
|
||||
array(
|
||||
'result' => true,
|
||||
@@ -49,12 +49,16 @@ class ImportExport {
|
||||
}
|
||||
|
||||
function processImport($data) {
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(json_decode($data, true));
|
||||
wp_send_json($import->process());
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $import->process();
|
||||
}
|
||||
|
||||
function processExport($data) {
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(json_decode($data, true));
|
||||
wp_send_json($export->process());
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $export->process();
|
||||
}
|
||||
}
|
@@ -5,16 +5,19 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
function send($data) {
|
||||
$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']);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => ($result) ? true : false
|
||||
)
|
||||
);
|
||||
$response = 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) {
|
||||
$result = false;
|
||||
$response['errors'] = array($e->getMessage());
|
||||
}
|
||||
$response['result'] = ($result) ? true : false;
|
||||
return $response;
|
||||
}
|
||||
}
|
@@ -9,42 +9,33 @@ class NewsletterTemplates {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int) $data['id'] : 0;
|
||||
function get($id = false) {
|
||||
$template = NewsletterTemplate::findOne($id);
|
||||
if($template === false) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
$template->body = json_decode($template->body);
|
||||
wp_send_json($template->asArray());
|
||||
return $template->asArray();
|
||||
}
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = NewsletterTemplate::findArray();
|
||||
$collection = array_map(function($item) {
|
||||
$item['body'] = json_decode($item['body']);
|
||||
return $item;
|
||||
$collection = NewsletterTemplate::findMany();
|
||||
return array_map(function($item) {
|
||||
return $item->asArray();
|
||||
}, $collection);
|
||||
wp_send_json($collection);
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$result = NewsletterTemplate::createOrUpdate($data);
|
||||
if($result !== true) {
|
||||
wp_send_json($result);
|
||||
} else {
|
||||
wp_send_json(true);
|
||||
}
|
||||
$template = NewsletterTemplate::createOrUpdate($data);
|
||||
return ($template->getErrors() === false && $template->id() > 0);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$template = NewsletterTemplate::findOne($id);
|
||||
if($template !== false) {
|
||||
$result = $template->delete();
|
||||
return $template->delete();
|
||||
} else {
|
||||
$result = false;
|
||||
return false;
|
||||
}
|
||||
wp_send_json($result);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Config\Shortcodes;
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Mailer\API\MailPoet;
|
||||
use MailPoet\Models\Newsletter;
|
||||
@@ -20,11 +21,10 @@ class Newsletters {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int) $data['id'] : 0;
|
||||
function get($id = false) {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter === false) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
$segments = $newsletter->segments()->findArray();
|
||||
$options = $newsletter->options()->findArray();
|
||||
@@ -33,42 +33,32 @@ class Newsletters {
|
||||
return $segment['id'];
|
||||
}, $segments);
|
||||
$newsletter['options'] = $options;
|
||||
$newsletter['body'] = json_decode($newsletter['body']);
|
||||
|
||||
wp_send_json($newsletter);
|
||||
return $newsletter;
|
||||
}
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = Newsletter::findArray();
|
||||
$collection = array_map(function($item) {
|
||||
$item['body'] = json_decode($item['body']);
|
||||
return $item;
|
||||
}, $collection);
|
||||
wp_send_json($collection);
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$segment_ids = array();
|
||||
if(isset($data['segments'])) {
|
||||
$segment_ids = $data['segments'];
|
||||
unset($data['segments']);
|
||||
}
|
||||
|
||||
$options = array();
|
||||
if(isset($data['options'])) {
|
||||
$options = $data['options'];
|
||||
unset($data['options']);
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
$result = false;
|
||||
|
||||
$newsletter = Newsletter::createOrUpdate($data);
|
||||
$errors = $newsletter->getErrors();
|
||||
|
||||
if($newsletter !== false && !$newsletter->id()) {
|
||||
$errors = $newsletter->getValidationErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$result = true;
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
NewsletterSegment::where('newsletter_id', $newsletter->id)
|
||||
->deleteMany();
|
||||
@@ -85,136 +75,75 @@ class Newsletters {
|
||||
NewsletterOption::where('newsletter_id', $newsletter->id)
|
||||
->deleteMany();
|
||||
|
||||
$optionFields = NewsletterOptionField::where(
|
||||
$option_fields = NewsletterOptionField::where(
|
||||
'newsletter_type',
|
||||
$data['type']
|
||||
)->findArray();
|
||||
|
||||
foreach($optionFields as $optionField) {
|
||||
if(isset($options[$optionField['name']])) {
|
||||
foreach($option_fields as $option_field) {
|
||||
if(isset($options[$option_field['name']])) {
|
||||
$relation = NewsletterOption::create();
|
||||
$relation->newsletter_id = $newsletter->id;
|
||||
$relation->option_field_id = $optionField['id'];
|
||||
$relation->value = $options[$optionField['name']];
|
||||
$relation->option_field_id = $option_field['id'];
|
||||
$relation->value = $options[$option_field['name']];
|
||||
$relation->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'result' => true
|
||||
);
|
||||
}
|
||||
wp_send_json(array(
|
||||
'result' => $result,
|
||||
'errors' => $errors
|
||||
));
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
$result = false;
|
||||
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$result = $newsletter->restore();
|
||||
$newsletter->restore();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($newsletter->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
$result = false;
|
||||
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$result = $newsletter->trash();
|
||||
$newsletter->trash();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($newsletter->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$result = false;
|
||||
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$newsletter->delete();
|
||||
$result = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id) {
|
||||
$result = false;
|
||||
|
||||
function duplicate($id = false) {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$data = array(
|
||||
return $newsletter->duplicate(array(
|
||||
'subject' => sprintf(__('Copy of %s'), $newsletter->subject)
|
||||
);
|
||||
$result = $newsletter->duplicate($data)->asArray();
|
||||
))->asArray();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
}
|
||||
|
||||
function send($data = array()) {
|
||||
$newsletter = Newsletter::findOne($data['id'])->asArray();
|
||||
|
||||
if(empty($data['segments'])) {
|
||||
return wp_send_json(array(
|
||||
'errors' => array(
|
||||
__("You need to select a list.")
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
$segments = Segment::whereIdIn($data['segments'])->findMany();
|
||||
$subscribers = array();
|
||||
foreach($segments as $segment) {
|
||||
$segment_subscribers = $segment->subscribers()->findMany();
|
||||
foreach($segment_subscribers as $segment_subscriber) {
|
||||
$subscribers[$segment_subscriber->email] = $segment_subscriber
|
||||
->asArray();
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($subscribers)) {
|
||||
return wp_send_json(array(
|
||||
'errors' => array(
|
||||
__("No subscribers found.")
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
// TODO: TO REMOVE once we add the columns from/reply_to
|
||||
$newsletter = array_merge($newsletter, $data['newsletter']);
|
||||
// END - TO REMOVE
|
||||
|
||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
||||
$newsletter['body']['html'] = $renderer->render();
|
||||
$newsletter['body']['text'] = '';
|
||||
|
||||
$subscribers = Subscriber::find_array();
|
||||
$fromEmail = Setting::where('name', 'from_address')->findOne()->value;
|
||||
$fromName = Setting::where('name', 'from_name')->findOne()->value;
|
||||
$apiKey = Setting::where('name', 'api_key')->findOne()->value;
|
||||
$mailer = new MailPoet($apiKey, $fromEmail, $fromName);
|
||||
|
||||
foreach ($subscribers as $subscriber) {
|
||||
$result = $mailer->send(
|
||||
$newsletter,
|
||||
sprintf('%s %s <%s>', $subscriber['first_name'], $subscriber['last_name'], $subscriber['email'])
|
||||
);
|
||||
if ($result !== true) wp_send_json(false);
|
||||
}
|
||||
|
||||
wp_send_json(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
function render($data = array()) {
|
||||
if(!isset($data['body'])) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
}
|
||||
$renderer = new Renderer($data);
|
||||
wp_send_json(array('rendered_body' => $renderer->render()));
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$rendered_newsletter['html'],
|
||||
$data
|
||||
);
|
||||
$rendered_newsletter = $shortcodes->replace();
|
||||
return array('rendered_body' => $rendered_newsletter);
|
||||
}
|
||||
|
||||
function sendPreview($data = array()) {
|
||||
@@ -222,37 +151,50 @@ class Newsletters {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => false
|
||||
));
|
||||
);
|
||||
}
|
||||
if(empty($data['subscriber'])) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please specify receiver information')),
|
||||
));
|
||||
'errors' => array(__('Please specify receiver information'))
|
||||
);
|
||||
}
|
||||
|
||||
$newsletter = $newsletter->asArray();
|
||||
|
||||
$renderer = new Renderer($newsletter);
|
||||
$rendered_body = $renderer->render();
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$rendered_newsletter['html'],
|
||||
$newsletter
|
||||
);
|
||||
$processed_newsletter['html'] = $shortcodes->replace();
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$rendered_newsletter['text'],
|
||||
$newsletter
|
||||
);
|
||||
$processed_newsletter['text'] = $shortcodes->replace();
|
||||
$newsletter['body'] = array(
|
||||
'html' => $rendered_body,
|
||||
'text' => '',
|
||||
'html' => $processed_newsletter['html'],
|
||||
'text' => $processed_newsletter['text'],
|
||||
);
|
||||
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(false, false, false);
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
$mailer = false,
|
||||
$sender = false,
|
||||
$reply_to = false
|
||||
);
|
||||
$result = $mailer->send($newsletter, $data['subscriber']);
|
||||
|
||||
wp_send_json(array(
|
||||
'result' => $mailer->send($newsletter, $data['subscriber'])
|
||||
));
|
||||
return array('result' => $result);
|
||||
} catch(\Exception $e) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage()),
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +222,7 @@ class Newsletters {
|
||||
$item['queue'] = ($queue !== false) ? $queue->asArray() : null;
|
||||
}
|
||||
|
||||
wp_send_json($listing_data);
|
||||
return $listing_data;
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
@@ -288,46 +230,54 @@ class Newsletters {
|
||||
'\MailPoet\Models\Newsletter',
|
||||
$data
|
||||
);
|
||||
wp_send_json($bulk_action->apply());
|
||||
return $bulk_action->apply();
|
||||
}
|
||||
|
||||
function create($data = array()) {
|
||||
$newsletter = Newsletter::create();
|
||||
$newsletter->type = $data['type'];
|
||||
$newsletter->subject = $data['subject'];
|
||||
$newsletter->body = '{}';
|
||||
|
||||
// try to load template data
|
||||
$template_id = (!empty($data['template']) ? (int)$data['template'] : 0);
|
||||
$template = NewsletterTemplate::findOne($template_id);
|
||||
if($template !== false) {
|
||||
$newsletter->body = $template->body;
|
||||
}
|
||||
|
||||
$options = array();
|
||||
if(isset($data['options'])) {
|
||||
$options = $data['options'];
|
||||
unset($data['options']);
|
||||
}
|
||||
|
||||
$result = $newsletter->save();
|
||||
if($result !== true) {
|
||||
wp_send_json($newsletter->getValidationErrors());
|
||||
$newsletter = Newsletter::createOrUpdate($data);
|
||||
|
||||
// try to load template data
|
||||
$template_id = (!empty($data['template']) ? (int)$data['template'] : false);
|
||||
$template = NewsletterTemplate::findOne($template_id);
|
||||
if($template !== false) {
|
||||
$newsletter->body = $template->body;
|
||||
} else {
|
||||
$newsletter->body = array();
|
||||
}
|
||||
|
||||
$newsletter->save();
|
||||
$errors = $newsletter->getErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' =>$errors
|
||||
);
|
||||
} else {
|
||||
if(!empty($options)) {
|
||||
$optionFields = NewsletterOptionField::where('newsletter_type', $newsletter->type)->findArray();
|
||||
$option_fields = NewsletterOptionField::where(
|
||||
'newsletter_type', $newsletter->type
|
||||
)->findArray();
|
||||
|
||||
foreach($optionFields as $optionField) {
|
||||
if(isset($options[$optionField['name']])) {
|
||||
foreach($option_fields as $option_field) {
|
||||
if(isset($options[$option_field['name']])) {
|
||||
$relation = NewsletterOption::create();
|
||||
$relation->newsletter_id = $newsletter->id;
|
||||
$relation->option_field_id = $optionField['id'];
|
||||
$relation->value = $options[$optionField['name']];
|
||||
$relation->option_field_id = $option_field['id'];
|
||||
$relation->value = $options[$option_field['name']];
|
||||
$relation->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
$newsletter->body = json_decode($newsletter->body);
|
||||
wp_send_json($newsletter->asArray());
|
||||
return array(
|
||||
'result' => true,
|
||||
'newsletter' => $newsletter->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ class Permissions {
|
||||
}
|
||||
|
||||
function set($permissions = array()) {
|
||||
$result = \MailPoet\Util\Permissions::set($permissions);
|
||||
wp_send_json($result);
|
||||
return \MailPoet\Util\Permissions::set($permissions);
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,15 @@ class Router {
|
||||
$endpoint = __NAMESPACE__ . "\\" . $class;
|
||||
$method = $_POST['method'];
|
||||
$data = isset($_POST['data']) ? stripslashes_deep($_POST['data']) : array();
|
||||
$endpoint = new $endpoint();
|
||||
$endpoint->$method($data);
|
||||
|
||||
try {
|
||||
$endpoint = new $endpoint();
|
||||
$response = $endpoint->$method($data);
|
||||
wp_send_json($response);
|
||||
} catch(Exception $e) {
|
||||
error_log($e->getMessage());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function setToken() {
|
||||
|
@@ -12,14 +12,12 @@ class Segments {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : 0);
|
||||
|
||||
function get($id = false) {
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment === false) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
wp_send_json($segment->asArray());
|
||||
return $segment->asArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,63 +62,48 @@ class Segments {
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json($listing_data);
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = Segment::findArray();
|
||||
wp_send_json($collection);
|
||||
return $listing_data;
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$errors = array();
|
||||
$result = false;
|
||||
|
||||
$segment = Segment::createOrUpdate($data);
|
||||
$errors = $segment->getErrors();
|
||||
|
||||
if($segment !== false && !$segment->id()) {
|
||||
$errors = $segment->getValidationErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$result = true;
|
||||
return array(
|
||||
'result' => true
|
||||
);
|
||||
}
|
||||
wp_send_json(array(
|
||||
'result' => $result,
|
||||
'errors' => $errors
|
||||
));
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
$result = false;
|
||||
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
$result = $segment->restore();
|
||||
$segment->restore();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($segment->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
$result = false;
|
||||
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
$result = $segment->trash();
|
||||
$segment->trash();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($segment->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$result = false;
|
||||
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
$segment->delete();
|
||||
$result = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id) {
|
||||
@@ -134,13 +117,13 @@ class Segments {
|
||||
$result = $segment->duplicate($data)->asArray();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function synchronize() {
|
||||
$result = WP::synchronizeUsers();
|
||||
|
||||
wp_send_json($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
@@ -149,6 +132,6 @@ class Segments {
|
||||
$data
|
||||
);
|
||||
|
||||
wp_send_json($bulk_action->apply());
|
||||
return $bulk_action->apply();
|
||||
}
|
||||
}
|
||||
|
@@ -13,25 +13,21 @@ class SendingQueue {
|
||||
try {
|
||||
new Mailer(false);
|
||||
} catch(\Exception $e) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage())
|
||||
)
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
$queue = \MailPoet\Models\SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
$queue = \MailPoet\Models\SendingQueue::whereNull('status')
|
||||
->where('newsletter_id', $data['newsletter_id'])
|
||||
->findArray();
|
||||
if(count($queue)) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Send operation is already in progress.'))
|
||||
)
|
||||
|
||||
if(!empty($queue)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Send operation is already in progress.'))
|
||||
);
|
||||
exit;
|
||||
}
|
||||
$queue = \MailPoet\Models\SendingQueue::create();
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
@@ -40,50 +36,39 @@ class SendingQueue {
|
||||
->findMany();
|
||||
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
$subscriber_ids = array_merge(
|
||||
$subscriber_ids,
|
||||
Helpers::arrayColumn(
|
||||
$segment->subscribers()->findArray(), 'id'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if(empty($subscriber_ids)) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('There are no subscribers.'))
|
||||
)
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('There are no subscribers.'))
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
$queue->subscribers = serialize(
|
||||
array(
|
||||
'to_process' => $subscriber_ids
|
||||
)
|
||||
);
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$result = $queue->save();
|
||||
if($result === false) {
|
||||
$errors = array(__('Queue could not be created.'));
|
||||
|
||||
if(!empty($queue->getValidationErrors())) {
|
||||
$errors = array_merge($errors, $queue->getValidationErrors());
|
||||
}
|
||||
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
)
|
||||
$queue->save();
|
||||
$errors = $queue->getErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -94,14 +79,15 @@ class SendingQueue {
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
|
||||
if($queue !== false) {
|
||||
$result = $queue->pause();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => $result
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
function resume($newsletter_id) {
|
||||
@@ -110,125 +96,14 @@ class SendingQueue {
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
|
||||
if($queue !== false) {
|
||||
$result = $queue->resume();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => $result
|
||||
));
|
||||
}
|
||||
|
||||
function addQueues($data) {
|
||||
$newsletterIds = Helpers::arrayColumn($data, 'newsletter_id');
|
||||
$queues = \MailPoet\Models\SendingQueue::whereIn('newsletter_id', $newsletterIds)
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
if(count($queues)) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Send operation is already in progress.'))
|
||||
)
|
||||
);
|
||||
}
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = \MailPoet\Models\SendingQueue::create();
|
||||
$queue->newsletter_id = $queueData['newsletter_id'];
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $queueData['subscribers']
|
||||
)
|
||||
);
|
||||
$queue->count_total = $queue->count_to_process = count($queueData['subscribers']);
|
||||
$queue->save();
|
||||
return array(
|
||||
'newsletter_id' => $queue->newsletter_id,
|
||||
'queue_id' => $queue->id
|
||||
);
|
||||
}, $data);
|
||||
$result = Helpers::arrayColumn($result, 'queue_id', 'newsletter_id');
|
||||
wp_send_json(
|
||||
count($data) != count($result) ?
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Some queues could not be created.')),
|
||||
'data' => $result
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteQueue($data) {
|
||||
$queue = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id']);
|
||||
if(!$queue) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Queue not found.'))
|
||||
)
|
||||
);
|
||||
}
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function deleteQueues($data) {
|
||||
$queues = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findResultSet();
|
||||
if(!$queues->count()) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Queues not found.'))
|
||||
)
|
||||
);
|
||||
}
|
||||
foreach($queues as $queue) {
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
}
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function getQueueStatus($data) {
|
||||
$queue = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id'])
|
||||
->asArray();
|
||||
wp_send_json(
|
||||
!$queue ?
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Queue not found.'))
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueuesStatus($data) {
|
||||
$queues = \MailPoet\Models\SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findArray();
|
||||
wp_send_json(
|
||||
!$queues ?
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Queue not found.'))
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queues
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@@ -10,17 +10,17 @@ class Settings {
|
||||
|
||||
function get() {
|
||||
$settings = Setting::getAll();
|
||||
wp_send_json($settings);
|
||||
return $settings;
|
||||
}
|
||||
|
||||
function set($settings = array()) {
|
||||
if(empty($settings)) {
|
||||
wp_send_json(false);
|
||||
return false;
|
||||
} else {
|
||||
foreach($settings as $name => $value) {
|
||||
Setting::setValue($name, $value);
|
||||
}
|
||||
wp_send_json(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,8 +17,8 @@ class Setup {
|
||||
} catch(Exception $e) {
|
||||
$result = false;
|
||||
}
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => $result
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -15,22 +15,18 @@ class Subscribers {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int) $data['id'] : 0);
|
||||
|
||||
function get($id = false) {
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber === false) {
|
||||
wp_send_json(false);
|
||||
} else {
|
||||
if($subscriber !== false && $subscriber->id() > 0) {
|
||||
$segments = $subscriber->segments()->findArray();
|
||||
|
||||
$subscriber = $subscriber->withCustomFields()->asArray();
|
||||
$subscriber['segments'] = array_map(function($segment) {
|
||||
return $segment['id'];
|
||||
}, $segments);
|
||||
|
||||
wp_send_json($subscriber);
|
||||
}
|
||||
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
@@ -57,39 +53,23 @@ class Subscribers {
|
||||
}, $relations);
|
||||
}
|
||||
|
||||
wp_send_json($listing_data);
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = Subscriber::findArray();
|
||||
wp_send_json($collection);
|
||||
return $listing_data;
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$errors = array();
|
||||
$result = false;
|
||||
$segment_ids = array();
|
||||
|
||||
if(array_key_exists('segments', $data)) {
|
||||
$segment_ids = (array)$data['segments'];
|
||||
unset($data['segments']);
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
$errors = $subscriber->getErrors();
|
||||
|
||||
if($subscriber !== false && !$subscriber->id()) {
|
||||
$errors = $subscriber->getValidationErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
$result = true;
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
$subscriber->addToSegments($segment_ids);
|
||||
}
|
||||
return array(
|
||||
'result' => true
|
||||
);
|
||||
}
|
||||
wp_send_json(array(
|
||||
'result' => $result,
|
||||
'errors' => $errors
|
||||
));
|
||||
}
|
||||
|
||||
function subscribe($data = array()) {
|
||||
@@ -113,10 +93,10 @@ class Subscribers {
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
$subscriber = Subscriber::subscribe($data, $segment_ids);
|
||||
@@ -129,10 +109,10 @@ class Subscribers {
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
// get success message to display after subscription
|
||||
@@ -163,15 +143,15 @@ class Subscribers {
|
||||
}
|
||||
}
|
||||
|
||||
switch ($form_settings['on_success']) {
|
||||
switch($form_settings['on_success']) {
|
||||
case 'page':
|
||||
// response depending on context
|
||||
if($doing_ajax === true) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => $result,
|
||||
'page' => get_permalink($form_settings['success_page']),
|
||||
'message' => $message
|
||||
));
|
||||
);
|
||||
} else {
|
||||
$redirect_to = ($result === false) ? $referer : get_permalink($form_settings['success_page']);
|
||||
wp_redirect(add_query_arg($params, $redirect_to));
|
||||
@@ -182,10 +162,10 @@ class Subscribers {
|
||||
default:
|
||||
// response depending on context
|
||||
if($doing_ajax === true) {
|
||||
wp_send_json(array(
|
||||
return array(
|
||||
'result' => true,
|
||||
'message' => $message
|
||||
));
|
||||
);
|
||||
} else {
|
||||
// redirect to previous page
|
||||
wp_redirect(add_query_arg($params, $referer));
|
||||
@@ -196,37 +176,28 @@ class Subscribers {
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
$result = false;
|
||||
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
$result = $subscriber->restore();
|
||||
$subscriber->restore();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($subscriber->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
$result = false;
|
||||
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
$result = $subscriber->trash();
|
||||
$subscriber->trash();
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return ($subscriber->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$result = false;
|
||||
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
$subscriber->delete();
|
||||
$result = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
return false;
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
@@ -235,6 +206,6 @@ class Subscribers {
|
||||
$data
|
||||
);
|
||||
|
||||
wp_send_json($bulk_action->apply());
|
||||
return $bulk_action->apply();
|
||||
}
|
||||
}
|
||||
|
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use \MailPoet\Newsletter\Editor\Transformer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Wordpress {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function getPostTypes() {
|
||||
wp_send_json(get_post_types(array(), 'objects'));
|
||||
}
|
||||
|
||||
function getTaxonomies($args) {
|
||||
$post_type = (isset($args['postType'])) ? $args['postType'] : 'post';
|
||||
wp_send_json(get_object_taxonomies($post_type, 'objects'));
|
||||
}
|
||||
|
||||
function getTerms($args) {
|
||||
$taxonomies = (isset($args['taxonomies'])) ? $args['taxonomies'] : array();
|
||||
$search = (isset($args['search'])) ? $args['search'] : '';
|
||||
$limit = (isset($args['limit'])) ? (int)$args['limit'] : 10;
|
||||
$page = (isset($args['page'])) ? (int)$args['page'] : 1;
|
||||
|
||||
wp_send_json(get_terms($taxonomies, array(
|
||||
'hide_empty' => false,
|
||||
'search' => $search,
|
||||
'number' => $limit,
|
||||
'offset' => $limit * ($page - 1),
|
||||
)));
|
||||
}
|
||||
|
||||
function getPosts($args) {
|
||||
$parameters = array(
|
||||
'posts_per_page' => (isset($args['amount'])) ? (int)$args['amount'] : 10,
|
||||
'post_type' => (isset($args['contentType'])) ? $args['contentType'] : 'post',
|
||||
'post_status' => (isset($args['postStatus'])) ? $args['postStatus'] : 'publish',
|
||||
'orderby' => 'date',
|
||||
'order' => ($args['sortBy'] === 'newest') ? 'DESC' : 'ASC',
|
||||
);
|
||||
|
||||
if (isset($args['search'])) {
|
||||
$parameters['s'] = $args['search'];
|
||||
}
|
||||
|
||||
$parameters['tax_query'] = $this->constructTaxonomiesQuery($args);
|
||||
|
||||
wp_send_json(get_posts($parameters));
|
||||
}
|
||||
|
||||
function getTransformedPosts($args) {
|
||||
$parameters = array(
|
||||
'posts_per_page' => (isset($args['amount'])) ? (int)$args['amount'] : 10,
|
||||
'post_type' => (isset($args['contentType'])) ? $args['contentType'] : 'post',
|
||||
'orderby' => 'date',
|
||||
'order' => ($args['sortBy'] === 'newest') ? 'DESC' : 'ASC',
|
||||
);
|
||||
|
||||
if (isset($args['posts']) && is_array($args['posts'])) {
|
||||
$parameters['post__in'] = $args['posts'];
|
||||
}
|
||||
|
||||
$parameters['tax_query'] = $this->constructTaxonomiesQuery($args);
|
||||
|
||||
$posts = get_posts($parameters);
|
||||
|
||||
$transformer = new Transformer($args);
|
||||
wp_send_json($transformer->transform($posts));
|
||||
}
|
||||
|
||||
private function constructTaxonomiesQuery($args) {
|
||||
$taxonomies_query = array();
|
||||
|
||||
if (isset($args['terms']) && is_array($args['terms'])) {
|
||||
// Add filtering by tags and categories
|
||||
$tags = array();
|
||||
$categories = array();
|
||||
foreach($args['terms'] as $term) {
|
||||
if ($term['taxonomy'] === 'category') $categories[] = $term['id'];
|
||||
else if ($term['taxonomy'] === 'post_tag') $tags[] = $term['id'];
|
||||
}
|
||||
|
||||
$taxonomies = array('post_tag' => $tags, 'category' => $categories);
|
||||
foreach ($taxonomies as $taxonomy => $terms) {
|
||||
if (!empty($terms)) {
|
||||
$tax = array(
|
||||
'taxonomy' => $taxonomy,
|
||||
'field' => 'id',
|
||||
'terms' => $terms,
|
||||
);
|
||||
if ($args['inclusionType'] === 'exclude') $tax['operator'] = 'NOT IN';
|
||||
$taxonomies_query[] = $tax;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($taxonomies_query)) {
|
||||
// With exclusion we want to use 'AND', because we want posts that
|
||||
// don't have excluded tags/categories. But with inclusion we want to
|
||||
// use 'OR', because we want posts that have any of the included
|
||||
// tags/categories
|
||||
$taxonomies_query['relation'] = ($args['inclusionType'] === 'exclude') ? 'AND' : 'OR';
|
||||
|
||||
return $taxonomies_query;
|
||||
}
|
||||
}
|
||||
|
||||
return $taxonomies_query;
|
||||
}
|
||||
}
|
@@ -61,10 +61,10 @@ class WP {
|
||||
$segment = Segment::getWPUsers();
|
||||
|
||||
// count WP users
|
||||
$users_count = \count_users()['total_users'];
|
||||
$users_count = \count_users();
|
||||
$linked_subscribers_count = $segment->subscribers()->count();
|
||||
|
||||
if($users_count !== $linked_subscribers_count) {
|
||||
if($users_count['total_users'] !== $linked_subscribers_count) {
|
||||
$linked_subscribers = Subscriber::select('wp_user_id')
|
||||
->whereNotNull('wp_user_id')
|
||||
->findArray();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user