Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
5019131b21 | |||
da483fb88f | |||
788bed4622 | |||
3fbe5423d0 | |||
8357295be2 | |||
8072b162d4 | |||
3f2f0ec1a9 | |||
5a5a777b7d | |||
6cac7f3652 | |||
6a9313107c | |||
72c9d301b7 | |||
ad925de801 | |||
1da28b7299 | |||
e837ad7014 | |||
daec56191f | |||
7bd25660df | |||
3b9821fbe1 | |||
cabe2d61b7 | |||
a6d802e2fa | |||
1732c4f634 | |||
bb77134224 | |||
f1cb64b240 | |||
3689545589 | |||
9b67c56281 | |||
dc38b19667 | |||
a574733217 | |||
b90aaa629e | |||
8de186c0e6 | |||
e3719967f9 | |||
138a631ed7 | |||
07b7636a72 | |||
a63ce3cdac | |||
f5c7bb87af | |||
2c8d925971 | |||
0c5beb2511 | |||
9c0316a87d | |||
46c1b682fa | |||
7954346a3f | |||
d87ff67f50 | |||
6642bb3bfa | |||
2cb32e7a78 | |||
fcea9adbd9 | |||
bbdd0dbb6e | |||
1b2cf7bd16 | |||
b7cfa549d5 |
@ -19,6 +19,8 @@ a:focus
|
||||
|
||||
// select 2
|
||||
.select2-container
|
||||
width: 25em !important
|
||||
|
||||
// textareas
|
||||
textarea.regular-text
|
||||
width: 25em !important
|
||||
|
@ -125,6 +125,7 @@ handle_icon = '../img/handle.png'
|
||||
float: none
|
||||
|
||||
#mailpoet_form_toolbar
|
||||
z-index: 999
|
||||
position: absolute
|
||||
width: 400px
|
||||
|
||||
|
@ -90,7 +90,7 @@ body.mailpoet_modal_opened
|
||||
padding: 0
|
||||
margin: 0
|
||||
width: 100%
|
||||
transition: margin 250ms ease-out
|
||||
transition: margin 350ms ease-out
|
||||
|
||||
.mailpoet_panel_wrapper
|
||||
background-color: #f1f1f1
|
||||
|
@ -7,7 +7,6 @@ $tool-active-secondary-color = #ffffff
|
||||
|
||||
$tool-width = 20px
|
||||
$master-column-tool-width = 24px
|
||||
$layer-selector-width = 30px
|
||||
|
||||
.mailpoet_tools
|
||||
position: absolute
|
||||
@ -33,10 +32,35 @@ $layer-selector-width = 30px
|
||||
width: $master-column-tool-width
|
||||
height: $master-column-tool-width
|
||||
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
max-width: 100%
|
||||
max-height: $master-column-tool-width
|
||||
opacity: 1
|
||||
display: block
|
||||
|
||||
.mailpoet_delete_block_confirm,
|
||||
.mailpoet_delete_block_cancel
|
||||
max-width: 100%
|
||||
max-height: 0
|
||||
opacity: 0
|
||||
overflow: hidden
|
||||
display: block
|
||||
|
||||
.mailpoet_delete_block_activated
|
||||
width: auto
|
||||
height: auto
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
overflow: hidden
|
||||
max-height: 0
|
||||
opacity: 0
|
||||
|
||||
.mailpoet_delete_block_confirm,
|
||||
.mailpoet_delete_block_cancel
|
||||
max-height: $master-column-tool-width*2
|
||||
opacity: 1
|
||||
|
||||
.mailpoet_tool
|
||||
display: inline-block
|
||||
width: $tool-width
|
||||
@ -82,9 +106,10 @@ $layer-selector-width = 30px
|
||||
padding: 0
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
max-width: 100%
|
||||
max-width: $tool-width
|
||||
display: inline-block
|
||||
opacity: 1
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
|
||||
.mailpoet_delete_block_confirm,
|
||||
.mailpoet_delete_block_cancel
|
||||
@ -95,12 +120,12 @@ $layer-selector-width = 30px
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
|
||||
.mailpoet_delete_block_activated
|
||||
height: auto
|
||||
width: auto
|
||||
border-radius(3px)
|
||||
background-color: $warning-background-color
|
||||
padding: 3px 5px
|
||||
line-height: 1.2em
|
||||
height: auto
|
||||
|
||||
.mailpoet_delete_block_activate
|
||||
overflow: hidden
|
||||
|
@ -129,3 +129,7 @@ body
|
||||
|
||||
#mailpoet_modal_close
|
||||
display: none
|
||||
|
||||
.wrap > .mailpoet_notice,
|
||||
.update-nag
|
||||
margin-left: 2px + 15px !important
|
||||
|
@ -13,8 +13,9 @@ animation-background-color()
|
||||
|
||||
animation-fade-in()
|
||||
animation-name: fadeIn
|
||||
animation-duration: 250ms
|
||||
animation-duration: 300ms
|
||||
animation-fill-mode: forwards
|
||||
animation-timing-function: ease-in
|
||||
|
||||
animation-fade-in-and-scale-horizontally()
|
||||
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||
|
@ -1,31 +1,31 @@
|
||||
define([
|
||||
'react',
|
||||
'react-checkbox-group'
|
||||
'react'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
CheckboxGroup
|
||||
React
|
||||
) {
|
||||
var FormFieldCheckbox = React.createClass({
|
||||
const FormFieldCheckbox = React.createClass({
|
||||
onValueChange: function(e) {
|
||||
e.target.value = this.refs.checkbox.checked ? '1' : '';
|
||||
return this.props.onValueChange(e);
|
||||
},
|
||||
render: function() {
|
||||
var selected_values = this.props.item[this.props.field.name] || '';
|
||||
if(
|
||||
selected_values !== undefined
|
||||
&& selected_values.constructor !== Array
|
||||
) {
|
||||
selected_values = selected_values.split(';').map(function(value) {
|
||||
return value.trim();
|
||||
});
|
||||
}
|
||||
var count = Object.keys(this.props.field.values).length;
|
||||
const isChecked = !!(this.props.item[this.props.field.name]);
|
||||
|
||||
var options = Object.keys(this.props.field.values).map(
|
||||
const options = Object.keys(this.props.field.values).map(
|
||||
function(value, index) {
|
||||
return (
|
||||
<p key={ 'checkbox-' + index }>
|
||||
<label>
|
||||
<input type="checkbox" value={ value } />
|
||||
{ this.props.field.values[value] }
|
||||
<input
|
||||
ref="checkbox"
|
||||
type="checkbox"
|
||||
value="1"
|
||||
checked={ isChecked }
|
||||
onChange={ this.onValueChange }
|
||||
name={ this.props.field.name }
|
||||
/>
|
||||
{ this.props.field.values[value] }
|
||||
</label>
|
||||
</p>
|
||||
);
|
||||
@ -33,30 +33,10 @@ function(
|
||||
);
|
||||
|
||||
return (
|
||||
<CheckboxGroup
|
||||
name={ this.props.field.name }
|
||||
value={ selected_values }
|
||||
ref={ this.props.field.name }
|
||||
onChange={ this.handleValueChange }>
|
||||
<div>
|
||||
{ options }
|
||||
</CheckboxGroup>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleValueChange: function() {
|
||||
var field = this.props.field.name;
|
||||
var group = this.refs[field];
|
||||
var selected_values = [];
|
||||
|
||||
if(group !== undefined) {
|
||||
selected_values = group.getCheckedValues();
|
||||
}
|
||||
|
||||
return this.props.onValueChange({
|
||||
target: {
|
||||
name: field,
|
||||
value: selected_values.join(';')
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
196
assets/js/src/form/fields/date.jsx
Normal file
196
assets/js/src/form/fields/date.jsx
Normal file
@ -0,0 +1,196 @@
|
||||
define([
|
||||
'react',
|
||||
'moment',
|
||||
], function(
|
||||
React,
|
||||
Moment
|
||||
) {
|
||||
class FormFieldDateYear extends React.Component {
|
||||
render() {
|
||||
const yearsRange = 100;
|
||||
const years = [];
|
||||
const currentYear = Moment().year();
|
||||
for (let i = currentYear; i >= currentYear - yearsRange; i--) {
|
||||
years.push((
|
||||
<option
|
||||
key={ i }
|
||||
value={ i }
|
||||
>{ i }</option>
|
||||
));
|
||||
}
|
||||
return (
|
||||
<select
|
||||
name={ this.props.name + '[year]' }
|
||||
value={ this.props.year }
|
||||
onChange={ this.props.onValueChange }
|
||||
>
|
||||
{ years }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormFieldDateMonth extends React.Component {
|
||||
render() {
|
||||
const months = [];
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
months.push((
|
||||
<option
|
||||
key={ i }
|
||||
value={ i }
|
||||
>{ this.props.monthNames[i - 1] }</option>
|
||||
));
|
||||
}
|
||||
return (
|
||||
<select
|
||||
name={ this.props.name + '[month]' }
|
||||
value={ this.props.month }
|
||||
onChange={ this.props.onValueChange }
|
||||
>
|
||||
{ months }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormFieldDateDay extends React.Component {
|
||||
render() {
|
||||
const days = [];
|
||||
for (let i = 1; i <= 31; i++) {
|
||||
days.push((
|
||||
<option
|
||||
key={ i }
|
||||
value={ i }
|
||||
>{ i }</option>
|
||||
));
|
||||
}
|
||||
|
||||
return (
|
||||
<select
|
||||
name={ this.props.name + '[day]' }
|
||||
value={ this.props.day }
|
||||
onChange={ this.props.onValueChange }
|
||||
>
|
||||
{ days }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormFieldDate extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
year: Moment().year(),
|
||||
month: 1,
|
||||
day: 1
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
}
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (
|
||||
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||
&& (this.props.item.id !== prevProps.item.id)
|
||||
) {
|
||||
this.extractTimeStamp();
|
||||
}
|
||||
}
|
||||
extractTimeStamp() {
|
||||
const timeStamp = parseInt(this.props.item[this.props.field.name], 10);
|
||||
|
||||
this.setState({
|
||||
year: Moment.unix(timeStamp).year(),
|
||||
// Moment returns the month as [0..11]
|
||||
// We increment it to match PHP's mktime() which expects [1..12]
|
||||
month: Moment.unix(timeStamp).month() + 1,
|
||||
day: Moment.unix(timeStamp).date()
|
||||
});
|
||||
}
|
||||
updateTimeStamp(field) {
|
||||
let newTimeStamp = Moment(
|
||||
`${this.state.month}/${this.state.day}/${this.state.year}`,
|
||||
'M/D/YYYY'
|
||||
).valueOf();
|
||||
if (!isNaN(newTimeStamp) && parseInt(newTimeStamp, 10) > 0) {
|
||||
// convert milliseconds to seconds
|
||||
newTimeStamp /= 1000;
|
||||
return this.props.onValueChange({
|
||||
target: {
|
||||
name: field,
|
||||
value: newTimeStamp
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
onValueChange(e) {
|
||||
// extract property from name
|
||||
const matches = e.target.name.match(/(.*?)\[(.*?)\]/);
|
||||
let field = null;
|
||||
let property = null;
|
||||
|
||||
if (matches !== null && matches.length === 3) {
|
||||
field = matches[1];
|
||||
property = matches[2];
|
||||
|
||||
let value = parseInt(e.target.value, 10);
|
||||
|
||||
this.setState({
|
||||
[`${property}`]: value
|
||||
}, () => {
|
||||
this.updateTimeStamp(field);
|
||||
});
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const monthNames = window.mailpoet_month_names || [];
|
||||
|
||||
const dateType = this.props.field.params.date_type;
|
||||
|
||||
const dateSelects = dateType.split('_');
|
||||
|
||||
const fields = dateSelects.map(type => {
|
||||
switch(type) {
|
||||
case 'year':
|
||||
return (<FormFieldDateYear
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'year' }
|
||||
key={ 'year' }
|
||||
name={ this.props.field.name }
|
||||
year={ this.state.year }
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
return (<FormFieldDateMonth
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'month' }
|
||||
key={ 'month' }
|
||||
name={ this.props.field.name }
|
||||
month={ this.state.month }
|
||||
monthNames={ monthNames }
|
||||
/>);
|
||||
break;
|
||||
|
||||
case 'day':
|
||||
return (<FormFieldDateDay
|
||||
onValueChange={ this.onValueChange.bind(this) }
|
||||
ref={ 'day' }
|
||||
key={ 'day' }
|
||||
name={ this.props.field.name }
|
||||
day={ this.state.day }
|
||||
/>);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{fields}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return FormFieldDate;
|
||||
});
|
@ -5,7 +5,8 @@ define([
|
||||
'form/fields/select.jsx',
|
||||
'form/fields/radio.jsx',
|
||||
'form/fields/checkbox.jsx',
|
||||
'form/fields/selection.jsx'
|
||||
'form/fields/selection.jsx',
|
||||
'form/fields/date.jsx',
|
||||
],
|
||||
function(
|
||||
React,
|
||||
@ -14,7 +15,8 @@ function(
|
||||
FormFieldSelect,
|
||||
FormFieldRadio,
|
||||
FormFieldCheckbox,
|
||||
FormFieldSelection
|
||||
FormFieldSelection,
|
||||
FormFieldDate
|
||||
) {
|
||||
var FormField = React.createClass({
|
||||
renderField: function(data, inline = false) {
|
||||
@ -55,6 +57,10 @@ function(
|
||||
case 'selection':
|
||||
field = (<FormFieldSelection {...data} />);
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
field = (<FormFieldDate {...data} />);
|
||||
break;
|
||||
}
|
||||
|
||||
if(inline === true) {
|
||||
@ -66,10 +72,10 @@ function(
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<p key={ 'field-' + (data.index || 0) }>
|
||||
<div key={ 'field-' + (data.index || 0) }>
|
||||
{ field }
|
||||
{ description }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -7,7 +7,6 @@ function(
|
||||
var FormFieldRadio = React.createClass({
|
||||
render: function() {
|
||||
var selected_value = this.props.item[this.props.field.name];
|
||||
var count = Object.keys(this.props.field.values).length;
|
||||
|
||||
var options = Object.keys(this.props.field.values).map(
|
||||
function(value, index) {
|
||||
@ -20,7 +19,7 @@ function(
|
||||
value={ value }
|
||||
onChange={ this.props.onValueChange }
|
||||
name={ this.props.field.name } />
|
||||
{ this.props.field.values[value] }
|
||||
{ this.props.field.values[value] }
|
||||
</label>
|
||||
</p>
|
||||
);
|
||||
|
@ -617,6 +617,28 @@ var WysijaForm = {
|
||||
// this is a url, so do not encode the protocol
|
||||
return encodeURI(str).replace(/[!'()*]/g, escape);
|
||||
}
|
||||
},
|
||||
updateBlock: function(field) {
|
||||
var hasUpdated = false;
|
||||
WysijaForm.getBlocks().each(function(b) {
|
||||
if(b.block.getData().id === field.id) {
|
||||
hasUpdated = true;
|
||||
b.block.redraw(field);
|
||||
}
|
||||
});
|
||||
|
||||
return hasUpdated;
|
||||
},
|
||||
removeBlock: function(field, callback) {
|
||||
var hasRemoved = false;
|
||||
WysijaForm.getBlocks().each(function(b) {
|
||||
if(b.block.getData().id === field.id) {
|
||||
hasRemoved = true;
|
||||
b.block.removeBlock(callback);
|
||||
}
|
||||
});
|
||||
|
||||
return hasRemoved;
|
||||
}
|
||||
};
|
||||
|
||||
@ -825,10 +847,6 @@ WysijaForm.Block = Class.create({
|
||||
Effect.Fade(this.element.identify(), {
|
||||
duration: 0.2,
|
||||
afterFinish: function(effect) {
|
||||
if(effect.element.next('.mailpoet_form_block') !== undefined && callback !== false) {
|
||||
// show controls of next block to allow mass delete
|
||||
WysijaForm.get(effect.element.next('.mailpoet_form_block')).block.showControls();
|
||||
}
|
||||
// remove placeholder
|
||||
if(effect.element.previous('.block_placeholder') !== undefined) {
|
||||
effect.element.previous('.block_placeholder').remove();
|
||||
|
@ -133,10 +133,10 @@ define([
|
||||
}.bind(this));
|
||||
},
|
||||
transitionIn: function() {
|
||||
return this._transition('slideDown', 'fadeIn', 'easeIn');
|
||||
return this._transition('slideDown', 'fadeIn', 'easeOut');
|
||||
},
|
||||
transitionOut: function() {
|
||||
return this._transition('slideUp', 'fadeOut', 'easeOut');
|
||||
return this._transition('slideUp', 'fadeOut', 'easeIn');
|
||||
},
|
||||
_transition: function(slideDirection, fadeDirection, easing) {
|
||||
var promise = jQuery.Deferred();
|
||||
|
@ -63,16 +63,17 @@ define([
|
||||
};
|
||||
|
||||
Module.saveNewsletter = function(options) {
|
||||
return Module._query({
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
options: options,
|
||||
data: options || {},
|
||||
});
|
||||
};
|
||||
|
||||
Module.previewNewsletter = function(options) {
|
||||
return MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'preview',
|
||||
action: 'sendPreview',
|
||||
data: options || {},
|
||||
});
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
define([
|
||||
'newsletter_editor/App',
|
||||
'newsletter_editor/components/communication',
|
||||
'mailpoet',
|
||||
'notice',
|
||||
'backbone',
|
||||
@ -8,7 +9,18 @@ define([
|
||||
'blob',
|
||||
'filesaver',
|
||||
'html2canvas'
|
||||
], function(App, MailPoet, Notice, Backbone, Marionette, jQuery, Blob, FileSaver, html2canvas) {
|
||||
], function(
|
||||
App,
|
||||
CommunicationComponent,
|
||||
MailPoet,
|
||||
Notice,
|
||||
Backbone,
|
||||
Marionette,
|
||||
jQuery,
|
||||
Blob,
|
||||
FileSaver,
|
||||
html2canvas
|
||||
) {
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -17,26 +29,33 @@ define([
|
||||
|
||||
// Save editor contents to server
|
||||
Module.save = function() {
|
||||
App.getChannel().trigger('beforeEditorSave');
|
||||
|
||||
var json = App.toJSON();
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(json.body)) {
|
||||
json.body = JSON.stringify(json.body);
|
||||
}
|
||||
|
||||
App.getChannel().trigger('beforeEditorSave', json);
|
||||
|
||||
// save newsletter
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: json,
|
||||
}).done(function(response) {
|
||||
CommunicationComponent.saveNewsletter(json).done(function(response) {
|
||||
if(response.success !== undefined && response.success === true) {
|
||||
// TODO: Handle translations
|
||||
//MailPoet.Notice.success("<?php _e('Newsletter has been saved.'); ?>");
|
||||
} else if(response.error !== undefined) {
|
||||
if(response.error.length === 0) {
|
||||
// TODO: Handle translations
|
||||
MailPoet.Notice.error("<?php _e('An unknown error occurred, please check your settings.'); ?>");
|
||||
MailPoet.Notice.error(
|
||||
"An unknown error occurred, please check your settings.",
|
||||
{
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$(response.error).each(function(i, error) {
|
||||
MailPoet.Notice.error(error);
|
||||
MailPoet.Notice.error(error, { scroll: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -58,7 +77,7 @@ define([
|
||||
promise.then(function(thumbnail) {
|
||||
var data = _.extend(options || {}, {
|
||||
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
||||
body: App.getBody(),
|
||||
body: JSON.stringify(App.getBody()),
|
||||
});
|
||||
|
||||
return MailPoet.Ajax.post({
|
||||
@ -154,6 +173,7 @@ define([
|
||||
App.getConfig().get('translations.templateNameMissing'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
} else if (templateDescription === '') {
|
||||
@ -161,6 +181,7 @@ define([
|
||||
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
@ -174,6 +195,7 @@ define([
|
||||
App.getConfig().get('translations.templateSaved'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
}).fail(function() {
|
||||
@ -182,6 +204,7 @@ define([
|
||||
App.getConfig().get('translations.templateSaveFailed'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -206,6 +229,7 @@ define([
|
||||
App.getConfig().get('translations.templateNameMissing'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
} else if (templateDescription === '') {
|
||||
@ -213,6 +237,7 @@ define([
|
||||
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||
{
|
||||
positionAfter: that.$el,
|
||||
scroll: true,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -242,26 +242,29 @@ define([
|
||||
console.log('trying to send a preview');
|
||||
// get form data
|
||||
var data = {
|
||||
from_name: this.$('#mailpoet_preview_from_name').val(),
|
||||
from_email: this.$('#mailpoet_preview_from_email').val(),
|
||||
to_email: this.$('#mailpoet_preview_to_email').val(),
|
||||
newsletter: App.newsletterId,
|
||||
subscriber: this.$('#mailpoet_preview_to_email').val(),
|
||||
id: App.getNewsletter().get('id'),
|
||||
};
|
||||
|
||||
// send test email
|
||||
MailPoet.Modal.loading(true);
|
||||
|
||||
// TODO: Migrate logic to new AJAX format
|
||||
CommunicationComponent.previewNewsletter(data).done(function(response) {
|
||||
if(response.success !== undefined && response.success === true) {
|
||||
MailPoet.Notice.success(App.getConfig().get('translations.testEmailSent'));
|
||||
} else if(response.error !== undefined) {
|
||||
if(response.error.length === 0) {
|
||||
MailPoet.Notice.error(App.getConfig().get('translations.unknownErrorOccurred'));
|
||||
} else {
|
||||
$(response.error).each(function(i, error) {
|
||||
MailPoet.Notice.error(error);
|
||||
if(response.result !== undefined && response.result === true) {
|
||||
MailPoet.Notice.success(App.getConfig().get('translations.newsletterPreviewSent'), { scroll: true });
|
||||
} else {
|
||||
if (_.isArray(response.errors)) {
|
||||
response.errors.map(function(error) {
|
||||
MailPoet.Notice.error(error, { scroll: true });
|
||||
});
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
App.getConfig().get('translations.newsletterPreviewFailedToSend'),
|
||||
{
|
||||
scroll: true,
|
||||
static: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
MailPoet.Modal.loading(false);
|
||||
|
@ -18,6 +18,12 @@ define(
|
||||
|
||||
var ImportTemplate = React.createClass({
|
||||
saveTemplate: function(template) {
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(template.body)) {
|
||||
template.body = JSON.stringify(template.body);
|
||||
}
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
@ -111,12 +117,19 @@ define(
|
||||
}.bind(this));
|
||||
},
|
||||
handleSelectTemplate: function(template) {
|
||||
var body = template.body;
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(body)) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: {
|
||||
id: this.props.params.id,
|
||||
body: template.body
|
||||
body: body
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
|
@ -20,10 +20,7 @@ function(
|
||||
$('form.mailpoet_form').each(function() {
|
||||
var form = $(this);
|
||||
|
||||
form.parsley({
|
||||
errorsWrapper: '<p></p>',
|
||||
errorTemplate: '<span></span>'
|
||||
}).on('form:submit', function(parsley) {
|
||||
form.parsley().on('form:submit', function(parsley) {
|
||||
|
||||
var data = form.serializeObject() || {};
|
||||
|
||||
|
@ -51,6 +51,28 @@ define(
|
||||
}
|
||||
];
|
||||
|
||||
var custom_fields = window.mailpoet_custom_fields || [];
|
||||
custom_fields.map(custom_field => {
|
||||
if(custom_field.type === 'input') {
|
||||
custom_field.type = 'text';
|
||||
}
|
||||
|
||||
let field = {
|
||||
name: 'cf_' + custom_field.id,
|
||||
label: custom_field.name,
|
||||
type: custom_field.type
|
||||
};
|
||||
if(custom_field.params) {
|
||||
field.params = custom_field.params;
|
||||
}
|
||||
|
||||
if(custom_field.params.values) {
|
||||
field.values = custom_field.params.values;
|
||||
}
|
||||
|
||||
fields.push(field);
|
||||
});
|
||||
|
||||
var messages = {
|
||||
onUpdate: function() {
|
||||
MailPoet.Notice.success('Subscriber successfully updated!');
|
||||
|
@ -8,12 +8,14 @@ define(
|
||||
'papaparse',
|
||||
'select2'
|
||||
],
|
||||
function (Backbone,
|
||||
_,
|
||||
jQuery,
|
||||
MailPoet,
|
||||
Handlebars,
|
||||
Papa) {
|
||||
function (
|
||||
Backbone,
|
||||
_,
|
||||
jQuery,
|
||||
MailPoet,
|
||||
Handlebars,
|
||||
Papa
|
||||
) {
|
||||
if (!jQuery('#mailpoet_subscribers_import').length) {
|
||||
return;
|
||||
}
|
||||
@ -138,6 +140,14 @@ define(
|
||||
*/
|
||||
uploadElement.change(function () {
|
||||
MailPoet.Notice.hide();
|
||||
var ext = this.value.match(/\.(.+)$/);
|
||||
if (ext === null || ext[1].toLowerCase() !== 'csv') {
|
||||
this.value = '';
|
||||
MailPoet.Notice.error(MailPoetI18n.wrongFileFormat, {
|
||||
timeout: 3000,
|
||||
});
|
||||
}
|
||||
|
||||
toggleNextStepButton(
|
||||
uploadProcessButtonElement,
|
||||
(this.value.trim() !== '') ? 'on' : 'off'
|
||||
@ -416,7 +426,10 @@ define(
|
||||
}
|
||||
else {
|
||||
MailPoet.Modal.loading(false);
|
||||
MailPoet.Notice.error(MailPoetI18n.noValidRecords, {
|
||||
var errorNotice = MailPoetI18n.noValidRecords;
|
||||
errorNotice = errorNotice.replace('[link]', MailPoetI18n.csvKBLink);
|
||||
errorNotice = errorNotice.replace('[/link]', '</a>');
|
||||
MailPoet.Notice.error(errorNotice, {
|
||||
timeout: 3000,
|
||||
});
|
||||
}
|
||||
@ -721,7 +734,7 @@ define(
|
||||
}
|
||||
});
|
||||
|
||||
// reduce subscribers object if the total length is geater than the
|
||||
// reduce subscribers object if the total length is greater than the
|
||||
// maximum number of defined rows
|
||||
if (subscribers.subscribersCount > (maxRowsToShow + 1)) {
|
||||
subscribers.subscribers.splice(
|
||||
|
608
composer.lock
generated
608
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,61 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Setting;
|
||||
|
||||
class Hooks {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Subscribe in comments
|
||||
if((bool)Setting::getValue('subscribe.on_comment.enabled')) {
|
||||
add_action(
|
||||
'comment_form_after_fields',
|
||||
'\MailPoet\Subscription\Comment::extendForm'
|
||||
);
|
||||
|
||||
add_action(
|
||||
'comment_post',
|
||||
'\MailPoet\Subscription\Comment::onSubmit',
|
||||
60,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wp_set_comment_status',
|
||||
'\MailPoet\Subscription\Comment::onStatusUpdate',
|
||||
60,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
// Subscribe in registration form
|
||||
if((bool)Setting::getValue('subscribe.on_register.enabled')) {
|
||||
if(is_multisite()) {
|
||||
add_action(
|
||||
'signup_extra_fields',
|
||||
'\MailPoet\Subscription\Registration::extendForm'
|
||||
);
|
||||
add_action(
|
||||
'wpmu_validate_user_signup',
|
||||
'\MailPoet\Subscription\Registration::onMultiSiteRegister',
|
||||
60,
|
||||
1
|
||||
);
|
||||
} else {
|
||||
add_action(
|
||||
'register_form',
|
||||
'\MailPoet\Subscription\Registration::extendForm'
|
||||
);
|
||||
add_action(
|
||||
'register_post',
|
||||
'\MailPoet\Subscription\Registration::onRegister',
|
||||
60,
|
||||
3
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// WP Users synchronization
|
||||
add_action(
|
||||
'user_register',
|
||||
|
@ -5,6 +5,7 @@ use MailPoet\Models;
|
||||
use MailPoet\Cron\Supervisor;
|
||||
use MailPoet\Router;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Settings\Pages;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -31,6 +32,7 @@ class Initializer {
|
||||
$this->runQueueSupervisor();
|
||||
$this->setupShortcodes();
|
||||
$this->setupHooks();
|
||||
$this->setupPages();
|
||||
$this->setupImages();
|
||||
}
|
||||
|
||||
@ -127,6 +129,11 @@ class Initializer {
|
||||
$changelog->init();
|
||||
}
|
||||
|
||||
function setupPages() {
|
||||
$pages = new Pages();
|
||||
$pages->init();
|
||||
}
|
||||
|
||||
function setupShortcodes() {
|
||||
$shortcodes = new Shortcodes();
|
||||
$shortcodes->init();
|
||||
|
@ -190,6 +190,8 @@ class Menu {
|
||||
}
|
||||
|
||||
function welcome() {
|
||||
if((bool)(defined('DOING_AJAX') && DOING_AJAX)) return;
|
||||
|
||||
global $wp;
|
||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||
$redirect_url =
|
||||
@ -240,6 +242,7 @@ class Menu {
|
||||
|
||||
function settings() {
|
||||
$settings = Setting::getAll();
|
||||
$flags = $this->_getFlags();
|
||||
|
||||
// dkim: check if public/private keys have been generated
|
||||
if(
|
||||
@ -258,10 +261,9 @@ class Menu {
|
||||
|
||||
$data = array(
|
||||
'settings' => $settings,
|
||||
'segments' => Segment::getPublished()
|
||||
->findArray(),
|
||||
'segments' => Segment::getPublic()->findArray(),
|
||||
'pages' => Pages::getAll(),
|
||||
'flags' => $this->_getFlags(),
|
||||
'flags' => $flags,
|
||||
'charsets' => Charsets::getAll(),
|
||||
'current_user' => wp_get_current_user(),
|
||||
'permissions' => Permissions::getAll(),
|
||||
@ -294,7 +296,7 @@ class Menu {
|
||||
} else {
|
||||
// check if users can register
|
||||
$flags['registration_enabled'] =
|
||||
(bool) get_option('users_can_register', false);
|
||||
(bool)get_option('users_can_register', false);
|
||||
}
|
||||
|
||||
return $flags;
|
||||
@ -305,6 +307,23 @@ class Menu {
|
||||
|
||||
$data['segments'] = Segment::findArray();
|
||||
|
||||
$data['custom_fields'] = array_map(function($field) {
|
||||
$field['params'] = unserialize($field['params']);
|
||||
|
||||
if(!empty($field['params']['values'])) {
|
||||
$values = array();
|
||||
|
||||
foreach($field['params']['values'] as $value) {
|
||||
$values[$value['value']] = $value['value'];
|
||||
}
|
||||
$field['params']['values'] = $values;
|
||||
}
|
||||
return $field;
|
||||
}, CustomField::findArray());
|
||||
|
||||
$data['date_formats'] = Block\Date::getDateFormats();
|
||||
$data['month_names'] = Block\Date::getMonthNames();
|
||||
|
||||
echo $this->renderer->render('subscribers/subscribers.html', $data);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlankTemplate;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Segments\WP;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Settings\Pages;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
@ -48,6 +49,29 @@ class Populator {
|
||||
|
||||
$this->createDefaultSegments();
|
||||
$this->createDefaultSettings();
|
||||
$this->createMailPoetPage();
|
||||
}
|
||||
|
||||
private function createMailPoetPage() {
|
||||
$pages = get_posts(array(
|
||||
'posts_per_page' => 1,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'post_type' => 'mailpoet_page'
|
||||
));
|
||||
|
||||
$page = null;
|
||||
if(!empty($pages)) {
|
||||
$page = array_shift($pages);
|
||||
if(strpos($page->post_content, '[mailpoet_page]') === false) {
|
||||
$page = null;
|
||||
}
|
||||
}
|
||||
|
||||
if($page === null) {
|
||||
$mailpoet_page_id = Pages::createMailPoetPage();
|
||||
Setting::setValue('subscription.page', $mailpoet_page_id);
|
||||
}
|
||||
}
|
||||
|
||||
private function createDefaultSettings() {
|
||||
@ -72,6 +96,9 @@ class Populator {
|
||||
'name' => $user_name,
|
||||
'address' => $current_user->user_email
|
||||
));
|
||||
|
||||
// enable signup confirmation by default
|
||||
Setting::setValue('signup_confirmation.enabled', true);
|
||||
}
|
||||
|
||||
private function createDefaultSegments() {
|
||||
|
@ -1,5 +1,8 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Newsletter;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Models\SubscriberSegment;
|
||||
|
||||
class Shortcodes {
|
||||
function __construct() {
|
||||
@ -9,6 +12,26 @@ class Shortcodes {
|
||||
// form widget shortcode
|
||||
add_shortcode('mailpoet_form', array($this, 'formWidget'));
|
||||
add_shortcode('wysija_form', array($this, 'formWidget'));
|
||||
|
||||
// subscribers count shortcode
|
||||
add_shortcode('mailpoet_subscribers_count', array(
|
||||
$this, 'getSubscribersCount'
|
||||
));
|
||||
add_shortcode('wysija_subscribers_count', array(
|
||||
$this, 'getSubscribersCount'
|
||||
));
|
||||
|
||||
// archives page
|
||||
add_shortcode('mailpoet_archive', array(
|
||||
$this, 'getArchive'
|
||||
));
|
||||
|
||||
add_filter('mailpoet_archive_date', array(
|
||||
$this, 'renderArchiveDate'
|
||||
), 2);
|
||||
add_filter('mailpoet_archive_subject', array(
|
||||
$this, 'renderArchiveSubject'
|
||||
), 2);
|
||||
}
|
||||
|
||||
function formWidget($params = array()) {
|
||||
@ -23,4 +46,76 @@ class Shortcodes {
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function getSubscribersCount($params) {
|
||||
if(!empty($params['segments'])) {
|
||||
$segment_ids = array_map(function($segment_id) {
|
||||
return (int)trim($segment_id);
|
||||
}, explode(',', $params['segments']));
|
||||
}
|
||||
|
||||
if(empty($segment_ids)) {
|
||||
return Subscriber::filter('subscribed')->count();
|
||||
} else {
|
||||
return SubscriberSegment::whereIn('segment_id', $segment_ids)
|
||||
->select('subscriber_id')->distinct()
|
||||
->filter('subscribed')
|
||||
->findResultSet()->count();
|
||||
}
|
||||
}
|
||||
|
||||
function getArchive($params) {
|
||||
if(!empty($params['segments'])) {
|
||||
$segment_ids = array_map(function($segment_id) {
|
||||
return (int)trim($segment_id);
|
||||
}, explode(',', $params['segments']));
|
||||
}
|
||||
|
||||
$newsletters = array();
|
||||
$html = '';
|
||||
|
||||
// TODO: needs more advanced newsletters in order to finish
|
||||
$newsletters = Newsletter::limit(10)->orderByDesc('created_at')->findMany();
|
||||
|
||||
if(empty($newsletters)) {
|
||||
return apply_filters(
|
||||
'mailpoet_archive_no_newsletters',
|
||||
__('Oops! There are no newsletters to display.')
|
||||
);
|
||||
} else {
|
||||
$title = apply_filters('mailpoet_archive_title', '');
|
||||
if(!empty($title)) {
|
||||
$html .= '<h3 class="mailpoet_archive_title">'.$title.'</h3>';
|
||||
}
|
||||
|
||||
$html .= '<ul class="mailpoet_archive">';
|
||||
foreach($newsletters as $newsletter) {
|
||||
$html .= '<li>'.
|
||||
'<span class="mailpoet_archive_date">'.
|
||||
apply_filters('mailpoet_archive_date', $newsletter).
|
||||
'</span>
|
||||
<span class="mailpoet_archive_subject">'.
|
||||
apply_filters('mailpoet_archive_subject', $newsletter).
|
||||
'</span>
|
||||
</li>';
|
||||
}
|
||||
$html .= '</ul>';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
function renderArchiveDate($newsletter) {
|
||||
return date_i18n(
|
||||
get_option('date_format'),
|
||||
strtotime($newsletter->created_at)
|
||||
);
|
||||
}
|
||||
|
||||
function renderArchiveSubject($newsletter) {
|
||||
return '<a href="TODO" target="_blank" title="'
|
||||
.esc_attr(__('Preview in new tab')).'">'
|
||||
.esc_attr($newsletter->subject).
|
||||
'</a>';
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
use \MailPoet\Util\Security;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
@ -22,18 +21,6 @@ class Widget {
|
||||
|
||||
function registerWidget() {
|
||||
register_widget('\MailPoet\Form\Widget');
|
||||
|
||||
// subscribers count shortcode
|
||||
add_shortcode('mailpoet_subscribers_count', array(
|
||||
$this, 'getSubscribersCount'
|
||||
));
|
||||
add_shortcode('wysija_subscribers_count', array(
|
||||
$this, 'getSubscribersCount'
|
||||
));
|
||||
}
|
||||
|
||||
function getSubscribersCount($params) {
|
||||
return Subscriber::filter('subscribed')->count();
|
||||
}
|
||||
|
||||
function setupDependencies() {
|
||||
|
@ -22,8 +22,9 @@ class Supervisor {
|
||||
return $this->startDaemon();
|
||||
}
|
||||
if(
|
||||
!$this->force_start &&
|
||||
in_array($this->daemon['status'], array('stopped', 'stopping'))
|
||||
!$this->force_start
|
||||
&& isset($this->daemon['status'])
|
||||
&& in_array($this->daemon['status'], array('stopped', 'stopping'))
|
||||
) {
|
||||
return $this->daemon['status'];
|
||||
}
|
||||
|
@ -13,7 +13,9 @@ abstract class Base {
|
||||
if($block['id'] === 'segments') {
|
||||
$rules['required'] = true;
|
||||
$rules['mincheck'] = 1;
|
||||
$rules['error-message'] = __('You need to select a list');
|
||||
$rules['group'] = $block['id'];
|
||||
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||
$rules['required-message'] = __('You need to select a list');
|
||||
}
|
||||
|
||||
if(!empty($block['params']['required'])) {
|
||||
@ -29,7 +31,7 @@ abstract class Base {
|
||||
}
|
||||
}
|
||||
|
||||
if($block['type'] === 'radio') {
|
||||
if(in_array($block['type'], array('radio', 'checkbox'))) {
|
||||
$rules['group'] = 'custom_field_'.$block['id'];
|
||||
$rules['errors-container'] = '.mailpoet_error_'.$block['id'];
|
||||
$rules['required-message'] = __('You need to select at least one option.');
|
||||
|
@ -9,15 +9,16 @@ class Checkbox extends Base {
|
||||
$field_name = static::getFieldName($block);
|
||||
$field_validation = static::getInputValidation($block);
|
||||
|
||||
// TODO: check if it still makes sense
|
||||
// create hidden default value
|
||||
// $html .= '<input type="hidden"name="'.$field_name.'" value="0" '.static::getInputValidation($block).'/>';
|
||||
|
||||
$html .= '<p class="mailpoet_paragraph">';
|
||||
|
||||
$html .= static::renderLabel($block);
|
||||
|
||||
foreach($block['params']['values'] as $option) {
|
||||
$options = (!empty($block['params']['values'])
|
||||
? $block['params']['values']
|
||||
: array()
|
||||
);
|
||||
|
||||
foreach($options as $option) {
|
||||
$html .= '<label class="mailpoet_checkbox_label">';
|
||||
|
||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||
@ -35,6 +36,8 @@ class Checkbox extends Base {
|
||||
$html .= '</label>';
|
||||
}
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
|
||||
$html .= '</p>';
|
||||
|
||||
return $html;
|
||||
|
@ -13,9 +13,12 @@ class Radio extends Base {
|
||||
|
||||
$html .= static::renderLabel($block);
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
$options = (!empty($block['params']['values'])
|
||||
? $block['params']['values']
|
||||
: array()
|
||||
);
|
||||
|
||||
foreach($block['params']['values'] as $option) {
|
||||
foreach($options as $option) {
|
||||
$html .= '<label class="mailpoet_radio_label">';
|
||||
|
||||
$html .= '<input type="radio" class="mailpoet_radio" ';
|
||||
@ -33,6 +36,8 @@ class Radio extends Base {
|
||||
$html .= '</label>';
|
||||
}
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
|
||||
$html .= '</p>';
|
||||
|
||||
return $html;
|
||||
|
@ -13,23 +13,27 @@ class Segment extends Base {
|
||||
|
||||
$html .= static::renderLabel($block);
|
||||
|
||||
if(!empty($block['params']['values'])) {
|
||||
// display values
|
||||
foreach($block['params']['values'] as $segment) {
|
||||
if(!isset($segment['id']) || !isset($segment['name'])) continue;
|
||||
$options = (!empty($block['params']['values'])
|
||||
? $block['params']['values']
|
||||
: array()
|
||||
);
|
||||
|
||||
$is_checked = (isset($segment['is_checked']) && $segment['is_checked']) ? 'checked="checked"' : '';
|
||||
foreach($options as $option) {
|
||||
if(!isset($option['id']) || !isset($option['name'])) continue;
|
||||
|
||||
$html .= '<label class="mailpoet_checkbox_label">';
|
||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||
$html .= 'name="'.$field_name.'[]" ';
|
||||
$html .= 'value="'.$segment['id'].'" '.$is_checked.' ';
|
||||
$html .= $field_validation;
|
||||
$html .= ' />'.$segment['name'];
|
||||
$html .= '</label>';
|
||||
}
|
||||
$is_checked = (isset($option['is_checked']) && $option['is_checked']) ? 'checked="checked"' : '';
|
||||
|
||||
$html .= '<label class="mailpoet_checkbox_label">';
|
||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||
$html .= 'name="'.$field_name.'[]" ';
|
||||
$html .= 'value="'.$option['id'].'" '.$is_checked.' ';
|
||||
$html .= $field_validation;
|
||||
$html .= ' />'.$option['name'];
|
||||
$html .= '</label>';
|
||||
}
|
||||
|
||||
$html .= '<span class="mailpoet_error_'.$block['id'].'"></span>';
|
||||
|
||||
$html .= '</p>';
|
||||
|
||||
return $html;
|
||||
|
@ -6,11 +6,11 @@ class Submit extends Base {
|
||||
static function render($block) {
|
||||
$html = '';
|
||||
|
||||
$html .= '<input class="mailpoet_submit" type="submit" ';
|
||||
$html .= '<p class="mailpoet_submit"><input type="submit" ';
|
||||
|
||||
$html .= 'value="'.static::getFieldLabel($block).'" ';
|
||||
|
||||
$html .= '/>';
|
||||
$html .= '/></p>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
@ -194,96 +194,4 @@ class Widget extends \WP_Widget {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the content filter to replace the shortcode
|
||||
if(isset($_GET['mailpoet_page']) && strlen(trim($_GET['mailpoet_page'])) > 0) {
|
||||
switch($_GET['mailpoet_page']) {
|
||||
|
||||
case 'mailpoet_form_iframe':
|
||||
$id = (isset($_GET['mailpoet_form']) && (int)$_GET['mailpoet_form'] > 0) ? (int)$_GET['mailpoet_form'] : null;
|
||||
$form = Form::findOne($id);
|
||||
|
||||
if($form !== false) {
|
||||
// render form
|
||||
$output = Util\Export::get('html', $form->asArray());
|
||||
// $output = do_shortcode($output);
|
||||
print $output;
|
||||
exit;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// add_filter('wp_title', 'mailpoet_meta_page_title'));
|
||||
add_filter('the_title', 'mailpoet_page_title', 10, 2);
|
||||
add_filter('the_content', 'mailpoet_page_content', 98, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function mailpoet_page_title($title = '', $id = null) {
|
||||
// get signup confirmation page id
|
||||
$signup_confirmation = Setting::getValue('signup_confirmation');
|
||||
$page_id = $signup_confirmation['page'];
|
||||
|
||||
// check if we're on the signup confirmation page
|
||||
if((int)$page_id === (int)$id) {
|
||||
global $post;
|
||||
|
||||
// disable comments
|
||||
$post->comment_status = 'close';
|
||||
// disable password
|
||||
$post->post_password = '';
|
||||
|
||||
$subscriber = null;
|
||||
|
||||
// get subscriber key from url
|
||||
$subscriber_digest = (isset($_GET['mailpoet_key']) && strlen(trim($_GET['mailpoet_key'])) === 32) ? trim($_GET['mailpoet_key']) : null;
|
||||
|
||||
if($subscriber_digest !== null) {
|
||||
// get subscriber
|
||||
// TODO: change select() to selectOne() once it's implemented
|
||||
$subscribers = $mailpoet->subscribers()->select(array(
|
||||
'filter' => array(
|
||||
'subscriber_digest' => $subscriber_digest
|
||||
),
|
||||
'limit' => 1
|
||||
));
|
||||
|
||||
if(!empty($subscribers)) {
|
||||
$subscriber = array_shift($subscribers);
|
||||
}
|
||||
}
|
||||
|
||||
// check if we have a subscriber record
|
||||
if($subscriber === null) {
|
||||
return __('Your confirmation link expired, please subscribe again.');
|
||||
} else {
|
||||
// we have a subscriber, let's check its state
|
||||
switch($subscriber['subscriber_state']) {
|
||||
case MailPoetSubscribers::STATE_UNCONFIRMED:
|
||||
case MailPoetSubscribers::STATE_UNSUBSCRIBED:
|
||||
// set subscriber state as confirmed
|
||||
$mailpoet->subscribers()->update(array(
|
||||
'subscriber' => $subscriber['subscriber'],
|
||||
'subscriber_state' => MailPoetSubscribers::STATE_SUBSCRIBED,
|
||||
'subscriber_confirmed_at' => time()
|
||||
));
|
||||
return __("You've subscribed");
|
||||
break;
|
||||
case MailPoetSubscribers::STATE_SUBSCRIBED:
|
||||
return __("You've already subscribed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
|
||||
function mailpoet_page_content($content = '') {
|
||||
if(strpos($content, '[mailpoet_page]') !== FALSE) {
|
||||
$content = str_replace('[mailpoet_page]', '', $content);
|
||||
}
|
||||
return $content;
|
||||
}
|
@ -16,27 +16,73 @@ class Setting extends Model {
|
||||
}
|
||||
|
||||
public static function getValue($key, $default = null) {
|
||||
$setting = Setting::where('name', $key)->findOne();
|
||||
if($setting === false) {
|
||||
return $default;
|
||||
} else {
|
||||
if(is_serialized($setting->value)) {
|
||||
return unserialize($setting->value);
|
||||
$keys = explode('.', $key);
|
||||
|
||||
if(count($keys) === 1) {
|
||||
$setting = Setting::where('name', $key)->findOne();
|
||||
if($setting === false) {
|
||||
return $default;
|
||||
} else {
|
||||
return $setting->value;
|
||||
if(is_serialized($setting->value)) {
|
||||
return unserialize($setting->value);
|
||||
} else {
|
||||
return $setting->value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$main_key = array_shift($keys);
|
||||
|
||||
$setting = static::getValue($main_key, $default);
|
||||
|
||||
if($setting !== $default) {
|
||||
for($i = 0, $count = count($keys); $i < $count; $i++) {
|
||||
if(array_key_exists($keys[$i], $setting)) {
|
||||
$setting = $setting[$keys[$i]];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $setting;
|
||||
}
|
||||
}
|
||||
|
||||
public static function setValue($key, $value) {
|
||||
if(is_array($value)) {
|
||||
$value = serialize($value);
|
||||
}
|
||||
$keys = explode('.', $key);
|
||||
|
||||
return Setting::createOrUpdate(array(
|
||||
'name' => $key,
|
||||
'value' => $value
|
||||
));
|
||||
if(count($keys) === 1) {
|
||||
if(is_array($value)) {
|
||||
$value = serialize($value);
|
||||
}
|
||||
|
||||
return Setting::createOrUpdate(array(
|
||||
'name' => $key,
|
||||
'value' => $value
|
||||
));
|
||||
} else {
|
||||
$main_key = array_shift($keys);
|
||||
|
||||
$setting_value = static::getValue($main_key, array());
|
||||
$current_value = &$setting_value;
|
||||
$last_key = array_pop($keys);
|
||||
|
||||
foreach($keys as $key) {
|
||||
if(!is_array($current_value)) {
|
||||
$current_value = array();
|
||||
}
|
||||
|
||||
if(!array_key_exists($key, $current_value)) {
|
||||
$current_value = array($key => array());
|
||||
}
|
||||
$current_value =& $current_value[$key];
|
||||
}
|
||||
if(is_scalar($current_value)) {
|
||||
$current_value = array();
|
||||
}
|
||||
$current_value[$last_key] = $value;
|
||||
|
||||
return static::setValue($main_key, $setting_value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getAll() {
|
||||
|
@ -32,6 +32,51 @@ class Subscriber extends Model {
|
||||
return parent::delete();
|
||||
}
|
||||
|
||||
function addToSegments(array $segment_ids = array()) {
|
||||
$segments = Segment::whereIn('id', $segment_ids)->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $this->id;
|
||||
$association->segment_id = $segment->id;
|
||||
$association->save();
|
||||
}
|
||||
}
|
||||
|
||||
function sendConfirmationEmail() {
|
||||
$this->set('status', 'unconfirmed');
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
static function subscribe($subscriber_data = array(), $segment_ids = array()) {
|
||||
if(empty($subscriber_data) or empty($segment_ids)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subscriber = static::createOrUpdate($subscriber_data);
|
||||
|
||||
if($subscriber !== false && $subscriber->id() > 0) {
|
||||
// restore deleted subscriber
|
||||
if($subscriber->deleted_at !== NULL) {
|
||||
$subscriber->setExpr('deleted_at', 'NULL');
|
||||
}
|
||||
|
||||
if((bool)Setting::getValue('signup_confirmation.enabled')) {
|
||||
if($subscriber->status !== 'subscribed') {
|
||||
$subscriber->sendConfirmationEmail();
|
||||
}
|
||||
} else {
|
||||
$subscriber->set('status', 'subscribed');
|
||||
}
|
||||
|
||||
if($subscriber->save()) {
|
||||
$subscriber->addToSegments($segment_ids);
|
||||
}
|
||||
}
|
||||
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
if(strlen(trim($search) === 0)) {
|
||||
return $orm;
|
||||
@ -181,21 +226,82 @@ class Subscriber extends Model {
|
||||
$subscriber = false;
|
||||
|
||||
if(isset($data['id']) && (int)$data['id'] > 0) {
|
||||
$subscriber = self::findOne((int)$data['id']);
|
||||
$subscriber = static::findOne((int)$data['id']);
|
||||
unset($data['id']);
|
||||
}
|
||||
|
||||
if($subscriber === false && !empty($data['email'])) {
|
||||
$subscriber = static::where('email', $data['email'])->findOne();
|
||||
if($subscriber !== false) {
|
||||
unset($data['email']);
|
||||
}
|
||||
}
|
||||
|
||||
// custom fields
|
||||
$custom_fields = array();
|
||||
|
||||
foreach($data as $key => $value) {
|
||||
if(strpos($key, 'cf_') === 0) {
|
||||
$custom_fields[(int)substr($key, 3)] = $value;
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if($subscriber === false) {
|
||||
$subscriber = self::create();
|
||||
$subscriber = static::create();
|
||||
$subscriber->hydrate($data);
|
||||
} else {
|
||||
$subscriber->set($data);
|
||||
}
|
||||
|
||||
$subscriber->save();
|
||||
if($subscriber->save()) {
|
||||
if(!empty($custom_fields)) {
|
||||
foreach($custom_fields as $custom_field_id => $value) {
|
||||
$subscriber->setCustomField($custom_field_id, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
function withCustomFields() {
|
||||
$custom_fields = CustomField::select('id')->findArray();
|
||||
if(empty($custom_fields)) return $this;
|
||||
|
||||
$custom_field_ids = Helpers::arrayColumn($custom_fields, 'id');
|
||||
$relations = SubscriberCustomField::select('custom_field_id')
|
||||
->select('value')
|
||||
->whereIn('custom_field_id', $custom_field_ids)
|
||||
->where('subscriber_id', $this->id())
|
||||
->findMany();
|
||||
foreach($relations as $relation) {
|
||||
$this->{'cf_'.$relation->custom_field_id} = $relation->value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
function getCustomField($custom_field_id, $default = null) {
|
||||
$custom_field = SubscriberCustomField::select('value')
|
||||
->where('custom_field_id', $custom_field_id)
|
||||
->where('subscriber_id', $this->id())
|
||||
->findOne();
|
||||
|
||||
if($custom_field === false) {
|
||||
return $default;
|
||||
} else {
|
||||
return $custom_field->value;
|
||||
}
|
||||
}
|
||||
|
||||
function setCustomField($custom_field_id, $value) {
|
||||
return SubscriberCustomField::createOrUpdate(array(
|
||||
'subscriber_id' => $this->id(),
|
||||
'custom_field_id' => $custom_field_id,
|
||||
'value' => $value
|
||||
));
|
||||
}
|
||||
|
||||
static function bulkMoveToList($orm, $data = array()) {
|
||||
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
||||
$segment = Segment::findOne($segment_id);
|
||||
@ -273,8 +379,7 @@ class Subscriber extends Model {
|
||||
|
||||
if(!empty($subscribers)) {
|
||||
foreach($subscribers as $subscriber) {
|
||||
// TODO: send confirmation email
|
||||
// $subscriber->sendConfirmationEmail()
|
||||
$subscriber->sendConfirmationEmail();
|
||||
}
|
||||
|
||||
return $subscribers->count();
|
||||
|
@ -12,6 +12,49 @@ class SubscriberCustomField extends Model {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
static function createOrUpdate($data = array()) {
|
||||
$custom_field = CustomField::findOne($data['custom_field_id']);
|
||||
if($custom_field === false) {
|
||||
return false;
|
||||
} else {
|
||||
$custom_field = $custom_field->asArray();
|
||||
}
|
||||
|
||||
if($custom_field['type'] === 'date') {
|
||||
if(is_array($data['value'])) {
|
||||
$day = (
|
||||
isset($data['value']['day'])
|
||||
? (int)$data['value']['day']
|
||||
: 1
|
||||
);
|
||||
$month = (
|
||||
isset($data['value']['month'])
|
||||
? (int)$data['value']['month']
|
||||
: 1
|
||||
);
|
||||
$year = (
|
||||
isset($data['value']['year'])
|
||||
? (int)$data['value']['year']
|
||||
: 1970
|
||||
);
|
||||
$data['value'] = mktime(0, 0, 0, $month, $day, $year);
|
||||
}
|
||||
}
|
||||
|
||||
$relation = self::where('custom_field_id', $data['custom_field_id'])
|
||||
->where('subscriber_id', $data['subscriber_id'])
|
||||
->findOne();
|
||||
|
||||
if($relation === false) {
|
||||
$relation = self::create();
|
||||
$relation->hydrate($data);
|
||||
} else {
|
||||
$relation->set($data);
|
||||
}
|
||||
|
||||
return $relation->save();
|
||||
}
|
||||
|
||||
static function createMultiple($values) {
|
||||
$values = array_map('array_values', $values);
|
||||
return self::rawExecute(
|
||||
|
@ -33,6 +33,10 @@ class SubscriberSegment extends Model {
|
||||
return $orm;
|
||||
}
|
||||
|
||||
static function subscribed($orm) {
|
||||
return $orm->where('status', 'subscribed');
|
||||
}
|
||||
|
||||
static function createMultiple($segmnets, $subscribers) {
|
||||
$values = Helpers::flattenArray(
|
||||
array_map(function ($segment) use ($subscribers) {
|
||||
|
@ -18,15 +18,19 @@ class CustomFields {
|
||||
}
|
||||
|
||||
function delete($id) {
|
||||
$result = false;
|
||||
|
||||
$custom_field = CustomField::findOne($id);
|
||||
if($custom_field !== false) {
|
||||
if($custom_field === false or !$custom_field->id()) {
|
||||
wp_send_json(array(
|
||||
'result' => false
|
||||
));
|
||||
} else {
|
||||
$custom_field->delete();
|
||||
$result = true;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
wp_send_json(array(
|
||||
'result' => true,
|
||||
'field' => $custom_field->asArray()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
|
@ -30,10 +30,6 @@ class NewsletterTemplates {
|
||||
}
|
||||
|
||||
function save($data = array()) {
|
||||
if (isset($data['body'])) {
|
||||
$data['body'] = json_encode($data['body']);
|
||||
}
|
||||
|
||||
$result = NewsletterTemplate::createOrUpdate($data);
|
||||
if($result !== true) {
|
||||
wp_send_json($result);
|
||||
|
@ -59,10 +59,6 @@ class Newsletters {
|
||||
unset($data['options']);
|
||||
}
|
||||
|
||||
if (isset($data['body'])) {
|
||||
$data['body'] = json_encode($data['body']);
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
$result = false;
|
||||
|
||||
@ -221,6 +217,45 @@ class Newsletters {
|
||||
wp_send_json(array('rendered_body' => $renderer->render()));
|
||||
}
|
||||
|
||||
function sendPreview($data = array()) {
|
||||
$id = (isset($data['id'])) ? (int) $data['id'] : 0;
|
||||
$newsletter = Newsletter::findOne($id);
|
||||
|
||||
if($newsletter === false) {
|
||||
wp_send_json(array(
|
||||
'result' => false
|
||||
));
|
||||
}
|
||||
if(empty($data['subscriber'])) {
|
||||
wp_send_json(array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please specify receiver information')),
|
||||
));
|
||||
}
|
||||
|
||||
$newsletter = $newsletter->asArray();
|
||||
|
||||
$renderer = new Renderer($newsletter);
|
||||
$rendered_body = $renderer->render();
|
||||
$newsletter['body'] = array(
|
||||
'html' => $rendered_body,
|
||||
'text' => '',
|
||||
);
|
||||
|
||||
try {
|
||||
$mailer = new \MailPoet\Mailer\Mailer(false, false, false);
|
||||
|
||||
wp_send_json(array(
|
||||
'result' => $mailer->send($newsletter, $data['subscriber'])
|
||||
));
|
||||
} catch(\Exception $e) {
|
||||
wp_send_json(array(
|
||||
'result' => false,
|
||||
'errors' => array($e->getMessage()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
function listing($data = array()) {
|
||||
$listing = new Listing\Handler(
|
||||
'\MailPoet\Models\Newsletter',
|
||||
|
@ -24,7 +24,7 @@ class Subscribers {
|
||||
} else {
|
||||
$segments = $subscriber->segments()->findArray();
|
||||
|
||||
$subscriber = $subscriber->asArray();
|
||||
$subscriber = $subscriber->withCustomFields()->asArray();
|
||||
$subscriber['segments'] = array_map(function($segment) {
|
||||
return $segment['id'];
|
||||
}, $segments);
|
||||
@ -68,10 +68,10 @@ class Subscribers {
|
||||
function save($data = array()) {
|
||||
$errors = array();
|
||||
$result = false;
|
||||
$segments = false;
|
||||
$segment_ids = array();
|
||||
|
||||
if(array_key_exists('segments', $data)) {
|
||||
$segments = $data['segments'];
|
||||
$segment_ids = (array)$data['segments'];
|
||||
unset($data['segments']);
|
||||
}
|
||||
|
||||
@ -82,18 +82,8 @@ class Subscribers {
|
||||
} else {
|
||||
$result = true;
|
||||
|
||||
if($segments !== false) {
|
||||
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
||||
->deleteMany();
|
||||
|
||||
if(!empty($segments)) {
|
||||
foreach($segments as $segment_id) {
|
||||
$relation = SubscriberSegment::create();
|
||||
$relation->segment_id = $segment_id;
|
||||
$relation->subscriber_id = $subscriber->id;
|
||||
$relation->save();
|
||||
}
|
||||
}
|
||||
if(!empty($segment_ids)) {
|
||||
$subscriber->addToSegments($segment_ids);
|
||||
}
|
||||
}
|
||||
wp_send_json(array(
|
||||
@ -112,109 +102,37 @@ class Subscribers {
|
||||
$errors[] = __('This form does not exist.');
|
||||
}
|
||||
|
||||
if(empty($data['segments'])) {
|
||||
$errors[] = __('You need to select a list');
|
||||
} else {
|
||||
$segments = Segment::whereIn('id', (array)$data['segments'])->findMany();
|
||||
|
||||
if(empty($segments)) {
|
||||
$errors[] = __('You need to select a list');
|
||||
}
|
||||
}
|
||||
$segment_ids = (!empty($data['segments'])
|
||||
? (array)$data['segments']
|
||||
: array()
|
||||
);
|
||||
unset($data['segments']);
|
||||
|
||||
$subscriber = false;
|
||||
if(empty($segment_ids)) {
|
||||
$errors[] = __('You need to select a list');
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
wp_send_json(array('errors' => $errors));
|
||||
} else {
|
||||
if(!empty($data['email'])) {
|
||||
$subscriber = Subscriber::where('email', $data['email'])->findOne();
|
||||
}
|
||||
}
|
||||
|
||||
$signup_confirmation = Setting::getValue('signup_confirmation', array());
|
||||
|
||||
if($subscriber === false) {
|
||||
// create new subscriber
|
||||
$data['status'] = (
|
||||
(!empty($signup_confirmation['enabled']))
|
||||
? 'unconfirmed' : 'subscribed'
|
||||
);
|
||||
|
||||
// custom fields
|
||||
$custom_fields = array();
|
||||
foreach($data as $key => $value) {
|
||||
if(strpos($key, 'cf_') === 0) {
|
||||
$custom_fields[substr($key, 3)] = $value;
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// insert new subscriber
|
||||
$subscriber = Subscriber::createOrUpdate($data);
|
||||
|
||||
if($subscriber === false || !$subscriber->id()) {
|
||||
$errors = array_merge($errors, $subscriber->getValidationErrors());
|
||||
} else {
|
||||
// add custom fields
|
||||
if(!empty($custom_fields)) {
|
||||
foreach($custom_fields as $custom_field_id => $value) {
|
||||
if(is_array($value)) {
|
||||
// date
|
||||
$value = mktime(0, 0, 0, $value['month'], $value['day'], $value['year']);
|
||||
}
|
||||
$subscriber_custom_field = SubscriberCustomField::create();
|
||||
$subscriber_custom_field->hydrate(array(
|
||||
'subscriber_id' => $subscriber->id(),
|
||||
'custom_field_id' => $custom_field_id,
|
||||
'value' => $value
|
||||
));
|
||||
$subscriber_custom_field->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$subscriber->set('status', (
|
||||
!empty($signup_confirmation['enabled'])
|
||||
? 'unconfirmed' : 'subscribed'
|
||||
wp_send_json(array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
));
|
||||
|
||||
// restore deleted subscriber
|
||||
if($subscriber->deleted_at !== NULL) {
|
||||
$subscriber->setExpr('deleted_at', 'NULL');
|
||||
}
|
||||
|
||||
if(!$subscriber->save()) {
|
||||
$errors[] = __('An error occurred. Please try again later.');
|
||||
}
|
||||
}
|
||||
|
||||
// get segments
|
||||
// IDEA: $subscriptions->addToSegments($data['segments']);
|
||||
$segments_subscribed = array();
|
||||
foreach($segments as $segment) {
|
||||
if($segment->addSubscriber($subscriber->id())) {
|
||||
$segments_subscribed[] = $segment->id;
|
||||
}
|
||||
$subscriber = Subscriber::subscribe($data, $segment_ids);
|
||||
|
||||
$result = false;
|
||||
if($subscriber === false || !$subscriber->id()) {
|
||||
$errors = array_merge($errors, $subscriber->getValidationErrors());
|
||||
} else {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
// if signup confirmation is enabled and the subscriber is unconfirmed
|
||||
if(!empty($signup_confirmation['enabled'])
|
||||
&& !empty($segments_subscribed)
|
||||
&& $subscriber->status !== 'subscribed'
|
||||
) {
|
||||
// TODO: send confirmation email
|
||||
// resend confirmation email
|
||||
$is_sent = true;
|
||||
/*$is_sent = static::sendSignupConfirmation(
|
||||
$subscriber->asArray(),
|
||||
$segments->asArray()
|
||||
);*/
|
||||
|
||||
// error message if the email could not be sent
|
||||
if($is_sent === false) {
|
||||
$errors[] = __('The signup confirmation email could not be sent. Please check your settings.');
|
||||
}
|
||||
if(!empty($errors)) {
|
||||
wp_send_json(array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
));
|
||||
}
|
||||
|
||||
// get success message to display after subscription
|
||||
@ -223,15 +141,6 @@ class Subscribers {
|
||||
? unserialize($form->settings) : null
|
||||
);
|
||||
|
||||
if(!empty($errors)) {
|
||||
wp_send_json(array(
|
||||
'result' => false,
|
||||
'errors' => $errors
|
||||
));
|
||||
} else {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
if($form_settings !== null) {
|
||||
$message = $form_settings['success_message'];
|
||||
|
||||
@ -274,7 +183,7 @@ class Subscribers {
|
||||
// response depending on context
|
||||
if($doing_ajax === true) {
|
||||
wp_send_json(array(
|
||||
'result' => $result,
|
||||
'result' => true,
|
||||
'message' => $message
|
||||
));
|
||||
} else {
|
||||
|
@ -2,22 +2,71 @@
|
||||
namespace MailPoet\Settings;
|
||||
|
||||
class Pages {
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
static function getAll() {
|
||||
$mailpoet_pages = \get_posts(array(
|
||||
function init() {
|
||||
register_post_type('mailpoet_page', array(
|
||||
'labels' => array(
|
||||
'name' => __('MailPoet Page'),
|
||||
'singular_name' => __('MailPoet Page')
|
||||
),
|
||||
'public' => true,
|
||||
'has_archive' => false,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => false,
|
||||
'rewrite' => false,
|
||||
'show_in_nav_menus'=>false,
|
||||
'can_export'=>false,
|
||||
'publicly_queryable'=>true,
|
||||
'exclude_from_search'=>true
|
||||
));
|
||||
}
|
||||
|
||||
static function createMailPoetPage() {
|
||||
remove_all_actions('pre_post_update');
|
||||
remove_all_actions('save_post');
|
||||
remove_all_actions('wp_insert_post');
|
||||
|
||||
$id = wp_insert_post(array(
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'mailpoet_page',
|
||||
'post_author' => 1,
|
||||
'post_content' => '[mailpoet_page]',
|
||||
'post_title' => __('MailPoet Page'),
|
||||
'post_name' => 'subscriptions'
|
||||
));
|
||||
flush_rewrite_rules();
|
||||
|
||||
return ((int)$id > 0) ? (int)$id : false;
|
||||
}
|
||||
|
||||
static function getMailPoetPages() {
|
||||
return get_posts(array(
|
||||
'post_type' => 'mailpoet_page'
|
||||
));
|
||||
}
|
||||
|
||||
static function getAll() {
|
||||
$all_pages = array_merge(
|
||||
static::getMailPoetPages(),
|
||||
get_pages()
|
||||
);
|
||||
|
||||
$pages = array();
|
||||
foreach(array_merge($mailpoet_pages, \get_pages()) as $page) {
|
||||
$pages[] = array(
|
||||
'id' => $page->ID,
|
||||
'title' => $page->post_title,
|
||||
'preview_url' => \get_permalink($page->ID),
|
||||
'edit_url' => \get_edit_post_link($page->ID)
|
||||
);
|
||||
foreach($all_pages as $page) {
|
||||
$pages[] = static::getPageData($page);
|
||||
}
|
||||
|
||||
return $pages;
|
||||
}
|
||||
|
||||
static function getPageData($page) {
|
||||
return array(
|
||||
'id' => $page->ID,
|
||||
'title' => $page->post_title,
|
||||
'preview_url' => get_permalink($page->ID),
|
||||
'edit_url' => get_edit_post_link($page->ID)
|
||||
);
|
||||
}
|
||||
}
|
@ -113,7 +113,7 @@ class MailChimp {
|
||||
'invalid' => false,
|
||||
'duplicate' => false,
|
||||
'header' => $header,
|
||||
'count' => count($subscribers)
|
||||
'subscribersCount' => count($subscribers)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
85
lib/Subscription/Comment.php
Normal file
85
lib/Subscription/Comment.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
|
||||
class Comment {
|
||||
const SPAM = 'spam';
|
||||
const APPROVED = 1;
|
||||
const PENDING_APPROVAL = 0;
|
||||
|
||||
static function extendForm() {
|
||||
$label = Setting::getValue(
|
||||
'subscribe.on_comment.label',
|
||||
__('Yes, add me to your mailing list.')
|
||||
);
|
||||
|
||||
print '<p class="comment-form-mailpoet">
|
||||
<label for="mailpoet_subscribe_on_comment">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="mailpoet_subscribe_on_comment"
|
||||
value="1"
|
||||
name="mailpoet[subscribe_on_comment]"
|
||||
/> '.esc_attr($label).'
|
||||
</label>
|
||||
</p>';
|
||||
}
|
||||
|
||||
static function onSubmit($comment_id, $comment_status) {
|
||||
if($comment_status === Comment::SPAM) return;
|
||||
|
||||
if(
|
||||
isset($_POST['mailpoet']['subscribe_on_comment'])
|
||||
&& (bool)$_POST['mailpoet']['subscribe_on_comment'] === true
|
||||
) {
|
||||
if($comment_status === Comment::PENDING_APPROVAL) {
|
||||
// add a comment meta to remember to subscribe the user
|
||||
// once the comment gets approved
|
||||
add_comment_meta(
|
||||
$comment_id,
|
||||
'mailpoet',
|
||||
'subscribe_on_comment',
|
||||
true
|
||||
);
|
||||
} else if($comment_status === Comment::APPROVED) {
|
||||
static::subscribeAuthorOfComment($comment_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function onStatusUpdate($comment_id, $action) {
|
||||
if($action === 'approve') {
|
||||
// check if the comment's author wants to subscribe
|
||||
$do_subscribe = (
|
||||
get_comment_meta(
|
||||
$comment_id,
|
||||
'mailpoet',
|
||||
true
|
||||
) === 'subscribe_on_comment'
|
||||
);
|
||||
|
||||
if($do_subscribe === true) {
|
||||
static::subscribeAuthorOfComment($comment_id);
|
||||
|
||||
delete_comment_meta($comment_id, 'mailpoet');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function subscribeAuthorOfComment($comment_id) {
|
||||
$segment_ids = Setting::getValue('subscribe.on_comment.segments', array());
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
$comment = get_comment($comment_id);
|
||||
|
||||
$result = Subscriber::subscribe(
|
||||
array(
|
||||
'email' => $comment->comment_author_email,
|
||||
'first_name' => $comment->comment_author
|
||||
),
|
||||
$segment_ids
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
74
lib/Subscription/Registration.php
Normal file
74
lib/Subscription/Registration.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
namespace MailPoet\Subscription;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Subscriber;
|
||||
|
||||
class Registration {
|
||||
|
||||
static function extendForm() {
|
||||
$label = Setting::getValue(
|
||||
'subscribe.on_register.label',
|
||||
__('Yes, add me to your mailing list.')
|
||||
);
|
||||
|
||||
print '<p class="registration-form-mailpoet">
|
||||
<label for="mailpoet_subscribe_on_register">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="mailpoet_subscribe_on_register"
|
||||
value="1"
|
||||
name="mailpoet[subscribe_on_register]"
|
||||
/> '.esc_attr($label).'
|
||||
</label>
|
||||
</p>';
|
||||
}
|
||||
|
||||
static function onMultiSiteRegister($result) {
|
||||
if(empty($result['errors']->errors)) {
|
||||
if(
|
||||
isset($_POST['mailpoet']['subscribe_on_register'])
|
||||
&& (bool)$_POST['mailpoet']['subscribe_on_register'] === true
|
||||
) {
|
||||
static::subscribeNewUser(
|
||||
$result['user_name'],
|
||||
$result['user_email']
|
||||
);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function onRegister(
|
||||
$user_login,
|
||||
$user_email = null,
|
||||
$errors = null
|
||||
) {
|
||||
if(
|
||||
empty($errors->errors)
|
||||
&& isset($_POST['mailpoet']['subscribe_on_register'])
|
||||
&& (bool)$_POST['mailpoet']['subscribe_on_register'] === true
|
||||
) {
|
||||
static::subscribeNewUser(
|
||||
$user_login,
|
||||
$user_email
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static function subscribeNewUser($name, $email) {
|
||||
$segment_ids = Setting::getValue(
|
||||
'subscribe.on_register.segments',
|
||||
array()
|
||||
);
|
||||
|
||||
if(!empty($segment_ids)) {
|
||||
Subscriber::subscribe(
|
||||
array(
|
||||
'email' => $email,
|
||||
'first_name' => $name
|
||||
),
|
||||
$segment_ids
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -38,7 +38,8 @@ class i18n extends \Twig_Extension {
|
||||
$output[] = '<script type="text/javascript">';
|
||||
$output[] = ' var MailPoetI18n = MailPoetI18n || {}';
|
||||
foreach($translations as $key => $translation) {
|
||||
$output[] = 'MailPoetI18n[\''.$key.'\'] = "'.$translation.'";';
|
||||
$output[] =
|
||||
'MailPoetI18n["'.$key.'"] = "'. str_replace('"', '\"', $translation) . '";';
|
||||
}
|
||||
$output[] = '</script>';
|
||||
return join("\n", $output);
|
||||
|
@ -5,7 +5,7 @@ if (!defined('ABSPATH')) exit;
|
||||
|
||||
/*
|
||||
* Plugin Name: MailPoet
|
||||
* Version: 0.0.10
|
||||
* Version: 0.0.12
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: MailPoet Newsletters.
|
||||
* Author: MailPoet
|
||||
@ -23,7 +23,7 @@ if (!defined('ABSPATH')) exit;
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
define('MAILPOET_VERSION', '0.0.10');
|
||||
define('MAILPOET_VERSION', '0.0.12');
|
||||
|
||||
$initializer = new Initializer(array(
|
||||
'file' => __FILE__,
|
||||
|
@ -25,7 +25,6 @@
|
||||
"papaparse": "4.1.1",
|
||||
"parsleyjs": "^2.1.2",
|
||||
"react": "0.14.3",
|
||||
"react-checkbox-group": "0.2.2",
|
||||
"react-dom": "0.14.3",
|
||||
"react-infinity": "1.2.2",
|
||||
"react-prefixr": "0.1.0",
|
||||
|
@ -1,21 +1,18 @@
|
||||
define([
|
||||
'newsletter_editor/App',
|
||||
'newsletter_editor/components/save',
|
||||
'amd-inject-loader!newsletter_editor/components/save'
|
||||
], function(EditorApplication, SaveComponent, SaveInjector) {
|
||||
'amd-inject-loader!newsletter_editor/components/save',
|
||||
'jquery'
|
||||
], function(EditorApplication, SaveComponent, SaveInjector, jQuery) {
|
||||
|
||||
describe('Save', function() {
|
||||
describe('save method', function() {
|
||||
var module;
|
||||
before(function() {
|
||||
module = SaveInjector({
|
||||
'mailpoet': {
|
||||
Ajax: {
|
||||
post: function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
}
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: function() {
|
||||
return jQuery.Deferred();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -26,29 +23,41 @@ define([
|
||||
global.stubChannel(EditorApplication, {
|
||||
trigger: spy,
|
||||
});
|
||||
EditorApplication.toJSON = sinon.stub();
|
||||
EditorApplication.toJSON = sinon.stub().returns({
|
||||
body: {
|
||||
type: 'container',
|
||||
},
|
||||
});
|
||||
module.save();
|
||||
expect(spy.withArgs('beforeEditorSave').calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('triggers afterEditorSave event', function() {
|
||||
var stub = sinon.stub().callsArgWith(2, { success: true }),
|
||||
spy = sinon.spy();
|
||||
var spy = sinon.spy(),
|
||||
promise = jQuery.Deferred();
|
||||
global.stubChannel(EditorApplication, {
|
||||
trigger: spy,
|
||||
});
|
||||
EditorApplication.toJSON = sinon.stub();
|
||||
EditorApplication.toJSON = sinon.stub().returns({
|
||||
body: {
|
||||
type: 'container',
|
||||
},
|
||||
});
|
||||
var module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: sinon.stub().returns(promise),
|
||||
}
|
||||
});
|
||||
promise.resolve({ success: true });
|
||||
module.save();
|
||||
expect(spy.withArgs('afterEditorSave').calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('sends newsletter json to server for saving', function() {
|
||||
var mock = sinon.mock({ saveNewsletter: function() {} }).expects('saveNewsletter').once().returns(jQuery.Deferred());
|
||||
var mock = sinon.mock().once().returns(jQuery.Deferred());
|
||||
var module = SaveInjector({
|
||||
'mailpoet': {
|
||||
Ajax: {
|
||||
post: mock,
|
||||
}
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: mock,
|
||||
}
|
||||
});
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -58,6 +67,29 @@ define([
|
||||
|
||||
mock.verify();
|
||||
});
|
||||
|
||||
it('encodes newsletter body in JSON format', function() {
|
||||
var body = {type: 'testType'},
|
||||
mock = sinon.mock()
|
||||
.once()
|
||||
.withArgs({
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
.returns(jQuery.Deferred());
|
||||
global.stubChannel(EditorApplication);
|
||||
|
||||
EditorApplication.toJSON = sinon.stub().returns({
|
||||
body: body,
|
||||
});
|
||||
var module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: mock,
|
||||
}
|
||||
});
|
||||
module.save();
|
||||
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
|
||||
describe('view', function() {
|
||||
|
@ -79,6 +79,31 @@ class SettingCest {
|
||||
expect($record->value)->equals('new data');
|
||||
}
|
||||
|
||||
function itCanGetAndSetValue() {
|
||||
expect(Setting::setValue('test', '123'))->true();
|
||||
expect(Setting::getValue('test'))->equals('123');
|
||||
}
|
||||
|
||||
function itCanGetAndSetNestedValue() {
|
||||
expect(Setting::setValue('test.key', '123'))->true();
|
||||
expect(Setting::getValue('test.key'))->equals('123');
|
||||
|
||||
expect(Setting::setValue('test.key.subkey', '123'))->true();
|
||||
expect(Setting::setValue('test.key.subkey2', '456'))->true();
|
||||
|
||||
expect(Setting::getValue('test.key'))->notEmpty();
|
||||
expect(Setting::getValue('test.key.subkey'))->equals('123');
|
||||
expect(Setting::getValue('test.key.subkey2'))->equals('456');
|
||||
}
|
||||
|
||||
function itCanSetValueToNull() {
|
||||
expect(Setting::setValue('test.key', true))->true();
|
||||
expect(Setting::getValue('test.key'))->equals(true);
|
||||
|
||||
expect(Setting::setValue('test.key', null))->true();
|
||||
expect(Setting::getValue('test.key'))->null();
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::forTable(Setting::$_table)
|
||||
->deleteMany();
|
||||
|
@ -317,6 +317,102 @@ class SubscriberCest {
|
||||
expect($subscribers[0]['first_name'])->equals($values[0]['first_name']);
|
||||
}
|
||||
|
||||
function itCanSubscribe() {
|
||||
$segment = Segment::create();
|
||||
$segment->hydrate(array('name' => 'List #1'));
|
||||
$segment->save();
|
||||
|
||||
$segment2 = Segment::create();
|
||||
$segment2->hydrate(array('name' => 'List #2'));
|
||||
$segment2->save();
|
||||
|
||||
$subscriber = Subscriber::subscribe(
|
||||
$this->data,
|
||||
array($segment->id(), $segment2->id())
|
||||
);
|
||||
|
||||
expect($subscriber->id() > 0)->equals(true);
|
||||
expect($subscriber->segments()->count())->equals(2);
|
||||
expect($subscriber->email)->equals($this->data['email']);
|
||||
expect($subscriber->first_name)->equals($this->data['first_name']);
|
||||
expect($subscriber->last_name)->equals($this->data['last_name']);
|
||||
expect($subscriber->status)->equals('subscribed');
|
||||
expect($subscriber->deleted_at)->equals(null);
|
||||
}
|
||||
|
||||
function itCanBeAddedToSegments() {
|
||||
$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 itCanBeUpdatedByEmail() {
|
||||
$subscriber_updated = Subscriber::createOrUpdate(array(
|
||||
'email' => $this->data['email'],
|
||||
'first_name' => 'JoJo',
|
||||
'last_name' => 'DoDo'
|
||||
));
|
||||
|
||||
expect($this->subscriber->id())->equals($subscriber_updated->id());
|
||||
|
||||
$subscriber = Subscriber::findOne($this->subscriber->id());
|
||||
expect($subscriber->email)->equals($this->data['email']);
|
||||
expect($subscriber->first_name)->equals('JoJo');
|
||||
expect($subscriber->last_name)->equals('DoDo');
|
||||
}
|
||||
|
||||
function itCanSetCustomField() {
|
||||
$custom_field = CustomField::createOrUpdate(array(
|
||||
'name' => 'Date of Birth',
|
||||
'type' => 'date'
|
||||
));
|
||||
|
||||
expect($custom_field->id() > 0)->true();
|
||||
|
||||
$value = array(
|
||||
'year' => 1984,
|
||||
'month' => 3,
|
||||
'day' => 9
|
||||
);
|
||||
|
||||
$subscriber = Subscriber::findOne($this->subscriber->id());
|
||||
$subscriber->setCustomField($custom_field->id(), $value);
|
||||
|
||||
$subscriber = $subscriber->withCustomFields()->asArray();
|
||||
|
||||
expect($subscriber['cf_'.$custom_field->id()])->equals(
|
||||
mktime(0, 0, 0, $value['month'], $value['day'], $value['year'])
|
||||
);
|
||||
}
|
||||
|
||||
function itCanGetCustomField() {
|
||||
$subscriber = Subscriber::findOne($this->subscriber->id());
|
||||
|
||||
expect($subscriber->getCustomField(9999, 'default_value'))
|
||||
->equals('default_value');
|
||||
|
||||
$custom_field = CustomField::createOrUpdate(array(
|
||||
'name' => 'Custom field: text input',
|
||||
'type' => 'input'
|
||||
));
|
||||
|
||||
$subscriber->setCustomField($custom_field->id(), 'non_default_value');
|
||||
|
||||
expect($subscriber->getCustomField($custom_field->id(), 'default_value'))
|
||||
->equals('non_default_value');
|
||||
}
|
||||
|
||||
function _after() {
|
||||
ORM::forTable(Subscriber::$_table)
|
||||
->deleteMany();
|
||||
|
@ -58,7 +58,7 @@ class MailChimpCest {
|
||||
expect(isset($subscribers['data']['duplicate']))->true();
|
||||
expect(isset($subscribers['data']['header']))->true();
|
||||
expect(count($subscribers['data']['subscribers']))->equals(1);
|
||||
expect($subscribers['data']['count'])->equals(1);
|
||||
expect($subscribers['data']['subscribersCount'])->equals(1);
|
||||
}
|
||||
|
||||
function itFailsWhenListHeadersDontMatch() {
|
||||
|
@ -66,7 +66,7 @@
|
||||
type="radio"
|
||||
name="on_success"
|
||||
value="message"
|
||||
<% if(form.data.settings.on_success is empty or form.data.settings.on_success == 'message') %>
|
||||
<% if(form.settings.on_success is empty or form.settings.on_success == 'message') %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('Show message') %>
|
||||
@ -77,15 +77,15 @@
|
||||
type="radio"
|
||||
name="on_success"
|
||||
value="page"
|
||||
<% if(form.data.settings.on_success == 'page') %>
|
||||
<% if(form.settings.on_success == 'page') %>
|
||||
checked="checked"
|
||||
<% endif %>
|
||||
/><%= __('Go to page') %>
|
||||
</label>
|
||||
</p>
|
||||
<!-- default success message -->
|
||||
<% if form.data.settings.success_message %>
|
||||
<% set success_message = form.data.settings.success_message %>
|
||||
<% if form.settings.success_message %>
|
||||
<% set success_message = form.settings.success_message %>
|
||||
<% else %>
|
||||
<% set success_message = __('Check your inbox now to confirm your subscription.') %>
|
||||
<% endif %>
|
||||
@ -103,7 +103,7 @@
|
||||
<select name="success_page">
|
||||
<% for page in pages %>
|
||||
<option value="<%= page.id %>"
|
||||
<%- if form.data.settings.success_page != page.id %>
|
||||
<%- if form.settings.success_page == page.id %>
|
||||
<%=- ' selected="selected"' %>
|
||||
<%- endif %>><%= page.title %></option>
|
||||
<% endfor %>
|
||||
@ -445,28 +445,31 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
var message = null;
|
||||
if(callback !== false) {
|
||||
var message = null;
|
||||
|
||||
if(response.is_widget === true) {
|
||||
message = "<%= __('Saved! The changes are already active in your widget.') %>";
|
||||
} else {
|
||||
message = "<%= __('Saved! Add this form to %1$sa widget%2$s.') | format("<a href='widgets.php' target='_blank'>", '</a>') | raw %>";
|
||||
}
|
||||
if(response.is_widget === true) {
|
||||
message = "<%= __('Saved! The changes are already active in your widget.') %>";
|
||||
} else {
|
||||
message = "<%= __('Saved! Add this form to %1$sa widget%2$s.') | format("<a href='widgets.php' target='_blank'>", '</a>') | raw %>";
|
||||
}
|
||||
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.success(message, {
|
||||
scroll: true,
|
||||
static: (response.is_widget === false)
|
||||
});
|
||||
}
|
||||
if(message !== null) {
|
||||
MailPoet.Notice.hide();
|
||||
MailPoet.Notice.success(message, {
|
||||
scroll: true,
|
||||
static: (response.is_widget === false)
|
||||
});
|
||||
}
|
||||
|
||||
// if there is a callback, call it!
|
||||
if(callback !== undefined) {
|
||||
callback();
|
||||
// if there is a callback, call it!
|
||||
if(callback !== undefined) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
window.mailpoet_form_save = mailpoet_form_save;
|
||||
|
||||
// toolbar: on success toggle
|
||||
$(document).on('change', 'input[name="on_success"]', toggleOnSuccessOptions);
|
||||
@ -506,7 +509,7 @@
|
||||
// open popup
|
||||
MailPoet.Modal.popup({
|
||||
title: "<%= __('Add new field') %>",
|
||||
template: $('#form_template_field_new').html()
|
||||
template: $('#form_template_field_form').html()
|
||||
});
|
||||
|
||||
return false;
|
||||
@ -524,7 +527,7 @@
|
||||
if(response.result !== false) {
|
||||
MailPoet.Modal.popup({
|
||||
title: "<%= __('Edit field') %>",
|
||||
template: $('#form_template_field_new').html(),
|
||||
template: $('#form_template_field_form').html(),
|
||||
data: response
|
||||
});
|
||||
}
|
||||
@ -544,9 +547,16 @@
|
||||
endpoint: 'customFields',
|
||||
action: 'delete',
|
||||
data: id
|
||||
}).done(function(result) {
|
||||
if(result === true) {
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
item.remove();
|
||||
|
||||
if(response.field !== undefined) {
|
||||
WysijaForm.removeBlock(response.field, function() {
|
||||
mailpoet_form_save(false);
|
||||
});
|
||||
}
|
||||
|
||||
mailpoet_form_fields();
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Removed custom field “"+name+"“') %>"
|
||||
@ -685,8 +695,8 @@
|
||||
) %>
|
||||
|
||||
<!-- custom field: new -->
|
||||
<%= partial('form_template_field_new',
|
||||
'form/templates/settings/field_new.hbs'
|
||||
<%= partial('form_template_field_form',
|
||||
'form/templates/settings/field_form.hbs'
|
||||
) %>
|
||||
|
||||
<!-- form preview -->
|
||||
|
@ -6,7 +6,7 @@
|
||||
{{#ifCond type '==' 'input'}}
|
||||
{{> _settings_label }}
|
||||
{{> _settings_label_within }}
|
||||
{{#ifCond field 'in' 'first_name,last_name' }}
|
||||
{{#ifCond id 'in' 'first_name,last_name' }}
|
||||
{{> _settings_required }}
|
||||
{{/ifCond}}
|
||||
{{/ifCond}}
|
||||
|
@ -78,7 +78,16 @@
|
||||
data: data
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
// close popup
|
||||
MailPoet.Modal.close();
|
||||
|
||||
if(WysijaForm.updateBlock(response.field) === true) {
|
||||
// trigger save, if a block has been updated
|
||||
mailpoet_form_save(false);
|
||||
}
|
||||
|
||||
mailpoet_form_fields();
|
||||
|
||||
if(data.id) {
|
||||
MailPoet.Notice.success(
|
||||
"<%= __('Updated custom field “"+data.name+"“') %>"
|
||||
@ -88,9 +97,6 @@
|
||||
"<%= __('Added custom field “"+data.name+"“') %>"
|
||||
);
|
||||
}
|
||||
|
||||
// close popup
|
||||
MailPoet.Modal.success();
|
||||
} else {
|
||||
if(response.errors.length > 0) {
|
||||
$(response.errors).each(function(i, error) {
|
@ -20,7 +20,6 @@
|
||||
mailpoet_segment_selection_render();
|
||||
|
||||
setInputNames();
|
||||
setupSortableSegments();
|
||||
|
||||
// add segment
|
||||
$('.mailpoet_segment_add').on('click', function() {
|
||||
@ -125,6 +124,7 @@
|
||||
$(item).find('.mailpoet_segment_id').attr('name', 'params[values]['+index+'][id]');
|
||||
$(item).find('.mailpoet_segment_name').attr('name', 'params[values]['+index+'][name]');
|
||||
});
|
||||
setupSortableSegments();
|
||||
}
|
||||
});
|
||||
<{{!}}/script>
|
@ -16,8 +16,6 @@
|
||||
class="mailpoet_form mailpoet_form_<%= form_type %>"
|
||||
novalidate
|
||||
>
|
||||
<div class="mailpoet_message"></div>
|
||||
|
||||
<input type="hidden" name="form_id" value="<%= form.id %>" />
|
||||
|
||||
<% if not(form.settings.segments_selected_by == 'user') %>
|
||||
@ -26,6 +24,8 @@
|
||||
<% endfor %>
|
||||
<% endif %>
|
||||
<%= html | raw %>
|
||||
|
||||
<div class="mailpoet_message"></div>
|
||||
</form>
|
||||
</div>
|
||||
<%= after_widget | raw %>
|
||||
|
@ -1239,10 +1239,10 @@
|
||||
'<%= __('Select a shortcode') %>',
|
||||
unsubscribeLinkMissing:
|
||||
'<%= __('Please include an unsubscribe link to continue.') %>',
|
||||
testEmailSent:
|
||||
'<%= __('Test email successfully sent!') %>',
|
||||
unknownErrorOccurred:
|
||||
'<%= __('An unknown error occurred, please check your settings.') %>',
|
||||
newsletterPreviewSent:
|
||||
'<%= __('Newsletter preview email has been successfully sent!') %>',
|
||||
newsletterPreviewFailedToSend:
|
||||
'<%= __('Attempt to send a newsletter preview email failed. Please verify that your sending method is configured correctly try again.') %>',
|
||||
templateNameMissing:
|
||||
'<%= __('Please add a template name') %>',
|
||||
templateDescriptionMissing:
|
||||
|
@ -1,20 +1,6 @@
|
||||
<div class="handlediv" title="Click to toggle"><br></div>
|
||||
<h3><%= __('Preview') %></h3>
|
||||
<div class="mailpoet_region_content">
|
||||
<div class="mailpoet_form_field">
|
||||
<label>
|
||||
<%= __('From name') %><br />
|
||||
<input id="mailpoet_preview_from_name" class="mailpoet_input mailpoet_input_full" type="text" name="from_name" value="{{ from_name }}" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mailpoet_form_field">
|
||||
<label>
|
||||
<%= __('From email') %><br />
|
||||
<input id="mailpoet_preview_from_email" class="mailpoet_input mailpoet_input_full" type="text" name="from_email" value="{{ from_email }}" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mailpoet_form_field">
|
||||
<label>
|
||||
<%= __('Send preview to') %><br />
|
||||
|
@ -102,17 +102,20 @@
|
||||
<% endif %>
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label><%= __('Users will be subscribed to these lists:') %></label>
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="mailpoet_subscribe_on_comment_lists"
|
||||
name="subscribe[on_comment][lists][]"
|
||||
id="mailpoet_subscribe_on_comment_segments"
|
||||
name="subscribe[on_comment][segments][]"
|
||||
placeholder="<%= __('Choose a list') %>"
|
||||
multiple
|
||||
>
|
||||
<% for segment in segments %>
|
||||
<option
|
||||
value="<%= segment.id %>"
|
||||
<% if(segment.id in settings.subscribe.on_comment.lists) %>
|
||||
<% if(segment.id in settings.subscribe.on_comment.segments) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= segment.name %></option>
|
||||
@ -163,17 +166,20 @@
|
||||
<% endif %>
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label><%= __('Users will be subscribed to these lists:') %></label>
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="mailpoet_subscribe_on_register_lists"
|
||||
name="subscribe[on_register][lists][]"
|
||||
id="mailpoet_subscribe_on_register_segments"
|
||||
name="subscribe[on_register][segments][]"
|
||||
placeholder="<%= __('Choose a list') %>"
|
||||
multiple
|
||||
>
|
||||
<% for segment in segments %>
|
||||
<option
|
||||
value="<%= segment.id %>"
|
||||
<% if(segment.id in settings.subscribe.on_register.lists) %>
|
||||
<% if(segment.id in settings.subscribe.on_register.segments) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= segment.name %></option>
|
||||
@ -227,19 +233,19 @@
|
||||
><%= __('Edit') %></a>
|
||||
</p>
|
||||
<p>
|
||||
<label><%= __('Subscribers can choose from these lists :') %></label>
|
||||
<label><%= __('Subscribers can choose from these lists:') %></label>
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="mailpoet_subscription_edit_lists"
|
||||
name="subscription[lists][]"
|
||||
id="mailpoet_subscription_edit_segments"
|
||||
name="subscription[segments][]"
|
||||
placeholder="<%= __('Leave empty to show all lists') %>"
|
||||
multiple
|
||||
>
|
||||
<% for segment in segments %>
|
||||
<option
|
||||
value="<%= segment.id %>"
|
||||
<% if(segment.id in settings.subscription.lists) %>
|
||||
<% if(segment.id in settings.subscription.segments) %>
|
||||
selected="selected"
|
||||
<% endif %>
|
||||
><%= segment.name %></option>
|
||||
@ -307,7 +313,7 @@
|
||||
</p>
|
||||
<p>
|
||||
<select
|
||||
id="mailpoet_shortcode_subscribers_list"
|
||||
id="mailpoet_shortcode_subscribers_count"
|
||||
data-shortcode="mailpoet_subscribers_count"
|
||||
data-output="mailpoet_shortcode_subscribers"
|
||||
placeholder="<%= __('Leave empty to show all lists') %>"
|
||||
@ -328,25 +334,26 @@
|
||||
// on dom loaded
|
||||
$(function() {
|
||||
// select2 instances
|
||||
$('#mailpoet_subscribe_on_comment_lists').select2();
|
||||
$('#mailpoet_subscribe_on_register_lists').select2();
|
||||
$('#mailpoet_subscription_edit_lists').select2();
|
||||
$('#mailpoet_subscribe_on_comment_segments').select2();
|
||||
$('#mailpoet_subscribe_on_register_segments').select2();
|
||||
$('#mailpoet_subscription_edit_segments').select2();
|
||||
$('#mailpoet_shortcode_archives_list').select2();
|
||||
$('#mailpoet_shortcode_subscribers_list').select2();
|
||||
$('#mailpoet_shortcode_subscribers_count').select2();
|
||||
|
||||
// shortcodes
|
||||
$('#mailpoet_shortcode_archives_list, #mailpoet_shortcode_subscribers_list')
|
||||
$('#mailpoet_shortcode_archives_list, #mailpoet_shortcode_subscribers_count')
|
||||
.on('change', function() {
|
||||
var shortcode = $(this).data('shortcode'),
|
||||
values = $(this).val() || [];
|
||||
|
||||
if(values.length > 0) {
|
||||
shortcode += ' list_id="';
|
||||
if (values.length > 0) {
|
||||
shortcode += ' segments="';
|
||||
shortcode += values.join(',');
|
||||
shortcode += '"';
|
||||
}
|
||||
|
||||
$('#' + $(this).data('output')).val('[' + shortcode + ']');
|
||||
$('#' + $(this).data('output'))
|
||||
.val('[' + shortcode + ']');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,8 @@
|
||||
<% extends 'layout.html' %>
|
||||
<% block content %>
|
||||
<% set csvDescription = __('This needs to be in CSV style. See [link]examples in our support site[/link].') %>
|
||||
<% set csvKBLink = '<a target="_blank" href="http://support.mailpoet.com/knowledgebase/importing-subscribers-with-a-csv-file?utm_source=wpadmin&utm_campaign=import">' %>
|
||||
|
||||
<div id="mailpoet_subscribers_import" class="wrap">
|
||||
<h2 class="title">
|
||||
<%= __('Import') %>
|
||||
@ -19,9 +22,11 @@
|
||||
'noMailChimpLists': __('No active lists found.'),
|
||||
'serverError': __('Server error:'),
|
||||
'select': __('Select'),
|
||||
'csvKBLink': csvKBLink,
|
||||
'wrongFileFormat': __('Only comma-separated (CSV) file format is supported.'),
|
||||
'maxPostSizeNotice': __('Your CSV is over %s, and too big to process. Please split the file in two, or more.')|replace({'%s': maxPostSize}),
|
||||
'dataProcessingError': __("Your data couldn't be processed. Please make sure it is in the proper format."),
|
||||
'noValidRecords': __('No valid records were found.'),
|
||||
'dataProcessingError': __("Your data could not be processed. Please make sure it is in the proper format."),
|
||||
'noValidRecords': __('No valid records were found. This needs to be in CSV style. See [link]examples in our support site[/link]'),
|
||||
'importNoticeSkipped': __('%1$s records were skipped due to problems.'),
|
||||
'importNoticeInvalid': __('%1$s emails are not valid : %2$s.'),
|
||||
'importNoticeDuplicate': __('%1$s emails appear more than once in your file : %2$s.'),
|
||||
|
@ -30,14 +30,7 @@
|
||||
<th scope="row">
|
||||
<label for="paste_input"> <%= __('Copy and paste your subscribers from Excel/Sheets') %>
|
||||
<p class="description">
|
||||
<%=
|
||||
__('This needs to be in CSV style. See [link]examples in our support site[/link].')
|
||||
|replace({
|
||||
'[link]': '<a target="_blank" href="http://support.mailpoet.com/knowledgebase/importing-subscribers-with-a-csv-file/main.html?utm_source=wpadmin&utm_campaign=import">',
|
||||
'[/link]': '</a>'
|
||||
})
|
||||
|raw
|
||||
%>
|
||||
<%= csvDescription|replace({'[link]': csvKBLink, '[/link]': '</a>'})|raw %>
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
@ -60,23 +53,15 @@
|
||||
<th scope="row">
|
||||
<label for="file_local">
|
||||
<%= __('Upload a file') %>
|
||||
|
||||
<p class="description">
|
||||
<%=
|
||||
__('This needs to be in CSV style. See [link]examples in our support site[/link].')
|
||||
|replace({
|
||||
'[link]': '<a target="_blank" href="http://support.mailpoet.com/knowledgebase/importing-subscribers-with-a-csv-file/main.html?utm_source=wpadmin&utm_campaign=import">',
|
||||
'[/link]': '</a>'
|
||||
})
|
||||
|raw
|
||||
%>
|
||||
<%= csvDescription|replace({'[link]': csvKBLink, '[/link]': '</a>'})|raw %>
|
||||
</p>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="file" id="file_local">
|
||||
<input type="file" id="file_local" accept=".csv" />
|
||||
|
||||
<%= __( 'total max upload file size : %s' )|replace({'%s': maxPostSize}) %>
|
||||
<%= __('total max upload file size : %s')|format(maxPostSize) %>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -16,5 +16,7 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
var mailpoet_segments = <%= json_encode(segments) %>;
|
||||
var mailpoet_custom_fields = <%= json_encode(custom_fields) %>;
|
||||
var mailpoet_month_names = <%= json_encode(month_names) %>;
|
||||
</script>
|
||||
<% endblock %>
|
||||
|
@ -63,6 +63,7 @@
|
||||
border-color: #df4a02;
|
||||
text-align: right;
|
||||
height:auto;
|
||||
text-shadow: none;
|
||||
}
|
||||
#mailpoet_welcome .welcome_sub .button_thanks:hover,
|
||||
.welcome_sub .button_thanks:active {
|
||||
|
Reference in New Issue
Block a user