Compare commits
141 Commits
Author | SHA1 | Date | |
---|---|---|---|
5b2ede8b83 | |||
bff6aecd0d | |||
a121583c2d | |||
8c436180d9 | |||
b834a6af4d | |||
1bd8aed192 | |||
cfdf72867e | |||
5888620fc1 | |||
55ba605eb0 | |||
7a73ca7d1a | |||
1918894c5c | |||
0c5589a3e3 | |||
d6eaa4ac8a | |||
b0571b97f5 | |||
6d51ca8011 | |||
d3289dfb84 | |||
bfffdd7274 | |||
c5b8b2aef0 | |||
d7bcf1b817 | |||
f30ed153ce | |||
f436088a16 | |||
db8cb7499d | |||
49c4adc754 | |||
405e743171 | |||
3508ac36b4 | |||
f17c8228cd | |||
3dd5ac0536 | |||
4ebdff49e0 | |||
4a72995bf4 | |||
ef27ac0b84 | |||
2b4adef6c2 | |||
f650455a90 | |||
afbe25e215 | |||
d93249f077 | |||
6223ef77d9 | |||
a423123b66 | |||
1b3d3082b0 | |||
fa117cc7dd | |||
acd407c1f1 | |||
9baf4b068f | |||
18d852e147 | |||
b8dc306741 | |||
6ea056c042 | |||
bcf1b37c6a | |||
2986cdba85 | |||
53a8ae74e2 | |||
8bab01506c | |||
c664045444 | |||
6b8149210d | |||
f31d30b318 | |||
d9fbbdc02d | |||
8136ee2d9b | |||
f7cf6e2131 | |||
f2d1787bd5 | |||
fb51765d3f | |||
088ad5fb42 | |||
2f5b3c0c0a | |||
04ac4d896c | |||
f3b96af863 | |||
eb42b0b98d | |||
304667eb49 | |||
dad1082cd7 | |||
37cf0f3d29 | |||
d61c6dff58 | |||
3734ac578d | |||
b3f56c9d8e | |||
3603eeee77 | |||
59d30cc139 | |||
6ff3bbbb72 | |||
a561e10156 | |||
99f2cf6702 | |||
c6b72e729b | |||
c5bc0f36a4 | |||
efc5c34bf9 | |||
3929efbdd9 | |||
0e0c41882e | |||
79cc708fc6 | |||
8fa98879b8 | |||
331ba385e9 | |||
71ce46d78d | |||
c493de6569 | |||
ff2c2ace86 | |||
7fa789cfd1 | |||
ae6269eb63 | |||
a8f4779bfe | |||
6868142e35 | |||
133d123919 | |||
05c128d12d | |||
bdab0c12fa | |||
75b94690e2 | |||
80fddd6c58 | |||
c807ead5fd | |||
f004bb5368 | |||
1d756e95a7 | |||
1fb0da9fda | |||
a0017b91ee | |||
444ab17342 | |||
44f3058326 | |||
ec09fbcb78 | |||
ed352bb1d3 | |||
375bbd2759 | |||
9fb9d25132 | |||
30f79aa589 | |||
69f8daac95 | |||
03f3a6080c | |||
44f84c6cdb | |||
31008a6895 | |||
2490d8c919 | |||
5886dbfd25 | |||
e48d55f0b1 | |||
42339927cf | |||
b492bcecc0 | |||
6ab7debb7b | |||
b76ce6c26f | |||
6fbc7b1593 | |||
69c8670b01 | |||
da44a87415 | |||
9fb17d4a6b | |||
16dd286f9d | |||
5025f10f9f | |||
1278d9648c | |||
289811a595 | |||
916ae97f73 | |||
876e386966 | |||
9582e58dda | |||
213bca8050 | |||
dc97d3115e | |||
90eb443965 | |||
c5a02c6136 | |||
7f091d7188 | |||
81c277ca93 | |||
f8fea75130 | |||
46b0fcf37b | |||
b07c4d0e6e | |||
eb107799a7 | |||
4eec0a42f9 | |||
9a5a3a08c6 | |||
151683c632 | |||
fd2103d1aa | |||
7696b6ec5d | |||
d972b96255 |
15
.circle_ci/apache/mailpoet.loc.conf
Normal file
@ -0,0 +1,15 @@
|
||||
Listen 8080
|
||||
|
||||
<VirtualHost *:8080>
|
||||
UseCanonicalName Off
|
||||
ServerName mailpoet.loc
|
||||
DocumentRoot /home/ubuntu/mailpoet/wordpress
|
||||
DirectoryIndex index.php
|
||||
LogLevel notice
|
||||
|
||||
<Directory /home/ubuntu/mailpoet/wordpress>
|
||||
AllowOverride All
|
||||
Allow from All
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
40
RoboFile.php
@ -102,31 +102,51 @@ class RoboFile extends \Robo\Tasks {
|
||||
);
|
||||
}
|
||||
|
||||
function testUnit($file = null) {
|
||||
function testUnit($opts=['file' => null, 'xml' => false]) {
|
||||
$this->loadEnv();
|
||||
$this->_exec('vendor/bin/codecept build');
|
||||
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
||||
|
||||
$command = 'vendor/bin/codecept run unit -f '.(($opts['file']) ? $opts['file'] : '');
|
||||
|
||||
if($opts['xml']) {
|
||||
$command .= ' --xml';
|
||||
}
|
||||
return $this->_exec($command);
|
||||
}
|
||||
|
||||
function testCoverage($file = null) {
|
||||
function testCoverage($opts=['file' => null, 'xml' => false]) {
|
||||
$this->loadEnv();
|
||||
$this->_exec('vendor/bin/codecept build');
|
||||
$this->_exec(join(' ', array(
|
||||
$command = join(' ', array(
|
||||
'vendor/bin/codecept run',
|
||||
(($file) ? $file : ''),
|
||||
(($opts['file']) ? $opts['file'] : ''),
|
||||
'--coverage',
|
||||
'--coverage-html'
|
||||
)));
|
||||
($opts['xml']) ? '--coverage-xml' : '--coverage-html'
|
||||
));
|
||||
|
||||
if($opts['xml']) {
|
||||
$command .= ' --xml';
|
||||
}
|
||||
return $this->_exec($command);
|
||||
}
|
||||
|
||||
function testJavascript() {
|
||||
function testJavascript($xml_output_file = null) {
|
||||
$this->compileJs();
|
||||
|
||||
$this->_exec(join(' ', array(
|
||||
$command = join(' ', array(
|
||||
'./node_modules/.bin/mocha',
|
||||
'-r tests/javascript/mochaTestHelper.js',
|
||||
'tests/javascript/testBundles/**/*.js'
|
||||
)));
|
||||
));
|
||||
|
||||
if(!empty($xml_output_file)) {
|
||||
$command .= sprintf(
|
||||
' --reporter xunit --reporter-options output="%s"',
|
||||
$xml_output_file
|
||||
);
|
||||
}
|
||||
|
||||
return $this->_exec($command);
|
||||
}
|
||||
|
||||
function testDebug() {
|
||||
|
@ -60,15 +60,20 @@
|
||||
.mailpoet_boxes .mailpoet_description
|
||||
float:left
|
||||
width: 245px
|
||||
max-height: calc(110px - 2em)
|
||||
max-height: calc(115px - 2em)
|
||||
padding-bottom: 2em
|
||||
overflow: hidden
|
||||
|
||||
.mailpoet_boxes .mailpoet_description h3
|
||||
margin: 0 0 0.7em 0
|
||||
overflow: hidden
|
||||
max-width: 210px
|
||||
line-height: 1.4em
|
||||
h3
|
||||
margin: 0 0 0.7em 0
|
||||
overflow: hidden
|
||||
max-width: 210px
|
||||
line-height: 1.4em
|
||||
|
||||
p
|
||||
font-size: 13px
|
||||
line-height: 1.5
|
||||
margin: 1em 0
|
||||
|
||||
.mailpoet_boxes .mailpoet_actions
|
||||
position: absolute
|
||||
|
@ -1,6 +1,6 @@
|
||||
$tool-inactive-color = #bbbbbb
|
||||
$tool-inactive-color = #333333
|
||||
$tool-inactive-secondary-color = #ffffff
|
||||
$tool-hover-color = #333333
|
||||
$tool-hover-color = #bbbbbb
|
||||
$tool-hover-secondary-color = #ffffff
|
||||
$tool-active-color = #d2d2d4
|
||||
$tool-active-secondary-color = #ffffff
|
||||
@ -12,21 +12,42 @@ $master-column-tool-width = 24px
|
||||
position: absolute
|
||||
top: 0
|
||||
right: 0
|
||||
display: none
|
||||
z-index: 20
|
||||
padding: 2px
|
||||
text-align: right
|
||||
overflow: hidden
|
||||
|
||||
.mailpoet_tool_slider
|
||||
position: relative
|
||||
right: -100%
|
||||
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)
|
||||
opacity: 0
|
||||
|
||||
&.mailpoet_display_tools
|
||||
.mailpoet_tool_slider
|
||||
right: 0
|
||||
opacity: 1
|
||||
|
||||
a
|
||||
vertical-align: top
|
||||
|
||||
.mailpoet_container_horizontal + &
|
||||
left: 100%
|
||||
right: initial
|
||||
padding-left: 5px
|
||||
|
||||
.mailpoet_tool_slider
|
||||
left: -100%
|
||||
right: initial
|
||||
|
||||
&.mailpoet_display_tools
|
||||
.mailpoet_tool_slider
|
||||
left: 0
|
||||
|
||||
.mailpoet_tool
|
||||
width: $master-column-tool-width
|
||||
height: $master-column-tool-width
|
||||
display: block
|
||||
|
||||
.mailpoet_tool_icon
|
||||
width: $master-column-tool-width
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
.mailpoet_input_title,
|
||||
.mailpoet_input_preheader
|
||||
width: 400px
|
||||
width: 500px
|
||||
padding: 3px
|
||||
line-height: normal
|
||||
|
||||
|
@ -5,8 +5,8 @@ $active-social-icon-set-border-color = #adadad
|
||||
$active-social-icon-set-background-color = #daebf2
|
||||
$social-icon-set-hover-border-color = $primary-active-color
|
||||
|
||||
$tool-inactive-color = #bbbbbb
|
||||
$tool-hover-color = #333333
|
||||
$tool-inactive-color = #333333
|
||||
$tool-hover-color = #bbbbbb
|
||||
$tool-active-color = #d2d2d4
|
||||
|
||||
$tool-width = 16px
|
||||
|
@ -1,12 +1,12 @@
|
||||
animation-slide-open-downwards()
|
||||
animation-slide-open-downwards($max-height = 2000px)
|
||||
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
max-height: 2000px
|
||||
max-height: $max-height
|
||||
opacity: 1
|
||||
overflow-y: hidden
|
||||
|
||||
&.mailpoet_closed
|
||||
max-height: 0
|
||||
max-height: 0px
|
||||
opacity: 0
|
||||
overflow-y: hidden
|
||||
|
||||
animation-background-color()
|
||||
transition: background 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
BIN
assets/img/sample_templates/discount/bicycle-header2.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
assets/img/sample_templates/discount/bicycle-header3.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
assets/img/sample_templates/discount/orange-bicycle.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
assets/img/sample_templates/discount/red-icycle.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
assets/img/sample_templates/restaurant/boyga-1329911-639x852.jpg
Normal file
After Width: | Height: | Size: 303 KiB |
BIN
assets/img/sample_templates/restaurant/burger.jpg
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
assets/img/sample_templates/restaurant/header.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 498 KiB |
BIN
assets/img/sample_templates/travel/gallery1.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
assets/img/sample_templates/travel/gallery2.jpg
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
assets/img/sample_templates/travel/gallery3.jpg
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
assets/img/sample_templates/travel/gallery4.jpg
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
assets/img/sample_templates/travel/glow-worms.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
assets/img/sample_templates/travel/header.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
assets/img/sample_templates/travel/holiday-park.jpg
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
assets/img/sample_templates/travel/luge.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
assets/img/welcome_template/beacon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.8 KiB |
BIN
assets/img/welcome_template/mailpoet-logo.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
@ -1,72 +0,0 @@
|
||||
define(
|
||||
[
|
||||
'react',
|
||||
'react-dom',
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
ReactDOM,
|
||||
MailPoet
|
||||
) {
|
||||
var CronControl = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
status: 'loading'
|
||||
};
|
||||
},
|
||||
getCronData: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'getStatus'
|
||||
}).done((response) => {
|
||||
this.setState({
|
||||
status: response.data.status
|
||||
});
|
||||
}).fail((response) => {
|
||||
this.setState({
|
||||
status: false
|
||||
});
|
||||
});
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
this.getCronData();
|
||||
setInterval(this.getCronData, 5000);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
let status;
|
||||
|
||||
switch(this.state.status) {
|
||||
case false:
|
||||
case 'stopping':
|
||||
case 'stopped':
|
||||
status = MailPoet.I18n.t('cronDaemonIsNotRunning');
|
||||
break;
|
||||
case 'starting':
|
||||
case 'started':
|
||||
status = MailPoet.I18n.t('cronDaemonIsRunning');
|
||||
break;
|
||||
case 'loading':
|
||||
status = MailPoet.I18n.t('loadingDaemonStatus');
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ status }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const container = document.getElementById('cron_container');
|
||||
|
||||
if(container) {
|
||||
ReactDOM.render(
|
||||
<CronControl />,
|
||||
container
|
||||
);
|
||||
}
|
||||
});
|
@ -127,37 +127,12 @@ define([
|
||||
return;
|
||||
}
|
||||
|
||||
const dateType = this.props.field.params.date_type;
|
||||
const dateParts = value.split('-');
|
||||
let year = '';
|
||||
let month = '';
|
||||
let day = '';
|
||||
|
||||
switch(dateType) {
|
||||
case 'year_month_day':
|
||||
year = ~~(dateParts[0]);
|
||||
month = ~~(dateParts[1]);
|
||||
day = ~~(dateParts[2]);
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
year = ~~(dateParts[0]);
|
||||
month = ~~(dateParts[1]);
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
month = ~~(dateParts[0]);
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
year = ~~(dateParts[0]);
|
||||
break;
|
||||
}
|
||||
const dateTime = Moment(value);
|
||||
|
||||
this.setState({
|
||||
year: year,
|
||||
month: month,
|
||||
day: day
|
||||
year: dateTime.format('YYYY'),
|
||||
month: dateTime.format('M'),
|
||||
day: dateTime.format('D')
|
||||
});
|
||||
}
|
||||
formatValue() {
|
||||
@ -228,7 +203,7 @@ define([
|
||||
|
||||
const fields = dateSelects.map(type => {
|
||||
switch(type) {
|
||||
case 'yyyy':
|
||||
case 'YYYY':
|
||||
return (<FormFieldDateYear
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'year' }
|
||||
@ -239,7 +214,7 @@ define([
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'mm':
|
||||
case 'MM':
|
||||
return (<FormFieldDateMonth
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'month' }
|
||||
@ -251,7 +226,7 @@ define([
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'dd':
|
||||
case 'DD':
|
||||
return (<FormFieldDateDay
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'day' }
|
||||
|
@ -66,22 +66,22 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'get',
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
if(response === false) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {}
|
||||
}, function() {
|
||||
this.context.router.push('/new');
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: response
|
||||
});
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}.bind(this));
|
||||
}).done((response) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: response.data
|
||||
});
|
||||
}).fail((response) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {}
|
||||
}, function() {
|
||||
this.context.router.push('/new');
|
||||
});
|
||||
});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
@ -115,29 +115,25 @@ define(
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'save',
|
||||
data: item
|
||||
}).done(function(response) {
|
||||
}).always(() => {
|
||||
this.setState({ loading: false });
|
||||
|
||||
if(response.result === true) {
|
||||
if(this.props.onSuccess !== undefined) {
|
||||
this.props.onSuccess();
|
||||
} else {
|
||||
this.context.router.push('/');
|
||||
}
|
||||
|
||||
if(this.props.params.id !== undefined) {
|
||||
this.props.messages.onUpdate();
|
||||
} else {
|
||||
this.props.messages.onCreate();
|
||||
}
|
||||
}).done((response) => {
|
||||
if(this.props.onSuccess !== undefined) {
|
||||
this.props.onSuccess();
|
||||
} else {
|
||||
if(response.result === false) {
|
||||
if(response.errors.length > 0) {
|
||||
this.setState({ errors: response.errors });
|
||||
}
|
||||
}
|
||||
this.context.router.push('/');
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
if(this.props.params.id !== undefined) {
|
||||
this.props.messages.onUpdate();
|
||||
} else {
|
||||
this.props.messages.onCreate();
|
||||
}
|
||||
}).fail((response) => {
|
||||
if(response.errors.length > 0) {
|
||||
this.setState({ errors: response.errors });
|
||||
}
|
||||
});
|
||||
},
|
||||
handleValueChange: function(e) {
|
||||
if (this.props.onChange) {
|
||||
@ -159,7 +155,7 @@ define(
|
||||
var errors = this.getErrors().map(function(error, index) {
|
||||
return (
|
||||
<p key={ 'error-'+index } className="mailpoet_error">
|
||||
{ error }
|
||||
{ error.message }
|
||||
</p>
|
||||
);
|
||||
});
|
||||
|
@ -27,48 +27,48 @@ const columns = [
|
||||
];
|
||||
|
||||
const messages = {
|
||||
onTrash: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneFormTrashed')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleFormsTrashed')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneFormDeleted')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleFormsDeleted')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneFormRestored')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleFormsRestored')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
@ -99,14 +99,21 @@ const item_actions = [
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'forms',
|
||||
action: 'duplicate',
|
||||
data: item.id
|
||||
}).done(function(response) {
|
||||
if (response !== false && response['name'] !== undefined) {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('formDuplicated')).replace('%$1s', response.name)
|
||||
data: {
|
||||
id: item.id
|
||||
}
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('formDuplicated')).replace('%$1s', response.data.name)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -120,9 +127,14 @@ const FormList = React.createClass({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'forms',
|
||||
action: 'create'
|
||||
}).done(function(response) {
|
||||
if(response.result && response.form_id) {
|
||||
window.location = mailpoet_form_edit_url + response.form_id;
|
||||
}).done((response) => {
|
||||
window.location = mailpoet_form_edit_url + response.data.id;
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -53,7 +53,10 @@ function(
|
||||
}
|
||||
|
||||
if(data.action) {
|
||||
this.props.onBulkAction(selected_ids, data).then(onSuccess);
|
||||
const promise = this.props.onBulkAction(selected_ids, data);
|
||||
if (promise !== false) {
|
||||
promise.then(onSuccess);
|
||||
};
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
@ -456,22 +456,29 @@ const Listing = React.createClass({
|
||||
sort_by: this.state.sort_by,
|
||||
sort_order: this.state.sort_order
|
||||
}
|
||||
}).done(function(response) {
|
||||
}).always(() => {
|
||||
this.setState({ loading: false });
|
||||
}).done((response) => {
|
||||
this.setState({
|
||||
items: response.items || [],
|
||||
filters: response.filters || {},
|
||||
groups: response.groups || [],
|
||||
count: response.count || 0,
|
||||
loading: false
|
||||
}, function() {
|
||||
if (this.props['onGetItems'] !== undefined) {
|
||||
const count = (response.groups[0] !== undefined)
|
||||
? ~~(response.groups[0].count)
|
||||
: 0;
|
||||
this.props.onGetItems(count);
|
||||
items: response.data || [],
|
||||
filters: response.meta.filters || {},
|
||||
groups: response.meta.groups || [],
|
||||
count: response.meta.count || 0
|
||||
}, () => {
|
||||
// if viewing an empty trash
|
||||
if (this.state.group === 'trash' && response.meta.count === 0) {
|
||||
// redirect to default group
|
||||
this.handleGroup('all');
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
});
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleRestoreItem: function(id) {
|
||||
@ -483,8 +490,10 @@ const Listing = React.createClass({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'restore',
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done((response) => {
|
||||
if (
|
||||
this.props.messages !== undefined
|
||||
&& this.props.messages['onRestore'] !== undefined
|
||||
@ -492,7 +501,12 @@ const Listing = React.createClass({
|
||||
this.props.messages.onRestore(response);
|
||||
}
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleTrashItem: function(id) {
|
||||
this.setState({
|
||||
@ -503,8 +517,10 @@ const Listing = React.createClass({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'trash',
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done((response) => {
|
||||
if (
|
||||
this.props.messages !== undefined
|
||||
&& this.props.messages['onTrash'] !== undefined
|
||||
@ -512,7 +528,12 @@ const Listing = React.createClass({
|
||||
this.props.messages.onTrash(response);
|
||||
}
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleDeleteItem: function(id) {
|
||||
this.setState({
|
||||
@ -523,8 +544,10 @@ const Listing = React.createClass({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'delete',
|
||||
data: id
|
||||
}).done(function(response) {
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done((response) => {
|
||||
if (
|
||||
this.props.messages !== undefined
|
||||
&& this.props.messages['onDelete'] !== undefined
|
||||
@ -532,22 +555,29 @@ const Listing = React.createClass({
|
||||
this.props.messages.onDelete(response);
|
||||
}
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleEmptyTrash: function() {
|
||||
return this.handleBulkAction('all', {
|
||||
action: 'delete',
|
||||
group: 'trash'
|
||||
}).then(function(response) {
|
||||
if (~~(response) > 0) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('permanentlyDeleted').replace('%d', response)
|
||||
);
|
||||
}
|
||||
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('permanentlyDeleted').replace('%d', response.meta.count)
|
||||
);
|
||||
// redirect to default group
|
||||
this.handleGroup('all');
|
||||
}.bind(this));
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleBulkAction: function(selected_ids, params) {
|
||||
if (
|
||||
@ -555,7 +585,7 @@ const Listing = React.createClass({
|
||||
&& this.state.selected_ids.length === 0
|
||||
&& selected_ids !== 'all'
|
||||
) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.setState({ loading: true });
|
||||
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Show Settings Behavior
|
||||
*
|
||||
* Opens up settings of a BlockView if contents are clicked upon
|
||||
*/
|
||||
define([
|
||||
'backbone.marionette',
|
||||
'jquery',
|
||||
'newsletter_editor/behaviors/BehaviorsLookup',
|
||||
], function(Marionette, jQuery, BehaviorsLookup) {
|
||||
|
||||
BehaviorsLookup.ShowSettingsBehavior = Marionette.Behavior.extend({
|
||||
defaults: {
|
||||
ignoreFrom: '', // selector
|
||||
},
|
||||
events: {
|
||||
'click .mailpoet_content': 'showSettings',
|
||||
},
|
||||
showSettings: function(event) {
|
||||
if(!this.isIgnoredElement(event.target)) {
|
||||
this.view.triggerMethod('showSettings');
|
||||
}
|
||||
},
|
||||
isIgnoredElement: function(element) {
|
||||
return this.options.ignoreFrom
|
||||
&& this.options.ignoreFrom.length > 0
|
||||
&& jQuery(element).is(this.options.ignoreFrom);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -35,7 +35,12 @@ define([
|
||||
|
||||
Module.ALCSupervisor = SuperModel.extend({
|
||||
initialize: function() {
|
||||
this.listenTo(App.getChannel(), 'automatedLatestContentRefresh', this.refresh);
|
||||
var DELAY_REFRESH_FOR_MS = 500;
|
||||
this.listenTo(
|
||||
App.getChannel(),
|
||||
'automatedLatestContentRefresh',
|
||||
_.debounce(this.refresh, DELAY_REFRESH_FOR_MS)
|
||||
);
|
||||
},
|
||||
refresh: function() {
|
||||
var models = App.findModels(function(model) {
|
||||
@ -107,9 +112,7 @@ define([
|
||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:featuredImagePosition 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);
|
||||
this.on('add remove update reset', function(model, collection, options) {
|
||||
App.getChannel().trigger('automatedLatestContentRefresh');
|
||||
});
|
||||
this.on('add remove update reset', this._scheduleFetchPosts);
|
||||
this.on('refreshPosts', this.updatePosts, this);
|
||||
},
|
||||
updatePosts: function(posts) {
|
||||
@ -120,16 +123,7 @@ define([
|
||||
* ALC posts on each model change
|
||||
*/
|
||||
_scheduleFetchPosts: function() {
|
||||
var TIMEOUT = 500,
|
||||
that = this;
|
||||
if (this._fetchPostsTimer !== undefined) {
|
||||
clearTimeout(this._fetchPostsTimer);
|
||||
}
|
||||
this._fetchPostsTimer = setTimeout(function() {
|
||||
//that.fetchPosts();
|
||||
App.getChannel().trigger('automatedLatestContentRefresh');
|
||||
that._fetchPostsTimer = undefined;
|
||||
}, TIMEOUT);
|
||||
App.getChannel().trigger('automatedLatestContentRefresh');
|
||||
},
|
||||
});
|
||||
|
||||
@ -180,17 +174,17 @@ define([
|
||||
"change .mailpoet_automated_latest_content_title_format": 'changeTitleFormat',
|
||||
"change .mailpoet_automated_latest_content_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||
"change .mailpoet_automated_latest_content_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||
"keyup .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
||||
"input .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
||||
"change .mailpoet_automated_latest_content_content_type": _.partial(this.changeField, "contentType"),
|
||||
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_automated_latest_content_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"input .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
"keyup .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"keyup .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"input .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"input .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"change .mailpoet_automated_latest_content_sort_by": _.partial(this.changeField, "sortBy"),
|
||||
"click .mailpoet_done_editing": "close",
|
||||
};
|
||||
|
@ -99,12 +99,12 @@ define([
|
||||
},
|
||||
showTools: function(_event) {
|
||||
if (!this.showingToolsDisabled) {
|
||||
this.$('> .mailpoet_tools').show();
|
||||
this.$('> .mailpoet_tools').addClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('showTools');
|
||||
}
|
||||
},
|
||||
hideTools: function(e) {
|
||||
this.$('> .mailpoet_tools').hide();
|
||||
this.$('> .mailpoet_tools').removeClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('hideTools');
|
||||
},
|
||||
enableShowingTools: function() {
|
||||
|
@ -44,6 +44,9 @@ define([
|
||||
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block",
|
||||
getTemplate: function() { return templates.buttonBlock; },
|
||||
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
||||
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||
ShowSettingsBehavior: {},
|
||||
}),
|
||||
initialize: function() {
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
|
||||
@ -65,8 +68,8 @@ define([
|
||||
getTemplate: function() { return templates.buttonBlockSettings; },
|
||||
events: function() {
|
||||
return {
|
||||
"keyup .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
||||
"keyup .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
||||
"input .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
||||
"input .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
||||
"change .mailpoet_field_button_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||
"change .mailpoet_field_button_font_color": _.partial(this.changeColorField, "styles.block.fontColor"),
|
||||
"change .mailpoet_field_button_font_family": _.partial(this.changeField, "styles.block.fontFamily"),
|
||||
@ -77,23 +80,19 @@ define([
|
||||
|
||||
"input .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"keyup .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"input .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"change .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"change .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"keyup .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
"input .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"change .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"change .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"keyup .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
"input .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||
|
||||
"input .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"change .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"change .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"keyup .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
"input .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||
|
||||
"click .mailpoet_field_button_replace_all_styles": "applyToAll",
|
||||
"click .mailpoet_done_editing": "close",
|
||||
|
@ -186,13 +186,13 @@ define([
|
||||
},
|
||||
showTools: function() {
|
||||
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
||||
this.$(this.ui.tools).show();
|
||||
this.$(this.ui.tools).addClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('showTools');
|
||||
}
|
||||
},
|
||||
hideTools: function() {
|
||||
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
||||
this.$(this.ui.tools).hide();
|
||||
this.$(this.ui.tools).removeClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('hideTools');
|
||||
}
|
||||
},
|
||||
|
@ -43,6 +43,9 @@ define([
|
||||
minLength: 0, // TODO: Move this number to editor configuration
|
||||
modelField: 'styles.block.padding',
|
||||
},
|
||||
ShowSettingsBehavior: {
|
||||
ignoreFrom: '.mailpoet_resize_handle'
|
||||
},
|
||||
}, base.BlockView.prototype.behaviors),
|
||||
onDragSubstituteBy: function() { return Module.DividerWidgetView; },
|
||||
initialize: function() {
|
||||
@ -88,8 +91,7 @@ define([
|
||||
|
||||
"input .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"change .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"keyup .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
"input .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||
|
||||
"change .mailpoet_field_divider_border_color": _.partial(this.changeColorField, "styles.block.borderColor"),
|
||||
"change .mailpoet_field_divider_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
|
||||
|
@ -41,6 +41,9 @@ define([
|
||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||
},
|
||||
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||
ShowSettingsBehavior: {},
|
||||
}),
|
||||
onRender: function() {
|
||||
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
||||
this.toolsRegion.show(this.toolsView);
|
||||
@ -61,9 +64,9 @@ define([
|
||||
getTemplate: function() { return templates.imageBlockSettings; },
|
||||
events: function() {
|
||||
return {
|
||||
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||
"input .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||
"input .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||
"input .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
|
||||
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
||||
|
@ -273,7 +273,7 @@ define([
|
||||
return {
|
||||
'change .mailpoet_settings_posts_content_type': _.partial(this.changeField, 'contentType'),
|
||||
'change .mailpoet_posts_post_status': _.partial(this.changeField, 'postStatus'),
|
||||
'keyup .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||
};
|
||||
},
|
||||
constructor: function() {
|
||||
@ -414,17 +414,17 @@ define([
|
||||
"change .mailpoet_posts_title_format": 'changeTitleFormat',
|
||||
"change .mailpoet_posts_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||
"change .mailpoet_posts_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||
"keyup .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
||||
"input .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
||||
"change .mailpoet_posts_content_type": _.partial(this.changeField, "contentType"),
|
||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||
"change .mailpoet_posts_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
||||
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"input .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
||||
"keyup .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"keyup .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"input .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||
"input .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||
"change .mailpoet_posts_sort_by": _.partial(this.changeField, "sortBy"),
|
||||
};
|
||||
},
|
||||
|
@ -141,6 +141,7 @@ define([
|
||||
},
|
||||
},
|
||||
HighlightEditingBehavior: {},
|
||||
ShowSettingsBehavior: {},
|
||||
},
|
||||
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
|
||||
constructor: function() {
|
||||
@ -149,6 +150,7 @@ define([
|
||||
Marionette.CompositeView.apply(this, arguments);
|
||||
},
|
||||
initialize: function() {
|
||||
this.on('showSettings', this.showSettings, this);
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
@ -169,13 +171,16 @@ define([
|
||||
this.regionManager.destroy();
|
||||
},
|
||||
showTools: function(_event) {
|
||||
this.$(this.ui.tools).show();
|
||||
this.$(this.ui.tools).addClass('mailpoet_display_tools');
|
||||
_event.stopPropagation();
|
||||
},
|
||||
hideTools: function(_event) {
|
||||
this.$(this.ui.tools).hide();
|
||||
this.$(this.ui.tools).removeClass('mailpoet_display_tools');
|
||||
_event.stopPropagation();
|
||||
},
|
||||
showSettings: function(options) {
|
||||
this.toolsView.triggerMethod('showSettings', options);
|
||||
},
|
||||
getDropFunc: function() {
|
||||
return function() {
|
||||
return this.model.clone();
|
||||
@ -275,9 +280,9 @@ define([
|
||||
return {
|
||||
"click .mailpoet_delete_block": "deleteIcon",
|
||||
"change .mailpoet_social_icon_field_type": _.partial(this.changeField, "iconType"),
|
||||
"keyup .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
||||
"keyup .mailpoet_social_icon_field_link": this.changeLink,
|
||||
"keyup .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
||||
"input .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
||||
"input .mailpoet_social_icon_field_link": this.changeLink,
|
||||
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
||||
};
|
||||
},
|
||||
modelEvents: {
|
||||
|
@ -36,6 +36,9 @@ define([
|
||||
minLength: 20, // TODO: Move this number to editor configuration
|
||||
modelField: 'styles.block.height',
|
||||
},
|
||||
ShowSettingsBehavior: {
|
||||
ignoreFrom: '.mailpoet_resize_handle'
|
||||
},
|
||||
}, base.BlockView.prototype.behaviors),
|
||||
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
|
||||
onDragSubstituteBy: function() { return Module.SpacerWidgetView; },
|
||||
|
@ -11,7 +11,7 @@ define([
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'automatedLatestContent',
|
||||
action: args.action,
|
||||
data: args.options || {},
|
||||
data: args.options || {}
|
||||
});
|
||||
};
|
||||
Module._cachedQuery = _.memoize(Module._query, JSON.stringify);
|
||||
@ -19,14 +19,14 @@ define([
|
||||
Module.getNewsletter = function(options) {
|
||||
return Module._query({
|
||||
action: 'get',
|
||||
options: options,
|
||||
options: options
|
||||
});
|
||||
};
|
||||
|
||||
Module.getPostTypes = function() {
|
||||
return Module._cachedQuery({
|
||||
action: 'getPostTypes',
|
||||
options: {},
|
||||
options: {}
|
||||
}).then(function(response) {
|
||||
return _.values(response.data);
|
||||
});
|
||||
@ -83,7 +83,7 @@ define([
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: options || {},
|
||||
data: options || {}
|
||||
});
|
||||
};
|
||||
|
||||
@ -91,7 +91,7 @@ define([
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'sendPreview',
|
||||
data: options || {},
|
||||
data: options || {}
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -232,6 +232,12 @@ define([
|
||||
'click .mailpoet_show_preview': 'showPreview',
|
||||
'click #mailpoet_send_preview': 'sendPreview',
|
||||
},
|
||||
onBeforeDestroy: function() {
|
||||
if (this.previewView) {
|
||||
this.previewView.destroy();
|
||||
this.previewView = null;
|
||||
}
|
||||
},
|
||||
showPreview: function() {
|
||||
var json = App.toJSON();
|
||||
|
||||
@ -246,18 +252,31 @@ define([
|
||||
endpoint: 'newsletters',
|
||||
action: 'showPreview',
|
||||
data: json,
|
||||
}).done(function(response){
|
||||
}).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function(response) {
|
||||
this.previewView = new Module.NewsletterPreviewView({
|
||||
previewUrl: response.meta.preview_url
|
||||
});
|
||||
|
||||
if (response.result === true) {
|
||||
window.open(response.data.url, '_blank')
|
||||
var view = this.previewView.render();
|
||||
|
||||
MailPoet.Modal.popup({
|
||||
template: '',
|
||||
element: this.previewView.$el,
|
||||
title: MailPoet.I18n.t('newsletterPreview'),
|
||||
onCancel: function() {
|
||||
this.previewView.destroy();
|
||||
this.previewView = null;
|
||||
}.bind(this)
|
||||
});
|
||||
}.bind(this)).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}).fail(function(error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('newsletterPreviewFailed')
|
||||
);
|
||||
});
|
||||
},
|
||||
sendPreview: function() {
|
||||
@ -282,32 +301,39 @@ define([
|
||||
// send test email
|
||||
MailPoet.Modal.loading(true);
|
||||
|
||||
CommunicationComponent.previewNewsletter(data).done(function(response) {
|
||||
if(response.result !== undefined && response.result === true) {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('newsletterPreviewSent'), { scroll: true });
|
||||
} else {
|
||||
if (_.isArray(response.errors)) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error, { scroll: true });
|
||||
});
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('newsletterPreviewFailedToSend'),
|
||||
{
|
||||
scroll: true,
|
||||
static: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
CommunicationComponent.previewNewsletter(data).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterPreviewSent'),
|
||||
{ scroll: true });
|
||||
}).fail(function(response) {
|
||||
// an error occurred
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true, static: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Module.NewsletterPreviewView = Marionette.ItemView.extend({
|
||||
getTemplate: function() { return templates.newsletterPreview; },
|
||||
initialize: function(options) {
|
||||
this.previewUrl = options.previewUrl;
|
||||
this.width = App.getConfig().get('newsletterPreview.width');
|
||||
this.height = App.getConfig().get('newsletterPreview.height')
|
||||
},
|
||||
templateHelpers: function() {
|
||||
return {
|
||||
previewUrl: this.previewUrl,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function(options) {
|
||||
App.registerWidget = Module.registerWidget;
|
||||
App.getWidgets = Module.getWidgets;
|
||||
|
@ -17,8 +17,8 @@ import {
|
||||
} from 'newsletters/scheduling/common.jsx'
|
||||
|
||||
const messages = {
|
||||
onTrash(response) {
|
||||
const count = ~~response;
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -28,12 +28,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete(response) {
|
||||
const count = ~~response;
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -43,12 +43,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore(response) {
|
||||
const count = ~~response;
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -58,7 +58,7 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
@ -127,16 +127,23 @@ const newsletter_actions = [
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'duplicate',
|
||||
data: newsletter.id
|
||||
}).done(function(response) {
|
||||
if (response !== false && response.subject !== undefined) {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.subject
|
||||
)
|
||||
data: {
|
||||
id: newsletter.id
|
||||
}
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.data.subject
|
||||
)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -12,8 +12,8 @@ import { QueueMixin, StatisticsMixin } from 'newsletters/listings/mixins.jsx'
|
||||
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||
|
||||
const messages = {
|
||||
onTrash(response) {
|
||||
const count = ~~response;
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -23,12 +23,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete(response) {
|
||||
const count = ~~response;
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -38,12 +38,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore(response) {
|
||||
const count = ~~response;
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -53,7 +53,7 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
@ -122,16 +122,23 @@ const newsletter_actions = [
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'duplicate',
|
||||
data: newsletter.id
|
||||
}).done(function(response) {
|
||||
if (response !== false && response.subject !== undefined) {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.subject
|
||||
)
|
||||
data: {
|
||||
id: newsletter.id
|
||||
}
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.data.subject
|
||||
)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -15,8 +15,8 @@ const mailpoet_segments = window.mailpoet_segments || {};
|
||||
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||
|
||||
const messages = {
|
||||
onTrash(response) {
|
||||
const count = ~~response;
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -26,12 +26,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete(response) {
|
||||
const count = ~~response;
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -41,12 +41,12 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore(response) {
|
||||
const count = ~~response;
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (count === 1) {
|
||||
@ -56,7 +56,7 @@ const messages = {
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
@ -125,16 +125,23 @@ const newsletter_actions = [
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'duplicate',
|
||||
data: newsletter.id
|
||||
}).done(function(response) {
|
||||
if (response !== false && response.subject !== undefined) {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.subject
|
||||
)
|
||||
data: {
|
||||
id: newsletter.id
|
||||
}
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||
'%$1s', response.data.subject
|
||||
)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
refresh();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -66,22 +66,22 @@ define(
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'get',
|
||||
data: id
|
||||
}).done((response) => {
|
||||
if(response === false) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {},
|
||||
}, function() {
|
||||
this.context.router.push('/new');
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: response,
|
||||
fields: this.getFieldsByNewsletter(response),
|
||||
});
|
||||
data: {
|
||||
id: id
|
||||
}
|
||||
}).done((response) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: response.data,
|
||||
fields: this.getFieldsByNewsletter(response.data)
|
||||
});
|
||||
}).fail((response) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {}
|
||||
}, () => {
|
||||
this.context.router.push('/new');
|
||||
});
|
||||
});
|
||||
},
|
||||
handleSend: function(e) {
|
||||
|
@ -28,17 +28,16 @@ define(
|
||||
type: type,
|
||||
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.context.router.push(`/template/${response.newsletter.id}`);
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}).done((response) => {
|
||||
this.context.router.push(`/template/${response.data.id}`);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -50,17 +50,16 @@ define(
|
||||
type: 'notification',
|
||||
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
||||
}),
|
||||
}).done(function(response) {
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}).done((response) => {
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.context.router.push(`/template/${newsletterId}`);
|
||||
|
@ -25,19 +25,18 @@ define(
|
||||
endpoint: 'newsletters',
|
||||
action: 'create',
|
||||
data: {
|
||||
type: 'standard',
|
||||
type: 'standard'
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
}).done((response) => {
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -113,17 +113,16 @@ const WelcomeScheduling = React.createClass({
|
||||
type: 'welcome',
|
||||
options: this.state
|
||||
}
|
||||
}).done(function(response) {
|
||||
if (response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
}).done((response) => {
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.context.router.push(`/template/${ newsletterId }`);
|
||||
|
@ -57,18 +57,17 @@ define(
|
||||
data: _.extend({}, this.state, {
|
||||
type: 'welcome',
|
||||
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
||||
}),
|
||||
}).done(function(response) {
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
}).done((response) => {
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.context.router.push(`/template/${newsletterId}`);
|
||||
|
@ -36,48 +36,48 @@ var columns = [
|
||||
];
|
||||
|
||||
const messages = {
|
||||
onTrash: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSegmentTrashed')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSegmentsTrashed')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSegmentDeleted')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSegmentsDeleted')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
var count = ~~response;
|
||||
var message = null;
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if(count === 1) {
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSegmentRestored')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSegmentsRestored')
|
||||
).replace('%$1d', count);
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
@ -106,16 +106,23 @@ const item_actions = [
|
||||
{
|
||||
name: 'duplicate_segment',
|
||||
label: MailPoet.I18n.t('duplicate'),
|
||||
onClick: function(item, refresh) {
|
||||
onClick: (item, refresh) => {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'segments',
|
||||
action: 'duplicate',
|
||||
data: item.id
|
||||
}).done(function(response) {
|
||||
data: {
|
||||
id: item.id
|
||||
}
|
||||
}).done((response) => {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('listDuplicated')).replace('%$1s', response.name)
|
||||
MailPoet.I18n.t('listDuplicated').replace('%$1s', response.data.name)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
display: function(segment) {
|
||||
|
@ -133,8 +133,7 @@ define(
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processExport',
|
||||
data: JSON.stringify({
|
||||
@ -144,25 +143,22 @@ define(
|
||||
'segments': (exportData.segments) ? segmentsContainerElement.val() : false,
|
||||
'subscriber_fields': subscriberFieldsContainerElement.val()
|
||||
})
|
||||
})
|
||||
.done(function (response) {
|
||||
}).always(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
} else {
|
||||
resultMessage = MailPoet.I18n.t('exportMessage')
|
||||
.replace('%1$s', '<strong>' + parseInt(response.data.totalExported).toLocaleString() + '</strong>')
|
||||
.replace('[link]', '<a href="' + response.data.exportFileURL + '" target="_blank" >')
|
||||
.replace('[/link]', '</a>');
|
||||
jQuery('#export_result_notice').html('<p>' + resultMessage + '</p>').show();
|
||||
window.location.href = response.data.exportFileURL;
|
||||
}).done(function(response) {
|
||||
resultMessage = MailPoet.I18n.t('exportMessage')
|
||||
.replace('%1$s', '<strong>' + parseInt(response.data.totalExported).toLocaleString() + '</strong>')
|
||||
.replace('[link]', '<a href="' + response.data.exportFileURL + '" target="_blank" >')
|
||||
.replace('[/link]', '</a>');
|
||||
jQuery('#export_result_notice').html('<p>' + resultMessage + '</p>').show();
|
||||
window.location.href = response.data.exportFileURL;
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -51,6 +51,12 @@ define(
|
||||
* STEP 1 (upload or copy/paste)
|
||||
*/
|
||||
router.on('route:step1', function () {
|
||||
// set or reset temporary validation rule on all columns
|
||||
mailpoetColumns = jQuery.map(mailpoetColumns, function (column, columnIndex) {
|
||||
column.validation_rule = false;
|
||||
return column;
|
||||
});
|
||||
|
||||
if (typeof (importData.step1) !== 'undefined') {
|
||||
showCurrentStep();
|
||||
return;
|
||||
@ -185,68 +191,59 @@ define(
|
||||
mailChimpKeyVerifyButtonElement.click(function () {
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
endpoint: 'importExport',
|
||||
action: 'getMailChimpLists',
|
||||
data: {api_key: mailChimpKeyInputElement.val()}
|
||||
}).done(function (response) {
|
||||
if (response.result === false) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(response.errors);
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-error');
|
||||
data: {
|
||||
api_key: mailChimpKeyInputElement.val()
|
||||
}
|
||||
}).always(function() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function(response) {
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.html('')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-ok');
|
||||
if (response.data.length === 0) {
|
||||
jQuery('.mailpoet_mailchimp-key-status').html(MailPoet.I18n.t('noMailChimpLists'));
|
||||
mailChimpListsContainerElement.hide();
|
||||
toggleNextStepButton(mailChimpProcessButtonElement, 'off');
|
||||
} else {
|
||||
jQuery('.mailpoet_mailchimp-key-status')
|
||||
.html('')
|
||||
.removeClass()
|
||||
.addClass('mailpoet_mailchimp-key-status mailpoet_mailchimp-ok');
|
||||
if (!response.data) {
|
||||
jQuery('.mailpoet_mailchimp-key-status').html(MailPoet.I18n.t('noMailChimpLists'));
|
||||
mailChimpListsContainerElement.hide();
|
||||
toggleNextStepButton(mailChimpProcessButtonElement, 'off');
|
||||
} else {
|
||||
displayMailChimpLists(response.data);
|
||||
}
|
||||
displayMailChimpLists(response.data);
|
||||
}
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
MailPoet.Modal.loading(false);
|
||||
}).error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
MailPoet.Modal.loading(false);
|
||||
});
|
||||
|
||||
mailChimpProcessButtonElement.click(function () {
|
||||
if (mailChimpProcessButtonElement.closest('table a').hasClass('disabled')) {
|
||||
if (mailChimpProcessButtonElement.closest('table a').hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
endpoint: 'importExport',
|
||||
action: 'getMailChimpSubscribers',
|
||||
data: {
|
||||
api_key: mailChimpKeyInputElement.val(),
|
||||
lists: mailChimpListsContainerElement.find('select').val()
|
||||
}
|
||||
}).done(function (response) {
|
||||
if (response.result === true) {
|
||||
importData.step1 = response.data;
|
||||
router.navigate('step2', {trigger: true});
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}
|
||||
}).always(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).error(function () {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + result.statusText.toLowerCase() + '.'
|
||||
);
|
||||
}).done(function(response) {
|
||||
importData.step1 = response.data;
|
||||
router.navigate('step2', {trigger: true});
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -455,7 +452,7 @@ define(
|
||||
null,
|
||||
new Array(subscribers.subscribers[0].length)
|
||||
).map(String.prototype.valueOf, filler),
|
||||
fillterPosition;
|
||||
fillerPosition;
|
||||
|
||||
showCurrentStep();
|
||||
|
||||
@ -565,79 +562,54 @@ define(
|
||||
})
|
||||
}
|
||||
|
||||
jQuery('.mailpoet_create_segment').click(function () {
|
||||
jQuery('.mailpoet_create_segment').click(function() {
|
||||
MailPoet.Modal.popup({
|
||||
title: MailPoet.I18n.t('addNewList'),
|
||||
template: jQuery('#new_segment_template').html()
|
||||
})
|
||||
jQuery('#new_segment_name').keypress(function (e) {
|
||||
jQuery('#new_segment_name').keypress(function(e) {
|
||||
if (e.which == 13) {
|
||||
jQuery('#new_segment_process').click();
|
||||
}
|
||||
});
|
||||
jQuery('#new_segment_process').click(function () {
|
||||
var segmentName = jQuery('#new_segment_name').val().trim(),
|
||||
segmentDescription = jQuery('#new_segment_description').val().trim(),
|
||||
isDuplicateListName = ( jQuery.map(mailpoetSegments, function (el) {
|
||||
if (el.name.toLowerCase() === segmentName.toLowerCase()) {
|
||||
return true;
|
||||
}
|
||||
}).length && segmentName) ? true : false;
|
||||
if (segmentName === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:hidden').show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:visible').hide();
|
||||
}
|
||||
if (isDuplicateListName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_not_unique"]:hidden').show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_not_unique"]:visible').hide();
|
||||
}
|
||||
if (segmentName && !isDuplicateListName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="segment_name_required"]:visible').hide();
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addSegment',
|
||||
data: {
|
||||
name: segmentName,
|
||||
description: segmentDescription
|
||||
}
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === true) {
|
||||
mailpoetSegments.push({
|
||||
'id': response.segment.id,
|
||||
'name': response.segment.name
|
||||
});
|
||||
var segmentName = jQuery('#new_segment_name').val().trim();
|
||||
var segmentDescription = jQuery('#new_segment_description').val().trim();
|
||||
|
||||
var selected_values = segmentSelectElement.val();
|
||||
if (selected_values === null) {
|
||||
selected_values = [response.segment.id]
|
||||
} else {
|
||||
selected_values.push(response.segment.id);
|
||||
}
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addSegment',
|
||||
data: {
|
||||
name: segmentName,
|
||||
description: segmentDescription
|
||||
}
|
||||
}).done(function(response) {
|
||||
mailpoetSegments.push({
|
||||
'id': response.data.id,
|
||||
'name': response.data.name
|
||||
});
|
||||
|
||||
enableSegmentSelection(mailpoetSegments);
|
||||
segmentSelectElement.val(selected_values).trigger('change');
|
||||
jQuery('.mailpoet_segments:hidden').show();
|
||||
jQuery('.mailpoet_no_segments:visible').hide();
|
||||
MailPoet.Modal.close();
|
||||
}
|
||||
else {
|
||||
MailPoet.Modal.close();
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('segmentCreateError') + response.message + '.'
|
||||
);
|
||||
}
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.close();
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
}
|
||||
var selected_values = segmentSelectElement.val();
|
||||
if (selected_values === null) {
|
||||
selected_values = [response.data.id]
|
||||
} else {
|
||||
selected_values.push(response.data.id);
|
||||
}
|
||||
|
||||
enableSegmentSelection(mailpoetSegments);
|
||||
segmentSelectElement.val(selected_values).trigger('change');
|
||||
jQuery('.mailpoet_segments:hidden').show();
|
||||
jQuery('.mailpoet_no_segments:visible').hide();
|
||||
MailPoet.Modal.close();
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ positionAfter: '#new_segment_name' }
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
jQuery('#new_segment_cancel').click(function () {
|
||||
MailPoet.Modal.close();
|
||||
@ -707,7 +679,7 @@ define(
|
||||
// display filler data (e.g., ellipsis) if we've reached the maximum number of rows and
|
||||
// subscribers count is greater than the maximum number of rows we're displaying
|
||||
if (index === maxRowsToShow && subscribers.subscribersCount > (maxRowsToShow + 1)) {
|
||||
fillterPosition = index;
|
||||
fillerPosition = index;
|
||||
return filler;
|
||||
}
|
||||
// if we're on the last line, show the total count of subscribers data
|
||||
@ -745,114 +717,70 @@ define(
|
||||
.on('select2:selecting', function (selectEvent) {
|
||||
var selectElement = this,
|
||||
selectedOptionId = selectEvent.params.args.data.id;
|
||||
// CREATE CUSTOM FIELD
|
||||
if (selectedOptionId === 'create') {
|
||||
selectEvent.preventDefault();
|
||||
jQuery(selectElement).select2('close');
|
||||
MailPoet.Modal.popup({
|
||||
title: MailPoet.I18n.t('addNewColumn'),
|
||||
template: jQuery('#new_column_template').html()
|
||||
title: MailPoet.I18n.t('addNewField'),
|
||||
template: jQuery('#form_template_field_form').html()
|
||||
});
|
||||
jQuery('#new_column_name').keypress(function (e) {
|
||||
if (e.which == 13) {
|
||||
jQuery('#new_column_process').click();
|
||||
}
|
||||
});
|
||||
jQuery('#new_column_process').click(function () {
|
||||
var name = jQuery('#new_column_name').val().trim(),
|
||||
type = jQuery('#new_column_type').val().trim(),
|
||||
columnNames = mailpoetColumns.map(function (el) {
|
||||
return el.name.toLowerCase();
|
||||
jQuery('#form_field_new').parsley().on('form:submit', function(parsley) {
|
||||
// get data
|
||||
var data = jQuery(this.$element).serializeObject();
|
||||
|
||||
// save custom field
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'customFields',
|
||||
action: 'save',
|
||||
data: data
|
||||
}).done(function(response) {
|
||||
var new_column_data = {
|
||||
'id': response.data.id,
|
||||
'name': response.data.name,
|
||||
'type': response.data.type,
|
||||
'params': response.data.params,
|
||||
'custom': true
|
||||
};
|
||||
// if this is the first custom column, create an "optgroup"
|
||||
if (mailpoetColumnsSelect2.length === 2) {
|
||||
mailpoetColumnsSelect2.push({
|
||||
'name': MailPoet.I18n.t('userColumns'),
|
||||
'children': []
|
||||
});
|
||||
isDuplicateColumnName =
|
||||
(name && columnNames.indexOf(name.toLowerCase()) > -1)
|
||||
? true
|
||||
: false;
|
||||
if (name === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_required"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_required"]')
|
||||
.hide();
|
||||
}
|
||||
if (type === '') {
|
||||
jQuery('.mailpoet_validation_error[data-error="type_required"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="type_required"]')
|
||||
.hide();
|
||||
}
|
||||
if (isDuplicateColumnName) {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_not_unique"]')
|
||||
.show();
|
||||
} else {
|
||||
jQuery('.mailpoet_validation_error[data-error="name_not_unique"]')
|
||||
.hide();
|
||||
}
|
||||
// create new field
|
||||
if (name && type && !isDuplicateColumnName) {
|
||||
MailPoet.Modal
|
||||
.close()
|
||||
.loading(true);
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'addCustomField',
|
||||
data: {
|
||||
name: name,
|
||||
type: type
|
||||
}
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === true) {
|
||||
var new_column_data = {
|
||||
'id': response.customField.id,
|
||||
'name': name,
|
||||
'type': type,
|
||||
'custom': true,
|
||||
};
|
||||
// if this is the first custom column, create an "optgroup"
|
||||
if (mailpoetColumnsSelect2.length === 2) {
|
||||
mailpoetColumnsSelect2.push({
|
||||
'name': MailPoet.I18n.t('userColumns'),
|
||||
'children': []
|
||||
});
|
||||
}
|
||||
mailpoetColumnsSelect2[2].children.push(new_column_data);
|
||||
mailpoetColumns.push(new_column_data);
|
||||
jQuery('select.mailpoet_subscribers_column_data_match')
|
||||
.each(function () {
|
||||
jQuery(this)
|
||||
.html('')
|
||||
.select2('destroy')
|
||||
.select2({
|
||||
data: mailpoetColumnsSelect2,
|
||||
width: '15em',
|
||||
templateResult: function (item) {
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return item.name;
|
||||
}
|
||||
mailpoetColumnsSelect2[2].children.push(new_column_data);
|
||||
mailpoetColumns.push(new_column_data);
|
||||
jQuery('select.mailpoet_subscribers_column_data_match')
|
||||
.each(function () {
|
||||
jQuery(this)
|
||||
.html('')
|
||||
.select2('destroy')
|
||||
.select2({
|
||||
data: mailpoetColumnsSelect2,
|
||||
width: '15em',
|
||||
templateResult: function (item) {
|
||||
return item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return item.name;
|
||||
}
|
||||
})
|
||||
});
|
||||
jQuery(selectElement).data('column-id', new_column_data.id);
|
||||
filterSubscribers();
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('customFieldCreateError'));
|
||||
}
|
||||
MailPoet.Modal.loading(false);
|
||||
})
|
||||
.error(function (error) {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
jQuery('#new_column_cancel').click(function () {
|
||||
MailPoet.Modal.close();
|
||||
})
|
||||
});
|
||||
jQuery(selectElement).data('column-id', new_column_data.id);
|
||||
jQuery(selectElement).data('validation-rule', false);
|
||||
filterSubscribers();
|
||||
// close popup
|
||||
MailPoet.Modal.close();
|
||||
}).fail(function(response) {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ positionAfter: '#field_name' }
|
||||
);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
// CHANGE COLUMN
|
||||
@ -890,22 +818,22 @@ define(
|
||||
.remove();
|
||||
var subscribersClone = jQuery.extend(true, {}, subscribers),
|
||||
preventNextStep = false,
|
||||
displayedColumnsIds = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (data) {
|
||||
var columnId = jQuery(data).data('column-id');
|
||||
jQuery(data).val(columnId).trigger('change');
|
||||
return columnId;
|
||||
displayedColumns = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (element, elementIndex) {
|
||||
var columnId = jQuery(element).data('column-id');
|
||||
var validationRule = jQuery(element).data('validation-rule');
|
||||
jQuery(element).val(columnId).trigger('change');
|
||||
return { id: columnId, index: elementIndex, validationRule: validationRule, element: element };
|
||||
});
|
||||
// iterate through the object of mailpoet columns
|
||||
jQuery.map(mailpoetColumns, function (column) {
|
||||
jQuery.map(mailpoetColumns, function (column, columnIndex) {
|
||||
// check if the column id matches the selected id of one of the
|
||||
// subscriber's data columns
|
||||
var matchedColumn = jQuery.inArray(column.id, displayedColumnsIds);
|
||||
|
||||
// EMAIL filter: if the last value in the column doesn't have a valid
|
||||
var matchedColumn = _.find(displayedColumns, function(data) { return data.id === column.id; });
|
||||
// EMAIL filter: if the first value in the column doesn't have a valid
|
||||
// email, hide the next button
|
||||
if (column.id === "email") {
|
||||
if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn])) {
|
||||
if (column.id === 'email') {
|
||||
if (!emailRegex.test(subscribersClone.subscribers[0][matchedColumn.index])) {
|
||||
preventNextStep = true;
|
||||
if (!jQuery('[data-id="notice_invalidEmail"]').length) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidElement'), {
|
||||
@ -921,35 +849,63 @@ define(
|
||||
}
|
||||
}
|
||||
// DATE filter: if column type is date, check if we can recognize it
|
||||
if (column.type === 'date' && matchedColumn !== -1) {
|
||||
jQuery.map(subscribersClone.subscribers, function (data, position) {
|
||||
var rowData = data[matchedColumn];
|
||||
if (position !== fillterPosition) {
|
||||
// check if date exists
|
||||
if (rowData.trim() === '') {
|
||||
data[matchedColumn] =
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('emptyDate')
|
||||
+ '</span>';
|
||||
preventNextStep = true;
|
||||
return;
|
||||
}
|
||||
// check if date is valid and is before today
|
||||
if (Moment(rowData).isValid() && Moment(rowData).isBefore(Moment())) {
|
||||
data[matchedColumn] +=
|
||||
'<span class="mailpoet_data_match" title="'
|
||||
+ MailPoet.I18n.t('verifyDateMatch') + '">'
|
||||
+ MailPoet.Date.format(rowData) + '</span>';
|
||||
}
|
||||
else {
|
||||
data[matchedColumn] +=
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('dateMatchError') + '</span>';
|
||||
preventNextStep = true;
|
||||
if (column.type === 'date' && matchedColumn) {
|
||||
var allowedDateFormats = [
|
||||
Moment.ISO_8601,
|
||||
'YYYY/MM/DD',
|
||||
'MM/DD/YYYY',
|
||||
'DD/MM/YYYY',
|
||||
'YYYY/MM/DD',
|
||||
'YYYY/DD/MM',
|
||||
'MM/YYYY',
|
||||
'YYYY/MM',
|
||||
'YYYY'
|
||||
];
|
||||
var firstRowData = subscribersClone.subscribers[0][matchedColumn.index];
|
||||
var validationRule = false;
|
||||
// check if date exists
|
||||
if (firstRowData.trim() === '') {
|
||||
subscribersClone.subscribers[0][matchedColumn.index] =
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('emptyFirstRowDate')
|
||||
+ '</span>';
|
||||
preventNextStep = true;
|
||||
}
|
||||
else {
|
||||
for (var format in allowedDateFormats) {
|
||||
var testedFormat = allowedDateFormats[format]
|
||||
if (Moment(firstRowData, testedFormat, true).isValid()) {
|
||||
var validationRule = (typeof(testedFormat) === 'function') ?
|
||||
'datetime' :
|
||||
testedFormat
|
||||
// set validation on the column element
|
||||
jQuery(matchedColumn.element).data('validation-rule', validationRule);
|
||||
break;
|
||||
}
|
||||
if (validationRule === 'datetime') validationRule = Moment.ISO_8601;
|
||||
}
|
||||
}
|
||||
jQuery.map(subscribersClone.subscribers, function (data, index) {
|
||||
var rowData = data[matchedColumn.index];
|
||||
if (index === fillerPosition || rowData.trim() === '') return;
|
||||
var date = Moment(rowData, testedFormat, true);
|
||||
// validate date
|
||||
if (date.isValid()) {
|
||||
data[matchedColumn.index] +=
|
||||
'<span class="mailpoet_data_match" title="'
|
||||
+ MailPoet.I18n.t('verifyDateMatch') + '">'
|
||||
+ MailPoet.Date.format(date)
|
||||
+ '</span>';
|
||||
}
|
||||
else {
|
||||
data[matchedColumn.index] +=
|
||||
'<span class="mailpoet_data_match mailpoet_import_error" title="'
|
||||
+ MailPoet.I18n.t('noDateFieldMatch') + '">'
|
||||
+ MailPoet.I18n.t('dateMatchError')
|
||||
+ '</span>';
|
||||
preventNextStep = true;
|
||||
};
|
||||
});
|
||||
if (preventNextStep && !jQuery('.mailpoet_invalidDate').length) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidDate'), {
|
||||
@ -983,11 +939,11 @@ define(
|
||||
nextStepButton.addClass(disabled);
|
||||
}
|
||||
|
||||
previousStepButton.off().click(function () {
|
||||
router.navigate('step1', {trigger: true});
|
||||
previousStepButton.off().on('click', function () {
|
||||
router.navigate('step1', { trigger: true });
|
||||
});
|
||||
|
||||
nextStepButton.off().click(function () {
|
||||
nextStepButton.off().on('click', function () {
|
||||
if (jQuery(this).hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
@ -1019,44 +975,41 @@ define(
|
||||
_.each(jQuery('select.mailpoet_subscribers_column_data_match'),
|
||||
function (column, columnIndex) {
|
||||
var columnId = jQuery(column).data('column-id');
|
||||
var validationRule = jQuery(column).data('validation-rule');
|
||||
if (columnId === 'ignore') {
|
||||
return;
|
||||
}
|
||||
columns[columnId] = columnIndex;
|
||||
columns[columnId] = { index: columnIndex, validation_rule: validationRule };
|
||||
});
|
||||
|
||||
_.each(subscribers, function () {
|
||||
queue.add(function (queue) {
|
||||
queue.add(function(queue) {
|
||||
queue.pause();
|
||||
MailPoet.Ajax
|
||||
.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processImport',
|
||||
data: JSON.stringify({
|
||||
columns: columns,
|
||||
subscribers: subscribers[batchNumber],
|
||||
timestamp: timestamp,
|
||||
segments: segmentSelectElement.val(),
|
||||
updateSubscribers: (jQuery(':radio[name="subscriber_update_option"]:checked').val() === 'yes') ? true : false
|
||||
})
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'ImportExport',
|
||||
action: 'processImport',
|
||||
data: JSON.stringify({
|
||||
columns: columns,
|
||||
subscribers: subscribers[batchNumber],
|
||||
timestamp: timestamp,
|
||||
segments: segmentSelectElement.val(),
|
||||
updateSubscribers: (jQuery(':radio[name="subscriber_update_option"]:checked').val() === 'yes') ? true : false
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.result === false) {
|
||||
importResults.errors.push(response.errors);
|
||||
} else {
|
||||
importResults.created = response.data.created;
|
||||
importResults.updated = response.data.updated;
|
||||
importResults.segments = response.data.segments;
|
||||
importResults.added_to_segment_with_welcome_notification = response.data.added_to_segment_with_welcome_notification;
|
||||
}
|
||||
queue.run();
|
||||
})
|
||||
.error(function (error) {
|
||||
importResults.errors.push(
|
||||
MailPoet.I18n.t('serverError') + error.statusText.toLowerCase() + '.'
|
||||
}).done(function(response) {
|
||||
importResults.created = response.data.created;
|
||||
importResults.updated = response.data.updated;
|
||||
importResults.segments = response.data.segments;
|
||||
importResults.added_to_segment_with_welcome_notification = response.data.added_to_segment_with_welcome_notification;
|
||||
queue.run();
|
||||
}).fail(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
queue.run();
|
||||
});
|
||||
}
|
||||
});
|
||||
batchNumber++;
|
||||
})
|
||||
});
|
||||
@ -1146,4 +1099,4 @@ define(
|
||||
Backbone.history.start();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
@ -37,59 +37,50 @@ const columns = [
|
||||
];
|
||||
|
||||
const messages = {
|
||||
onTrash: function(response) {
|
||||
if (response) {
|
||||
var message = null;
|
||||
if (~~response === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberTrashed')
|
||||
);
|
||||
} else if (~~response > 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersTrashed')
|
||||
).replace('%$1d', (~~response).toLocaleString());
|
||||
}
|
||||
onTrash: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberTrashed')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersTrashed')
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onDelete: function(response) {
|
||||
if (response) {
|
||||
var message = null;
|
||||
if (~~response === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberDeleted')
|
||||
);
|
||||
} else if (~~response > 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersDeleted')
|
||||
).replace('%$1d', ~~response);
|
||||
}
|
||||
onDelete: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberDeleted')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersDeleted')
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
},
|
||||
onRestore: function(response) {
|
||||
if (response) {
|
||||
var message = null;
|
||||
if (~~response === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberRestored')
|
||||
);
|
||||
} else if (~~response > 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersRestored')
|
||||
).replace('%$1d', (~~response).toLocaleString());
|
||||
}
|
||||
onRestore: (response) => {
|
||||
const count = ~~response.meta.count;
|
||||
let message = null;
|
||||
|
||||
if (message !== null) {
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
if (count === 1) {
|
||||
message = (
|
||||
MailPoet.I18n.t('oneSubscriberRestored')
|
||||
);
|
||||
} else {
|
||||
message = (
|
||||
MailPoet.I18n.t('multipleSubscribersRestored')
|
||||
).replace('%$1d', count.toLocaleString());
|
||||
}
|
||||
MailPoet.Notice.success(message);
|
||||
}
|
||||
};
|
||||
|
||||
@ -120,8 +111,8 @@ const bulk_actions = [
|
||||
onSuccess: function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersMovedToList')
|
||||
.replace('%$1d', (~~(response.subscribers)).toLocaleString())
|
||||
.replace('%$2s', response.segment)
|
||||
.replace('%$1d', (~~(response.meta.count)).toLocaleString())
|
||||
.replace('%$2s', response.meta.segment)
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -151,8 +142,8 @@ const bulk_actions = [
|
||||
onSuccess: function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersAddedToList')
|
||||
.replace('%$1d', (~~response.subscribers).toLocaleString())
|
||||
.replace('%$2s', response.segment)
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
.replace('%$2s', response.meta.segment)
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -182,8 +173,8 @@ const bulk_actions = [
|
||||
onSuccess: function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersRemovedFromList')
|
||||
.replace('%$1d', (~~response.subscribers).toLocaleString())
|
||||
.replace('%$2s', response.segment)
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
.replace('%$2s', response.meta.segment)
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -193,7 +184,7 @@ const bulk_actions = [
|
||||
onSuccess: function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersRemovedFromAllLists')
|
||||
.replace('%$1d', (~~response).toLocaleString())
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -203,7 +194,7 @@ const bulk_actions = [
|
||||
onSuccess: function(response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleConfirmationEmailsSent')
|
||||
.replace('%$1d', (~~response).toLocaleString())
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
);
|
||||
}
|
||||
},
|
||||
@ -330,16 +321,23 @@ const SubscriberList = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
onGetItems: function(count) {
|
||||
jQuery('#mailpoet_export_button')[(count > 0) ? 'show' : 'hide']();
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link>
|
||||
<a className="page-title-action" href="?page=mailpoet-import#step1">{MailPoet.I18n.t('import')}</a>
|
||||
<a id="mailpoet_export_button" className="page-title-action" href="?page=mailpoet-export">{MailPoet.I18n.t('export')}</a>
|
||||
{MailPoet.I18n.t('pageTitle')} <Link
|
||||
className="page-title-action"
|
||||
to="/new"
|
||||
>{MailPoet.I18n.t('new')}</Link>
|
||||
<a
|
||||
className="page-title-action"
|
||||
href="?page=mailpoet-import#step1"
|
||||
>{MailPoet.I18n.t('import')}</a>
|
||||
<a
|
||||
id="mailpoet_export_button"
|
||||
className="page-title-action"
|
||||
href="?page=mailpoet-export"
|
||||
>{MailPoet.I18n.t('export')}</a>
|
||||
</h1>
|
||||
|
||||
<Listing
|
||||
@ -352,7 +350,6 @@ const SubscriberList = React.createClass({
|
||||
bulk_actions={ bulk_actions }
|
||||
item_actions={ item_actions }
|
||||
messages={ messages }
|
||||
onGetItems={ this.onGetItems }
|
||||
sort_by={ 'created_at' }
|
||||
sort_order={ 'desc' }
|
||||
/>
|
||||
|
61
circle.yml
Normal file
@ -0,0 +1,61 @@
|
||||
machine:
|
||||
timezone:
|
||||
UTC
|
||||
|
||||
hosts:
|
||||
mailpoet.loc: 127.0.0.1
|
||||
|
||||
## Customize dependencies
|
||||
dependencies:
|
||||
pre:
|
||||
# install PHP dependencies for WordPress
|
||||
- sudo apt-get update
|
||||
- sudo apt-get --assume-yes install php5-mysql
|
||||
# configure Apache
|
||||
- sudo cp ./.circle_ci/apache/mailpoet.loc.conf /etc/apache2/sites-available
|
||||
- sudo a2ensite mailpoet.loc
|
||||
- sudo a2enmod rewrite
|
||||
- sudo service apache2 restart
|
||||
# install Phoenix dependencies
|
||||
- composer install
|
||||
- ./do install
|
||||
# Set up Wordpress
|
||||
# No password is required for the MySQL user `ubuntu`
|
||||
- mysql -u ubuntu -e "create database wordpress"
|
||||
# Use cURL to fetch WP-CLI
|
||||
- curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
# Make sure WP-CLI is executable
|
||||
- chmod +x wp-cli.phar
|
||||
# Download WordPress into `wordpress` directory
|
||||
- ./wp-cli.phar core download --allow-root --path=wordpress
|
||||
# Generate `wp-config.php` file
|
||||
- echo "define(\"WP_DEBUG\", true);" | ./wp-cli.phar core config --allow-root --dbname=wordpress --dbuser=ubuntu --dbhost=127.0.0.1:3306 --path=wordpress --extra-php
|
||||
# Install WordPress
|
||||
- ./wp-cli.phar core install --allow-root --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc:8080 --title=WordPress --path=wordpress
|
||||
# Softlink MailPoet to plugin path
|
||||
- ln -s ../../.. wordpress/wp-content/plugins/mailpoet
|
||||
# Activate MailPoet
|
||||
- ./wp-cli.phar plugin activate mailpoet --path=wordpress
|
||||
# Create .env file with correct path to WP installation
|
||||
- echo "WP_TEST_PATH=\"/home/ubuntu/mailpoet/wordpress\"" > .env
|
||||
|
||||
# Enable XDebug for coverage reports.
|
||||
# Comment out if not running PHP coverage reports, for performance
|
||||
#- sed -i 's/^;//' /opt/circleci/php/$(phpenv global)/etc/conf.d/xdebug.ini
|
||||
|
||||
## tests override
|
||||
test:
|
||||
override:
|
||||
# Run JS tests
|
||||
- mkdir $CIRCLE_TEST_REPORTS/mocha
|
||||
- ./do t:j $CIRCLE_TEST_REPORTS/mocha/junit.xml
|
||||
|
||||
# Run PHP tests
|
||||
- ./do t:u --xml
|
||||
# Uncomment to run coverage tests instead
|
||||
#- ./do t:c --xml
|
||||
# Copy the report
|
||||
- mkdir $CIRCLE_TEST_REPORTS/codeception
|
||||
- cp tests/_output/report.xml $CIRCLE_TEST_REPORTS/codeception/report.xml
|
||||
# Uncomment to copy PHP coverage report
|
||||
#- cp tests/_output/coverage.xml $CIRCLE_TEST_REPORTS/codeception/coverage.xml
|
@ -10,6 +10,7 @@ settings:
|
||||
colors: true
|
||||
memory_limit: 1024M
|
||||
log: true
|
||||
strict_xml: true
|
||||
extensions:
|
||||
enabled:
|
||||
- Codeception\Extension\RunFailed
|
||||
|
@ -36,23 +36,25 @@ class API {
|
||||
|
||||
function setupAdmin() {
|
||||
if($this->checkToken() === false) {
|
||||
(new ErrorResponse(
|
||||
$error_response = new ErrorResponse(
|
||||
array(
|
||||
Error::UNAUTHORIZED => __('You need to specify a valid API token.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_UNAUTHORIZED
|
||||
))->send();
|
||||
);
|
||||
$error_response->send();
|
||||
}
|
||||
|
||||
if($this->checkPermissions() === false) {
|
||||
(new ErrorResponse(
|
||||
$error_response = new ErrorResponse(
|
||||
array(
|
||||
Error::FORBIDDEN => __('You do not have the required permissions.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_FORBIDDEN
|
||||
))->send();
|
||||
);
|
||||
$error_response->send();
|
||||
}
|
||||
|
||||
$this->processRoute();
|
||||
@ -60,13 +62,14 @@ class API {
|
||||
|
||||
function setupPublic() {
|
||||
if($this->checkToken() === false) {
|
||||
(new ErrorResponse(
|
||||
$error_response = new ErrorResponse(
|
||||
array(
|
||||
Error::UNAUTHORIZED => __('You need to specify a valid API token.')
|
||||
),
|
||||
array(),
|
||||
Response::STATUS_UNAUTHORIZED
|
||||
))->send();
|
||||
);
|
||||
$error_response->send();
|
||||
}
|
||||
|
||||
$this->processRoute();
|
||||
@ -99,18 +102,12 @@ class API {
|
||||
try {
|
||||
$endpoint = new $endpoint();
|
||||
$response = $endpoint->$method($data);
|
||||
|
||||
// TODO: remove this condition once the API unification is complete
|
||||
if(is_object($response)) {
|
||||
$response->send();
|
||||
} else {
|
||||
// LEGACY API
|
||||
wp_send_json($response);
|
||||
}
|
||||
$response->send();
|
||||
} catch(\Exception $e) {
|
||||
(new ErrorResponse(
|
||||
$error_response = new ErrorResponse(
|
||||
array($e->getCode() => $e->getMessage())
|
||||
))->send();
|
||||
);
|
||||
$error_response->send();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Cron extends APIEndpoint {
|
||||
function getStatus() {
|
||||
$daemon = Setting::getValue(CronHelper::DAEMON_SETTING, false);
|
||||
|
||||
if($daemon === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('Cron daemon is not running.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse($daemon);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +1,32 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
use \MailPoet\Models\CustomField;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CustomFields {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
class CustomFields extends APIEndpoint {
|
||||
function getAll() {
|
||||
$collection = CustomField::findMany();
|
||||
$custom_fields = array_map(function($custom_field) {
|
||||
return $custom_field->asArray();
|
||||
}, $collection);
|
||||
|
||||
return $custom_fields;
|
||||
return $this->successResponse($custom_fields);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false or !$custom_field->id()) {
|
||||
return array('result' => false);
|
||||
if($custom_field === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
$custom_field->delete();
|
||||
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
);
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,24 +35,23 @@ class CustomFields {
|
||||
$errors = $custom_field->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
return $this->successResponse(
|
||||
CustomField::findOne($custom_field->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function get($id) {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : null);
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field === false) {
|
||||
return false;
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This custom field does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $custom_field->asArray();
|
||||
return $this->successResponse($custom_field->asArray());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use MailPoet\API\Endpoint as APIEndpoint;
|
||||
use MailPoet\API\Error as APIError;
|
||||
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Models\StatisticsForms;
|
||||
@ -9,16 +11,17 @@ use \MailPoet\Form\Util;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Forms {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($id = false) {
|
||||
class Forms extends APIEndpoint {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
$form = $form->asArray();
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse($form->asArray());
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
@ -29,8 +32,8 @@ class Forms {
|
||||
|
||||
$listing_data = $listing->get();
|
||||
|
||||
// fetch segments relations for each returned item
|
||||
foreach($listing_data['items'] as $key => $form) {
|
||||
$data = array();
|
||||
foreach($listing_data['items'] as $form) {
|
||||
$form = $form->asArray();
|
||||
|
||||
$form['signups'] = StatisticsForms::getTotalSignups($form['id']);
|
||||
@ -40,10 +43,15 @@ class Forms {
|
||||
? $form['settings']['segments']
|
||||
: array()
|
||||
);
|
||||
$listing_data['items'][$key] = $form;
|
||||
|
||||
$data[] = $form;
|
||||
}
|
||||
|
||||
return $listing_data;
|
||||
return $this->successResponse($data, array(
|
||||
'count' => $listing_data['count'],
|
||||
'filters' => $listing_data['filters'],
|
||||
'groups' => $listing_data['groups']
|
||||
));
|
||||
}
|
||||
|
||||
function create() {
|
||||
@ -87,14 +95,10 @@ class Forms {
|
||||
$errors = $form->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true,
|
||||
'form_id' => $form->id()
|
||||
return $this->successResponse(
|
||||
Form::findOne($form->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -109,76 +113,74 @@ class Forms {
|
||||
// styles
|
||||
$css = new Util\Styles(FormRenderer::getStyles($data));
|
||||
|
||||
return array(
|
||||
return $this->successResponse(array(
|
||||
'html' => $html,
|
||||
'css' => $css->render()
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
function exportsEditor($id) {
|
||||
$exports = false;
|
||||
|
||||
function exportsEditor($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
|
||||
if($form !== false) {
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
$exports = Util\Export::getAll($form->asArray());
|
||||
return $this->successResponse($exports);
|
||||
}
|
||||
|
||||
return $exports;
|
||||
}
|
||||
|
||||
function saveEditor($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
|
||||
$form_id = (isset($data['id']) ? (int)$data['id'] : 0);
|
||||
$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'] : '');
|
||||
|
||||
if(empty($body) || empty($settings)) {
|
||||
// error
|
||||
return false;
|
||||
} else {
|
||||
// check if the form is used as a widget
|
||||
$is_widget = false;
|
||||
$widgets = get_option('widget_mailpoet_form');
|
||||
if(!empty($widgets)) {
|
||||
foreach($widgets as $widget) {
|
||||
if(isset($widget['form']) && (int)$widget['form'] === $form_id) {
|
||||
$is_widget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if the user gets to pick his own lists
|
||||
// or if it's selected by the admin
|
||||
$has_segment_selection = false;
|
||||
|
||||
foreach($body as $i => $block) {
|
||||
if($block['type'] === 'segment') {
|
||||
$has_segment_selection = true;
|
||||
if(!empty($block['params']['values'])) {
|
||||
$list_selection = array_filter(
|
||||
array_map(function($segment) {
|
||||
return (isset($segment['id'])
|
||||
? (int)$segment['id']
|
||||
: null
|
||||
);
|
||||
}, $block['params']['values'])
|
||||
);
|
||||
}
|
||||
// check if the form is used as a widget
|
||||
$is_widget = false;
|
||||
$widgets = get_option('widget_mailpoet_form');
|
||||
if(!empty($widgets)) {
|
||||
foreach($widgets as $widget) {
|
||||
if(isset($widget['form']) && (int)$widget['form'] === $form_id) {
|
||||
$is_widget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check list selection
|
||||
if($has_segment_selection === true) {
|
||||
$settings['segments_selected_by'] = 'user';
|
||||
} else {
|
||||
$settings['segments_selected_by'] = 'admin';
|
||||
// check if the user gets to pick his own lists
|
||||
// or if it's selected by the admin
|
||||
$has_segment_selection = false;
|
||||
|
||||
foreach($body as $i => $block) {
|
||||
if($block['type'] === 'segment') {
|
||||
$has_segment_selection = true;
|
||||
if(!empty($block['params']['values'])) {
|
||||
$list_selection = array_filter(
|
||||
array_map(function($segment) {
|
||||
return (isset($segment['id'])
|
||||
? (int)$segment['id']
|
||||
: null
|
||||
);
|
||||
}, $block['params']['values'])
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check list selection
|
||||
if($has_segment_selection === true) {
|
||||
$settings['segments_selected_by'] = 'user';
|
||||
} else {
|
||||
$settings['segments_selected_by'] = 'admin';
|
||||
}
|
||||
|
||||
$form = Form::createOrUpdate(array(
|
||||
'id' => $form_id,
|
||||
'name' => $name,
|
||||
@ -187,64 +189,101 @@ class Forms {
|
||||
'styles' => $styles
|
||||
));
|
||||
|
||||
if($form->getErrors() === false) {
|
||||
return array(
|
||||
'result' => true,
|
||||
'is_widget' => $is_widget
|
||||
);
|
||||
$errors = $form->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $form->getErrors()
|
||||
return $this->successResponse(
|
||||
Form::findOne($form->id)->asArray(),
|
||||
array('is_widget' => $is_widget)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
function restore($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
$form->restore();
|
||||
return $this->successResponse(
|
||||
Form::findOne($form->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($form->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
function trash($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
$form->trash();
|
||||
return $this->successResponse(
|
||||
Form::findOne($form->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($form->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
$form->delete();
|
||||
return 1;
|
||||
return $this->successResponse(null, array('count' => 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id) {
|
||||
$result = false;
|
||||
|
||||
function duplicate($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
|
||||
if($form === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This form does not exist.')
|
||||
));
|
||||
} else {
|
||||
$data = array(
|
||||
'name' => sprintf(__('Copy of %s'), $form->name)
|
||||
);
|
||||
$result = $form->duplicate($data)->asArray();
|
||||
}
|
||||
$duplicate = $form->duplicate($data);
|
||||
$errors = $duplicate->getErrors();
|
||||
|
||||
return $result;
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Form::findOne($duplicate->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Form',
|
||||
$data
|
||||
);
|
||||
|
||||
return $bulk_action->apply();
|
||||
try {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Form',
|
||||
$data
|
||||
);
|
||||
$meta = $bulk_action->apply();
|
||||
return $this->successResponse(null, $meta);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Subscribers\ImportExport\Import\MailChimp;
|
||||
use MailPoet\Models\CustomField;
|
||||
@ -7,58 +9,69 @@ use MailPoet\Models\Segment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class ImportExport {
|
||||
class ImportExport extends APIEndpoint {
|
||||
function getMailChimpLists($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
return $mailChimp->getLists();
|
||||
try {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
$lists = $mailChimp->getLists();
|
||||
return $this->successResponse($lists);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function getMailChimpSubscribers($data) {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
return $mailChimp->getSubscribers($data['lists']);
|
||||
try {
|
||||
$mailChimp = new MailChimp($data['api_key']);
|
||||
$subscribers = $mailChimp->getSubscribers($data['lists']);
|
||||
return $this->successResponse($subscribers);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function addSegment($data) {
|
||||
$segment = Segment::createOrUpdate($data);
|
||||
return (
|
||||
($segment->id) ?
|
||||
array(
|
||||
'result' => true,
|
||||
'segment' => $segment->asArray()
|
||||
) :
|
||||
array(
|
||||
'result' => false
|
||||
)
|
||||
);
|
||||
}
|
||||
$errors = $segment->getErrors();
|
||||
|
||||
function addCustomField($data) {
|
||||
$customField = CustomField::create();
|
||||
$customField->hydrate($data);
|
||||
$result = $customField->save();
|
||||
return (
|
||||
($result) ?
|
||||
array(
|
||||
'result' => true,
|
||||
'customField' => $customField->asArray()
|
||||
) :
|
||||
array(
|
||||
'result' => false
|
||||
)
|
||||
);
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function processImport($data) {
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $import->process();
|
||||
try {
|
||||
$import = new \MailPoet\Subscribers\ImportExport\Import\Import(
|
||||
json_decode($data, true)
|
||||
);
|
||||
$process = $import->process();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function processExport($data) {
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
||||
json_decode($data, true)
|
||||
);
|
||||
return $export->process();
|
||||
try {
|
||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
||||
json_decode($data, true)
|
||||
);
|
||||
$process = $export->process();
|
||||
return $this->successResponse($process);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\NewsletterTemplate;
|
||||
use MailPoet\Models\NewsletterSegment;
|
||||
@ -21,19 +22,20 @@ if(!defined('ABSPATH')) exit;
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
class Newsletters extends APIEndpoint {
|
||||
function get($id = false) {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter === false) {
|
||||
return false;
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$segments = $newsletter->segments()->findArray();
|
||||
$options = $newsletter->options()->findArray();
|
||||
$newsletter = $newsletter->asArray();
|
||||
$newsletter['segments'] = array_map(function($segment) {
|
||||
return $segment['id'];
|
||||
}, $segments);
|
||||
$newsletter['options'] = Helpers::arrayColumn($options, 'value', 'name');
|
||||
return $newsletter;
|
||||
return $this->successResponse(
|
||||
$newsletter
|
||||
->withSegments()
|
||||
->withOptions()
|
||||
->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +97,6 @@ class Newsletters extends APIEndpoint {
|
||||
}
|
||||
|
||||
function setStatus($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
$status = (isset($data['status']) ? $data['status'] : null);
|
||||
|
||||
if(!$status) {
|
||||
@ -105,6 +105,9 @@ class Newsletters extends APIEndpoint {
|
||||
));
|
||||
}
|
||||
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
@ -118,142 +121,179 @@ class Newsletters extends APIEndpoint {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
$newsletter->asArray()
|
||||
Newsletter::findOne($newsletter->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
function restore($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$newsletter->restore();
|
||||
}
|
||||
return ($newsletter->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$newsletter->trash();
|
||||
}
|
||||
return ($newsletter->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$newsletter->delete();
|
||||
return 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id = false) {
|
||||
$result = false;
|
||||
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter !== false) {
|
||||
$duplicate = $newsletter->duplicate(array(
|
||||
'subject' => sprintf(__('Copy of %s'), $newsletter->subject)
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$newsletter->restore();
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($newsletter->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if($duplicate !== false && $duplicate->getErrors() === false) {
|
||||
$result = $duplicate->asArray();
|
||||
function trash($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$newsletter->trash();
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($newsletter->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$newsletter->delete();
|
||||
return $this->successResponse(null, array('count' => 1));
|
||||
}
|
||||
}
|
||||
|
||||
function duplicate($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$data = array(
|
||||
'subject' => sprintf(__('Copy of %s'), $newsletter->subject)
|
||||
);
|
||||
$duplicate = $newsletter->duplicate($data);
|
||||
$errors = $duplicate->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($duplicate->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function showPreview($data = array()) {
|
||||
if(!isset($data['body'])) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Newsletter data is missing'))
|
||||
);
|
||||
if(empty($data['body'])) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST => __('Newsletter data is missing.')
|
||||
));
|
||||
}
|
||||
$newsletter_id = (isset($data['id'])) ? (int)$data['id'] : null;
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
if(!$newsletter) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Newsletter could not be read'))
|
||||
);
|
||||
}
|
||||
$newsletter->body = $data['body'];
|
||||
$newsletter->save();
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
$data, $subscriber, $queue = false, $preview = true
|
||||
);
|
||||
return array(
|
||||
'result' => true,
|
||||
'data' => array('url' => $preview_url)
|
||||
);
|
||||
}
|
||||
|
||||
function sendPreview($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
return array(
|
||||
'result' => false
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$newsletter->body = $data['body'];
|
||||
$newsletter->save();
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
$data, $subscriber, $queue = false, $preview = true
|
||||
);
|
||||
}
|
||||
if(empty($data['subscriber'])) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please specify receiver information.'))
|
||||
);
|
||||
}
|
||||
|
||||
$newsletter = $newsletter->asArray();
|
||||
|
||||
$renderer = new Renderer($newsletter, $preview = true);
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$data_for_shortcodes =
|
||||
array_merge(array($newsletter['subject']), $rendered_newsletter);
|
||||
$body = implode($divider, $data_for_shortcodes);
|
||||
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$subscriber = ($subscriber) ? $subscriber->asArray() : false;
|
||||
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$newsletter,
|
||||
$subscriber
|
||||
);
|
||||
list($newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
$mailer = false,
|
||||
$sender = false,
|
||||
$reply_to = false
|
||||
);
|
||||
$result = $mailer->send($newsletter, $data['subscriber']);
|
||||
|
||||
return array('result' => $result);
|
||||
} catch(\Exception $e) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage()),
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($newsletter->id)->asArray(),
|
||||
array('preview_url' => $preview_url)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
function sendPreview($data = array()) {
|
||||
if(empty($data['subscriber'])) {
|
||||
return $this->badRequest(array(
|
||||
APIError::BAD_REQUEST => __('Please specify receiver information.')
|
||||
));
|
||||
}
|
||||
|
||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This newsletter does not exist.')
|
||||
));
|
||||
} else {
|
||||
$newsletter = $newsletter->asArray();
|
||||
|
||||
$renderer = new Renderer($newsletter, $preview = true);
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$data_for_shortcodes = array_merge(
|
||||
array($newsletter['subject']),
|
||||
$rendered_newsletter
|
||||
);
|
||||
|
||||
$body = implode($divider, $data_for_shortcodes);
|
||||
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$subscriber = ($subscriber) ? $subscriber->asArray() : false;
|
||||
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$newsletter,
|
||||
$subscriber
|
||||
);
|
||||
list(
|
||||
$newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
$mailer = false,
|
||||
$sender = false,
|
||||
$reply_to = false
|
||||
);
|
||||
$mailer->send($newsletter, $data['subscriber']);
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($id)->asArray()
|
||||
);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
$listing = new Listing\Handler(
|
||||
'\MailPoet\Models\Newsletter',
|
||||
$data
|
||||
);
|
||||
$listing_data = $listing->get();
|
||||
|
||||
foreach($listing_data['items'] as $key => $newsletter) {
|
||||
$data = array();
|
||||
foreach($listing_data['items'] as $newsletter) {
|
||||
$queue = false;
|
||||
|
||||
if($newsletter->type === Newsletter::TYPE_STANDARD) {
|
||||
$newsletter
|
||||
@ -277,22 +317,40 @@ class Newsletters extends APIEndpoint {
|
||||
->withStatistics();
|
||||
}
|
||||
|
||||
// get preview url
|
||||
$newsletter->preview_url = NewsletterUrl::getViewInBrowserUrl($newsletter);
|
||||
if($newsletter->status === Newsletter::STATUS_SENT ||
|
||||
$newsletter->status === Newsletter::STATUS_SENDING
|
||||
) {
|
||||
$queue = $newsletter->getQueue();
|
||||
}
|
||||
|
||||
// convert object to array
|
||||
$listing_data['items'][$key] = $newsletter->asArray();
|
||||
// get preview url
|
||||
$subscriber = Subscriber::getCurrentWPUser();
|
||||
$newsletter->preview_url = NewsletterUrl::getViewInBrowserUrl(
|
||||
$newsletter, $subscriber, $queue, $preview = true);
|
||||
|
||||
$data[] = $newsletter->asArray();
|
||||
}
|
||||
|
||||
return $listing_data;
|
||||
return $this->successResponse($data, array(
|
||||
'count' => $listing_data['count'],
|
||||
'filters' => $listing_data['filters'],
|
||||
'groups' => $listing_data['groups']
|
||||
));
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Newsletter',
|
||||
$data
|
||||
);
|
||||
return $bulk_action->apply();
|
||||
try {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Newsletter',
|
||||
$data
|
||||
);
|
||||
$meta = $bulk_action->apply();
|
||||
return $this->successResponse(null, $meta);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function create($data = array()) {
|
||||
@ -303,23 +361,25 @@ class Newsletters extends APIEndpoint {
|
||||
}
|
||||
|
||||
$newsletter = Newsletter::createOrUpdate($data);
|
||||
$errors = $newsletter->getErrors();
|
||||
|
||||
// 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;
|
||||
if(!empty($errors)) {
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
$newsletter->body = array();
|
||||
// try to load template data
|
||||
$template_id = (isset($data['template']) ? (int)$data['template'] : false);
|
||||
$template = NewsletterTemplate::findOne($template_id);
|
||||
if($template === false) {
|
||||
$newsletter->body = array();
|
||||
} else {
|
||||
$newsletter->body = $template->body;
|
||||
}
|
||||
}
|
||||
|
||||
$newsletter->save();
|
||||
$errors = $newsletter->getErrors();
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' =>$errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
if(!empty($options)) {
|
||||
$option_fields = NewsletterOptionField::where(
|
||||
@ -336,15 +396,19 @@ class Newsletters extends APIEndpoint {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!isset($data['id']) &&
|
||||
isset($data['type']) &&
|
||||
$data['type'] === 'notification'
|
||||
|
||||
if(
|
||||
empty($data['id'])
|
||||
&&
|
||||
isset($data['type'])
|
||||
&&
|
||||
$data['type'] === Newsletter::TYPE_NOTIFICATION
|
||||
) {
|
||||
Scheduler::processPostNotificationSchedule($newsletter->id);
|
||||
}
|
||||
return array(
|
||||
'result' => true,
|
||||
'newsletter' => $newsletter->asArray()
|
||||
|
||||
return $this->successResponse(
|
||||
Newsletter::findOne($newsletter->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
@ -9,16 +11,16 @@ use \MailPoet\Segments\WP;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Segments {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($id = false) {
|
||||
class Segments extends APIEndpoint {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment === false) {
|
||||
return false;
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This list does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $segment->asArray();
|
||||
return $this->successResponse($segment->asArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,18 +32,22 @@ class Segments {
|
||||
|
||||
$listing_data = $listing->get();
|
||||
|
||||
// fetch segments relations for each returned item
|
||||
foreach($listing_data['items'] as $key => $segment) {
|
||||
$data = array();
|
||||
foreach($listing_data['items'] as $segment) {
|
||||
$segment->subscribers_url = admin_url(
|
||||
'admin.php?page=mailpoet-subscribers#/filter[segment='.$segment->id.']'
|
||||
);
|
||||
|
||||
$listing_data['items'][$key] = $segment
|
||||
$data[] = $segment
|
||||
->withSubscribersCount()
|
||||
->asArray();
|
||||
}
|
||||
|
||||
return $listing_data;
|
||||
return $this->successResponse($data, array(
|
||||
'count' => $listing_data['count'],
|
||||
'filters' => $listing_data['filters'],
|
||||
'groups' => $listing_data['groups']
|
||||
));
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
@ -49,68 +55,109 @@ class Segments {
|
||||
$errors = $segment->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
function restore($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
if($segment === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This list does not exist.')
|
||||
));
|
||||
} else {
|
||||
$segment->restore();
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($segment->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
function trash($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
if($segment === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This list does not exist.')
|
||||
));
|
||||
} else {
|
||||
$segment->trash();
|
||||
return $this->successResponse(
|
||||
Segment::findOne($segment->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($segment->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
if($segment === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This list does not exist.')
|
||||
));
|
||||
} else {
|
||||
$segment->delete();
|
||||
return 1;
|
||||
return $this->successResponse(null, array('count' => 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function duplicate($id) {
|
||||
$result = false;
|
||||
|
||||
function duplicate($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$segment = Segment::findOne($id);
|
||||
if($segment !== false) {
|
||||
|
||||
if($segment === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This list does not exist.')
|
||||
));
|
||||
} else {
|
||||
$data = array(
|
||||
'name' => sprintf(__('Copy of %s'), $segment->name)
|
||||
);
|
||||
$result = $segment->duplicate($data)->asArray();
|
||||
}
|
||||
$duplicate = $segment->duplicate($data);
|
||||
$errors = $duplicate->getErrors();
|
||||
|
||||
return $result;
|
||||
if(!empty($errors)) {
|
||||
return $this->errorResponse($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Segment::findOne($duplicate->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function synchronize() {
|
||||
$result = WP::synchronizeUsers();
|
||||
try {
|
||||
WP::synchronizeUsers();
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $this->successResponse(null);
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Segment',
|
||||
$data
|
||||
);
|
||||
|
||||
return $bulk_action->apply();
|
||||
try {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Segment',
|
||||
$data
|
||||
);
|
||||
$meta = $bulk_action->apply();
|
||||
return $this->successResponse(null, $meta);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\API\Endpoints;
|
||||
use \MailPoet\API\Endpoint as APIEndpoint;
|
||||
use \MailPoet\API\Error as APIError;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Subscriber;
|
||||
@ -13,19 +15,22 @@ use MailPoet\Util\Url;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Subscribers {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function get($id = null) {
|
||||
class Subscribers extends APIEndpoint {
|
||||
function get($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
$subscriber = $subscriber
|
||||
->withCustomFields()
|
||||
->withSubscriptions()
|
||||
->asArray();
|
||||
if($subscriber === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This subscriber does not exist.')
|
||||
));
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
$subscriber
|
||||
->withCustomFields()
|
||||
->withSubscriptions()
|
||||
->asArray()
|
||||
);
|
||||
}
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
@ -36,30 +41,18 @@ class Subscribers {
|
||||
|
||||
$listing_data = $listing->get();
|
||||
|
||||
// fetch segments relations for each returned item
|
||||
foreach($listing_data['items'] as $key => $subscriber) {
|
||||
$listing_data['items'][$key] = $subscriber
|
||||
$data = array();
|
||||
foreach($listing_data['items'] as $subscriber) {
|
||||
$data[] = $subscriber
|
||||
->withSubscriptions()
|
||||
->asArray();
|
||||
}
|
||||
|
||||
return $listing_data;
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
$errors = $subscriber->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
);
|
||||
} else {
|
||||
return array(
|
||||
'result' => true
|
||||
);
|
||||
}
|
||||
return $this->successResponse($data, array(
|
||||
'count' => $listing_data['count'],
|
||||
'filters' => $listing_data['filters'],
|
||||
'groups' => $listing_data['groups']
|
||||
));
|
||||
}
|
||||
|
||||
function subscribe($data = array()) {
|
||||
@ -148,37 +141,76 @@ class Subscribers {
|
||||
}
|
||||
}
|
||||
|
||||
function restore($id) {
|
||||
function save($data = array()) {
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
$errors = $subscriber->getErrors();
|
||||
|
||||
if(!empty($errors)) {
|
||||
return $this->badRequest($errors);
|
||||
} else {
|
||||
return $this->successResponse(
|
||||
Subscriber::findOne($subscriber->id)->asArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function restore($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
if($subscriber === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This subscriber does not exist.')
|
||||
));
|
||||
} else {
|
||||
$subscriber->restore();
|
||||
return $this->successResponse(
|
||||
Subscriber::findOne($subscriber->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($subscriber->getErrors() === false);
|
||||
}
|
||||
|
||||
function trash($id) {
|
||||
function trash($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
if($subscriber === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This subscriber does not exist.')
|
||||
));
|
||||
} else {
|
||||
$subscriber->trash();
|
||||
return $this->successResponse(
|
||||
Subscriber::findOne($subscriber->id)->asArray(),
|
||||
array('count' => 1)
|
||||
);
|
||||
}
|
||||
return ($subscriber->getErrors() === false);
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
function delete($data = array()) {
|
||||
$id = (isset($data['id']) ? (int)$data['id'] : false);
|
||||
$subscriber = Subscriber::findOne($id);
|
||||
if($subscriber !== false) {
|
||||
if($subscriber === false) {
|
||||
return $this->errorResponse(array(
|
||||
APIError::NOT_FOUND => __('This subscriber does not exist.')
|
||||
));
|
||||
} else {
|
||||
$subscriber->delete();
|
||||
return 1;
|
||||
return $this->successResponse(null, array('count' => 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function bulkAction($data = array()) {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Subscriber',
|
||||
$data
|
||||
);
|
||||
|
||||
return $bulk_action->apply();
|
||||
try {
|
||||
$bulk_action = new Listing\BulkAction(
|
||||
'\MailPoet\Models\Subscriber',
|
||||
$data
|
||||
);
|
||||
$meta = $bulk_action->apply();
|
||||
return $this->successResponse(null, $meta);
|
||||
} catch(\Exception $e) {
|
||||
return $this->errorResponse(array(
|
||||
$e->getCode() => $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,11 @@ abstract class Response {
|
||||
$response = array_merge($response, $data);
|
||||
}
|
||||
|
||||
if(empty($response)) {
|
||||
die();
|
||||
} else {
|
||||
wp_send_json($response);
|
||||
if(!empty($response)) {
|
||||
@header('Content-Type: application/json; charset='.get_option('blog_charset'));
|
||||
echo wp_json_encode($response);
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
abstract function getData();
|
||||
|
@ -27,6 +27,7 @@ class Env {
|
||||
static $db_password;
|
||||
static $db_charset;
|
||||
static $db_timezone_offset;
|
||||
static $subscribers_limit = 2000;
|
||||
|
||||
static function init($file, $version) {
|
||||
global $wpdb;
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Models;
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use MailPoet\Router;
|
||||
use MailPoet\API;
|
||||
@ -122,7 +121,7 @@ class Initializer {
|
||||
|
||||
try {
|
||||
$this->setupAPI();
|
||||
$this->setupFrontRouter();
|
||||
$this->setupRouter();
|
||||
$this->setupPages();
|
||||
} catch(\Exception $e) {
|
||||
$this->handleFailedInitialization($e);
|
||||
@ -187,14 +186,17 @@ class Initializer {
|
||||
$api->init();
|
||||
}
|
||||
|
||||
function setupFrontRouter() {
|
||||
$router = new Router\Front();
|
||||
function setupRouter() {
|
||||
$router = new Router\Router();
|
||||
$router->init();
|
||||
}
|
||||
|
||||
function setupCronTrigger() {
|
||||
$cron_trigger = new CronTrigger();
|
||||
$cron_trigger->init();
|
||||
// setup cron trigger only outside of cli environment
|
||||
if(php_sapi_name() !== 'cli') {
|
||||
$cron_trigger = new CronTrigger();
|
||||
$cron_trigger->init();
|
||||
}
|
||||
}
|
||||
|
||||
function setupImages() {
|
||||
|
@ -8,6 +8,7 @@ use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Shortcodes\ShortcodesHelper;
|
||||
use MailPoet\Settings\Hosts;
|
||||
use MailPoet\Settings\Pages;
|
||||
@ -33,6 +34,16 @@ class Menu {
|
||||
);
|
||||
}
|
||||
|
||||
function checkSubscribersLimit() {
|
||||
$subscribers_count = Subscriber::getTotalSubscribers();
|
||||
if($subscribers_count > Env::$subscribers_limit) {
|
||||
echo $this->renderer->render('limit.html', array(
|
||||
'limit' => Env::$subscribers_limit
|
||||
));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function setup() {
|
||||
$main_page_slug = 'mailpoet-newsletters';
|
||||
|
||||
@ -185,15 +196,6 @@ class Menu {
|
||||
'mailpoet-newsletter-editor',
|
||||
array($this, 'newletterEditor')
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
$main_page_slug,
|
||||
$this->setPageTitle(__('Cron')),
|
||||
__('Cron'),
|
||||
'manage_options',
|
||||
'mailpoet-cron',
|
||||
array($this, 'cron')
|
||||
);
|
||||
}
|
||||
|
||||
function welcome() {
|
||||
@ -250,6 +252,8 @@ class Menu {
|
||||
}
|
||||
|
||||
function settings() {
|
||||
$this->checkSubscribersLimit();
|
||||
|
||||
$settings = Setting::getAll();
|
||||
$flags = $this->_getFlags();
|
||||
|
||||
@ -322,12 +326,16 @@ class Menu {
|
||||
}
|
||||
|
||||
function segments() {
|
||||
$this->checkSubscribersLimit();
|
||||
|
||||
$data = array();
|
||||
$data['items_per_page'] = $this->getLimitPerPage('segments');
|
||||
echo $this->renderer->render('segments.html', $data);
|
||||
}
|
||||
|
||||
function forms() {
|
||||
$this->checkSubscribersLimit();
|
||||
|
||||
$data = array();
|
||||
|
||||
$data['items_per_page'] = $this->getLimitPerPage('forms');
|
||||
@ -337,6 +345,8 @@ class Menu {
|
||||
}
|
||||
|
||||
function newsletters() {
|
||||
$this->checkSubscribersLimit();
|
||||
|
||||
global $wp_roles;
|
||||
|
||||
$data = array();
|
||||
@ -368,6 +378,7 @@ class Menu {
|
||||
$data = array(
|
||||
'shortcodes' => ShortcodesHelper::getShortcodes(),
|
||||
'settings' => Setting::getAll(),
|
||||
'current_wp_user' => Subscriber::getCurrentWPUser(),
|
||||
'sub_menu' => 'mailpoet-newsletters'
|
||||
);
|
||||
wp_enqueue_media();
|
||||
@ -379,7 +390,12 @@ class Menu {
|
||||
function import() {
|
||||
$import = new ImportExportFactory('import');
|
||||
$data = $import->bootstrap();
|
||||
$data['sub_menu'] = 'mailpoet-subscribers';
|
||||
$data = array_merge($data, array(
|
||||
'date_types' => Block\Date::getDateTypes(),
|
||||
'date_formats' => Block\Date::getDateFormats(),
|
||||
'month_names' => Block\Date::getMonthNames(),
|
||||
'sub_menu' => 'mailpoet-subscribers'
|
||||
));
|
||||
echo $this->renderer->render('subscribers/importExport/import.html', $data);
|
||||
}
|
||||
|
||||
@ -411,10 +427,6 @@ class Menu {
|
||||
echo $this->renderer->render('form/editor.html', $data);
|
||||
}
|
||||
|
||||
function cron() {
|
||||
echo $this->renderer->render('cron.html');
|
||||
}
|
||||
|
||||
function setPageTitle($title) {
|
||||
return sprintf(
|
||||
'%s - %s',
|
||||
@ -435,4 +447,4 @@ class Menu {
|
||||
? (int)$listing_per_page
|
||||
: Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Config\PopulatorData\Templates\FranksRoastHouseTemplate;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank12Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank121Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\NewsletterBlank13Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank1Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank12Column;
|
||||
use MailPoet\Config\PopulatorData\Templates\SimpleText;
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Segments\WP;
|
||||
@ -22,12 +13,31 @@ if(!defined('ABSPATH')) exit;
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
|
||||
class Populator {
|
||||
public $prefix;
|
||||
public $models;
|
||||
public $templates;
|
||||
const TEMPLATES_NAMESPACE = '\MailPoet\Config\PopulatorData\Templates\\';
|
||||
|
||||
function __construct() {
|
||||
$this->prefix = Env::$db_prefix;
|
||||
$this->models = array(
|
||||
'newsletter_option_fields',
|
||||
'newsletter_templates',
|
||||
);
|
||||
$this->templates = array(
|
||||
"FranksRoastHouseTemplate",
|
||||
"NewsletterBlank1Column",
|
||||
"NewsletterBlank12Column",
|
||||
"NewsletterBlank121Column",
|
||||
"NewsletterBlank13Column",
|
||||
"PostNotificationsBlank1Column",
|
||||
"WelcomeBlank1Column",
|
||||
"WelcomeBlank12Column",
|
||||
"SimpleText",
|
||||
"Restaurant",
|
||||
"StoreDiscount",
|
||||
"TravelEmail"
|
||||
);
|
||||
}
|
||||
|
||||
function up() {
|
||||
@ -104,6 +114,10 @@ class Populator {
|
||||
'reply_to' => $sender
|
||||
));
|
||||
}
|
||||
|
||||
if(!Setting::getValue('installed_at')) {
|
||||
Setting::setValue('installed_at', date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
|
||||
private function createDefaultSegments() {
|
||||
@ -184,17 +198,13 @@ class Populator {
|
||||
}
|
||||
|
||||
private function newsletterTemplates() {
|
||||
return array(
|
||||
(new FranksRoastHouseTemplate(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank1Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank12Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank121Column(Env::$assets_url))->get(),
|
||||
(new NewsletterBlank13Column(Env::$assets_url))->get(),
|
||||
(new PostNotificationsBlank1Column(Env::$assets_url))->get(),
|
||||
(new WelcomeBlank1Column(Env::$assets_url))->get(),
|
||||
(new WelcomeBlank12Column(Env::$assets_url))->get(),
|
||||
(new SimpleText(Env::$assets_url))->get(),
|
||||
);
|
||||
$templates = array();
|
||||
foreach($this->templates as $template) {
|
||||
$template = self::TEMPLATES_NAMESPACE . $template;
|
||||
$template = new $template(Env::$assets_url);
|
||||
$templates[] = $template->get();
|
||||
}
|
||||
return $templates;
|
||||
}
|
||||
|
||||
private function populate($model) {
|
||||
|
@ -7,7 +7,7 @@ class FranksRoastHouseTemplate {
|
||||
|
||||
function __construct($assets_url) {
|
||||
$this->assets_url = $assets_url;
|
||||
$this->template_image_url = $this->assets_url . '/img/sample_template';
|
||||
$this->template_image_url = $this->assets_url . '/img/sample_templates/coffee';
|
||||
$this->social_icon_url = $this->assets_url . '/img/newsletter_editor/social-icons';
|
||||
}
|
||||
|
||||
|
412
lib/Config/PopulatorData/Templates/Restaurant.php
Normal file
405
lib/Config/PopulatorData/Templates/StoreDiscount.php
Normal file
526
lib/Config/PopulatorData/Templates/TravelEmail.php
Normal file
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class BootStrapMenu {
|
||||
function __construct() {
|
||||
$this->daemon = Setting::where('name', 'cron_daemon')
|
||||
->findOne();
|
||||
}
|
||||
|
||||
function bootStrap() {
|
||||
return ($this->daemon) ?
|
||||
array_merge(
|
||||
array(
|
||||
'timeSinceStart' => Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->created_at,
|
||||
'UTC'
|
||||
)->diffForHumans(),
|
||||
'timeSinceUpdate' => Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at,
|
||||
'UTC'
|
||||
)->diffForHumans()
|
||||
),
|
||||
json_decode($this->daemon->value, true)
|
||||
) :
|
||||
"false";
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ namespace MailPoet\Cron;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Router\Endpoints\Queue as QueueEndpoint;
|
||||
use MailPoet\Router\Front as FrontRouter;
|
||||
use MailPoet\Router\Router;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
@ -16,7 +16,6 @@ class CronHelper {
|
||||
|
||||
static function createDaemon($token) {
|
||||
$daemon = array(
|
||||
'status' => Daemon::STATUS_STARTING,
|
||||
'token' => $token
|
||||
);
|
||||
self::saveDaemon($daemon);
|
||||
@ -41,7 +40,6 @@ class CronHelper {
|
||||
|
||||
static function stopDaemon() {
|
||||
$daemon = self::getDaemon();
|
||||
$daemon['status'] = Daemon::STATUS_STOPPED;
|
||||
return self::saveDaemon($daemon);
|
||||
}
|
||||
|
||||
@ -55,11 +53,12 @@ class CronHelper {
|
||||
|
||||
static function accessDaemon($token, $timeout = self::DAEMON_REQUEST_TIMEOUT) {
|
||||
$data = array('token' => $token);
|
||||
$url = FrontRouter::buildRequest(
|
||||
$url = Router::buildRequest(
|
||||
QueueEndpoint::ENDPOINT,
|
||||
QueueEndpoint::ACTION_RUN,
|
||||
$data
|
||||
);
|
||||
$url = str_replace(home_url(), self::getSiteUrl(), $url);
|
||||
$args = array(
|
||||
'blocking' => false,
|
||||
'sslverify' => false,
|
||||
@ -70,20 +69,22 @@ class CronHelper {
|
||||
return wp_remote_retrieve_body($result);
|
||||
}
|
||||
|
||||
private static function getSiteUrl() {
|
||||
// additional check for some sites running on a virtual machine or behind
|
||||
static function getSiteUrl($site_url = false) {
|
||||
// additional check for some sites running inside 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
|
||||
$site_url = ($site_url) ? $site_url : home_url();
|
||||
$parsed_url = parse_url($site_url);
|
||||
// 1. if site URL does not contain a port, return the URL
|
||||
if(empty($parsed_url['port'])) return $site_url;
|
||||
// 2. if site URL contains valid port, try connecting to it
|
||||
$fp = @fsockopen($parsed_url['host'], $parsed_url['port'], $errno, $errstr, 1);
|
||||
if($fp) return $site_url;
|
||||
// 3. if connection fails, attempt to connect the standard port derived from URL
|
||||
// schema
|
||||
$port = (strtolower($parsed_url['scheme']) === 'http') ? 80 : 443;
|
||||
$fp = @fsockopen($parsed_url['host'], $port, $errno, $errstr, 1);
|
||||
if($fp) return sprintf('%s://%s', $parsed_url['scheme'], $parsed_url['host']);
|
||||
// 4. throw an error if all connection attempts failed
|
||||
throw new \Exception(__('Site URL is unreachable.'));
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,6 @@ class CronTrigger {
|
||||
|
||||
function init() {
|
||||
try {
|
||||
// configure cron trigger only outside of cli environment
|
||||
if(php_sapi_name() === 'cli') return;
|
||||
$trigger_class = __NAMESPACE__ . '\Triggers\\' . $this->current_method;
|
||||
return (class_exists($trigger_class)) ?
|
||||
$trigger_class::run() :
|
||||
|
@ -10,77 +10,75 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Daemon {
|
||||
public $daemon;
|
||||
public $data;
|
||||
public $refreshed_token;
|
||||
const STATUS_STOPPED = 'stopped';
|
||||
const STATUS_STOPPING = 'stopping';
|
||||
const STATUS_STARTED = 'started';
|
||||
const STATUS_STARTING = 'starting';
|
||||
public $request_data;
|
||||
public $timer;
|
||||
const REQUEST_TIMEOUT = 5;
|
||||
private $timer;
|
||||
|
||||
function __construct($data) {
|
||||
if(empty($data)) $this->abortWithError(__('Invalid or missing Cron data.'));
|
||||
ignore_user_abort();
|
||||
function __construct($request_data = false) {
|
||||
$this->request_data = $request_data;
|
||||
$this->daemon = CronHelper::getDaemon();
|
||||
$this->token = CronHelper::createToken();
|
||||
$this->data = $data;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
function run() {
|
||||
ignore_user_abort(true);
|
||||
if(!$this->request_data) {
|
||||
$error = __('Invalid or missing request data.');
|
||||
} else {
|
||||
if(!$this->daemon) {
|
||||
$error = __('Daemon does not exist.');
|
||||
} else {
|
||||
if(!isset($this->request_data['token']) ||
|
||||
$this->request_data['token'] !== $this->daemon['token']
|
||||
) {
|
||||
$error = 'Invalid or missing token.';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!empty($error)) {
|
||||
return $this->abortWithError($error);
|
||||
}
|
||||
$daemon = $this->daemon;
|
||||
if(!$daemon) {
|
||||
$this->abortWithError(__('Daemon does not exist.'));
|
||||
}
|
||||
if(!isset($this->data['token']) ||
|
||||
$this->data['token'] !== $daemon['token']
|
||||
) {
|
||||
$this->abortWithError(__('Invalid or missing token.'));
|
||||
}
|
||||
$daemon['token'] = $this->token;
|
||||
CronHelper::saveDaemon($daemon);
|
||||
$this->abortIfStopped($daemon);
|
||||
try {
|
||||
$scheduler = new SchedulerWorker($this->timer);
|
||||
$scheduler->process();
|
||||
$queue = new SendingQueueWorker($this->timer);
|
||||
$queue->process();
|
||||
$this->executeScheduleWorker();
|
||||
$this->executeQueueWorker();
|
||||
} catch(\Exception $e) {
|
||||
// continue processing, no need to handle errors
|
||||
}
|
||||
// if workers took less time to execute than the daemon execution limit,
|
||||
// pause daemon execution to ensure that daemon runs only once every X seconds
|
||||
$elapsed_time = microtime(true) - $this->timer;
|
||||
if($elapsed_time < CronHelper::DAEMON_EXECUTION_LIMIT) {
|
||||
sleep(CronHelper::DAEMON_EXECUTION_LIMIT - $elapsed_time);
|
||||
$this->pauseExecution(CronHelper::DAEMON_EXECUTION_LIMIT - $elapsed_time);
|
||||
}
|
||||
// after each execution, re-read daemon data in case its status was changed
|
||||
// its status has changed
|
||||
// after each execution, re-read daemon data in case it changed
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!$daemon || $daemon['token'] !== $this->token) {
|
||||
$this->terminateRequest();
|
||||
return $this->terminateRequest();
|
||||
}
|
||||
$this->abortIfStopped($daemon);
|
||||
if($daemon['status'] === self::STATUS_STARTING) {
|
||||
$daemon['status'] = self::STATUS_STARTED;
|
||||
}
|
||||
CronHelper::saveDaemon($daemon);
|
||||
$this->callSelf();
|
||||
return $this->callSelf();
|
||||
}
|
||||
|
||||
function abortIfStopped($daemon) {
|
||||
if($daemon['status'] === self::STATUS_STOPPED) {
|
||||
$this->terminateRequest();
|
||||
}
|
||||
if($daemon['status'] === self::STATUS_STOPPING) {
|
||||
$daemon['status'] = self::STATUS_STOPPED;
|
||||
CronHelper::saveDaemon($daemon);
|
||||
$this->terminateRequest();
|
||||
}
|
||||
function pauseExecution($pause_time) {
|
||||
return sleep($pause_time);
|
||||
}
|
||||
|
||||
function executeScheduleWorker() {
|
||||
$scheduler = new SchedulerWorker($this->timer);
|
||||
return $scheduler->process();
|
||||
}
|
||||
|
||||
function executeQueueWorker() {
|
||||
$queue = new SendingQueueWorker($this->timer);
|
||||
return $queue->process();
|
||||
}
|
||||
|
||||
function callSelf() {
|
||||
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
|
||||
$this->terminateRequest();
|
||||
return $this->terminateRequest();
|
||||
}
|
||||
|
||||
function abortWithError($message) {
|
||||
|
@ -15,7 +15,7 @@ class Supervisor {
|
||||
function checkDaemon() {
|
||||
$daemon = $this->daemon;
|
||||
$execution_timeout_exceeded =
|
||||
(time() - (int)$daemon['updated_at']) > CronHelper::DAEMON_EXECUTION_TIMEOUT;
|
||||
(time() - (int)$daemon['updated_at']) >= CronHelper::DAEMON_EXECUTION_TIMEOUT;
|
||||
if($execution_timeout_exceeded) {
|
||||
CronHelper::restartDaemon($this->token);
|
||||
return $this->runDaemon();
|
||||
|
@ -26,7 +26,7 @@ class Scheduler {
|
||||
|
||||
function process() {
|
||||
$scheduled_queues = self::getScheduledQueues();
|
||||
if(!count($scheduled_queues)) return;
|
||||
if(!count($scheduled_queues)) return false;
|
||||
foreach($scheduled_queues as $i => $queue) {
|
||||
$newsletter = Newsletter::filter('filterWithOptions')
|
||||
->findOne($queue->newsletter_id);
|
||||
@ -47,30 +47,30 @@ class Scheduler {
|
||||
$subscriber = unserialize($queue->subscribers);
|
||||
if(empty($subscriber['to_process'][0])) {
|
||||
$queue->delete();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
$subscriber_id = (int)$subscriber['to_process'][0];
|
||||
if($newsletter->event === 'segment') {
|
||||
if($this->verifyMailPoetSubscriber($subscriber_id, $newsletter, $queue) === false) {
|
||||
return;
|
||||
if($this->verifyMailpoetSubscriber($subscriber_id, $newsletter, $queue) === false) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if($newsletter->event === 'user') {
|
||||
if($this->verifyWPSubscriber($subscriber_id, $newsletter, $queue) === false) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$queue->status = null;
|
||||
$queue->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
function processPostNotificationNewsletter($newsletter, $queue) {
|
||||
// ensure that segments exist
|
||||
$segments = $newsletter->segments()->findArray();
|
||||
if(empty($segments)) {
|
||||
$this->deleteQueueOrUpdateNextRunDate($queue, $newsletter);
|
||||
return;
|
||||
return $this->deleteQueueOrUpdateNextRunDate($queue, $newsletter);
|
||||
}
|
||||
$segment_ids = array_map(function($segment) {
|
||||
return (int)$segment['id'];
|
||||
@ -83,13 +83,12 @@ class Scheduler {
|
||||
$subscribers = array_unique($subscribers);
|
||||
|
||||
if(empty($subscribers)) {
|
||||
$this->deleteQueueOrUpdateNextRunDate($queue, $newsletter);
|
||||
return;
|
||||
return $this->deleteQueueOrUpdateNextRunDate($queue, $newsletter);
|
||||
}
|
||||
|
||||
// create a duplicate newsletter that acts as a history record
|
||||
$notification_history = $this->createNotificationHistory($newsletter->id);
|
||||
if(!$notification_history) return;
|
||||
if(!$notification_history) return false;
|
||||
|
||||
// queue newsletter for delivery
|
||||
$queue->newsletter_id = $notification_history->id;
|
||||
@ -101,6 +100,7 @@ class Scheduler {
|
||||
$queue->count_total = $queue->count_to_process = count($subscribers);
|
||||
$queue->status = null;
|
||||
$queue->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
function processScheduledStandardNewsletter($newsletter, $queue) {
|
||||
@ -108,7 +108,6 @@ class Scheduler {
|
||||
$segment_ids = array_map(function($segment) {
|
||||
return $segment['id'];
|
||||
}, $segments);
|
||||
|
||||
$subscribers = Subscriber::getSubscribedInSegments($segment_ids)
|
||||
->findArray();
|
||||
$subscribers = Helpers::arrayColumn($subscribers, 'subscriber_id');
|
||||
@ -123,9 +122,10 @@ class Scheduler {
|
||||
$queue->count_total = $queue->count_to_process = count($subscribers);
|
||||
$queue->status = null;
|
||||
$queue->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifyMailPoetSubscriber($subscriber_id, $newsletter, $queue) {
|
||||
function verifyMailpoetSubscriber($subscriber_id, $newsletter, $queue) {
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
// check if subscriber is in proper segment
|
||||
$subscriber_in_segment =
|
||||
@ -184,7 +184,7 @@ class Scheduler {
|
||||
$notification_history :
|
||||
false;
|
||||
}
|
||||
|
||||
|
||||
static function getScheduledQueues() {
|
||||
return SendingQueue::where('status', 'scheduled')
|
||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||
|
@ -88,7 +88,6 @@ class Newsletter {
|
||||
);
|
||||
if($this->tracking_enabled) {
|
||||
$prepared_newsletter = NewsletterLinks::replaceSubscriberData(
|
||||
$newsletter['id'],
|
||||
$subscriber['id'],
|
||||
$queue['id'],
|
||||
$prepared_newsletter
|
||||
|
@ -2,7 +2,7 @@
|
||||
namespace MailPoet\Form\Block;
|
||||
|
||||
abstract class Base {
|
||||
protected static function getInputValidation($block) {
|
||||
protected static function getInputValidation($block, $extra_rules = array()) {
|
||||
$rules = array();
|
||||
|
||||
if($block['id'] === 'email') {
|
||||
@ -37,8 +37,15 @@ abstract class Base {
|
||||
$rules['required-message'] = __('Please select at least one option');
|
||||
}
|
||||
|
||||
if($block['type'] === 'date') {
|
||||
$rules['group'] = 'custom_field_'.$block['id'];
|
||||
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||
}
|
||||
|
||||
$validation = array();
|
||||
|
||||
$rules = array_merge($rules, $extra_rules);
|
||||
|
||||
if(!empty($rules)) {
|
||||
$rules = array_unique($rules);
|
||||
foreach($rules as $rule => $value) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Form\Block;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Date extends Base {
|
||||
|
||||
static function render($block) {
|
||||
@ -17,7 +19,6 @@ class Date extends Base {
|
||||
$html = '';
|
||||
|
||||
$field_name = static::getFieldName($block);
|
||||
$field_validation = static::getInputValidation($block);
|
||||
|
||||
$date_formats = static::getDateFormats();
|
||||
|
||||
@ -65,27 +66,38 @@ class Date extends Base {
|
||||
}
|
||||
|
||||
foreach($date_selectors as $date_selector) {
|
||||
if($date_selector === 'dd') {
|
||||
if($date_selector === 'DD') {
|
||||
$block['selected'] = $day;
|
||||
$html .= '<select class="mailpoet_date_day" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a day')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[day]" placeholder="'.__('Day').'">';
|
||||
$html .= static::getDays($block);
|
||||
$html .= '</select>';
|
||||
} else if($date_selector === 'mm') {
|
||||
} else if($date_selector === 'MM') {
|
||||
$block['selected'] = $month;
|
||||
$html .= '<select class="mailpoet_date_month" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a month')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[month]" placeholder="'.__('Month').'">';
|
||||
$html .= static::getMonths($block);
|
||||
$html .= '</select>';
|
||||
} else if($date_selector === 'yyyy') {
|
||||
} else if($date_selector === 'YYYY') {
|
||||
$block['selected'] = $year;
|
||||
$html .= '<select class="mailpoet_date_year" ';
|
||||
$html .= static::getInputValidation($block, array(
|
||||
'required-message' => __('Please select a year')
|
||||
));
|
||||
$html .= 'name="'.$field_name.'[year]" placeholder="'.__('Year').'">';
|
||||
$html .= static::getYears($block);
|
||||
$html .= '</select>';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
@ -100,10 +112,10 @@ class Date extends Base {
|
||||
|
||||
static function getDateFormats() {
|
||||
return array(
|
||||
'year_month_day' => array('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy/mm/dd'),
|
||||
'year_month' => array('mm/yyyy', 'yyyy/mm'),
|
||||
'year' => array('yyyy'),
|
||||
'month' => array('mm')
|
||||
'year_month_day' => array('MM/DD/YYYY', 'DD/MM/YYYY', 'YYYY/MM/DD'),
|
||||
'year_month' => array('MM/YYYY', 'YYYY/MM'),
|
||||
'year' => array('YYYY'),
|
||||
'month' => array('MM')
|
||||
);
|
||||
}
|
||||
static function getMonthNames() {
|
||||
@ -192,4 +204,85 @@ class Date extends Base {
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
static function convertDateToDatetime($date, $date_format) {
|
||||
$datetime = false;
|
||||
if($date_format === 'datetime') {
|
||||
$datetime = $date;
|
||||
} else {
|
||||
$parsed_date = explode('/', $date);
|
||||
$parsed_date_format = explode('/', $date_format);
|
||||
$year_position = array_search('YYYY', $parsed_date_format);
|
||||
$month_position = array_search('MM', $parsed_date_format);
|
||||
$day_position = array_search('DD', $parsed_date_format);
|
||||
if(count($parsed_date) === 3) {
|
||||
// create date from any combination of month, day and year
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => $parsed_date[$day_position]
|
||||
);
|
||||
} else if(count($parsed_date) === 2) {
|
||||
// create date from any combination of month and year
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => '01'
|
||||
);
|
||||
} else if($date_format === 'MM' && count($parsed_date) === 1) {
|
||||
// create date from month
|
||||
if((int)$parsed_date[$month_position] === 0) {
|
||||
$datetime = '';
|
||||
$parsed_date = false;
|
||||
} else {
|
||||
$parsed_date = array(
|
||||
'month' => $parsed_date[$month_position],
|
||||
'day' => '01',
|
||||
'year' => date('Y')
|
||||
);
|
||||
}
|
||||
} else if($date_format === 'YYYY' && count($parsed_date) === 1) {
|
||||
// create date from year
|
||||
if((int)$parsed_date[$year_position] === 0) {
|
||||
$datetime = '';
|
||||
$parsed_date = false;
|
||||
} else {
|
||||
$parsed_date = array(
|
||||
'year' => $parsed_date[$year_position],
|
||||
'month' => '01',
|
||||
'day' => '01'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$parsed_date = false;
|
||||
}
|
||||
if($parsed_date) {
|
||||
$year = $parsed_date['year'];
|
||||
$month = $parsed_date['month'];
|
||||
$day = $parsed_date['day'];
|
||||
// if all date parts are set to 0, date value is empty
|
||||
if((int)$year === 0 && (int)$month === 0 && (int)$day === 0) {
|
||||
$datetime = '';
|
||||
} else {
|
||||
if((int)$year === 0) $year = date('Y');
|
||||
if((int)$month === 0) $month = date('m');
|
||||
if((int)$day === 0) $day = date('d');
|
||||
$datetime = sprintf(
|
||||
'%s-%s-%s 00:00:00',
|
||||
$year,
|
||||
$month,
|
||||
$day
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if($datetime !== false && !empty($datetime)) {
|
||||
try {
|
||||
$datetime = Carbon::parse($datetime)->toDateTimeString();
|
||||
} catch(\Exception $e) {
|
||||
$datetime = false;
|
||||
}
|
||||
}
|
||||
return $datetime;
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ class BulkAction {
|
||||
|
||||
if(!method_exists($this->model_class, $bulk_action_method)) {
|
||||
throw new \Exception(
|
||||
$this->model_class. ' has not method "'.$bulk_action_method.'"'
|
||||
$this->model_class. ' has no method "'.$bulk_action_method.'"'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,7 @@ class Handler {
|
||||
);
|
||||
}
|
||||
|
||||
// get items and total count
|
||||
if(method_exists($this->model_class, 'listingQuery')) {
|
||||
$custom_query = call_user_func_array(
|
||||
array($this->model_class, 'listingQuery'),
|
||||
@ -135,7 +136,6 @@ class Handler {
|
||||
->findMany();
|
||||
}
|
||||
|
||||
|
||||
return array(
|
||||
'count' => $count,
|
||||
'filters' => $filters,
|
||||
|
@ -12,7 +12,7 @@ class Mailer {
|
||||
public $sender;
|
||||
public $reply_to;
|
||||
public $mailer_instance;
|
||||
const MAILER_CONFIG = 'mta';
|
||||
const MAILER_CONFIG_SETTING_NAME = 'mta';
|
||||
const SENDING_LIMIT_INTERVAL_MULTIPLIER = 60;
|
||||
const METHOD_MAILPOET = 'MailPoet';
|
||||
const METHOD_MAILGUN = 'MailGun';
|
||||
@ -100,7 +100,7 @@ class Mailer {
|
||||
|
||||
static function getMailerConfig($mailer = false) {
|
||||
if(!$mailer) {
|
||||
$mailer = Setting::getValue(self::MAILER_CONFIG);
|
||||
$mailer = Setting::getValue(self::MAILER_CONFIG_SETTING_NAME);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured'));
|
||||
}
|
||||
if(empty($mailer['frequency'])) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
use MailPoet\Form\Block\Date;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class CustomField extends Model {
|
||||
@ -43,28 +45,27 @@ class CustomField extends Model {
|
||||
// format custom field data depending on type
|
||||
if(is_array($value) && $this->type === 'date' ) {
|
||||
$custom_field_data = $this->asArray();
|
||||
|
||||
$date_format = $custom_field_data['params']['date_format'];
|
||||
$date_type = (isset($custom_field_data['params']['date_type'])
|
||||
? $custom_field_data['params']['date_type']
|
||||
: 'year_month_day'
|
||||
);
|
||||
$date_parts = explode('_', $date_type);
|
||||
|
||||
switch($date_type) {
|
||||
case 'year_month_day':
|
||||
$value = sprintf(
|
||||
'%04d-%02d-%02d',
|
||||
$value['year'],
|
||||
'%s/%s/%s',
|
||||
$value['month'],
|
||||
$value['day']
|
||||
$value['day'],
|
||||
$value['year']
|
||||
);
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
$value = sprintf(
|
||||
'%04d-%02d',
|
||||
$value['year'],
|
||||
$value['month']
|
||||
'%s/%s',
|
||||
$value['month'],
|
||||
$value['year']
|
||||
);
|
||||
break;
|
||||
|
||||
@ -73,12 +74,23 @@ class CustomField extends Model {
|
||||
$value = '';
|
||||
} else {
|
||||
$value = sprintf(
|
||||
'%02d',
|
||||
'%s',
|
||||
$value['month']
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'day':
|
||||
if((int)$value['day'] === 0) {
|
||||
$value = '';
|
||||
} else {
|
||||
$value = sprintf(
|
||||
'%s',
|
||||
$value['day']
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
if((int)$value['year'] === 0) {
|
||||
$value = '';
|
||||
@ -90,6 +102,10 @@ class CustomField extends Model {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!empty($value)) {
|
||||
$value = Date::convertDateToDatetime($value, $date_format);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
@ -5,6 +5,7 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Model extends \Sudzy\ValidModel {
|
||||
protected $_errors;
|
||||
protected $_new_record;
|
||||
|
||||
function __construct() {
|
||||
$this->_errors = array();
|
||||
@ -36,6 +37,7 @@ class Model extends \Sudzy\ValidModel {
|
||||
|
||||
function save() {
|
||||
$this->setTimestamp();
|
||||
$this->_new_record = $this->isNew();
|
||||
try {
|
||||
parent::save();
|
||||
} catch(\Sudzy\ValidationException $e) {
|
||||
@ -63,13 +65,19 @@ class Model extends \Sudzy\ValidModel {
|
||||
return $this;
|
||||
}
|
||||
|
||||
function isNew() {
|
||||
return (isset($this->_new_record)) ?
|
||||
$this->_new_record :
|
||||
parent::isNew();
|
||||
}
|
||||
|
||||
function trash() {
|
||||
return $this->set_expr('deleted_at', 'NOW()')->save();
|
||||
}
|
||||
|
||||
static function bulkTrash($orm) {
|
||||
$model = get_called_class();
|
||||
return self::bulkAction($orm, function($ids) use($model) {
|
||||
$count = self::bulkAction($orm, function($ids) use($model) {
|
||||
self::rawExecute(join(' ', array(
|
||||
'UPDATE `'.$model::$_table.'`',
|
||||
'SET `deleted_at` = NOW()',
|
||||
@ -78,13 +86,17 @@ class Model extends \Sudzy\ValidModel {
|
||||
$ids
|
||||
);
|
||||
});
|
||||
|
||||
return array('count' => $count);
|
||||
}
|
||||
|
||||
static function bulkDelete($orm) {
|
||||
$model = get_called_class();
|
||||
return self::bulkAction($orm, function($ids) use($model) {
|
||||
$count = self::bulkAction($orm, function($ids) use($model) {
|
||||
$model::whereIn('id', $ids)->deleteMany();
|
||||
});
|
||||
|
||||
return array('count' => $count);
|
||||
}
|
||||
|
||||
function restore() {
|
||||
@ -93,7 +105,7 @@ class Model extends \Sudzy\ValidModel {
|
||||
|
||||
static function bulkRestore($orm) {
|
||||
$model = get_called_class();
|
||||
return self::bulkAction($orm, function($ids) use($model) {
|
||||
$count = self::bulkAction($orm, function($ids) use($model) {
|
||||
self::rawExecute(join(' ', array(
|
||||
'UPDATE `'.$model::$_table.'`',
|
||||
'SET `deleted_at` = NULL',
|
||||
@ -102,6 +114,8 @@ class Model extends \Sudzy\ValidModel {
|
||||
$ids
|
||||
);
|
||||
});
|
||||
|
||||
return array('count' => $count);
|
||||
}
|
||||
|
||||
static function bulkAction($orm, $callback = false) {
|
||||
@ -137,14 +151,11 @@ class Model extends \Sudzy\ValidModel {
|
||||
$duplicate->set_expr('updated_at', 'NOW()');
|
||||
$duplicate->set_expr('deleted_at', 'NULL');
|
||||
|
||||
if($duplicate->save()) {
|
||||
return $duplicate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$duplicate->save();
|
||||
return $duplicate;
|
||||
}
|
||||
|
||||
private function setTimestamp() {
|
||||
function setTimestamp() {
|
||||
if($this->created_at === null) {
|
||||
$this->set_expr('created_at', 'NOW()');
|
||||
}
|
||||
@ -157,4 +168,4 @@ class Model extends \Sudzy\ValidModel {
|
||||
static function getTrashed() {
|
||||
return static::whereNotNull('deleted_at');
|
||||
}
|
||||
}
|
||||
}
|
@ -5,4 +5,9 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterLink extends Model {
|
||||
public static $_table = MP_NEWSLETTER_LINKS_TABLE;
|
||||
|
||||
static function getByHash($hash) {
|
||||
return parent::where('hash', $hash)
|
||||
->findOne();
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ class Segment extends Model {
|
||||
}
|
||||
|
||||
static function bulkTrash($orm) {
|
||||
return parent::bulkAction($orm, function($ids) {
|
||||
$count = parent::bulkAction($orm, function($ids) {
|
||||
parent::rawExecute(join(' ', array(
|
||||
'UPDATE `'.self::$_table.'`',
|
||||
'SET `deleted_at` = NOW()',
|
||||
@ -220,14 +220,18 @@ class Segment extends Model {
|
||||
'AND `type` = "default"'
|
||||
)), $ids);
|
||||
});
|
||||
|
||||
return array('count' => $count);
|
||||
}
|
||||
|
||||
static function bulkDelete($orm) {
|
||||
return parent::bulkAction($orm, function($ids) {
|
||||
$count = parent::bulkAction($orm, function($ids) {
|
||||
// delete segments (only default)
|
||||
Segment::whereIn('id', $ids)
|
||||
->where('type', 'default')
|
||||
->deleteMany();
|
||||
});
|
||||
|
||||
return array('count' => $count);
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,15 @@ class SendingQueue extends Model {
|
||||
return $subscribers;
|
||||
}
|
||||
|
||||
function getRenderedNewsletterBody() {
|
||||
return json_decode($this->newsletter_rendered_body, true);
|
||||
}
|
||||
|
||||
function isSubscriberProcessed($subscriber_id) {
|
||||
$subscribers = $this->getSubscribers();
|
||||
return in_array($subscriber_id, $subscribers['processed']);
|
||||
}
|
||||
|
||||
function asArray() {
|
||||
$model = parent::asArray();
|
||||
$model['subscribers'] = (is_serialized($this->subscribers))
|
||||
|
@ -50,6 +50,9 @@ class Setting extends Model {
|
||||
),
|
||||
'tracking' => array(
|
||||
'enabled' => true
|
||||
),
|
||||
'analytics' => array(
|
||||
'enabled' => false,
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -167,4 +170,4 @@ class Setting extends Model {
|
||||
$value = self::where('name', $value)->findOne();
|
||||
return ($value) ? $value->delete() : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,23 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsClicks extends Model {
|
||||
public static $_table = MP_STATISTICS_CLICKS_TABLE;
|
||||
|
||||
static function createOrUpdateClickCount($link_id, $subscriber_id, $newsletter_id, $queue_id) {
|
||||
$statistics = self::where('link_id', $link_id)
|
||||
->where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = self::create();
|
||||
$statistics->link_id = $link_id;
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->count = 1;
|
||||
} else {
|
||||
$statistics->count++;
|
||||
}
|
||||
return $statistics->save();
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,19 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsOpens extends Model {
|
||||
public static $_table = MP_STATISTICS_OPENS_TABLE;
|
||||
|
||||
static function getOrCreate($subscriber_id, $newsletter_id, $queue_id) {
|
||||
$statistics = self::where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = self::create();
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->save();
|
||||
}
|
||||
return $statistics;
|
||||
}
|
||||
}
|
||||
|