Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
cb3d49f200 | |||
c0da428c27 | |||
435cd9b777 | |||
bfde34eb8d | |||
a4c1b24c35 | |||
2cbd2d54f3 | |||
378f6d803a | |||
af4d29ebe6 | |||
599661e028 | |||
84294b7ee6 | |||
a3e6eb5bba | |||
67359980e9 | |||
f1b955d74a | |||
809be415c5 | |||
457a4d1bba | |||
1e16912763 | |||
e2c9971c99 | |||
c1d31ca400 | |||
a011c3aade | |||
e35e97cdbf | |||
49a59d35a1 | |||
9a46640c15 | |||
678a0b3835 | |||
0c008325c4 | |||
ad5441487b | |||
104620a40a | |||
c1a3ba67f5 | |||
c42bbf3dc4 | |||
7d34274fbf | |||
f930b3303b | |||
a25ea3ddf6 | |||
021349caee | |||
89f2958d23 | |||
8c8435766e | |||
40dd1bbb3b | |||
ba40437eb9 | |||
813db1ae33 | |||
9588397e4e | |||
ecf83ca419 | |||
9cc494f0fa | |||
dd4b7e4d1c | |||
738b2f6c17 | |||
33289342d3 | |||
a00f1efcfe | |||
b89897e6d4 | |||
c539837896 | |||
27edf5f71d | |||
32cc5644f9 | |||
8a664aa7f1 | |||
7e5e8a4282 | |||
70d5d609e2 | |||
19160c99e1 | |||
99b2a7457e | |||
945d7edc70 | |||
6a97badfed | |||
5ec8e4ed52 | |||
1569b5f80a | |||
e62ecc5036 | |||
b0150e184b |
Binary file not shown.
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 3.8 KiB |
@ -61,6 +61,10 @@ function(
|
||||
case 'date':
|
||||
field = (<FormFieldDate {...data} />);
|
||||
break;
|
||||
|
||||
case 'reactComponent':
|
||||
field = (<data.field.component {...data} />);
|
||||
break;
|
||||
}
|
||||
|
||||
if(inline === true) {
|
||||
@ -121,4 +125,4 @@ function(
|
||||
});
|
||||
|
||||
return FormField;
|
||||
});
|
||||
});
|
||||
|
@ -14,10 +14,12 @@ function(
|
||||
return {
|
||||
items: [],
|
||||
initialized: false
|
||||
}
|
||||
};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.loadCachedItems();
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadCachedItems();
|
||||
this.setupSelect2();
|
||||
},
|
||||
componentDidUpdate: function(prevProps, prevState) {
|
||||
@ -30,6 +32,9 @@ function(
|
||||
.trigger('change');
|
||||
}
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
jQuery('#'+this.refs.select.id).select2('destroy');
|
||||
},
|
||||
setupSelect2: function() {
|
||||
if(
|
||||
!this.props.field.multiple
|
||||
@ -67,11 +72,6 @@ function(
|
||||
|
||||
select2.on('change', this.handleChange);
|
||||
|
||||
select2.select2(
|
||||
'val',
|
||||
this.getSelectedValues()
|
||||
);
|
||||
|
||||
this.setState({ initialized: true });
|
||||
},
|
||||
getSelectedValues: function() {
|
||||
@ -161,4 +161,4 @@ function(
|
||||
});
|
||||
|
||||
return Selection;
|
||||
});
|
||||
});
|
||||
|
@ -30,4 +30,4 @@ function(
|
||||
});
|
||||
|
||||
return FormFieldText;
|
||||
});
|
||||
});
|
||||
|
@ -17,6 +17,11 @@ define(
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
params: {},
|
||||
};
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
loading: false,
|
||||
@ -24,6 +29,12 @@ define(
|
||||
item: {}
|
||||
};
|
||||
},
|
||||
getValues: function() {
|
||||
return this.props.item ? this.props.item : this.state.item;
|
||||
},
|
||||
getErrors: function() {
|
||||
return this.props.errors ? this.props.errors : this.state.errors;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.props.params.id !== undefined) {
|
||||
if(this.isMounted()) {
|
||||
@ -37,7 +48,9 @@ define(
|
||||
loading: false,
|
||||
item: {}
|
||||
});
|
||||
this.refs.form.reset();
|
||||
if (props.item === undefined) {
|
||||
this.refs.form.reset();
|
||||
}
|
||||
} else {
|
||||
this.loadItem(props.params.id);
|
||||
}
|
||||
@ -123,19 +136,23 @@ define(
|
||||
}.bind(this));
|
||||
},
|
||||
handleValueChange: function(e) {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
if (this.props.onChange) {
|
||||
return this.props.onChange(e);
|
||||
} else {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
|
||||
item[field] = e.target.value;
|
||||
item[field] = e.target.value;
|
||||
|
||||
this.setState({
|
||||
item: item
|
||||
});
|
||||
return true;
|
||||
this.setState({
|
||||
item: item
|
||||
});
|
||||
return true;
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
if(this.state.errors !== undefined) {
|
||||
var errors = this.state.errors.map(function(error, index) {
|
||||
if(this.getErrors() !== undefined) {
|
||||
var errors = this.getErrors().map(function(error, index) {
|
||||
return (
|
||||
<p key={ 'error-'+index } className="mailpoet_error">
|
||||
{ error }
|
||||
@ -146,14 +163,14 @@ define(
|
||||
|
||||
var formClasses = classNames(
|
||||
'mailpoet_form',
|
||||
{ 'mailpoet_form_loading': this.state.loading }
|
||||
{ 'mailpoet_form_loading': this.state.loading || this.props.loading }
|
||||
);
|
||||
|
||||
var fields = this.props.fields.map(function(field, i) {
|
||||
return (
|
||||
<FormField
|
||||
field={ field }
|
||||
item={ this.state.item }
|
||||
item={ this.getValues() }
|
||||
onValueChange={ this.handleValueChange }
|
||||
key={ 'field-'+i } />
|
||||
);
|
||||
|
@ -6,8 +6,8 @@ import NewsletterTypes from 'newsletters/types.jsx'
|
||||
import NewsletterTemplates from 'newsletters/templates.jsx'
|
||||
import NewsletterSend from 'newsletters/send.jsx'
|
||||
import NewsletterStandard from 'newsletters/types/standard.jsx'
|
||||
import NewsletterWelcome from 'newsletters/types/welcome.jsx'
|
||||
import NewsletterNotification from 'newsletters/types/notification.jsx'
|
||||
import NewsletterWelcome from 'newsletters/types/welcome/welcome.jsx'
|
||||
import NewsletterNotification from 'newsletters/types/notification/notification.jsx'
|
||||
import createHashHistory from 'history/lib/createHashHistory'
|
||||
|
||||
let history = createHashHistory({ queryKey: false })
|
||||
|
@ -2,137 +2,109 @@ define(
|
||||
[
|
||||
'react',
|
||||
'react-router',
|
||||
'underscore',
|
||||
'mailpoet',
|
||||
'form/form.jsx',
|
||||
'form/fields/selection.jsx',
|
||||
'newsletters/send/standard.jsx',
|
||||
'newsletters/send/notification.jsx',
|
||||
'newsletters/send/welcome.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
Router,
|
||||
_,
|
||||
MailPoet,
|
||||
Form,
|
||||
Selection,
|
||||
StandardNewsletterFields,
|
||||
NotificationNewsletterFields,
|
||||
WelcomeNewsletterFields,
|
||||
Breadcrumb
|
||||
) {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
tip: MailPoet.I18n.t('subjectLineTip'),
|
||||
type: 'text',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'segments',
|
||||
label: MailPoet.I18n.t('segments'),
|
||||
tip: MailPoet.I18n.t('segmentsTip'),
|
||||
type: 'selection',
|
||||
placeholder: MailPoet.I18n.t('selectSegmentPlaceholder'),
|
||||
id: "mailpoet_segments",
|
||||
endpoint: "segments",
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender',
|
||||
label: MailPoet.I18n.t('sender'),
|
||||
tip: MailPoet.I18n.t('senderTip'),
|
||||
fields: [
|
||||
{
|
||||
name: 'sender_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'reply-to',
|
||||
label: MailPoet.I18n.t('replyTo'),
|
||||
tip: MailPoet.I18n.t('replyToTip'),
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'reply_to_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||
},
|
||||
{
|
||||
name: 'reply_to_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
var messages = {
|
||||
onUpdate: function() {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('newsletterUpdated'));
|
||||
},
|
||||
onCreate: function() {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('newsletterAdded'));
|
||||
}
|
||||
};
|
||||
|
||||
var NewsletterSend = React.createClass({
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
componentDidMount: function() {
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
getInitialState: function() {
|
||||
return {
|
||||
fields: [],
|
||||
item: {},
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
getFieldsByNewsletter: function(newsletter) {
|
||||
switch(newsletter.type) {
|
||||
case 'notification': return NotificationNewsletterFields;
|
||||
case 'welcome': return WelcomeNewsletterFields;
|
||||
default: return StandardNewsletterFields;
|
||||
}
|
||||
},
|
||||
isAutomatedNewsletter: function() {
|
||||
return this.state.item.type !== 'standard';
|
||||
},
|
||||
isValid: function() {
|
||||
return jQuery('#mailpoet_newsletter').parsley().isValid();
|
||||
},
|
||||
handleSend: function() {
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
this.loadItem(this.props.params.id);
|
||||
}
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
},
|
||||
componentWillReceiveProps: function(props) {
|
||||
this.loadItem(props.params.id);
|
||||
},
|
||||
loadItem: function(id) {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'get',
|
||||
data: id
|
||||
}).done((response) => {
|
||||
if(response === false) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {},
|
||||
}, function() {
|
||||
this.history.pushState(null, '/new');
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: response,
|
||||
fields: this.getFieldsByNewsletter(response),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSend: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if(!this.isValid()) {
|
||||
jQuery('#mailpoet_newsletter').parsley().validate();
|
||||
} else {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id,
|
||||
segments: jQuery('#mailpoet_segments').val(),
|
||||
sender: {
|
||||
'name': jQuery('#mailpoet_newsletter [name="sender_name"]').val(),
|
||||
'address': jQuery('#mailpoet_newsletter [name="sender_address"]').val()
|
||||
},
|
||||
reply_to: {
|
||||
'name': jQuery('#mailpoet_newsletter [name="reply_to_name"]').val(),
|
||||
'address': jQuery('#mailpoet_newsletter [name="reply_to_address"]').val()
|
||||
}
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: this.state.item,
|
||||
}).then((response) => {
|
||||
if (response.result === true) {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: _.extend({}, this.state.item, {
|
||||
newsletter_id: this.props.params.id,
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
}).done(function(response) {
|
||||
}).done((response) => {
|
||||
this.setState({ loading: false });
|
||||
if(response.result === true) {
|
||||
this.history.pushState(null, '/');
|
||||
MailPoet.Notice.success(
|
||||
@ -147,10 +119,44 @@ define(
|
||||
);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleSave: function(e) {
|
||||
e.preventDefault();
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: this.state.item,
|
||||
}).done((response) => {
|
||||
this.setState({ loading: false });
|
||||
|
||||
if(response.result === true) {
|
||||
this.history.pushState(null, '/');
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
} else {
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(response.errors);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
handleFormChange: function(e) {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
|
||||
item[field] = e.target.value;
|
||||
|
||||
this.setState({
|
||||
item: item
|
||||
});
|
||||
return true;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
@ -160,18 +166,21 @@ define(
|
||||
|
||||
<Form
|
||||
id="mailpoet_newsletter"
|
||||
endpoint="newsletters"
|
||||
fields={ fields }
|
||||
params={ this.props.params }
|
||||
messages={ messages }
|
||||
isValid={ this.isValid }
|
||||
fields={ this.state.fields }
|
||||
item={ this.state.item }
|
||||
loading={ this.state.loading }
|
||||
onChange={this.handleFormChange}
|
||||
onSubmit={this.handleSave}
|
||||
>
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="button"
|
||||
onClick={ this.handleSend }
|
||||
value={MailPoet.I18n.t('send')} />
|
||||
value={
|
||||
this.isAutomatedNewsletter()
|
||||
? MailPoet.I18n.t('activate')
|
||||
: MailPoet.I18n.t('send')} />
|
||||
|
||||
<input
|
||||
className="button button-secondary"
|
||||
|
104
assets/js/src/newsletters/send/notification.jsx
Normal file
104
assets/js/src/newsletters/send/notification.jsx
Normal file
@ -0,0 +1,104 @@
|
||||
define(
|
||||
[
|
||||
'mailpoet',
|
||||
'newsletters/types/notification/scheduling.jsx'
|
||||
],
|
||||
function(
|
||||
MailPoet,
|
||||
Scheduling
|
||||
) {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
tip: MailPoet.I18n.t('postNotificationSubjectLineTip'),
|
||||
type: 'text',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'options',
|
||||
label: MailPoet.I18n.t('selectPeriodicity'),
|
||||
type: 'reactComponent',
|
||||
component: Scheduling,
|
||||
},
|
||||
{
|
||||
name: 'segments',
|
||||
label: MailPoet.I18n.t('segments'),
|
||||
tip: MailPoet.I18n.t('segmentsTip'),
|
||||
type: 'selection',
|
||||
placeholder: MailPoet.I18n.t('selectSegmentPlaceholder'),
|
||||
id: "mailpoet_segments",
|
||||
endpoint: "segments",
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
getLabel: function(segment) {
|
||||
var name = segment.name;
|
||||
if (segment.subscribers > 0) {
|
||||
name += ' (%$1s)'.replace('%$1s', segment.subscribers);
|
||||
}
|
||||
return name;
|
||||
},
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender',
|
||||
label: MailPoet.I18n.t('sender'),
|
||||
tip: MailPoet.I18n.t('senderTip'),
|
||||
fields: [
|
||||
{
|
||||
name: 'sender_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'reply-to',
|
||||
label: MailPoet.I18n.t('replyTo'),
|
||||
tip: MailPoet.I18n.t('replyToTip'),
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'reply_to_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||
},
|
||||
{
|
||||
name: 'reply_to_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return fields;
|
||||
}
|
||||
);
|
96
assets/js/src/newsletters/send/standard.jsx
Normal file
96
assets/js/src/newsletters/send/standard.jsx
Normal file
@ -0,0 +1,96 @@
|
||||
define(
|
||||
[
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
MailPoet
|
||||
) {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
tip: MailPoet.I18n.t('subjectLineTip'),
|
||||
type: 'text',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'segments',
|
||||
label: MailPoet.I18n.t('segments'),
|
||||
tip: MailPoet.I18n.t('segmentsTip'),
|
||||
type: 'selection',
|
||||
placeholder: MailPoet.I18n.t('selectSegmentPlaceholder'),
|
||||
id: "mailpoet_segments",
|
||||
endpoint: "segments",
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
getLabel: function(segment) {
|
||||
var name = segment.name;
|
||||
if (segment.subscribers > 0) {
|
||||
name += ' (%$1s)'.replace('%$1s', segment.subscribers);
|
||||
}
|
||||
return name;
|
||||
},
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender',
|
||||
label: MailPoet.I18n.t('sender'),
|
||||
tip: MailPoet.I18n.t('senderTip'),
|
||||
fields: [
|
||||
{
|
||||
name: 'sender_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'reply-to',
|
||||
label: MailPoet.I18n.t('replyTo'),
|
||||
tip: MailPoet.I18n.t('replyToTip'),
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'reply_to_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||
},
|
||||
{
|
||||
name: 'reply_to_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return fields;
|
||||
}
|
||||
);
|
81
assets/js/src/newsletters/send/welcome.jsx
Normal file
81
assets/js/src/newsletters/send/welcome.jsx
Normal file
@ -0,0 +1,81 @@
|
||||
define(
|
||||
[
|
||||
'mailpoet',
|
||||
'newsletters/types/welcome/scheduling.jsx'
|
||||
],
|
||||
function(
|
||||
MailPoet,
|
||||
Scheduling
|
||||
) {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
tip: MailPoet.I18n.t('subjectLineTip'),
|
||||
type: 'text',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'options',
|
||||
label: MailPoet.I18n.t('sendWelcomeEmailWhen'),
|
||||
type: 'reactComponent',
|
||||
component: Scheduling,
|
||||
},
|
||||
{
|
||||
name: 'sender',
|
||||
label: MailPoet.I18n.t('sender'),
|
||||
tip: MailPoet.I18n.t('senderTip'),
|
||||
fields: [
|
||||
{
|
||||
name: 'sender_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'sender_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'reply-to',
|
||||
label: MailPoet.I18n.t('replyTo'),
|
||||
tip: MailPoet.I18n.t('replyToTip'),
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'reply_to_name',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||
},
|
||||
{
|
||||
name: 'reply_to_address',
|
||||
type: 'text',
|
||||
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
|
||||
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
return fields;
|
||||
}
|
||||
);
|
||||
|
@ -0,0 +1,96 @@
|
||||
define(
|
||||
[
|
||||
'underscore',
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'newsletters/types/notification/scheduling.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
_,
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Scheduling,
|
||||
Breadcrumb
|
||||
) {
|
||||
|
||||
var field = {
|
||||
name: 'options',
|
||||
label: 'Periodicity',
|
||||
type: 'reactComponent',
|
||||
component: Scheduling,
|
||||
};
|
||||
|
||||
var NewsletterNotification = React.createClass({
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
getInitialState: function() {
|
||||
return {
|
||||
options: {
|
||||
intervalType: 'daily',
|
||||
timeOfDay: 0,
|
||||
weekDay: 1,
|
||||
monthDay: 0,
|
||||
nthWeekDay: 1,
|
||||
}
|
||||
};
|
||||
},
|
||||
handleValueChange: function(event) {
|
||||
var state = this.state;
|
||||
state[event.target.name] = event.target.value;
|
||||
this.setState(state);
|
||||
},
|
||||
handleNext: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'create',
|
||||
data: _.extend({}, this.state, {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.history.pushState(null, `/template/${newsletterId}`);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>
|
||||
<Breadcrumb step="type" />
|
||||
|
||||
<h3>{MailPoet.I18n.t('selectPeriodicity')}</h3>
|
||||
|
||||
<Scheduling
|
||||
item={this.state}
|
||||
field={field}
|
||||
onValueChange={this.handleValueChange} />
|
||||
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="button"
|
||||
onClick={ this.handleNext }
|
||||
value={MailPoet.I18n.t('next')} />
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return NewsletterNotification;
|
||||
}
|
||||
);
|
@ -4,26 +4,18 @@ define(
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'form/form.jsx',
|
||||
'form/fields/select.jsx',
|
||||
'form/fields/selection.jsx',
|
||||
'form/fields/text.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
'form/fields/select.jsx'
|
||||
],
|
||||
function(
|
||||
_,
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form,
|
||||
Select,
|
||||
Selection,
|
||||
Text,
|
||||
Breadcrumb
|
||||
Select
|
||||
) {
|
||||
|
||||
var intervalField = {
|
||||
name: 'interval',
|
||||
name: 'intervalType',
|
||||
values: {
|
||||
'daily': MailPoet.I18n.t('daily'),
|
||||
'weekly': MailPoet.I18n.t('weekly'),
|
||||
@ -96,137 +88,113 @@ define(
|
||||
},
|
||||
};
|
||||
|
||||
var NewsletterWelcome = React.createClass({
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
getInitialState: function() {
|
||||
return {
|
||||
intervalType: 'immediate', // 'immediate'|'daily'|'weekly'|'monthly'
|
||||
timeOfDay: 0,
|
||||
weekDay: 1,
|
||||
monthDay: 0,
|
||||
nthWeekDay: 1,
|
||||
};
|
||||
var NotificationScheduling = React.createClass({
|
||||
_getCurrentValue: function() {
|
||||
return this.props.item[this.props.field.name] || {};
|
||||
},
|
||||
handleValueChange: function(name, value) {
|
||||
var oldValue = this._getCurrentValue(),
|
||||
newValue = {};
|
||||
newValue[name] = value;
|
||||
|
||||
return this.props.onValueChange({
|
||||
target: {
|
||||
name: this.props.field.name,
|
||||
value: _.extend({}, oldValue, newValue)
|
||||
}
|
||||
});
|
||||
},
|
||||
handleIntervalChange: function(event) {
|
||||
this.setState({
|
||||
intervalType: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'intervalType',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleTimeOfDayChange: function(event) {
|
||||
this.setState({
|
||||
timeOfDay: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'timeOfDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleWeekDayChange: function(event) {
|
||||
this.setState({
|
||||
weekDay: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'weekDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleMonthDayChange: function(event) {
|
||||
this.setState({
|
||||
monthDay: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'monthDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleNthWeekDayChange: function(event) {
|
||||
this.setState({
|
||||
nthWeekDay: event.target.value,
|
||||
});
|
||||
},
|
||||
handleNext: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'create',
|
||||
data: {
|
||||
type: 'notification',
|
||||
options: this.state,
|
||||
},
|
||||
}).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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.history.pushState(null, `/template/${newsletterId}`);
|
||||
return this.handleValueChange(
|
||||
'nthWeekDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
var timeOfDaySelection,
|
||||
var value = this._getCurrentValue(),
|
||||
timeOfDaySelection,
|
||||
weekDaySelection,
|
||||
monthDaySelection,
|
||||
nthWeekDaySelection;
|
||||
|
||||
if (this.state.intervalType !== 'immediately') {
|
||||
|
||||
if (value.intervalType !== 'immediately') {
|
||||
timeOfDaySelection = (
|
||||
<Select
|
||||
field={timeOfDayField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleTimeOfDayChange} />
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.intervalType === 'weekly'
|
||||
|| this.state.intervalType === 'nthWeekDay') {
|
||||
if (value.intervalType === 'weekly'
|
||||
|| value.intervalType === 'nthWeekDay') {
|
||||
weekDaySelection = (
|
||||
<Select
|
||||
field={weekDayField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleWeekDayChange} />
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.intervalType === 'monthly') {
|
||||
if (value.intervalType === 'monthly') {
|
||||
monthDaySelection = (
|
||||
<Select
|
||||
field={monthDayField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleMonthDayChange} />
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.intervalType === 'nthWeekDay') {
|
||||
if (value.intervalType === 'nthWeekDay') {
|
||||
nthWeekDaySelection = (
|
||||
<Select
|
||||
field={nthWeekDayField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleNthWeekDayChange} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>
|
||||
<Breadcrumb step="type" />
|
||||
|
||||
<Select
|
||||
field={intervalField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleIntervalChange} />
|
||||
|
||||
{nthWeekDaySelection}
|
||||
{monthDaySelection}
|
||||
{weekDaySelection}
|
||||
{timeOfDaySelection}
|
||||
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="button"
|
||||
onClick={ this.handleNext }
|
||||
value={MailPoet.I18n.t('next')} />
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return NewsletterWelcome;
|
||||
return NotificationScheduling;
|
||||
}
|
||||
);
|
@ -3,16 +3,12 @@ define(
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'form/form.jsx',
|
||||
'form/fields/selection.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form,
|
||||
Selection,
|
||||
Breadcrumb
|
||||
) {
|
||||
|
||||
@ -32,7 +28,6 @@ define(
|
||||
type: 'standard',
|
||||
}
|
||||
}).done(function(response) {
|
||||
console.log(response);
|
||||
if(response.result && response.newsletter.id) {
|
||||
this.showTemplateSelection(response.newsletter.id);
|
||||
} else {
|
||||
|
@ -4,9 +4,7 @@ define(
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'form/form.jsx',
|
||||
'form/fields/select.jsx',
|
||||
'form/fields/selection.jsx',
|
||||
'form/fields/text.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
@ -15,9 +13,7 @@ define(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form,
|
||||
Select,
|
||||
Selection,
|
||||
Text,
|
||||
Breadcrumb
|
||||
) {
|
||||
@ -36,7 +32,11 @@ define(
|
||||
var availableSegmentValues = _.object(_.map(
|
||||
availableSegments,
|
||||
function(segment) {
|
||||
return [segment.id, segment.name];
|
||||
var name = segment.name;
|
||||
if (segment.subscribers > 0) {
|
||||
name += ' (%$1d)'.replace('%$1d', segment.subscribers);
|
||||
}
|
||||
return [segment.id, name];
|
||||
}
|
||||
));
|
||||
var segmentField = {
|
||||
@ -64,43 +64,51 @@ define(
|
||||
}
|
||||
};
|
||||
|
||||
var NewsletterWelcome = React.createClass({
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
getInitialState: function() {
|
||||
return {
|
||||
event: 'segment',
|
||||
segment: 1,
|
||||
role: 'subscriber',
|
||||
afterTimeNumber: 1,
|
||||
afterTimeType: 'immediate',
|
||||
};
|
||||
var WelcomeScheduling = React.createClass({
|
||||
_getCurrentValue: function() {
|
||||
return this.props.item[this.props.field.name] || {};
|
||||
},
|
||||
handleValueChange: function(name, value) {
|
||||
var oldValue = this._getCurrentValue(),
|
||||
newValue = {};
|
||||
newValue[name] = value;
|
||||
|
||||
return this.props.onValueChange({
|
||||
target: {
|
||||
name: this.props.field.name,
|
||||
value: _.extend({}, oldValue, newValue)
|
||||
}
|
||||
});
|
||||
},
|
||||
handleEventChange: function(event) {
|
||||
this.setState({
|
||||
event: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'event',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleSegmentChange: function(event) {
|
||||
this.setState({
|
||||
segment: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'segment',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleRoleChange: function(event) {
|
||||
this.setState({
|
||||
role: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'role',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleAfterTimeNumberChange: function(event) {
|
||||
this.setState({
|
||||
afterTimeNumber: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'afterTimeNumber',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleAfterTimeTypeChange: function(event) {
|
||||
this.setState({
|
||||
afterTimeType: event.target.value,
|
||||
});
|
||||
return this.handleValueChange(
|
||||
'afterTimeType',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleNext: function() {
|
||||
MailPoet.Ajax.post({
|
||||
@ -126,40 +134,38 @@ define(
|
||||
this.history.pushState(null, `/template/${newsletterId}`);
|
||||
},
|
||||
render: function() {
|
||||
var roleSegmentSelection, timeNumber;
|
||||
if (this.state.event === 'user') {
|
||||
var value = this._getCurrentValue(),
|
||||
roleSegmentSelection, timeNumber;
|
||||
|
||||
if (value.event === 'user') {
|
||||
roleSegmentSelection = (
|
||||
<Select
|
||||
field={roleField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleRoleChange} />
|
||||
);
|
||||
} else {
|
||||
roleSegmentSelection = (
|
||||
<Select
|
||||
field={segmentField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleSegmentChange} />
|
||||
);
|
||||
}
|
||||
if (this.state.afterTimeType !== 'immediate') {
|
||||
if (value.afterTimeType !== 'immediate') {
|
||||
timeNumber = (
|
||||
<Text
|
||||
field={afterTimeNumberField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleAfterTimeNumberChange} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('welcomeNewsletterTypeTitle')}</h1>
|
||||
<Breadcrumb step="type" />
|
||||
|
||||
<h3>{MailPoet.I18n.t('selectEventToSendWelcomeEmail')}</h3>
|
||||
|
||||
<Select
|
||||
field={events}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleEventChange} />
|
||||
|
||||
{roleSegmentSelection}
|
||||
@ -168,21 +174,14 @@ define(
|
||||
|
||||
<Select
|
||||
field={afterTimeTypeField}
|
||||
item={this.state}
|
||||
item={this._getCurrentValue()}
|
||||
onValueChange={this.handleAfterTimeTypeChange}/>
|
||||
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="button"
|
||||
onClick={ this.handleNext }
|
||||
value={MailPoet.I18n.t('next')} />
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return NewsletterWelcome;
|
||||
return WelcomeScheduling;
|
||||
}
|
||||
);
|
||||
|
96
assets/js/src/newsletters/types/welcome/welcome.jsx
Normal file
96
assets/js/src/newsletters/types/welcome/welcome.jsx
Normal file
@ -0,0 +1,96 @@
|
||||
define(
|
||||
[
|
||||
'underscore',
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'newsletters/types/welcome/scheduling.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
_,
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Scheduling,
|
||||
Breadcrumb
|
||||
) {
|
||||
|
||||
var field = {
|
||||
name: 'options',
|
||||
label: 'Event',
|
||||
type: 'reactComponent',
|
||||
component: Scheduling,
|
||||
};
|
||||
|
||||
var NewsletterWelcome = React.createClass({
|
||||
mixins: [
|
||||
Router.History
|
||||
],
|
||||
getInitialState: function() {
|
||||
return {
|
||||
options: {
|
||||
event: 'segment',
|
||||
segment: 1,
|
||||
role: 'subscriber',
|
||||
afterTimeNumber: 1,
|
||||
afterTimeType: 'immediate',
|
||||
}
|
||||
};
|
||||
},
|
||||
handleValueChange: function(event) {
|
||||
var state = this.state;
|
||||
state[event.target.name] = event.target.value;
|
||||
this.setState(state);
|
||||
},
|
||||
handleNext: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'create',
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
this.history.pushState(null, `/template/${newsletterId}`);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('welcomeNewsletterTypeTitle')}</h1>
|
||||
<Breadcrumb step="type" />
|
||||
|
||||
<h3>{MailPoet.I18n.t('selectEventToSendWelcomeEmail')}</h3>
|
||||
|
||||
<Scheduling
|
||||
item={this.state}
|
||||
field={field}
|
||||
onValueChange={this.handleValueChange} />
|
||||
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="button"
|
||||
onClick={ this.handleNext }
|
||||
value={MailPoet.I18n.t('next')} />
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return NewsletterWelcome;
|
||||
}
|
||||
);
|
@ -34,13 +34,16 @@ define(
|
||||
// show sending methods
|
||||
jQuery('.mailpoet_sending_methods').fadeIn();
|
||||
} else {
|
||||
// hide DKIM option when using MailPoet's API
|
||||
jQuery('#mailpoet_mta_dkim')[
|
||||
// toggle SPF/DKIM (hidden if the sending method is MailPoet)
|
||||
jQuery('#mailpoet_mta_spf')[
|
||||
(group === 'mailpoet')
|
||||
? 'hide'
|
||||
: 'show'
|
||||
]();
|
||||
|
||||
// (HIDDEN FOR BETA)
|
||||
jQuery('#mailpoet_mta_dkim').hide();
|
||||
|
||||
// hide sending methods
|
||||
jQuery('.mailpoet_sending_methods').hide();
|
||||
|
||||
|
@ -278,33 +278,18 @@ const SubscriberList = React.createClass({
|
||||
|
||||
if (subscriber.subscriptions.length > 0) {
|
||||
let subscribed_segments = [];
|
||||
let unsubscribed_segments = [];
|
||||
|
||||
subscriber.subscriptions.map((subscription) => {
|
||||
const segment = this.getSegmentFromId(subscription.segment_id);
|
||||
if(segment === false) return;
|
||||
if (subscription.status === 'subscribed') {
|
||||
subscribed_segments.push(segment.name);
|
||||
} else if (subscription.status === 'unsubscribed') {
|
||||
unsubscribed_segments.push(segment.name);
|
||||
}
|
||||
});
|
||||
segments = (
|
||||
<span>
|
||||
<span className="mailpoet_segments_subscribed">
|
||||
{ subscribed_segments.join(', ') }
|
||||
{
|
||||
(
|
||||
subscribed_segments.length > 0
|
||||
&& unsubscribed_segments.length > 0
|
||||
) ? ' / ' : ''
|
||||
}
|
||||
</span>
|
||||
<span
|
||||
className="mailpoet_segments_unsubscribed"
|
||||
title={MailPoet.I18n.t('listsToWhichSubscriberWasSubscribed')}
|
||||
>
|
||||
{ unsubscribed_segments.join(', ') }
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
@ -13,6 +13,7 @@ class Hooks {
|
||||
$this->setupWPUsers();
|
||||
$this->setupImageSize();
|
||||
$this->setupListing();
|
||||
$this->setupManageSubscription();
|
||||
}
|
||||
|
||||
function setupSubscribe() {
|
||||
@ -139,6 +140,18 @@ class Hooks {
|
||||
);
|
||||
}
|
||||
|
||||
function setupManageSubscription() {
|
||||
// handle subscription form submission
|
||||
add_action(
|
||||
'admin_post_mailpoet_subscription_update',
|
||||
'\MailPoet\Subscription\Manage::onSave'
|
||||
);
|
||||
add_action(
|
||||
'admin_post_nopriv_mailpoet_subscription_update',
|
||||
'\MailPoet\Subscription\Manage::onSave'
|
||||
);
|
||||
}
|
||||
|
||||
function setScreenOption($status, $option, $value) {
|
||||
if(preg_match('/^mailpoet_(.*)_per_page$/', $option)) {
|
||||
return $value;
|
||||
|
@ -39,7 +39,6 @@ class Initializer {
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupImages();
|
||||
$this->setupPublicAPI();
|
||||
$this->runQueueSupervisor();
|
||||
} catch(\Exception $e) {
|
||||
// if anything goes wrong during init
|
||||
@ -50,8 +49,8 @@ class Initializer {
|
||||
|
||||
function onInit() {
|
||||
$this->setupRouter();
|
||||
$this->setupPublicAPI();
|
||||
$this->setupPages();
|
||||
$this->runQueueSupervisor();
|
||||
}
|
||||
|
||||
function setupDB() {
|
||||
@ -69,35 +68,39 @@ class Initializer {
|
||||
'SET TIME_ZONE = "' . Env::$db_timezone_offset. '"'
|
||||
));
|
||||
|
||||
$subscribers = Env::$db_prefix . 'subscribers';
|
||||
$settings = Env::$db_prefix . 'settings';
|
||||
$newsletters = Env::$db_prefix . 'newsletters';
|
||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||
$segments = Env::$db_prefix . 'segments';
|
||||
$forms = Env::$db_prefix . 'forms';
|
||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||
$custom_fields = Env::$db_prefix . 'custom_fields';
|
||||
$subscribers = Env::$db_prefix . 'subscribers';
|
||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||
$sending_queues = Env::$db_prefix . 'sending_queues';
|
||||
$newsletters = Env::$db_prefix . 'newsletters';
|
||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||
$newsletter_option_fields = Env::$db_prefix . 'newsletter_option_fields';
|
||||
$newsletter_option = Env::$db_prefix . 'newsletter_option';
|
||||
$sending_queues = Env::$db_prefix . 'sending_queues';
|
||||
$newsletter_statistics = Env::$db_prefix . 'newsletter_statistics';
|
||||
$newsletter_links = Env::$db_prefix . 'newsletter_links';
|
||||
$statistics_newsletters = Env::$db_prefix . 'statistics_newsletters';
|
||||
$statistics_clicks = Env::$db_prefix . 'statistics_clicks';
|
||||
|
||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||
define('MP_SETTINGS_TABLE', $settings);
|
||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||
define('MP_SEGMENTS_TABLE', $segments);
|
||||
define('MP_FORMS_TABLE', $forms);
|
||||
define('MP_CUSTOM_FIELDS_TABLE', $custom_fields);
|
||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
||||
define('MP_NEWSLETTER_SEGMENT_TABLE', $newsletter_segment);
|
||||
define('MP_CUSTOM_FIELDS_TABLE', $custom_fields);
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||
define('MP_NEWSLETTER_LINKS_TABLE', $newsletter_links);
|
||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||
define('MP_STATISTICS_NEWSLETTERS_TABLE', $statistics_newsletters);
|
||||
define('MP_STATISTICS_CLICKS_TABLE', $statistics_clicks);
|
||||
}
|
||||
|
||||
function runMigrator() {
|
||||
@ -153,9 +156,6 @@ class Initializer {
|
||||
function setupPages() {
|
||||
$pages = new \MailPoet\Settings\Pages();
|
||||
$pages->init();
|
||||
|
||||
$subscription_pages = new \MailPoet\Subscription\Pages();
|
||||
$subscription_pages->init();
|
||||
}
|
||||
|
||||
function setupShortcodes() {
|
||||
@ -185,4 +185,4 @@ class Initializer {
|
||||
function setupImages() {
|
||||
add_image_size('mailpoet_newsletter_max', 1320);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ class Menu {
|
||||
|
||||
$data = array();
|
||||
|
||||
$data['segments'] = Segment::findArray();
|
||||
$data['segments'] = Segment::getSegmentsWithSubscriberCount();
|
||||
$data['settings'] = Setting::getAll();
|
||||
$data['roles'] = $wp_roles->get_names();
|
||||
$data['roles']['mailpoet_all'] = __('In any WordPress role');
|
||||
|
@ -10,20 +10,22 @@ class Migrator {
|
||||
$this->prefix = Env::$db_prefix;
|
||||
$this->charset = Env::$db_charset;
|
||||
$this->models = array(
|
||||
'subscribers',
|
||||
'segments',
|
||||
'settings',
|
||||
'custom_fields',
|
||||
'sending_queues',
|
||||
'subscribers',
|
||||
'subscriber_segment',
|
||||
'subscriber_custom_field',
|
||||
'newsletters',
|
||||
'newsletter_templates',
|
||||
'segments',
|
||||
'subscriber_segment',
|
||||
'newsletter_segment',
|
||||
'custom_fields',
|
||||
'subscriber_custom_field',
|
||||
'newsletter_option_fields',
|
||||
'newsletter_option',
|
||||
'sending_queues',
|
||||
'newsletter_statistics',
|
||||
'forms'
|
||||
'newsletter_segment',
|
||||
'newsletter_links',
|
||||
'forms',
|
||||
'statistics_newsletters',
|
||||
'statistics_clicks',
|
||||
);
|
||||
}
|
||||
|
||||
@ -49,6 +51,72 @@ class Migrator {
|
||||
array_map($drop_table, $this->models);
|
||||
}
|
||||
|
||||
function segments() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(90) NOT NULL,',
|
||||
'type varchar(90) NOT NULL DEFAULT "default",',
|
||||
'description varchar(250) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function settings() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(20) NOT NULL,',
|
||||
'value longtext,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function custom_fields() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(90) NOT NULL,',
|
||||
'type varchar(90) NOT NULL,',
|
||||
'params longtext NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function sending_queues() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'newsletter_rendered_body longtext,',
|
||||
'newsletter_rendered_body_hash varchar(250) NULL DEFAULT NULL,',
|
||||
'newsletter_rendered_subject varchar(250) NULL DEFAULT NULL,',
|
||||
'subscribers longtext,',
|
||||
'status varchar(12) NULL DEFAULT NULL,',
|
||||
'priority mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_total mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_processed mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_to_process mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_failed mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'scheduled_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'processed_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'PRIMARY KEY (id)',
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function subscribers() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
@ -66,15 +134,30 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function settings() {
|
||||
function subscriber_segment() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(20) NOT NULL,',
|
||||
'value longtext,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'segment_id mediumint(9) NOT NULL,',
|
||||
'status varchar(12) NOT NULL DEFAULT "subscribed",',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
'UNIQUE KEY subscriber_segment (subscriber_id,segment_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function subscriber_custom_field() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'custom_field_id mediumint(9) NOT NULL,',
|
||||
'value varchar(255) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY subscriber_id_custom_field_id (subscriber_id,custom_field_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
@ -113,76 +196,6 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function segments() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(90) NOT NULL,',
|
||||
'type varchar(90) NOT NULL DEFAULT "default",',
|
||||
'description varchar(250) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function subscriber_segment() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'segment_id mediumint(9) NOT NULL,',
|
||||
'status varchar(12) NOT NULL DEFAULT "subscribed",',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY subscriber_segment (subscriber_id,segment_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function newsletter_segment() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'segment_id mediumint(9) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY newsletter_segment (newsletter_id,segment_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function custom_fields() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'name varchar(90) NOT NULL,',
|
||||
'type varchar(90) NOT NULL,',
|
||||
'params longtext NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY name (name)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function subscriber_custom_field() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'custom_field_id mediumint(9) NOT NULL,',
|
||||
'value varchar(255) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY subscriber_id_custom_field_id (subscriber_id,custom_field_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function newsletter_option_fields() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
@ -210,37 +223,28 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function sending_queues() {
|
||||
function newsletter_segment() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'newsletter_rendered_body longtext,',
|
||||
'newsletter_rendered_body_hash varchar(250) NULL DEFAULT NULL,',
|
||||
'newsletter_rendered_subject varchar(250) NULL DEFAULT NULL,',
|
||||
'subscribers longtext,',
|
||||
'status varchar(12) NULL DEFAULT NULL,',
|
||||
'priority mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_total mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_processed mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_to_process mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'count_failed mediumint(9) NOT NULL DEFAULT 0,',
|
||||
'scheduled_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'processed_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'segment_id mediumint(9) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'PRIMARY KEY (id)',
|
||||
'PRIMARY KEY (id),',
|
||||
'UNIQUE KEY newsletter_segment (newsletter_id,segment_id)'
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function newsletter_statistics() {
|
||||
function newsletter_links() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'queue_id mediumint(9) NOT NULL,',
|
||||
'sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'url varchar(255) NOT NULL,',
|
||||
'hash varchar(20) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id)',
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
@ -261,6 +265,34 @@ class Migrator {
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function statistics_newsletters() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'queue_id mediumint(9) NOT NULL,',
|
||||
'sent_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id)',
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
function statistics_clicks() {
|
||||
$attributes = array(
|
||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||
'newsletter_id mediumint(9) NOT NULL,',
|
||||
'subscriber_id mediumint(9) NOT NULL,',
|
||||
'queue_id mediumint(9) NOT NULL,',
|
||||
'link_id mediumint(9) NOT NULL,',
|
||||
'count mediumint(9) NOT NULL,',
|
||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||
'PRIMARY KEY (id)',
|
||||
);
|
||||
return $this->sqlify(__FUNCTION__, $attributes);
|
||||
}
|
||||
|
||||
private function sqlify($model, $attributes) {
|
||||
$table = $this->prefix . $model;
|
||||
|
||||
|
@ -74,9 +74,14 @@ class Populator {
|
||||
$mailpoet_page_id = (int)$page->ID;
|
||||
}
|
||||
|
||||
Setting::setValue('subscription.unsubscribe_page', $mailpoet_page_id);
|
||||
Setting::setValue('subscription.manage_page', $mailpoet_page_id);
|
||||
Setting::setValue('subscription.confirmation_page', $mailpoet_page_id);
|
||||
$subscription = Setting::getValue('subscription.pages', array());
|
||||
if(empty($subscription)) {
|
||||
Setting::setValue('subscription.pages', array(
|
||||
'unsubscribe' => $mailpoet_page_id,
|
||||
'manage' => $mailpoet_page_id,
|
||||
'confirmation' => $mailpoet_page_id
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function createDefaultSettings() {
|
||||
|
@ -2,44 +2,67 @@
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Cron\Daemon;
|
||||
use MailPoet\Subscription;
|
||||
use MailPoet\Statistics\Track\Clicks;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class PublicAPI {
|
||||
public $api;
|
||||
public $section;
|
||||
public $endpoint;
|
||||
public $action;
|
||||
public $request_payload;
|
||||
public $data;
|
||||
|
||||
function __construct() {
|
||||
# http://example.com/?mailpoet-api§ion=&action=&request_payload=
|
||||
$this->api = isset($_GET['mailpoet-api']) ? true : false;
|
||||
$this->section = isset($_GET['section']) ? $_GET['section'] : false;
|
||||
# http://example.com/?mailpoet&endpoint=&action=&data=
|
||||
$this->api = isset($_GET['mailpoet']) ? true : false;
|
||||
$this->endpoint = isset($_GET['endpoint']) ?
|
||||
Helpers::underscoreToCamelCase($_GET['endpoint']) :
|
||||
false;
|
||||
$this->action = isset($_GET['action']) ?
|
||||
Helpers::underscoreToCamelCase($_GET['action']) :
|
||||
false;
|
||||
$this->request_payload = isset($_GET['request_payload']) ?
|
||||
unserialize(base64_decode($_GET['request_payload'])) :
|
||||
$this->data = isset($_GET['data']) ?
|
||||
$_GET['data'] :
|
||||
false;
|
||||
}
|
||||
|
||||
function init() {
|
||||
if(!$this->api && !$this->section) return;
|
||||
$this->_checkAndCallMethod($this, $this->section, $terminate = true);
|
||||
if(!$this->api && !$this->endpoint) return;
|
||||
$this->_checkAndCallMethod($this, $this->endpoint, $terminate_request = true);
|
||||
}
|
||||
|
||||
function queue() {
|
||||
try {
|
||||
$queue = new Daemon($this->request_payload);
|
||||
$queue = new Daemon($this->_decodeData());
|
||||
$this->_checkAndCallMethod($queue, $this->action);
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
private function _checkAndCallMethod($class, $method, $terminate = false) {
|
||||
function subscription() {
|
||||
try {
|
||||
$subscription = new Subscription\Pages($this->action, $this->_decodeData());
|
||||
$this->_checkAndCallMethod($subscription, $this->action);
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
function track() {
|
||||
try {
|
||||
if($this->action === 'click') {
|
||||
$track_class = new Clicks($this->data);
|
||||
}
|
||||
if(!isset($track_class)) return;
|
||||
$track_class->track();
|
||||
} catch(\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
private function _checkAndCallMethod($class, $method, $terminate_request = false) {
|
||||
if(!method_exists($class, $method)) {
|
||||
if(!$terminate) return;
|
||||
if(!$terminate_request) return;
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
exit;
|
||||
}
|
||||
@ -50,4 +73,12 @@ class PublicAPI {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function _decodeData() {
|
||||
if($this->data !== false) {
|
||||
return unserialize(base64_decode($this->data));
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Newsletter;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Subscription;
|
||||
|
||||
class Shortcodes {
|
||||
function __construct() {
|
||||
|
@ -38,9 +38,9 @@ class CronHelper {
|
||||
}
|
||||
|
||||
static function accessDaemon($token, $timeout = self::daemon_request_timeout) {
|
||||
$payload = serialize(array('token' => $token));
|
||||
$url = '/?mailpoet-api§ion=queue&action=run&request_payload=' .
|
||||
base64_encode($payload);
|
||||
$data = serialize(array('token' => $token));
|
||||
$url = '/?mailpoet&endpoint=queue&action=run&data=' .
|
||||
base64_encode($data);
|
||||
$args = array(
|
||||
'timeout' => $timeout,
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||
|
@ -10,17 +10,18 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Daemon {
|
||||
public $daemon;
|
||||
public $request_payload;
|
||||
public $data;
|
||||
public $refreshed_token;
|
||||
const daemon_request_timeout = 5;
|
||||
private $timer;
|
||||
|
||||
function __construct($request_payload = array()) {
|
||||
function __construct($data) {
|
||||
if(empty($data)) $this->abortWithError(__('Invalid or missing cron data.'));
|
||||
set_time_limit(0);
|
||||
ignore_user_abort();
|
||||
$this->daemon = CronHelper::getDaemon();
|
||||
$this->token = CronHelper::createToken();
|
||||
$this->request_payload = $request_payload;
|
||||
$this->data = $data;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
@ -29,8 +30,8 @@ class Daemon {
|
||||
if(!$daemon) {
|
||||
$this->abortWithError(__('Daemon does not exist.'));
|
||||
}
|
||||
if(!isset($this->request_payload['token']) ||
|
||||
$this->request_payload['token'] !== $daemon['token']
|
||||
if(!isset($this->data['token']) ||
|
||||
$this->data['token'] !== $daemon['token']
|
||||
) {
|
||||
$this->abortWithError(__('Invalid or missing token.'));
|
||||
}
|
||||
@ -49,7 +50,7 @@ class Daemon {
|
||||
// after each execution, re-read daemon data in case it was deleted or
|
||||
// its status has changed
|
||||
$daemon = CronHelper::getDaemon();
|
||||
if(!$daemon || $daemon['token'] !== $this->request_payload['token']) {
|
||||
if(!$daemon || $daemon['token'] !== $this->data['token']) {
|
||||
exit;
|
||||
}
|
||||
$daemon['counter']++;
|
||||
|
@ -69,11 +69,7 @@ class Scheduler {
|
||||
->findArray();
|
||||
$subscribers = Helpers::arrayColumn($subscribers, 'subscriber_id');
|
||||
$subscribers = array_unique($subscribers);
|
||||
if(!count($subscribers)) {
|
||||
$queue->delete();
|
||||
return;
|
||||
}
|
||||
if(!$this->checkIfNewsletterChanged($newsletter)) {
|
||||
if(!count($subscribers) || !$this->checkIfNewsletterChanged($newsletter)) {
|
||||
$queue->scheduled_at = $next_run_date;
|
||||
$queue->save();
|
||||
return;
|
||||
@ -141,7 +137,7 @@ class Scheduler {
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$new_hash = md5($rendered_newsletter['html']);
|
||||
$old_hash = $last_run_queue->newsletter_rendered_body_hash;
|
||||
return $new_hash !== $old_hash;
|
||||
return $new_hash === $old_hash;
|
||||
}
|
||||
|
||||
private function getQueueNextRunDate($schedule) {
|
||||
|
@ -4,9 +4,11 @@ namespace MailPoet\Cron\Workers;
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterStatistics;
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\StatisticsNewsletters;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Links\Links;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
use MailPoet\Util\Helpers;
|
||||
@ -17,6 +19,7 @@ class SendingQueue {
|
||||
public $mta_config;
|
||||
public $mta_log;
|
||||
public $processing_method;
|
||||
public $divider = '***MailPoet***';
|
||||
private $timer;
|
||||
const batch_size = 50;
|
||||
|
||||
@ -38,7 +41,7 @@ class SendingQueue {
|
||||
continue;
|
||||
}
|
||||
$newsletter = $newsletter->asArray();
|
||||
$newsletter['body'] = $this->getNewsletterBodyAndSubject($queue, $newsletter);
|
||||
$newsletter['body'] = $this->getOrRenderNewsletterBody($queue, $newsletter);
|
||||
$queue->subscribers = (object) unserialize($queue->subscribers);
|
||||
if(!isset($queue->subscribers->processed)) {
|
||||
$queue->subscribers->processed = array();
|
||||
@ -67,11 +70,25 @@ class SendingQueue {
|
||||
}
|
||||
}
|
||||
|
||||
function getNewsletterBodyAndSubject($queue, $newsletter) {
|
||||
function getOrRenderNewsletterBody($queue, $newsletter) {
|
||||
// check if newsletter has been rendered, in which case return its contents
|
||||
// or render & and for future use
|
||||
// or render and save for future reuse
|
||||
if($queue->newsletter_rendered_body === null) {
|
||||
$newsletter['body'] = $this->renderNewsletter($newsletter);
|
||||
// render newsletter
|
||||
$rendered_newsletter = $this->renderNewsletter($newsletter);
|
||||
if((boolean) Setting::getValue('tracking.enabled')) {
|
||||
// extract and replace links
|
||||
$processed_newsletter = $this->processLinks(
|
||||
$this->joinObject($rendered_newsletter),
|
||||
$newsletter['id'],
|
||||
$queue->id
|
||||
);
|
||||
list($newsletter['body']['html'], $newsletter['body']['text']) =
|
||||
$this->splitObject($processed_newsletter);
|
||||
}
|
||||
else {
|
||||
$newsletter['body'] = $rendered_newsletter;
|
||||
}
|
||||
$queue->newsletter_rendered_body = json_encode($newsletter['body']);
|
||||
$queue->newsletter_rendered_body_hash = md5($newsletter['body']['text']);
|
||||
$queue->save();
|
||||
@ -84,7 +101,7 @@ class SendingQueue {
|
||||
function processBulkSubscribers($mailer, $newsletter, $subscribers, $queue) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
$processed_newsletters[] =
|
||||
$this->processNewsletter($newsletter, $subscriber);
|
||||
$this->processNewsletter($newsletter, $subscriber, $queue);
|
||||
$transformed_subscribers[] =
|
||||
$mailer->transformSubscriber($subscriber);
|
||||
}
|
||||
@ -125,8 +142,8 @@ class SendingQueue {
|
||||
function processIndividualSubscriber($mailer, $newsletter, $subscribers, $queue) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
$this->checkSendingLimit();
|
||||
$processed_newsletter = $this->processNewsletter($newsletter, $subscriber);
|
||||
if (!$queue->newsletter_rendered_subject) {
|
||||
$processed_newsletter = $this->processNewsletter($newsletter, $subscriber, $queue);
|
||||
if(!$queue->newsletter_rendered_subject) {
|
||||
$queue->newsletter_rendered_subject = $processed_newsletter['subject'];
|
||||
}
|
||||
$transformed_subscriber = $mailer->transformSubscriber($subscriber);
|
||||
@ -154,7 +171,7 @@ class SendingQueue {
|
||||
}
|
||||
|
||||
function updateNewsletterStatistics($data) {
|
||||
return NewsletterStatistics::createMultiple($data);
|
||||
return StatisticsNewsletters::createMultiple($data);
|
||||
}
|
||||
|
||||
function renderNewsletter($newsletter) {
|
||||
@ -162,20 +179,61 @@ class SendingQueue {
|
||||
return $renderer->render();
|
||||
}
|
||||
|
||||
function processNewsletter($newsletter, $subscriber = false) {
|
||||
$divider = '***MailPoet***';
|
||||
$data_for_shortcodes =
|
||||
array_merge(array($newsletter['subject']), $newsletter['body']);
|
||||
$body = implode($divider, $data_for_shortcodes);
|
||||
function processLinks($text, $newsletter_id, $queue_id) {
|
||||
$links = new Links();
|
||||
list($text, $processed_links) = $links->replace($text);
|
||||
foreach($processed_links as $link) {
|
||||
// save extracted and processed links
|
||||
$newsletter_link = NewsletterLink::create();
|
||||
$newsletter_link->newsletter_id = $newsletter_id;
|
||||
$newsletter_link->queue_id = $queue_id;
|
||||
$newsletter_link->hash = $link['hash'];
|
||||
$newsletter_link->url = $link['url'];
|
||||
$newsletter_link->save();
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
function processNewsletter($newsletter, $subscriber = false, $queue) {
|
||||
$data_for_shortcodes = array(
|
||||
$newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
);
|
||||
$processed_newsletter = $this->replaceShortcodes(
|
||||
$newsletter,
|
||||
$subscriber,
|
||||
$this->joinObject($data_for_shortcodes)
|
||||
);
|
||||
if((boolean) Setting::getValue('tracking.enabled')) {
|
||||
$processed_newsletter = $this->replaceLinks(
|
||||
$newsletter['id'],
|
||||
$subscriber['id'],
|
||||
$queue->id,
|
||||
$processed_newsletter
|
||||
);
|
||||
}
|
||||
list($newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
) = $this->splitObject($processed_newsletter);
|
||||
return $newsletter;
|
||||
}
|
||||
|
||||
function replaceLinks($newsletter_id, $subscriber_id, $queue_id, $body) {
|
||||
return str_replace(
|
||||
'[mailpoet_data]',
|
||||
sprintf('%s-%s-%s', $newsletter_id, $subscriber_id, $queue_id),
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
function replaceShortcodes($newsletter, $subscriber, $body) {
|
||||
$shortcodes = new Shortcodes(
|
||||
$newsletter,
|
||||
$subscriber
|
||||
);
|
||||
list($newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
return $newsletter;
|
||||
return $shortcodes->replace($body);
|
||||
}
|
||||
|
||||
function sendNewsletter($mailer, $newsletter, $subscriber) {
|
||||
@ -284,4 +342,12 @@ class SendingQueue {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private function joinObject($object = array()) {
|
||||
return implode($this->divider, $object);
|
||||
}
|
||||
|
||||
private function splitObject($object = array()) {
|
||||
return explode($this->divider, $object);
|
||||
}
|
||||
}
|
12
lib/Models/NewsletterLink.php
Normal file
12
lib/Models/NewsletterLink.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterLink extends Model {
|
||||
public static $_table = MP_NEWSLETTER_LINKS_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ class Setting extends Model {
|
||||
const DEFAULT_SENDING_METHOD_GROUP = 'website';
|
||||
const DEFAULT_SENDING_METHOD = 'PHPMail';
|
||||
const DEFAULT_SENDING_FREQUENCY_EMAILS = 25;
|
||||
const DEFAULT_SENDING_FREQUENCY_INTERVAL = 15; // in minutes
|
||||
const DEFAULT_SENDING_FREQUENCY_INTERVAL = 5; // in minutes
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
12
lib/Models/StatisticsClicks.php
Normal file
12
lib/Models/StatisticsClicks.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class StatisticsClicks extends Model {
|
||||
public static $_table = MP_STATISTICS_CLICKS_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@ namespace MailPoet\Models;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class NewsletterStatistics extends Model {
|
||||
public static $_table = MP_NEWSLETTER_STATISTICS_TABLE;
|
||||
class StatisticsNewsletters extends Model {
|
||||
public static $_table = MP_STATISTICS_NEWSLETTERS_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
@ -12,7 +12,7 @@ class NewsletterStatistics extends Model {
|
||||
|
||||
static function createMultiple($data) {
|
||||
return self::rawExecute(
|
||||
'INSERT INTO `' . NewsletterStatistics::$_table . '` ' .
|
||||
'INSERT INTO `' . self::$_table . '` ' .
|
||||
'(newsletter_id, subscriber_id, queue_id) ' .
|
||||
'VALUES ' . rtrim(
|
||||
str_repeat('(?,?,?), ', count($data)/3),
|
@ -48,30 +48,6 @@ class Subscriber extends Model {
|
||||
return parent::delete();
|
||||
}
|
||||
|
||||
function addToSegments(array $segment_ids = array()) {
|
||||
$wp_users_segment = Segment::getWPUsers();
|
||||
|
||||
if($wp_users_segment !== false) {
|
||||
// delete all relations to segments except WP users
|
||||
SubscriberSegment::where('subscriber_id', $this->id)
|
||||
->whereNotEqual('segment_id', $wp_users_segment->id)
|
||||
->deleteMany();
|
||||
} else {
|
||||
// delete all relations to segments
|
||||
SubscriberSegment::where('subscriber_id', $this->id)->deleteMany();
|
||||
}
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
$segments = Segment::whereIn('id', $segment_ids)->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $this->id;
|
||||
$association->segment_id = $segment->id;
|
||||
$association->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendConfirmationEmail() {
|
||||
if($this->status === self::STATUS_UNCONFIRMED) {
|
||||
$signup_confirmation = Setting::getValue('signup_confirmation');
|
||||
@ -168,14 +144,18 @@ class Subscriber extends Model {
|
||||
$subscriber->setExpr('deleted_at', 'NULL');
|
||||
}
|
||||
|
||||
// auto subscribe when signup confirmation is disabled
|
||||
if($signup_confirmation_enabled === false) {
|
||||
$subscriber->set('status', self::STATUS_SUBSCRIBED);
|
||||
if($subscriber->status !== self::STATUS_SUBSCRIBED) {
|
||||
// auto subscribe when signup confirmation is disabled
|
||||
if($signup_confirmation_enabled === true) {
|
||||
$subscriber->set('status', self::STATUS_UNCONFIRMED);
|
||||
} else {
|
||||
$subscriber->set('status', self::STATUS_SUBSCRIBED);
|
||||
}
|
||||
}
|
||||
|
||||
if($subscriber->save()) {
|
||||
// link subscriber to segments
|
||||
$subscriber->addToSegments($segment_ids);
|
||||
SubscriberSegment::addSubscriptions($subscriber, $segment_ids);
|
||||
|
||||
// signup confirmation
|
||||
if($subscriber->status !== self::STATUS_SUBSCRIBED) {
|
||||
@ -409,8 +389,8 @@ class Subscriber extends Model {
|
||||
&&
|
||||
($new_status === self::STATUS_UNSUBSCRIBED)
|
||||
) {
|
||||
// make sure we unsubscribe the user from all lists
|
||||
SubscriberSegment::setSubscriptions($subscriber, array());
|
||||
// make sure we unsubscribe the user from all segments
|
||||
SubscriberSegment::removeSubscriptions($subscriber);
|
||||
} else {
|
||||
if($segment_ids !== false) {
|
||||
SubscriberSegment::setSubscriptions($subscriber, $segment_ids);
|
||||
|
@ -13,30 +13,58 @@ class SubscriberSegment extends Model {
|
||||
}
|
||||
|
||||
function subscriber() {
|
||||
return $this->has_one(__NAMESPACE__.'\Subscriber', 'id');
|
||||
return $this->has_one(__NAMESPACE__.'\Subscriber', 'id', 'subscriber_id');
|
||||
}
|
||||
|
||||
static function removeSubscriptions($subscriber, $segment_ids = array()) {
|
||||
if($subscriber->id > 0) {
|
||||
if(!empty($segment_ids)) {
|
||||
// subscribe to segments
|
||||
foreach($segment_ids as $segment_id) {
|
||||
if((int)$segment_id > 0) {
|
||||
self::createOrUpdate(array(
|
||||
'subscriber_id' => $subscriber->id,
|
||||
'segment_id' => $segment_id,
|
||||
'status' => Subscriber::STATUS_UNSUBSCRIBED
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// unsubscribe from all segments
|
||||
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
||||
->findResultSet()
|
||||
->set('status', Subscriber::STATUS_UNSUBSCRIBED)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function addSubscriptions($subscriber, $segment_ids = array()) {
|
||||
if($subscriber->id > 0) {
|
||||
if(!empty($segment_ids)) {
|
||||
// subscribe to segments
|
||||
foreach($segment_ids as $segment_id) {
|
||||
if((int)$segment_id > 0) {
|
||||
self::createOrUpdate(array(
|
||||
'subscriber_id' => $subscriber->id,
|
||||
'segment_id' => $segment_id,
|
||||
'status' => Subscriber::STATUS_SUBSCRIBED
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// subscribe to all segments
|
||||
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
||||
->findResultSet()
|
||||
->set('status', Subscriber::STATUS_SUBSCRIBED)
|
||||
->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function setSubscriptions($subscriber, $segment_ids = array()) {
|
||||
if($subscriber->id > 0) {
|
||||
// unsubscribe from current subscriptions
|
||||
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
||||
->findResultSet()
|
||||
->set('status', Subscriber::STATUS_UNSUBSCRIBED)
|
||||
->save();
|
||||
|
||||
// subscribe to segments
|
||||
foreach($segment_ids as $segment_id) {
|
||||
if((int)$segment_id > 0) {
|
||||
self::createOrUpdate(array(
|
||||
'subscriber_id' => $subscriber->id,
|
||||
'segment_id' => $segment_id,
|
||||
'status' => Subscriber::STATUS_SUBSCRIBED
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $subscriber;
|
||||
self::removeSubscriptions($subscriber);
|
||||
self::addSubscriptions($subscriber, $segment_ids);
|
||||
}
|
||||
|
||||
static function subscribed($orm) {
|
||||
|
67
lib/Newsletter/Links/Links.php
Normal file
67
lib/Newsletter/Links/Links.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Links;
|
||||
|
||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||
use MailPoet\Util\Security;
|
||||
|
||||
class Links {
|
||||
public $newsletter_id;
|
||||
public $queue_id;
|
||||
public $subscriber_id;
|
||||
|
||||
function __construct(
|
||||
$newsletter_id = false,
|
||||
$subscriber_id = false,
|
||||
$queue_id = false) {
|
||||
$this->newsletter_id = $newsletter_id;
|
||||
$this->queue_id = $queue_id;
|
||||
$this->subscriber_id = $subscriber_id;
|
||||
}
|
||||
|
||||
function extract($text) {
|
||||
// adopted from WP's wp_extract_urls() function & modified to work on hrefs
|
||||
# match href=' or href="
|
||||
$regex = '#(?:href.*?=.*?)(["\']?)('
|
||||
# match http://
|
||||
. '(?:([\w-]+:)?//?)'
|
||||
# match everything except for special characters # until .
|
||||
. '[^\s()<>]+'
|
||||
. '[.]'
|
||||
# conditionally match everything except for special characters after .
|
||||
. '(?:'
|
||||
. '\([\w\d]+\)|'
|
||||
. '(?:'
|
||||
. '[^`!()\[\]{};:\'".,<>«»“”‘’\s]|'
|
||||
. '(?:[:]\d+)?/?'
|
||||
. ')+'
|
||||
. ')'
|
||||
. ')\\1#';
|
||||
preg_match_all($regex, $text, $links);
|
||||
$shortcodes = new Shortcodes();;
|
||||
$shortcodes = $shortcodes->extract($text);
|
||||
return array_merge(
|
||||
array_unique($links[2]),
|
||||
$shortcodes
|
||||
);
|
||||
}
|
||||
|
||||
function replace($text, $links = false) {
|
||||
$links = ($links) ? $links : $this->extract($text);
|
||||
$processed_links = array();
|
||||
foreach($links as $link) {
|
||||
$hash = Security::generateRandomString(5);
|
||||
$processed_links[] = array(
|
||||
'hash' => $hash,
|
||||
'url' => $link
|
||||
);
|
||||
$encoded_link = sprintf(
|
||||
'%s/?mailpoet&endpoint=track&action=click&data=%s',
|
||||
home_url(),
|
||||
'[mailpoet_data]-'.$hash
|
||||
);
|
||||
$link_regex = '/' . preg_quote($link, '/') . '/';
|
||||
$text = preg_replace($link_regex, $encoded_link, $text);
|
||||
}
|
||||
return array($text, $processed_links);
|
||||
}
|
||||
}
|
@ -13,14 +13,14 @@ class Button {
|
||||
<div>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-spacing:0;mso-table-lspace:0;mso-table-rspace:0;">
|
||||
<tr>
|
||||
<td class="mailpoet_button-container" style="padding:8px 20px;text-align:' . $element['styles']['block']['textAlign'] . ';"><!--[if mso]>
|
||||
<td class="mailpoet_button-container" style="text-align:' . $element['styles']['block']['textAlign'] . ';"><!--[if mso]>
|
||||
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word"
|
||||
href="' . $element['url'] . '"
|
||||
style="height:' . $element['styles']['block']['lineHeight'] . ';
|
||||
width:' . $element['styles']['block']['width'] . ';
|
||||
v-text-anchor:middle;"
|
||||
arcsize="' . round($element['styles']['block']['borderRadius'] / $element['styles']['block']['lineHeight'] * 100) . '%"
|
||||
strokeweight="1px"
|
||||
strokeweight="' . $element['styles']['block']['borderWidth'] . '"
|
||||
strokecolor="' . $element['styles']['block']['borderColor'] . '"
|
||||
fillcolor="' . $element['styles']['block']['backgroundColor'] . '">
|
||||
<w:anchorlock/>
|
||||
|
@ -7,6 +7,9 @@ class Footer {
|
||||
static function render($element) {
|
||||
$element['text'] = preg_replace('/\n/', '<br /><br />', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p.*?>)/i', '', $element['text']);
|
||||
$line_height = sprintf(
|
||||
'%spx', StylesHelper::$line_height_multiplier * (int) $element['styles']['text']['fontSize']
|
||||
);
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($element['text']);
|
||||
if(isset($element['styles']['link'])) {
|
||||
@ -25,7 +28,7 @@ class Footer {
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_header_footer_padded mailpoet_footer" ' . $background_color . '
|
||||
style="line-height: ' . StylesHelper::$line_height . ';' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
style="line-height: ' . $line_height . ';' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
' . $DOM->html() . '
|
||||
</td>
|
||||
</tr>';
|
||||
|
@ -6,7 +6,10 @@ use MailPoet\Newsletter\Renderer\StylesHelper;
|
||||
class Header {
|
||||
static function render($element) {
|
||||
$element['text'] = preg_replace('/\n/', '<br /><br />', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p.*?>)/', '', $element['text']);
|
||||
$element['text'] = preg_replace('/(<\/?p.*?>)/i', '', $element['text']);
|
||||
$line_height = sprintf(
|
||||
'%spx', StylesHelper::$line_height_multiplier * (int) $element['styles']['text']['fontSize']
|
||||
);
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($element['text']);
|
||||
if(isset($element['styles']['link'])) {
|
||||
@ -25,8 +28,8 @@ class Header {
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_header_footer_padded mailpoet_header" ' . $background_color . '
|
||||
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
' . $DOM->html() . '
|
||||
style="line-height: ' . $line_height . ';' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||
' . $DOM->html() . '
|
||||
</td>
|
||||
</tr>';
|
||||
return $template;
|
||||
|
@ -11,7 +11,7 @@ class Image {
|
||||
$element = self::adjustImageDimensions($element, $column_count);
|
||||
$image_template = '
|
||||
<img style="max-width:' . $element['width'] . 'px;" src="' . $element['src'] . '"
|
||||
width="' . $element['width'] . '" height="' . $element['height'] . '" alt="' . $element['alt'] . '"/>
|
||||
width="' . $element['width'] . '" alt="' . $element['alt'] . '"/>
|
||||
';
|
||||
if(!empty($element['link'])) {
|
||||
$image_template = '<a href="' . $element['link'] . '">' . $image_template . '</a>';
|
||||
|
@ -20,7 +20,7 @@ class Renderer {
|
||||
}
|
||||
|
||||
function createElementFromBlockType($block, $column_count) {
|
||||
$block = StylesHelper::setTextAlign($block);
|
||||
$block = StylesHelper::applyTextAlignment($block);
|
||||
$block_class = __NAMESPACE__ . '\\' . ucfirst($block['type']);
|
||||
return (class_exists($block_class)) ? $block_class::render($block, $column_count) : '';
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class Text {
|
||||
$html = self::convertParagraphsToTables($html);
|
||||
$html = self::styleLists($html);
|
||||
$html = self::styleHeadings($html);
|
||||
$html = self::addLineBreakAfterTags($html);
|
||||
$html = self::removeLastLineBreak($html);
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_text mailpoet_padded_bottom mailpoet_padded_side" valign="top" style="word-break:break-word;word-wrap:break-word;">
|
||||
@ -56,6 +56,14 @@ class Text {
|
||||
</tr>
|
||||
</tbody>'
|
||||
);
|
||||
$blockquote->parent->insertChild(
|
||||
array(
|
||||
'tag_name' => 'br',
|
||||
'self_close' => true,
|
||||
'attributes' => array()
|
||||
),
|
||||
$blockquote->index() + 1
|
||||
);
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
@ -72,16 +80,23 @@ class Text {
|
||||
continue;
|
||||
}
|
||||
$style = $paragraph->style;
|
||||
if(!preg_match('/text-align/i', $style)) {
|
||||
$style = 'text-align: left;' . $style;
|
||||
}
|
||||
$contents = $paragraph->html();
|
||||
$paragraph->setTag('table');
|
||||
$paragraph->style = 'border-spacing:0;mso-table-lspace:0;mso-table-rspace:0;';
|
||||
$paragraph->width = '100%';
|
||||
$paragraph->cellpadding = 0;
|
||||
$next_element = $paragraph->getNextSibling();
|
||||
// unless this is the last element in column, add double line breaks
|
||||
$line_breaks = ($next_element && !$next_element->getInnerText()) ? '<br /><br />' : '';
|
||||
// if this element is followed by a list, add single line break
|
||||
$line_breaks = ($next_element && preg_match('/<li>/i', $next_element->getInnerText())) ? '<br />' : $line_breaks;
|
||||
$paragraph->html('
|
||||
<tr>
|
||||
<td class="mailpoet_paragraph" style="line-height:' . StylesHelper::$line_height . ';word-break:break-word;word-wrap:break-word;' . $style . '">
|
||||
' . $contents . '
|
||||
<br />
|
||||
<td class="mailpoet_paragraph" style="word-break:break-word;word-wrap:break-word;' . $style . '">
|
||||
' . $contents . $line_breaks . '
|
||||
</td>
|
||||
</tr>'
|
||||
);
|
||||
@ -96,11 +111,14 @@ class Text {
|
||||
if(!$lists->count()) return $html;
|
||||
foreach($lists as $list) {
|
||||
if($list->tag === 'li') {
|
||||
$list->setInnertext($list->text());
|
||||
$list->class = 'mailpoet_paragraph';
|
||||
} else {
|
||||
$list->class = 'mailpoet_paragraph';
|
||||
$list->style .= 'line-height:' . StylesHelper::$line_height . ';padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;';
|
||||
$list->style .= 'padding-top:0;padding-bottom:0;margin-top:10px;';
|
||||
}
|
||||
$list->style = StylesHelper::applyTextAlignment($list->style);
|
||||
$list->style .= 'margin-bottom:10px;';
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
@ -111,27 +129,13 @@ class Text {
|
||||
$headings = $DOM->query('h1, h2, h3, h4');
|
||||
if(!$headings->count()) return $html;
|
||||
foreach($headings as $heading) {
|
||||
$heading->style .= 'line-height:' . StylesHelper::$line_height . ';margin:0;font-style:normal;font-weight:normal;';
|
||||
$heading->style = StylesHelper::applyTextAlignment($heading->style);
|
||||
$heading->style .= 'padding:0;font-style:normal;font-weight:normal;';
|
||||
}
|
||||
return $DOM->__toString();
|
||||
}
|
||||
|
||||
static function addLineBreakAfterTags($html) {
|
||||
$DOM_parser = new \pQuery();
|
||||
$DOM = $DOM_parser->parseStr($html);
|
||||
$tags = $DOM->query('ul, ol, h1, h2, h3, h4, table.mailpoet_blockquote');
|
||||
if(!$tags->count()) return $html;
|
||||
foreach($tags as $tag) {
|
||||
$tag->parent->insertChild(
|
||||
array(
|
||||
'tag_name' => 'br',
|
||||
'self_close' => true,
|
||||
'attributes' => array()
|
||||
),
|
||||
$tag->index() + 1
|
||||
);
|
||||
}
|
||||
// remove last line break
|
||||
return preg_replace('/(^)?(<br.*?\/?>)+$/i', '', $DOM->__toString());
|
||||
static function removeLastLineBreak($html) {
|
||||
return preg_replace('/(^)?(<br.*?\/?>)+$/i', '', $html);
|
||||
}
|
||||
}
|
@ -62,25 +62,18 @@ class Renderer {
|
||||
$css = '';
|
||||
foreach($styles as $selector => $style) {
|
||||
switch($selector) {
|
||||
case 'text':
|
||||
$selector = 'td.mailpoet_paragraph, td.mailpoet_blockquote';
|
||||
break;
|
||||
case 'body':
|
||||
$selector = 'body, .mailpoet-wrapper';
|
||||
break;
|
||||
case 'link':
|
||||
$selector = '.mailpoet-wrapper a';
|
||||
break;
|
||||
case 'wrapper':
|
||||
$selector = '.mailpoet_content-wrapper';
|
||||
break;
|
||||
}
|
||||
if(isset($style['fontFamily'])) {
|
||||
$css .= StylesHelper::setFontFamily(
|
||||
$style['fontFamily'],
|
||||
$selector
|
||||
);
|
||||
unset($style['fontFamily']);
|
||||
case 'text':
|
||||
$selector = 'td.mailpoet_paragraph, td.mailpoet_blockquote, li.mailpoet_paragraph';
|
||||
break;
|
||||
case 'body':
|
||||
$selector = 'body, .mailpoet-wrapper';
|
||||
break;
|
||||
case 'link':
|
||||
$selector = '.mailpoet-wrapper a';
|
||||
break;
|
||||
case 'wrapper':
|
||||
$selector = '.mailpoet_content-wrapper';
|
||||
break;
|
||||
}
|
||||
$css .= StylesHelper::setStyle($style, $selector);
|
||||
}
|
||||
@ -88,7 +81,7 @@ class Renderer {
|
||||
}
|
||||
|
||||
function injectContentIntoTemplate($template, $data) {
|
||||
return preg_replace_callback('/{{\w+}}/', function ($matches) use (&$data) {
|
||||
return preg_replace_callback('/{{\w+}}/', function($matches) use (&$data) {
|
||||
return array_shift($data);
|
||||
}, $template);
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ class StylesHelper {
|
||||
'Trebuchet MS' => "'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif",
|
||||
'Verdana' => 'Verdana, Geneva, sans-serif'
|
||||
);
|
||||
static $line_height = 1.61803398875;
|
||||
static $line_height_multiplier = 1.6;
|
||||
static $heading_margin_multiplier = 0.3;
|
||||
static $padding_width = 20;
|
||||
|
||||
static function getBlockStyles($element, $ignore_specific_styles = false) {
|
||||
@ -52,38 +53,52 @@ class StylesHelper {
|
||||
$attribute;
|
||||
}
|
||||
|
||||
static function setFontFamily($font_family, $selector) {
|
||||
$font_family = (isset(self::$font[$font_family])) ?
|
||||
self::$font[$font_family] :
|
||||
self::$font['Arial'];
|
||||
$css = $selector . '{' . PHP_EOL;
|
||||
$css .= 'font-family:' . $font_family . ';' . PHP_EOL;
|
||||
$css .= '}' . PHP_EOL;
|
||||
return $css;
|
||||
}
|
||||
|
||||
static function setStyle($style, $selector) {
|
||||
$css = $selector . '{' . PHP_EOL;
|
||||
$style = self::applyHeadingMargin($style, $selector);
|
||||
$style = self::applyLineHeight($style, $selector);
|
||||
foreach($style as $attribute => $individual_style) {
|
||||
$individual_style = self::applyFontFamily($attribute, $individual_style);
|
||||
$css .= self::translateCSSAttribute($attribute) . ':' . $individual_style . ';' . PHP_EOL;
|
||||
}
|
||||
$css .= '}' . PHP_EOL;
|
||||
return $css;
|
||||
}
|
||||
|
||||
static function setTextAlign($block) {
|
||||
$alignments = array(
|
||||
'center',
|
||||
'right',
|
||||
'justify'
|
||||
);
|
||||
$text_alignment = isset($block['styles']['block']['textAlign']) ?
|
||||
strtolower($block['styles']['block']['textAlign']) :
|
||||
false;
|
||||
if(!$text_alignment || !in_array($text_alignment, $alignments)) {
|
||||
static function applyTextAlignment($block) {
|
||||
if(is_array($block)) {
|
||||
$text_alignment = isset($block['styles']['block']['textAlign']) ?
|
||||
strtolower($block['styles']['block']['textAlign']) :
|
||||
false;
|
||||
if(preg_match('/center|right|justify/i', $text_alignment)) {
|
||||
return $block;
|
||||
}
|
||||
$block['styles']['block']['textAlign'] = 'left';
|
||||
return $block;
|
||||
}
|
||||
$block['styles']['block']['textAlign'] = 'left';
|
||||
return $block;
|
||||
return (preg_match('/text-align.*?[center|justify|right]/i', $block)) ?
|
||||
$block :
|
||||
$block . 'text-align:left;';
|
||||
}
|
||||
|
||||
static function applyFontFamily($attribute, $style) {
|
||||
if($attribute !== 'fontFamily') return $style;
|
||||
return (isset(self::$font[$style])) ?
|
||||
self::$font[$style] :
|
||||
self::$font['Arial'];
|
||||
}
|
||||
|
||||
static function applyHeadingMargin($style, $selector) {
|
||||
if (!preg_match('/h[1-4]/i', $selector)) return $style;
|
||||
$font_size = (int) $style['fontSize'];
|
||||
$style['margin'] = sprintf('0 0 %spx 0', self::$heading_margin_multiplier * $font_size);
|
||||
return $style;
|
||||
}
|
||||
|
||||
static function applyLineHeight($style, $selector) {
|
||||
if (!preg_match('/mailpoet_paragraph|h[1-4]/i', $selector)) return $style;
|
||||
$font_size = (int) $style['fontSize'];
|
||||
$style['lineHeight'] = sprintf('%spx', self::$line_height_multiplier * $font_size);
|
||||
return $style;
|
||||
}
|
||||
}
|
@ -54,8 +54,8 @@
|
||||
}
|
||||
.mailpoet_button {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
padding: 5px 0 !important;
|
||||
box-sizing:border-box !important;
|
||||
}
|
||||
div, .mailpoet_cols-two, .mailpoet_cols-three {
|
||||
max-width: 100% !important;
|
||||
|
@ -43,7 +43,8 @@ class Scheduler {
|
||||
$option_field = NewsletterOptionField::where('name', 'schedule')
|
||||
->findOne()
|
||||
->asArray();
|
||||
$relation = NewsletterOption::where('option_field_id', $option_field['id'])
|
||||
$relation = NewsletterOption::where('newsletter_id', $newsletter_id)
|
||||
->where('option_field_id', $option_field['id'])
|
||||
->findOne();
|
||||
if(!$relation) {
|
||||
$relation = NewsletterOption::create();
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Newsletter\Shortcodes\Categories;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Subscription\Url as SubscriptionUrl;
|
||||
|
||||
class Subscription {
|
||||
@ -17,27 +18,41 @@ class Subscription {
|
||||
$action,
|
||||
$default_value = false,
|
||||
$newsletter = false,
|
||||
$subscriber = false
|
||||
$subscriber = false,
|
||||
$text = false,
|
||||
$shortcode
|
||||
) {
|
||||
switch($action) {
|
||||
case 'unsubscribe':
|
||||
return '<a target="_blank" href="'.
|
||||
esc_attr(SubscriptionUrl::getUnsubscribeUrl($subscriber))
|
||||
self::getShortcodeUrl(
|
||||
$shortcode,
|
||||
esc_attr(SubscriptionUrl::getUnsubscribeUrl($subscriber))
|
||||
)
|
||||
.'">'.__('Unsubscribe').'</a>';
|
||||
break;
|
||||
|
||||
case 'unsubscribe_url':
|
||||
return SubscriptionUrl::getUnsubscribeUrl($subscriber);
|
||||
return self::getShortcodeUrl(
|
||||
$shortcode,
|
||||
SubscriptionUrl::getUnsubscribeUrl($subscriber)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'manage':
|
||||
return '<a target="_blank" href="'.
|
||||
esc_attr(SubscriptionUrl::getManageUrl($subscriber))
|
||||
self::getShortcodeUrl(
|
||||
$shortcode,
|
||||
esc_attr(SubscriptionUrl::getManageUrl($subscriber))
|
||||
)
|
||||
.'">'.__('Manage subscription').'</a>';
|
||||
break;
|
||||
|
||||
case 'manage_url':
|
||||
return SubscriptionUrl::getManageUrl($subscriber);
|
||||
return self::getShortcodeUrl(
|
||||
$shortcode,
|
||||
SubscriptionUrl::getManageUrl($subscriber)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -45,4 +60,10 @@ class Subscription {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static function getShortcodeUrl($shortcode, $url) {
|
||||
return ((boolean) Setting::getValue('tracking.enabled')) ?
|
||||
$shortcode :
|
||||
$url;
|
||||
}
|
||||
}
|
@ -14,21 +14,27 @@ class Shortcodes {
|
||||
}
|
||||
|
||||
function extract($text) {
|
||||
preg_match_all('/\[(?:\w+):.*?\]/', $text, $shortcodes);
|
||||
preg_match_all('/\[(?:\w+):.*?\]/ism', $text, $shortcodes);
|
||||
return array_unique($shortcodes[0]);
|
||||
}
|
||||
|
||||
function match($shortcode) {
|
||||
preg_match(
|
||||
'/\[(?P<type>\w+):(?P<action>\w+)(?:.*?default:(?P<default>.*?))?\]/',
|
||||
$shortcode,
|
||||
$match
|
||||
);
|
||||
return $match;
|
||||
}
|
||||
|
||||
function process($shortcodes, $text) {
|
||||
$processed_shortcodes = array_map(
|
||||
function($shortcode) use($text) {
|
||||
preg_match(
|
||||
'/\[(?P<type>\w+):(?P<action>\w+)(?:.*?default:(?P<default>.*?))?\]/',
|
||||
$shortcode,
|
||||
$shortcode_details
|
||||
);
|
||||
$shortcode_class =
|
||||
__NAMESPACE__ . '\\Categories\\' . ucfirst($shortcode_details['type']);
|
||||
$shortcode_details = $this->match($shortcode);
|
||||
$shortcode_type = ucfirst($shortcode_details['type']);
|
||||
$shortcode_action = $shortcode_details['action'];
|
||||
$shortcode_class =
|
||||
__NAMESPACE__ . '\\Categories\\' . $shortcode_type;
|
||||
$shortcode_default_value = isset($shortcode_details['default'])
|
||||
? $shortcode_details['default'] : false;
|
||||
if(!class_exists($shortcode_class)) return false;
|
||||
@ -37,7 +43,8 @@ class Shortcodes {
|
||||
$shortcode_default_value,
|
||||
$this->newsletter,
|
||||
$this->subscriber,
|
||||
$text
|
||||
$text,
|
||||
$shortcode
|
||||
);
|
||||
}, $shortcodes);
|
||||
return $processed_shortcodes;
|
||||
|
@ -157,7 +157,7 @@ class Newsletters {
|
||||
if(empty($data['subscriber'])) {
|
||||
return array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please specify receiver information'))
|
||||
'errors' => array(__('Please specify receiver information.'))
|
||||
);
|
||||
}
|
||||
|
||||
@ -165,20 +165,17 @@ class Newsletters {
|
||||
|
||||
$renderer = new Renderer($newsletter);
|
||||
$rendered_newsletter = $renderer->render();
|
||||
$divider = '***MailPoet***';
|
||||
$data_for_shortcodes =
|
||||
array_merge(array($newsletter['subject']), $rendered_newsletter);
|
||||
$body = implode($divider, $data_for_shortcodes);
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$rendered_newsletter['html'],
|
||||
$newsletter
|
||||
);
|
||||
$processed_newsletter['html'] = $shortcodes->replace();
|
||||
$shortcodes = new \MailPoet\Newsletter\Shortcodes\Shortcodes(
|
||||
$rendered_newsletter['text'],
|
||||
$newsletter
|
||||
);
|
||||
$processed_newsletter['text'] = $shortcodes->replace();
|
||||
$newsletter['body'] = array(
|
||||
'html' => $processed_newsletter['html'],
|
||||
'text' => $processed_newsletter['text'],
|
||||
);
|
||||
list($newsletter['subject'],
|
||||
$newsletter['body']['html'],
|
||||
$newsletter['body']['text']
|
||||
) = explode($divider, $shortcodes->replace($body));
|
||||
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterOption;
|
||||
use MailPoet\Models\NewsletterOptionField;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
use MailPoet\Util\Helpers;
|
||||
use Cron\CronExpression as Cron;
|
||||
|
@ -18,23 +18,6 @@ class Hosts {
|
||||
'EU (Ireland)' => 'eu-west-1'
|
||||
)
|
||||
),
|
||||
'ElasticEmail' => array(
|
||||
'name' => 'ElasticEmail',
|
||||
'emails' => 100,
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'api_key'
|
||||
)
|
||||
),
|
||||
'MailGun' => array(
|
||||
'name' => 'MailGun',
|
||||
'emails' => 100,
|
||||
'interval' => 5,
|
||||
'fields' => array(
|
||||
'domain',
|
||||
'api_key'
|
||||
)
|
||||
),
|
||||
'SendGrid' => array(
|
||||
'name' => 'SendGrid',
|
||||
'emails' => 100,
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Settings;
|
||||
use \MailPoet\Subscription;
|
||||
|
||||
class Pages {
|
||||
function __construct() {
|
||||
@ -65,9 +66,11 @@ class Pages {
|
||||
return array(
|
||||
'id' => $page->ID,
|
||||
'title' => $page->post_title,
|
||||
'preview_url' => add_query_arg(array(
|
||||
'mailpoet_preview' => 1
|
||||
), get_permalink($page->ID))
|
||||
'url' => array(
|
||||
'unsubscribe' => Subscription\Url::getSubscriptionUrl($page, 'unsubscribe'),
|
||||
'manage' => Subscription\Url::getSubscriptionUrl($page, 'manage'),
|
||||
'confirm' => Subscription\Url::getSubscriptionUrl($page, 'confirm')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
66
lib/Statistics/Track/Clicks.php
Normal file
66
lib/Statistics/Track/Clicks.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace MailPoet\Statistics\Track;
|
||||
|
||||
use MailPoet\Models\NewsletterLink;
|
||||
use MailPoet\Models\StatisticsClicks;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Subscription\Url as SubscriptionUrl;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Clicks {
|
||||
public $url;
|
||||
|
||||
function __construct($url) {
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
function track($url = false) {
|
||||
$url = ($url) ? $url : $this->url;
|
||||
if(!preg_match('/\d+-\d+-\d+-[a-zA-Z0-9]/', $url)) $this->abort();
|
||||
list ($newsletter_id, $subscriber_id, $queue_id, $hash) = explode('-', $url);
|
||||
$subscriber = Subscriber::findOne($subscriber_id);
|
||||
$link = NewsletterLink::where('hash', $hash)
|
||||
->findOne();
|
||||
if(!$link || !$subscriber) $this->abort();
|
||||
$statistics = StatisticsClicks::where('link_id', $link->id)
|
||||
->where('subscriber_id', $subscriber_id)
|
||||
->where('newsletter_id', $newsletter_id)
|
||||
->where('queue_id', $queue_id)
|
||||
->findOne();
|
||||
if(!$statistics) {
|
||||
$statistics = StatisticsClicks::create();
|
||||
$statistics->newsletter_id = $newsletter_id;
|
||||
$statistics->link_id = $link->id;
|
||||
$statistics->subscriber_id = $subscriber_id;
|
||||
$statistics->queue_id = $queue_id;
|
||||
$statistics->count = 1;
|
||||
$statistics->save();
|
||||
} else {
|
||||
$statistics->count++;
|
||||
$statistics->save();
|
||||
}
|
||||
$url = (preg_match('/\[subscription:.*?\]/', $link->url)) ?
|
||||
$this->processSubscriptionUrl($link->url, $subscriber) :
|
||||
$link->url;
|
||||
header('Location: ' . $url, true, 302);
|
||||
}
|
||||
|
||||
function processSubscriptionUrl($url, $subscriber) {
|
||||
preg_match('/\[subscription:(.*?)\]/', $url, $match);
|
||||
$action = $match[1];
|
||||
if(preg_match('/unsubscribe/', $action)) {
|
||||
$url = SubscriptionUrl::getUnsubscribeUrl($subscriber);
|
||||
}
|
||||
if(preg_match('/manage/', $action)) {
|
||||
$url = SubscriptionUrl::getManageUrl($subscriber);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
private function abort() {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
exit;
|
||||
}
|
||||
}
|
32
lib/Subscription/Manage.php
Normal file
32
lib/Subscription/Manage.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Util\Url;
|
||||
|
||||
class Manage {
|
||||
|
||||
static function onSave() {
|
||||
$action = (isset($_POST['action']) ? $_POST['action'] : null);
|
||||
if($action !== 'mailpoet_subscription_update') {
|
||||
Url::redirectBack();
|
||||
}
|
||||
|
||||
$reserved_keywords = array('action', 'mailpoet_redirect');
|
||||
$subscriber_data = array_diff_key(
|
||||
$_POST,
|
||||
array_flip($reserved_keywords)
|
||||
);
|
||||
|
||||
if(isset($subscriber_data['email'])) {
|
||||
if($subscriber_data['email'] !== Pages::DEMO_EMAIL) {
|
||||
$subscriber = Subscriber::createOrUpdate($subscriber_data);
|
||||
$errors = $subscriber->getErrors();
|
||||
}
|
||||
}
|
||||
|
||||
// TBD: success/error messages (not present in MP2)
|
||||
Url::redirectBack();
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ namespace MailPoet\Subscription;
|
||||
|
||||
use \MailPoet\Router\Subscribers;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
use \MailPoet\Models\CustomField;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Segment;
|
||||
@ -13,51 +14,123 @@ use \MailPoet\Subscription;
|
||||
class Pages {
|
||||
const DEMO_EMAIL = 'demo@mailpoet.com';
|
||||
|
||||
function __construct() {
|
||||
private $action;
|
||||
private $data;
|
||||
private $subscriber;
|
||||
|
||||
function __construct($action, $data) {
|
||||
$this->action = $action;
|
||||
$this->data = $data;
|
||||
$this->subscriber = $this->getSubscriber();
|
||||
|
||||
// handle subscription pages title & content
|
||||
add_filter('wp_title', array($this,'setWindowTitle'), 10, 3);
|
||||
add_filter('document_title_parts', array($this,'setWindowTitleParts'), 10, 1);
|
||||
add_filter('the_title', array($this,'setPageTitle'), 10, 1);
|
||||
add_filter('the_content', array($this,'setPageContent'), 10, 1);
|
||||
|
||||
// manage subscription link shortcode
|
||||
// [mailpoet_manage text="Manage your subscription"]
|
||||
add_shortcode('mailpoet_manage', array($this, 'getManageLink'));
|
||||
}
|
||||
|
||||
function init() {
|
||||
$action = $this->getAction();
|
||||
if($action !== null) {
|
||||
add_filter('wp_title', array($this,'setWindowTitle'), 10, 3);
|
||||
add_filter('document_title_parts', array($this,'setWindowTitleParts'), 10, 1);
|
||||
add_filter('the_title', array($this,'setPageTitle'), 10, 1);
|
||||
add_filter('the_content', array($this,'setPageContent'), 10, 1);
|
||||
}
|
||||
add_action(
|
||||
'admin_post_mailpoet_subscriber_save',
|
||||
array($this, 'subscriberSave')
|
||||
);
|
||||
add_action(
|
||||
'admin_post_nopriv_mailpoet_subscriber_save',
|
||||
array($this, 'subscriberSave')
|
||||
private function isPreview() {
|
||||
return (
|
||||
array_key_exists('preview', $_GET)
|
||||
|| array_key_exists('preview', $this->data)
|
||||
);
|
||||
}
|
||||
|
||||
function subscriberSave() {
|
||||
$action = (isset($_POST['action']) ? $_POST['action'] : null);
|
||||
if($action !== 'mailpoet_subscriber_save') {
|
||||
Url::redirectBack();
|
||||
}
|
||||
function getSubscriber() {
|
||||
$token = (isset($this->data['token'])) ? $this->data['token'] : null;
|
||||
$email = (isset($this->data['email'])) ? $this->data['email'] : null;
|
||||
|
||||
$reserved_keywords = array('action', 'mailpoet_redirect');
|
||||
$subscriber_data = array_diff_key(
|
||||
$_POST,
|
||||
array_flip($reserved_keywords)
|
||||
);
|
||||
if(isset($subscriber_data['email'])) {
|
||||
if($subscriber_data['email'] !== self::DEMO_EMAIL) {
|
||||
$subscriber = Subscriber::createOrUpdate($subscriber_data);
|
||||
$errors = $subscriber->getErrors();
|
||||
if(Subscriber::generateToken($email) === $token) {
|
||||
$subscriber = Subscriber::findOne($email);
|
||||
if($subscriber !== false) {
|
||||
return $subscriber;
|
||||
}
|
||||
}
|
||||
// TBD: success/error messages (not present in MP2)
|
||||
|
||||
Url::redirectBack();
|
||||
return false;
|
||||
}
|
||||
|
||||
function isPreview() {
|
||||
return (array_key_exists('mailpoet_preview', $_GET));
|
||||
function confirm() {
|
||||
if($this->subscriber !== false) {
|
||||
if($this->subscriber->status !== Subscriber::STATUS_SUBSCRIBED) {
|
||||
$this->subscriber->status = Subscriber::STATUS_SUBSCRIBED;
|
||||
$this->subscriber->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function unsubscribe() {
|
||||
if($this->subscriber !== false) {
|
||||
if($this->subscriber->status !== Subscriber::STATUS_UNSUBSCRIBED) {
|
||||
$this->subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
|
||||
$this->subscriber->save();
|
||||
SubscriberSegment::removeSubscriptions($this->subscriber);
|
||||
}
|
||||
}
|
||||
}
|
||||
function setPageTitle($page_title = '') {
|
||||
global $post;
|
||||
|
||||
if($post->post_title !== __('MailPoet Page')) return $page_title;
|
||||
if(
|
||||
($this->isMailPoetPage($post->ID) === false)
|
||||
||
|
||||
($page_title !== single_post_title('', false))
|
||||
) {
|
||||
return $page_title;
|
||||
} else {
|
||||
switch($this->action) {
|
||||
case 'confirm':
|
||||
return $this->getConfirmTitle();
|
||||
break;
|
||||
|
||||
case 'manage':
|
||||
|
||||
return $this->getManageTitle();
|
||||
break;
|
||||
|
||||
case 'unsubscribe':
|
||||
return $this->getUnsubscribeTitle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $page_title;
|
||||
}
|
||||
|
||||
function setPageContent($page_content = '[mailpoet_page]') {
|
||||
global $post;
|
||||
|
||||
if(
|
||||
($this->isPreview() === false)
|
||||
&&
|
||||
($this->isMailPoetPage($post->ID) === false)
|
||||
) {
|
||||
return $page_content;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
|
||||
switch($this->action) {
|
||||
case 'confirm':
|
||||
$content = $this->getConfirmContent();
|
||||
break;
|
||||
case 'manage':
|
||||
$content = $this->getManageContent();
|
||||
break;
|
||||
case 'unsubscribe':
|
||||
$content = $this->getUnsubscribeContent();
|
||||
break;
|
||||
}
|
||||
|
||||
if(strpos($page_content, '[mailpoet_page]') !== false) {
|
||||
return str_replace('[mailpoet_page]', $content, $page_content);
|
||||
} else {
|
||||
return $page_content.$content;
|
||||
}
|
||||
}
|
||||
|
||||
function setWindowTitle($title, $separator, $separator_location = 'right') {
|
||||
@ -80,93 +153,24 @@ class Pages {
|
||||
|
||||
function isMailPoetPage($page_id = null) {
|
||||
$mailpoet_page_ids = array_unique(array_values(
|
||||
Setting::getValue('subscription', array())
|
||||
Setting::getValue('subscription.pages', array())
|
||||
));
|
||||
|
||||
return (in_array($page_id, $mailpoet_page_ids));
|
||||
}
|
||||
|
||||
function setPageTitle($page_title = '') {
|
||||
global $post;
|
||||
|
||||
if($post->post_title !== __('MailPoet Page')) return $page_title;
|
||||
|
||||
if(
|
||||
($this->isMailPoetPage($post->ID) === false)
|
||||
||
|
||||
($page_title !== single_post_title('', false))
|
||||
) {
|
||||
return $page_title;
|
||||
} else {
|
||||
$subscriber = $this->getSubscriber();
|
||||
switch($this->getAction()) {
|
||||
case 'confirm':
|
||||
return $this->getConfirmTitle($subscriber);
|
||||
break;
|
||||
|
||||
case 'manage':
|
||||
return $this->getManageTitle($subscriber);
|
||||
break;
|
||||
|
||||
case 'unsubscribe':
|
||||
if($subscriber !== false) {
|
||||
if($subscriber->status !== Subscriber::STATUS_UNSUBSCRIBED) {
|
||||
$subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
|
||||
$subscriber->save();
|
||||
}
|
||||
}
|
||||
return $this->getUnsubscribeTitle($subscriber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $page_title;
|
||||
}
|
||||
|
||||
function setPageContent($page_content = '[mailpoet_page]') {
|
||||
global $post;
|
||||
|
||||
if(
|
||||
($this->isPreview() === false)
|
||||
&&
|
||||
($this->isMailPoetPage($post->ID) === false)
|
||||
) {
|
||||
return $page_content;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
$subscriber = $this->getSubscriber();
|
||||
|
||||
switch($this->getAction()) {
|
||||
case 'confirm':
|
||||
$content = $this->getConfirmContent($subscriber);
|
||||
break;
|
||||
case 'manage':
|
||||
$content = $this->getManageContent($subscriber);
|
||||
break;
|
||||
case 'unsubscribe':
|
||||
$content = $this->getUnsubscribeContent($subscriber);
|
||||
break;
|
||||
}
|
||||
return str_replace('[mailpoet_page]', $content, $page_content);
|
||||
}
|
||||
|
||||
private function getConfirmTitle($subscriber) {
|
||||
private function getConfirmTitle() {
|
||||
if($this->isPreview()) {
|
||||
$title = sprintf(
|
||||
__("You've subscribed to: %s"),
|
||||
'demo 1, demo 2'
|
||||
);
|
||||
} else if($subscriber === false) {
|
||||
} else if($this->subscriber === false) {
|
||||
$title = __('Your confirmation link expired, please subscribe again.');
|
||||
} else {
|
||||
if($subscriber->status !== Subscriber::STATUS_SUBSCRIBED) {
|
||||
$subscriber->status = Subscriber::STATUS_SUBSCRIBED;
|
||||
$subscriber->save();
|
||||
}
|
||||
|
||||
$segment_names = array_map(function($segment) {
|
||||
return $segment->name;
|
||||
}, $subscriber->segments()->findMany());
|
||||
}, $this->subscriber->segments()->findMany());
|
||||
|
||||
if(empty($segment_names)) {
|
||||
$title = __("You've subscribed!");
|
||||
@ -180,41 +184,35 @@ class Pages {
|
||||
return $title;
|
||||
}
|
||||
|
||||
private function getManageTitle($subscriber) {
|
||||
if($this->isPreview()) {
|
||||
return sprintf(
|
||||
__('Edit your subscriber profile: %s'),
|
||||
self::DEMO_EMAIL
|
||||
);
|
||||
} else if($subscriber !== false) {
|
||||
return sprintf(
|
||||
__('Edit your subscriber profile: %s'),
|
||||
$subscriber->email
|
||||
);
|
||||
private function getManageTitle() {
|
||||
if($this->isPreview() || $this->subscriber !== false) {
|
||||
return __("Manage your subscription");
|
||||
}
|
||||
}
|
||||
|
||||
private function getUnsubscribeTitle($subscriber) {
|
||||
if($this->isPreview() || $subscriber !== false) {
|
||||
return __("You've unsubscribed!");
|
||||
private function getUnsubscribeTitle() {
|
||||
if($this->isPreview() || $this->subscriber !== false) {
|
||||
return __("You've successfully unsubscribed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getConfirmContent($subscriber) {
|
||||
if($this->isPreview() || $subscriber !== false) {
|
||||
private function getConfirmContent() {
|
||||
if($this->isPreview() || $this->subscriber !== false) {
|
||||
return __("Yup, we've added you to our list. You'll hear from us shortly.");
|
||||
}
|
||||
}
|
||||
|
||||
private function getManageContent($subscriber) {
|
||||
private function getManageContent() {
|
||||
if($this->isPreview()) {
|
||||
$subscriber = Subscriber::create();
|
||||
$subscriber->hydrate(array(
|
||||
'email' => self::DEMO_EMAIL
|
||||
'email' => self::DEMO_EMAIL,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe'
|
||||
));
|
||||
} else if($subscriber !== false) {
|
||||
$subscriber = $subscriber
|
||||
} else if($this->subscriber !== false) {
|
||||
$subscriber = $this->subscriber
|
||||
->withCustomFields()
|
||||
->withSubscriptions();
|
||||
} else {
|
||||
@ -238,8 +236,8 @@ class Pages {
|
||||
->findMany();
|
||||
}
|
||||
$subscribed_segment_ids = array();
|
||||
if(!empty($subscriber->subscriptions)) {
|
||||
foreach ($subscriber->subscriptions as $subscription) {
|
||||
if(!empty($this->subscriber->subscriptions)) {
|
||||
foreach ($this->subscriber->subscriptions as $subscription) {
|
||||
if($subscription['status'] === Subscriber::STATUS_SUBSCRIBED) {
|
||||
$subscribed_segment_ids[] = $subscription['segment_id'];
|
||||
}
|
||||
@ -255,16 +253,6 @@ class Pages {
|
||||
}, $segments);
|
||||
|
||||
$fields = array(
|
||||
array(
|
||||
'id' => 'email',
|
||||
'type' => 'text',
|
||||
'params' => array(
|
||||
'label' => __('Email'),
|
||||
'required' => true,
|
||||
'value' => $subscriber->email,
|
||||
'readonly' => true
|
||||
)
|
||||
),
|
||||
array(
|
||||
'id' => 'first_name',
|
||||
'type' => 'text',
|
||||
@ -333,53 +321,54 @@ class Pages {
|
||||
$form_html = '<form method="POST" '.
|
||||
'action="'.admin_url('admin-post.php').'" '.
|
||||
'novalidate>';
|
||||
$form_html .= '<input type="hidden" name="action" '.
|
||||
'value="mailpoet_subscriber_save" />';
|
||||
$form_html .= '<input type="hidden" name="action"'.
|
||||
' value="mailpoet_subscription_update" />';
|
||||
$form_html .= '<input type="hidden" name="segments" value="" />';
|
||||
$form_html .= '<input type="hidden" name="mailpoet_redirect" '.
|
||||
'value="'.Url::getCurrentUrl().'" />';
|
||||
$form_html .= '<input type="hidden" name="email" value="'.$subscriber->email.'" />';
|
||||
|
||||
$form_html .= '<p class="mailpoet_paragraph">';
|
||||
$form_html .= '<label>Email *<br /><strong>'.$subscriber->email.'</strong></label>';
|
||||
$form_html .= '<br /><span style="font-size:85%;">';
|
||||
if($subscriber->wp_user_id !== null) {
|
||||
$form_html .= str_replace(
|
||||
array('[link]', '[/link]'),
|
||||
array('<a href="'.wp_login_url().'" target="_blank">', '</a>'),
|
||||
__('[link]Log in to your account[/link] to update your email.')
|
||||
);
|
||||
} else {
|
||||
$form_html .= __('Need to change your email address? Unsubscribe here and simply sign up again.');
|
||||
}
|
||||
$form_html .= '</span>';
|
||||
$form_html .= '</p>';
|
||||
|
||||
// subscription form
|
||||
$form_html .= \MailPoet\Form\Renderer::renderBlocks($form);
|
||||
$form_html .= '</form>';
|
||||
return $form_html;
|
||||
}
|
||||
|
||||
private function getUnsubscribeContent($subscriber) {
|
||||
private function getUnsubscribeContent() {
|
||||
$content = '';
|
||||
if($this->isPreview() || $subscriber !== false) {
|
||||
$content = '<p>'.__("Great, you'll never hear from us again!").'</p>';
|
||||
if($subscriber !== false) {
|
||||
$content .= '<p><strong>'.
|
||||
str_replace(
|
||||
array('[link]', '[/link]'),
|
||||
array('<a href="'.Subscription\Url::getConfirmationUrl($subscriber).'">', '</a>'),
|
||||
__('You made a mistake? [link]Undo unsubscribe.[/link]')
|
||||
).
|
||||
'</strong></p>';
|
||||
}
|
||||
if($this->isPreview() || $this->subscriber !== false) {
|
||||
$content .= '<p>'.__('You made a mistake?').' <strong>';
|
||||
$content .= '[mailpoet_manage]';
|
||||
$content .= '</strong></p>';
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function getSubscriber() {
|
||||
$token = (isset($_GET['mailpoet_token']))
|
||||
? $_GET['mailpoet_token']
|
||||
: null;
|
||||
$email = (isset($_GET['mailpoet_email']))
|
||||
? $_GET['mailpoet_email']
|
||||
: null;
|
||||
function getManageLink($params) {
|
||||
// get label or display default label
|
||||
$text = (
|
||||
isset($params['text'])
|
||||
? $params['text']
|
||||
: __('Manage your subscription')
|
||||
);
|
||||
|
||||
if(Subscriber::generateToken($email) === $token) {
|
||||
$subscriber = Subscriber::findOne($email);
|
||||
if($subscriber !== false) {
|
||||
return $subscriber;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getAction() {
|
||||
return (isset($_GET['mailpoet_action']))
|
||||
? $_GET['mailpoet_action']
|
||||
: null;
|
||||
return '<a href="'.Subscription\Url::getManageUrl(
|
||||
$this->subscriber
|
||||
).'">'.$text.'</a>';
|
||||
}
|
||||
}
|
@ -6,21 +6,21 @@ use \MailPoet\Models\Setting;
|
||||
|
||||
class Url {
|
||||
static function getConfirmationUrl($subscriber = false) {
|
||||
$post = get_post(Setting::getValue('subscription.confirmation_page'));
|
||||
$post = get_post(Setting::getValue('subscription.pages.confirmation'));
|
||||
return self::getSubscriptionUrl($post, 'confirm', $subscriber);
|
||||
}
|
||||
|
||||
static function getManageUrl($subscriber = false) {
|
||||
$post = get_post(Setting::getValue('subscription.manage_page'));
|
||||
$post = get_post(Setting::getValue('subscription.pages.manage'));
|
||||
return self::getSubscriptionUrl($post, 'manage', $subscriber);
|
||||
}
|
||||
|
||||
static function getUnsubscribeUrl($subscriber = false) {
|
||||
$post = get_post(Setting::getValue('subscription.unsubscribe_page'));
|
||||
$post = get_post(Setting::getValue('subscription.pages.unsubscribe'));
|
||||
return self::getSubscriptionUrl($post, 'unsubscribe', $subscriber);
|
||||
}
|
||||
|
||||
private static function getSubscriptionUrl(
|
||||
static function getSubscriptionUrl(
|
||||
$post = null, $action = null, $subscriber = false
|
||||
) {
|
||||
if($post === null || $action === null) return;
|
||||
@ -28,22 +28,26 @@ class Url {
|
||||
$url = get_permalink($post);
|
||||
|
||||
if($subscriber !== false) {
|
||||
|
||||
if(is_object($subscriber)) {
|
||||
$subscriber = $subscriber->asArray();
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'mailpoet_action='.$action,
|
||||
'mailpoet_token='.Subscriber::generateToken($subscriber['email']),
|
||||
'mailpoet_email='.$subscriber['email']
|
||||
$data = array(
|
||||
'token' => Subscriber::generateToken($subscriber['email']),
|
||||
'email' => $subscriber['email']
|
||||
);
|
||||
} else {
|
||||
$params = array(
|
||||
'mailpoet_action='.$action,
|
||||
'mailpoet_preview=1'
|
||||
$data = array(
|
||||
'preview' => 1
|
||||
);
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'endpoint=subscription',
|
||||
'action='.$action,
|
||||
'data='.base64_encode(serialize($data))
|
||||
);
|
||||
|
||||
// add parameters
|
||||
$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').join('&', $params);
|
||||
|
||||
|
@ -116,6 +116,7 @@ class CSS {
|
||||
public function parseCSS($text)
|
||||
{
|
||||
$css = new csstidy();
|
||||
$css->settings['compress_colors'] = false;
|
||||
$css->parse($text);
|
||||
|
||||
$rules = array();
|
||||
|
@ -6,13 +6,7 @@ class Url {
|
||||
}
|
||||
|
||||
static function getCurrentUrl() {
|
||||
global $wp;
|
||||
return home_url(
|
||||
add_query_arg(
|
||||
$wp->query_string,
|
||||
$wp->request
|
||||
)
|
||||
);
|
||||
return home_url(add_query_arg(null, null));
|
||||
}
|
||||
|
||||
static function redirectTo($url = null) {
|
||||
|
@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
|
||||
use \MailPoet\Config\Initializer;
|
||||
/*
|
||||
* Plugin Name: MailPoet
|
||||
* Version: 0.0.22
|
||||
* Version: 0.0.24
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: MailPoet Newsletters.
|
||||
* Author: MailPoet
|
||||
@ -22,7 +22,7 @@ use \MailPoet\Config\Initializer;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
define('MAILPOET_VERSION', '0.0.22');
|
||||
define('MAILPOET_VERSION', '0.0.24');
|
||||
|
||||
$initializer = new Initializer(array(
|
||||
'file' => __FILE__,
|
||||
|
@ -333,23 +333,6 @@ class SubscriberTest extends MailPoetTest {
|
||||
expect($subscriber->deleted_at)->equals(null);
|
||||
}
|
||||
|
||||
function testItCanBeAddedToSegments() {
|
||||
$segment = Segment::create();
|
||||
$segment->hydrate(array('name' => 'List #1'));
|
||||
$segment->save();
|
||||
|
||||
$segment2 = Segment::create();
|
||||
$segment2->hydrate(array('name' => 'List #2'));
|
||||
$segment2->save();
|
||||
|
||||
$this->subscriber->addToSegments(array($segment->id(), $segment2->id()));
|
||||
$subscriber_segments = $this->subscriber->segments()->findArray();
|
||||
|
||||
expect($this->subscriber->segments()->count())->equals(2);
|
||||
expect($subscriber_segments[0]['name'])->equals('List #1');
|
||||
expect($subscriber_segments[1]['name'])->equals('List #2');
|
||||
}
|
||||
|
||||
function testItCanBeUpdatedByEmail() {
|
||||
$subscriber_updated = Subscriber::createOrUpdate(array(
|
||||
'email' => $this->data['email'],
|
||||
|
@ -207,11 +207,10 @@ class NewsletterRendererTest extends MailPoetTest {
|
||||
)
|
||||
)->true();
|
||||
expect($DOM('tr > td.mailpoet_text > ul.mailpoet_paragraph', 0)->attr('style'))
|
||||
->contains('padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;');
|
||||
->contains('padding-top:0;padding-bottom:0;margin-top:10px;text-align:left;margin-bottom:10px;');
|
||||
// headings should be styled
|
||||
expect($DOM('tr > td.mailpoet_text > h1', 0)->attr('style'))
|
||||
->contains('margin:0;font-style:normal;font-weight:normal;');
|
||||
|
||||
->contains('padding:0;font-style:normal;font-weight:normal;');
|
||||
}
|
||||
|
||||
function testItRendersDivider() {
|
||||
|
@ -14,51 +14,64 @@ class UrlTest extends MailPoetTest {
|
||||
// preview
|
||||
$url = Url::getConfirmationUrl(false);
|
||||
expect($url)->notNull();
|
||||
expect($url)->contains('mailpoet_action=confirm');
|
||||
expect($url)->contains('preview');
|
||||
expect($url)->contains('action=confirm');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
// actual subscriber
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'email' => 'john@mailpoet.com'
|
||||
));
|
||||
$url = Url::getConfirmationUrl($subscriber);
|
||||
expect($url)->contains('mailpoet_action=confirm');
|
||||
expect($url)->contains('mailpoet_token=');
|
||||
expect($url)->contains('mailpoet_email=');
|
||||
expect($url)->contains('action=confirm');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
$this->checkData($url);
|
||||
}
|
||||
|
||||
function testItReturnsTheManageSubscriptionUrl() {
|
||||
// preview
|
||||
$url = Url::getManageUrl(false);
|
||||
expect($url)->notNull();
|
||||
expect($url)->contains('mailpoet_action=manage');
|
||||
expect($url)->contains('preview');
|
||||
expect($url)->contains('action=manage');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
// actual subscriber
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'email' => 'john@mailpoet.com'
|
||||
));
|
||||
$url = Url::getManageUrl($subscriber);
|
||||
expect($url)->contains('mailpoet_action=manage');
|
||||
expect($url)->contains('mailpoet_token=');
|
||||
expect($url)->contains('mailpoet_email=');
|
||||
expect($url)->contains('action=manage');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
$this->checkData($url);
|
||||
}
|
||||
|
||||
function testItReturnsTheUnsubscribeUrl() {
|
||||
// preview
|
||||
$url = Url::getUnsubscribeUrl(false);
|
||||
expect($url)->notNull();
|
||||
expect($url)->contains('mailpoet_action=unsubscribe');
|
||||
expect($url)->contains('preview');
|
||||
expect($url)->contains('action=unsubscribe');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
// actual subscriber
|
||||
$subscriber = Subscriber::createOrUpdate(array(
|
||||
'email' => 'john@mailpoet.com'
|
||||
));
|
||||
$url = Url::getUnsubscribeUrl($subscriber);
|
||||
expect($url)->contains('mailpoet_action=unsubscribe');
|
||||
expect($url)->contains('mailpoet_token=');
|
||||
expect($url)->contains('mailpoet_email=');
|
||||
expect($url)->contains('action=unsubscribe');
|
||||
expect($url)->contains('endpoint=subscription');
|
||||
|
||||
$this->checkData($url);
|
||||
}
|
||||
|
||||
private function checkData($url) {
|
||||
// extract & decode data from url
|
||||
$url_params = parse_url($url);
|
||||
parse_str($url_params['query'], $params);
|
||||
$data = unserialize(base64_decode($params['data']));
|
||||
|
||||
expect($data['email'])->contains('john@mailpoet.com');
|
||||
expect($data['token'])->notEmpty();
|
||||
}
|
||||
|
||||
function _after() {
|
||||
|
@ -85,6 +85,11 @@
|
||||
'setUp': __('Set up'),
|
||||
'postNotificationNewsletterTypeTitle': __('Post notifications'),
|
||||
'postNotificationsNewsletterTypeDescription': __('Automatically send posts immediately, daily, weekly or monthly. Filter by categories, if you like.'),
|
||||
'selectPeriodicity': __('Select a periodicity'),
|
||||
'periodicity': __('Periodicity'),
|
||||
'postNotificationSubjectLineTip': __("Insert [newsletter:total] to show number of posts, [newsletter:post_title] to show the latest post's title & [newsletter:number] to display the issue number."),
|
||||
'activate': __('Activate'),
|
||||
'sendWelcomeEmailWhen': __('Send welcome email when...'),
|
||||
|
||||
'daily': __('Once a day at...'),
|
||||
'weekly': __('Weekly on...'),
|
||||
|
@ -36,6 +36,7 @@
|
||||
'emptyTrash': __('Empty Trash'),
|
||||
'restore': __('Restore'),
|
||||
'deletePermanently': __('Delete Permanently'),
|
||||
'save': __('Save'),
|
||||
|
||||
|
||||
'numberOfItems': __('%$1d items'),
|
||||
|
@ -61,6 +61,39 @@
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- link tracking -->
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label>
|
||||
<%= __('Open and click tracking') %>
|
||||
<p class="description"><%= __('Some users prefer not to track their subscribers.') %></p>
|
||||
</th>
|
||||
<td>
|
||||
<p>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="tracking[enabled]"
|
||||
value="1"
|
||||
<% if(settings.tracking.enabled) %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('Yes') %>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="tracking[enabled]"
|
||||
value=""
|
||||
<% if not(settings.tracking.enabled) %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('No') %>
|
||||
</label>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- share anonymous data? -->
|
||||
<tr>
|
||||
<th scope="row">
|
||||
|
@ -209,13 +209,13 @@
|
||||
<select
|
||||
class="mailpoet_page_selection"
|
||||
id="subscription_manage_page"
|
||||
name="subscription[manage_page]"
|
||||
name="subscription[pages][manage]"
|
||||
>
|
||||
<% for page in pages %>
|
||||
<option
|
||||
value="<%= page.id %>"
|
||||
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=manage"
|
||||
<% if(page.id == settings.subscription.manage_page) %>
|
||||
data-preview-url="<%= page.url.manage|raw %>"
|
||||
<% if(page.id == settings.subscription.pages.manage) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= page.title %></option>
|
||||
@ -256,6 +256,8 @@
|
||||
<%= __('Unsubscribe page') %>
|
||||
<p class="description">
|
||||
<%= __('The page your subscribers see when they click on "Unsubscribe" in your emails.') %>
|
||||
<br />
|
||||
<%= __('Use this shortcode in your own pages: [mailpoet_manage text="Manage your subscription"].') %>
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
@ -264,13 +266,13 @@
|
||||
<select
|
||||
class="mailpoet_page_selection"
|
||||
id="subscription_unsubscribe_page"
|
||||
name="subscription[unsubscribe_page]"
|
||||
name="subscription[pages][unsubscribe]"
|
||||
>
|
||||
<% for page in pages %>
|
||||
<option
|
||||
value="<%= page.id %>"
|
||||
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=unsubscribe"
|
||||
<% if(page.id == settings.subscription.unsubscribe_page) %>
|
||||
data-preview-url="<%= page.url.unsubscribe|raw %>"
|
||||
<% if(page.id == settings.subscription.pages.unsubscribe) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= page.title %></option>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<% set intervals = [1, 2, 5, 10, 15, 30, 60] %>
|
||||
<% set intervals = [1, 2, 5, 10, 15] %>
|
||||
<% set default_frequency = {
|
||||
'website': {
|
||||
'emails': 25,
|
||||
'interval': 15
|
||||
'interval': 5
|
||||
},
|
||||
'smtp': {
|
||||
'emails': 100,
|
||||
@ -66,15 +66,21 @@
|
||||
<img
|
||||
src="<%= assets_url %>/img/mailpoet_logo.png"
|
||||
alt="MailPoet"
|
||||
width="222"
|
||||
width="137"
|
||||
height="54"
|
||||
/>
|
||||
</h3>
|
||||
|
||||
<p class="mailpoet_description">
|
||||
<%= __('Send to 500 subscribers per month for <strong>free</strong>. Enjoy great deliverability, and speed.') %>
|
||||
<br /><br />
|
||||
<a href="#todo"><%= __('See pricing for more.') %></a>
|
||||
<strong><%= __('Currently in closed beta.') %></strong>
|
||||
<br />
|
||||
<%= __('[link]Sign up to our newsletter[/link] to get our latest news on this, and more.')
|
||||
| replace({
|
||||
'[link]': '<a href="http://www.mailpoet.com/subscribe/" target="_blank">',
|
||||
'[/link]': '</a>'
|
||||
})
|
||||
| raw
|
||||
%>
|
||||
</p>
|
||||
|
||||
<div class="mailpoet_status">
|
||||
@ -91,10 +97,12 @@
|
||||
data-group="website"
|
||||
<% if(settings.mta_group == 'website') %>class="mailpoet_active"<% endif %>
|
||||
>
|
||||
<h3><%= __('Your own website') %></h3>
|
||||
<h3><%= __('Your web host/server') %></h3>
|
||||
|
||||
<p class="mailpoet_description">
|
||||
<%= __('The simplest solution for small lists. Your web host sets a daily email limit.') %>
|
||||
<strong><%= __('Free, but not recommended.') %></strong>
|
||||
<br />
|
||||
<%= __('Web hosts generally have a bad reputation as senders. Your newsletter might be considered spam.') %>
|
||||
</p>
|
||||
|
||||
<div class="mailpoet_status">
|
||||
@ -114,6 +122,8 @@
|
||||
<h3><%= __('Third party') %></h3>
|
||||
|
||||
<p class="mailpoet_description">
|
||||
<strong><%= __('Currently the best solution.') %></strong>
|
||||
<br />
|
||||
<%= __('Send with an alternate email provider. Usually not free.') %>
|
||||
</p>
|
||||
|
||||
@ -136,29 +146,6 @@
|
||||
data-group="mailpoet"
|
||||
style="display:none;"
|
||||
>
|
||||
<h3><%= __('Open a free account with MailPoet, and get:') %></h3>
|
||||
<ol>
|
||||
<li>
|
||||
<%=
|
||||
__('Send up to 4000 emails with good deliverability for free. %1$sNeed more?%2$s')
|
||||
| format('<a href="#todo">', '</a>')
|
||||
| raw
|
||||
%>
|
||||
</li>
|
||||
<li>
|
||||
<%= __("Test your campaign's spam score") %>
|
||||
</li>
|
||||
<li>
|
||||
<%= __('Send on time, without delay, without setting up your own "cron"') %>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<a class="button-secondary">
|
||||
<%=- __('Create a free account to get a key') -%>
|
||||
</a>
|
||||
|
||||
<hr />
|
||||
|
||||
<h3><%= __('Already have a key?') %></h3>
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
@ -243,10 +230,11 @@
|
||||
type="number"
|
||||
min="1"
|
||||
max="1000"
|
||||
value="<%=
|
||||
settings.mta.frequency.emails
|
||||
| default(default_frequency.website.emails)
|
||||
%>"
|
||||
<% if(settings.mta_group == 'website') %>
|
||||
value="<%= settings.mta.frequency.emails %>"
|
||||
<% else %>
|
||||
value="<%= default_frequency.website.emails %>"
|
||||
<% endif %>
|
||||
/>
|
||||
<%= __('emails') %>
|
||||
<select id="website_frequency_interval">
|
||||
@ -264,7 +252,7 @@
|
||||
<% endif %>
|
||||
>
|
||||
<%= sending_frequency(interval) %>
|
||||
<% if(interval == 15) %>
|
||||
<% if(interval == default_frequency.website.interval) %>
|
||||
(<%= __('recommended') %>)
|
||||
<% endif %>
|
||||
</option>
|
||||
@ -274,7 +262,7 @@
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<%= __('<strong>Warning!</strong> Sending more than the recommended amount of emails might break the terms of your host or provider.') %>
|
||||
<%= __('<strong>Warning!</strong> Sending more than the recommended amount of emails might break the terms of your host or provider.') %>'
|
||||
<br />
|
||||
<%= __('Double check with them what maximum number of emails you can send daily.') %>
|
||||
</p>
|
||||
@ -335,10 +323,11 @@
|
||||
type="number"
|
||||
min="1"
|
||||
max="1000"
|
||||
value="<%=
|
||||
settings.mta.frequency.emails
|
||||
| default(default_frequency.smtp.emails)
|
||||
%>"
|
||||
<% if(settings.mta_group == 'smtp') %>
|
||||
value="<%= settings.mta.frequency.emails %>"
|
||||
<% else %>
|
||||
value="<%= default_frequency.smtp.emails %>"
|
||||
<% endif %>
|
||||
/>
|
||||
<%= __('emails') %>
|
||||
<select id="smtp_frequency_interval">
|
||||
@ -356,7 +345,7 @@
|
||||
<% endif %>
|
||||
>
|
||||
<%= sending_frequency(interval) %>
|
||||
<% if(interval == 15) %>
|
||||
<% if(interval == default_frequency.smtp.interval) %>
|
||||
(<%= __('recommended') %>)
|
||||
<% endif %>
|
||||
</option>
|
||||
@ -364,12 +353,6 @@
|
||||
</select>
|
||||
<span id="mailpoet_smtp_daily_emails"></span>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<%= __('<strong>Warning!</strong> Sending more than the recommended amount of emails might break the terms of your host or provider.') %>
|
||||
<br />
|
||||
<%= __('Double check with them what maximum number of emails you can send daily.') %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- smtp: host -->
|
||||
@ -617,13 +600,29 @@
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<!-- SPF -->
|
||||
<tr id="mailpoet_mta_spf">
|
||||
<th scope="row">
|
||||
<label>
|
||||
<%= __('SPF signature (recommended)') %>
|
||||
<p class="description">
|
||||
<%= __('Improves your spam score by allowing the recipient to verify that your website is allowed to send emails from your domain.') %>
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<p>
|
||||
<%= __('SPF is set in your DNS. Check the support documents of your host to set it up.') %>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- dkim -->
|
||||
<tr id="mailpoet_mta_dkim">
|
||||
<tr id="mailpoet_mta_dkim" style="display:none;">
|
||||
<th scope="row">
|
||||
<label for="settings[dkim_enabled]">
|
||||
<%= __('DKIM signature') %>
|
||||
<%= __('DKIM signature (recommended)') %>
|
||||
<p class="description">
|
||||
<%= __('Improve your spam score. Mailpoet can sign all your emails with DKIM.') %>
|
||||
<%= __('Improve your spam score. MailPoet can sign all your emails with DKIM.') %>
|
||||
<a
|
||||
href="#todo/guide-to-dkim-in-wysija/"
|
||||
target="_blank"
|
||||
@ -693,6 +692,7 @@
|
||||
<input
|
||||
id="mailpoet_mta_test_email"
|
||||
type="text"
|
||||
class="regular-text"
|
||||
value="<%= current_user.user_email %>"
|
||||
/>
|
||||
<a
|
||||
@ -745,6 +745,16 @@
|
||||
: $('#mta_group').val()
|
||||
);
|
||||
|
||||
// check that we have a from address
|
||||
if(settings.sender.address.length === 0) {
|
||||
// validation
|
||||
return MailPoet.Notice.error(
|
||||
'The email could not be sent. Make sure the option "Email notifications" has a FROM email address in the Basics tab.',
|
||||
{ scroll: true, static: true }
|
||||
);
|
||||
}
|
||||
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'mailer',
|
||||
action: 'send',
|
||||
@ -763,16 +773,35 @@
|
||||
}
|
||||
}
|
||||
}).done(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(response.result === true) {
|
||||
MailPoet.Notice.success("The email has been sent! Check your inbox.");
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('The email has been sent! Check your inbox.') %>",
|
||||
{ scroll: true }
|
||||
);
|
||||
} else {
|
||||
if (response.errors) {
|
||||
MailPoet.Notice.error("The email could not be sent. " + response.errors);
|
||||
MailPoet.Notice.error(
|
||||
"<%= __('The email could not be sent.') %> " + response.errors,
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
else {
|
||||
MailPoet.Notice.error("The email could not be sent. Please check your settings.");
|
||||
if(mailer.method === 'PHPMail') {
|
||||
MailPoet.Notice.error(
|
||||
"<%= __('The email could not be sent. Contact your host to help you fix any sending issues with your server.') %>",
|
||||
{ scroll: true, static: true }
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
"<%= __('The email could not be sent. Please check your settings.') %>",
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).error(function(response) {
|
||||
MailPoet.Modal.loading(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -965,7 +994,16 @@
|
||||
interval: $('#'+method+'_frequency_interval').val()
|
||||
};
|
||||
|
||||
options.daily_emails = ~~((1440 / options.interval) * options.emails);
|
||||
var MINUTES_PER_DAY = 1440;
|
||||
var SECONDS_PER_DAY = 86400;
|
||||
|
||||
options.daily_emails = ~~(
|
||||
(MINUTES_PER_DAY / options.interval) * options.emails
|
||||
);
|
||||
|
||||
options.emails_per_second = (~~(
|
||||
((options.daily_emails) / 86400) * 10)
|
||||
) / 10;
|
||||
|
||||
$('#mailpoet_'+method+'_daily_emails').html(
|
||||
sending_frequency_template(options)
|
||||
|
@ -151,13 +151,13 @@
|
||||
<p>
|
||||
<select
|
||||
class="mailpoet_page_selection"
|
||||
name="subscription[confirmation_page]"
|
||||
name="subscription[pages][confirmation]"
|
||||
>
|
||||
<% for page in pages %>
|
||||
<option
|
||||
value="<%= page.id %>"
|
||||
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=confirm"
|
||||
<% if(page.id == settings.subscription.confirmation_page) %>
|
||||
data-preview-url="<%= page.url.confirm|raw %>"
|
||||
<% if(page.id == settings.subscription.pages.confirmation) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= page.title %></option>
|
||||
|
@ -11,4 +11,15 @@
|
||||
__("That's <strong>%1$s emails</strong> per day.")
|
||||
| format('{{ daily_emails }}')
|
||||
| raw
|
||||
%>
|
||||
%>
|
||||
|
||||
{{#ifCond emails_per_second ">" "1"}}
|
||||
<br /><br />
|
||||
<span style="color: #d54e21;">
|
||||
<%=
|
||||
__("That's %1$s emails per second. <strong>We highly recommend to send 1 email per second at most.</strong> This is the time MailPoet needs to process and send a single email from most hosts. <strong>Alternatively, send with MailPoet which can be 50 times faster.</strong>")
|
||||
| format('{{ emails_per_second }}')
|
||||
| raw
|
||||
%>
|
||||
</span>
|
||||
{{/ifCond}}
|
Reference in New Issue
Block a user