Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
a1441dfde6 | |||
8e7336d352 | |||
e0e2933cdf | |||
c93ec629ea | |||
d613df6558 | |||
01c9096543 | |||
f120e839dd | |||
f0ab592c04 | |||
1a269d28b3 | |||
8d4a666bf0 | |||
4a96e483a6 | |||
263a66407f | |||
c4b728f4e1 | |||
9970ad7fb6 | |||
eb380499d9 | |||
4b528549f5 | |||
a903017bc2 | |||
afd25e9174 | |||
b1bbf1b3bc | |||
9e84e8df93 | |||
df775b5a07 | |||
c9c22b9b52 | |||
93d20688ea | |||
9ebcddfa2a | |||
85995bc8a6 | |||
a8f2959bc6 | |||
36242bd580 | |||
1e7dbc8449 | |||
12c159c627 | |||
82ed7e51c5 | |||
0b3aa0d12a | |||
4d788f69aa | |||
c721843c12 | |||
d2be407ccb | |||
e6337216cf | |||
f1c396f0b0 | |||
3622bc9fcb | |||
14fe333678 | |||
cf6466197a | |||
f56bee76f2 |
@ -32,5 +32,6 @@ $block-hover-highlight-color = $primary-active-color
|
|||||||
position: relative
|
position: relative
|
||||||
line-height: 1.61803398875
|
line-height: 1.61803398875
|
||||||
|
|
||||||
p
|
p, h1, h2, h3, h4, h5, h6
|
||||||
line-height: 1.61803398875
|
line-height: 1.61803398875
|
||||||
|
font-style: normal
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
h1, h2, h3, h4, h5, h6
|
h1, h2, h3, h4, h5, h6
|
||||||
padding: 0
|
padding: 0
|
||||||
margin: 0
|
margin: 0
|
||||||
|
font-weight: normal
|
||||||
|
|
||||||
p
|
p
|
||||||
margin-top: 0
|
margin-top: 0
|
||||||
|
font-weight: normal
|
||||||
|
|
||||||
blockquote
|
blockquote
|
||||||
margin: 1em
|
margin: 1em
|
||||||
|
@ -2,3 +2,13 @@
|
|||||||
|
|
||||||
@require 'parsley'
|
@require 'parsley'
|
||||||
@require 'form_validation'
|
@require 'form_validation'
|
||||||
|
|
||||||
|
/* labels */
|
||||||
|
.mailpoet_text_label
|
||||||
|
.mailpoet_textarea_label
|
||||||
|
.mailpoet_select_label
|
||||||
|
.mailpoet_radio_label
|
||||||
|
.mailpoet_checkbox_label
|
||||||
|
.mailpoet_list_label
|
||||||
|
.mailpoet_date_label
|
||||||
|
display:block
|
||||||
|
136
assets/js/src/date.js
Normal file
136
assets/js/src/date.js
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
define('date',
|
||||||
|
[
|
||||||
|
'mailpoet',
|
||||||
|
'jquery',
|
||||||
|
'moment'
|
||||||
|
], function(
|
||||||
|
MailPoet,
|
||||||
|
jQuery,
|
||||||
|
Moment
|
||||||
|
) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
MailPoet.Date = {
|
||||||
|
version: 0.1,
|
||||||
|
options: {},
|
||||||
|
defaults: {
|
||||||
|
offset: 0,
|
||||||
|
format: 'F, d Y H:i:s'
|
||||||
|
},
|
||||||
|
init: function(options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
// set UTC offset
|
||||||
|
if (
|
||||||
|
options.offset === undefined
|
||||||
|
&& window.mailpoet_date_offset !== undefined
|
||||||
|
) {
|
||||||
|
options.offset = window.mailpoet_date_offset;
|
||||||
|
}
|
||||||
|
// set date format
|
||||||
|
if (
|
||||||
|
options.format === undefined
|
||||||
|
&& window.mailpoet_date_format !== undefined
|
||||||
|
) {
|
||||||
|
options.format = window.mailpoet_date_format;
|
||||||
|
}
|
||||||
|
// merge options
|
||||||
|
this.options = jQuery.extend({}, this.defaults, options);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
format: function(date, options) {
|
||||||
|
this.init(options);
|
||||||
|
return Moment.utc(date)
|
||||||
|
.local()
|
||||||
|
.format(this.convertFormat(this.options.format));
|
||||||
|
},
|
||||||
|
short: function(date) {
|
||||||
|
return this.format(date, {
|
||||||
|
format: 'F, j Y'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
full: function(date) {
|
||||||
|
return this.format(date, {
|
||||||
|
format: 'F, j Y H:i:s'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
time: function(date) {
|
||||||
|
return this.format(date, {
|
||||||
|
format: 'H:i:s'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
convertFormat: function(format) {
|
||||||
|
const format_mappings = {
|
||||||
|
date: {
|
||||||
|
D: 'ddd',
|
||||||
|
l: 'dddd',
|
||||||
|
d: 'DD',
|
||||||
|
j: 'D',
|
||||||
|
z: 'DDDD',
|
||||||
|
N: 'E',
|
||||||
|
S: '',
|
||||||
|
M: 'MMM',
|
||||||
|
F: 'MMMM',
|
||||||
|
m: 'MM',
|
||||||
|
n: '',
|
||||||
|
t: '',
|
||||||
|
y: 'YY',
|
||||||
|
Y: 'YYYY',
|
||||||
|
H: 'HH',
|
||||||
|
h: 'hh',
|
||||||
|
g: 'h',
|
||||||
|
A: 'A',
|
||||||
|
i: 'mm',
|
||||||
|
s: 'ss',
|
||||||
|
T: 'z',
|
||||||
|
O: 'ZZ',
|
||||||
|
w: 'd',
|
||||||
|
W: 'WW'
|
||||||
|
},
|
||||||
|
strftime: {
|
||||||
|
a: 'ddd',
|
||||||
|
A: 'dddd',
|
||||||
|
b: 'MMM',
|
||||||
|
B: 'MMMM',
|
||||||
|
d: 'DD',
|
||||||
|
e: 'D',
|
||||||
|
F: 'YYYY-MM-DD',
|
||||||
|
H: 'HH',
|
||||||
|
I: 'hh',
|
||||||
|
j: 'DDDD',
|
||||||
|
k: 'H',
|
||||||
|
l: 'h',
|
||||||
|
m: 'MM',
|
||||||
|
M: 'mm',
|
||||||
|
p: 'A',
|
||||||
|
S: 'ss',
|
||||||
|
u: 'E',
|
||||||
|
w: 'd',
|
||||||
|
W: 'WW',
|
||||||
|
y: 'YY',
|
||||||
|
Y: 'YYYY',
|
||||||
|
z: 'ZZ',
|
||||||
|
Z: 'z'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const replacements = format_mappings['date'];
|
||||||
|
|
||||||
|
let outputFormat = '';
|
||||||
|
|
||||||
|
Object.keys(replacements).forEach(function(key) {
|
||||||
|
if (format.indexOf(key) !== -1) {
|
||||||
|
format = format.replace(key, '%'+key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
outputFormat = format;
|
||||||
|
Object.keys(replacements).forEach(function(key) {
|
||||||
|
if (outputFormat.indexOf('%'+key) !== -1) {
|
||||||
|
outputFormat = outputFormat.replace('%'+key, replacements[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return outputFormat;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
@ -146,7 +146,7 @@ const FormList = React.createClass({
|
|||||||
{ segments }
|
{ segments }
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Created on">
|
<td className="column-date" data-colname="Created on">
|
||||||
<abbr>{ form.created_at }</abbr>
|
<abbr>{ MailPoet.Date.full(form.created_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -230,15 +230,17 @@ define([
|
|||||||
json.body = JSON.stringify(json.body);
|
json.body = JSON.stringify(json.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MailPoet.Modal.loading(true);
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'render',
|
action: 'render',
|
||||||
data: json,
|
data: json,
|
||||||
}).done(function(response){
|
}).done(function(response){
|
||||||
console.log('Should open a new window');
|
MailPoet.Modal.loading(false);
|
||||||
window.open('data:text/html;charset=utf-8,' + encodeURIComponent(response.rendered_body), '_blank');
|
window.open('data:text/html;charset=utf-8,' + encodeURIComponent(response.rendered_body), '_blank');
|
||||||
}).fail(function(error) {
|
}).fail(function(error) {
|
||||||
console.log('Preview error', json);
|
MailPoet.Modal.loading(false);
|
||||||
alert('Something went wrong, check console');
|
alert('Something went wrong, check console');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -246,11 +248,23 @@ define([
|
|||||||
// testing sending method
|
// testing sending method
|
||||||
console.log('trying to send a preview');
|
console.log('trying to send a preview');
|
||||||
// get form data
|
// get form data
|
||||||
|
var $emailField = this.$('#mailpoet_preview_to_email');
|
||||||
var data = {
|
var data = {
|
||||||
subscriber: this.$('#mailpoet_preview_to_email').val(),
|
subscriber: $emailField.val(),
|
||||||
id: App.getNewsletter().get('id'),
|
id: App.getNewsletter().get('id'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (data.subscriber.length <= 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.newsletterPreviewEmailMissing'),
|
||||||
|
{
|
||||||
|
positionAfter: $emailField,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// send test email
|
// send test email
|
||||||
MailPoet.Modal.loading(true);
|
MailPoet.Modal.loading(true);
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ define(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
renderStatus: function(item) {
|
renderStatus: function(item) {
|
||||||
if(item.queue === null) {
|
if(!item.queue) {
|
||||||
return (
|
return (
|
||||||
<span>Not sent yet.</span>
|
<span>Not sent yet.</span>
|
||||||
);
|
);
|
||||||
@ -208,10 +208,8 @@ define(
|
|||||||
'has-row-actions'
|
'has-row-actions'
|
||||||
);
|
);
|
||||||
|
|
||||||
var segments = mailpoet_segments.filter(function(segment) {
|
var segments = newsletter.segments.map(function(segment) {
|
||||||
return (jQuery.inArray(segment.id, newsletter.segments) !== -1);
|
return segment.name
|
||||||
}).map(function(segment) {
|
|
||||||
return segment.name;
|
|
||||||
}).join(', ');
|
}).join(', ');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -229,10 +227,10 @@ define(
|
|||||||
{ segments }
|
{ segments }
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Subscribed on">
|
<td className="column-date" data-colname="Subscribed on">
|
||||||
<abbr>{ newsletter.created_at }</abbr>
|
<abbr>{ MailPoet.Date.full(newsletter.created_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Last modified on">
|
<td className="column-date" data-colname="Last modified on">
|
||||||
<abbr>{ newsletter.updated_at }</abbr>
|
<abbr>{ MailPoet.Date.full(newsletter.updated_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -190,7 +190,7 @@ const SegmentList = React.createClass({
|
|||||||
<abbr>{ segment.subscribers_count.unsubscribed || 0 }</abbr>
|
<abbr>{ segment.subscribers_count.unsubscribed || 0 }</abbr>
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Created on">
|
<td className="column-date" data-colname="Created on">
|
||||||
<abbr>{ segment.created_at }</abbr>
|
<abbr>{ MailPoet.Date.full(segment.created_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,15 +3,13 @@ define(
|
|||||||
'react',
|
'react',
|
||||||
'react-router',
|
'react-router',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'form/form.jsx',
|
'form/form.jsx'
|
||||||
'moment'
|
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React,
|
||||||
Router,
|
Router,
|
||||||
MailPoet,
|
MailPoet,
|
||||||
Form,
|
Form
|
||||||
Moment
|
|
||||||
) {
|
) {
|
||||||
var fields = [
|
var fields = [
|
||||||
{
|
{
|
||||||
@ -69,9 +67,8 @@ define(
|
|||||||
label = segment.name;
|
label = segment.name;
|
||||||
|
|
||||||
if (subscription.status === 'unsubscribed') {
|
if (subscription.status === 'unsubscribed') {
|
||||||
const unsubscribed_at = Moment(subscription.updated_at)
|
const unsubscribed_at = MailPoet.Date
|
||||||
.utcOffset(parseInt(mailpoet_date_offset))
|
.format(subscription.updated_at);
|
||||||
.format('ddd, D MMM YYYY HH:mm:ss');
|
|
||||||
label += ' (Unsubscribed on '+unsubscribed_at+')';
|
label += ' (Unsubscribed on '+unsubscribed_at+')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1056,7 +1056,7 @@ define(
|
|||||||
var columns = {},
|
var columns = {},
|
||||||
queue = new jQuery.AsyncQueue(),
|
queue = new jQuery.AsyncQueue(),
|
||||||
batchNumber = 0,
|
batchNumber = 0,
|
||||||
batchSize = 500,
|
batchSize = 2000,
|
||||||
timestamp = Date.now() / 1000,
|
timestamp = Date.now() / 1000,
|
||||||
subscribers = [],
|
subscribers = [],
|
||||||
importResults = {
|
importResults = {
|
||||||
|
@ -208,6 +208,16 @@ const bulk_actions = [
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'sendConfirmationEmail',
|
||||||
|
label: 'Resend confirmation email',
|
||||||
|
onSuccess: function(response) {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
'%$1d confirmation emails have been sent.'
|
||||||
|
.replace('%$1d', ~~response)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'trash',
|
name: 'trash',
|
||||||
label: 'Trash',
|
label: 'Trash',
|
||||||
@ -272,13 +282,13 @@ const SubscriberList = React.createClass({
|
|||||||
|
|
||||||
subscriber.subscriptions.map((subscription) => {
|
subscriber.subscriptions.map((subscription) => {
|
||||||
const segment = this.getSegmentFromId(subscription.segment_id);
|
const segment = this.getSegmentFromId(subscription.segment_id);
|
||||||
|
if(segment === false) return;
|
||||||
if (subscription.status === 'subscribed') {
|
if (subscription.status === 'subscribed') {
|
||||||
subscribed_segments.push(segment.name);
|
subscribed_segments.push(segment.name);
|
||||||
} else {
|
} else if (subscription.status === 'unsubscribed') {
|
||||||
unsubscribed_segments.push(segment.name);
|
unsubscribed_segments.push(segment.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
segments = (
|
segments = (
|
||||||
<span>
|
<span>
|
||||||
<span className="mailpoet_segments_subscribed">
|
<span className="mailpoet_segments_subscribed">
|
||||||
@ -331,10 +341,10 @@ const SubscriberList = React.createClass({
|
|||||||
{ segments }
|
{ segments }
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Subscribed on">
|
<td className="column-date" data-colname="Subscribed on">
|
||||||
<abbr>{ subscriber.created_at }</abbr>
|
<abbr>{ MailPoet.Date.full(subscriber.created_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
<td className="column-date" data-colname="Last modified on">
|
<td className="column-date" data-colname="Last modified on">
|
||||||
<abbr>{ subscriber.updated_at }</abbr>
|
<abbr>{ MailPoet.Date.full(subscriber.updated_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
use \MailPoet\Models\Setting;
|
use \MailPoet\Models\Setting;
|
||||||
|
use \MailPoet\Util\Url;
|
||||||
|
|
||||||
class Changelog {
|
class Changelog {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$doing_ajax = (bool)(defined('DOING_AJAX') && DOING_AJAX);
|
$doing_ajax = (bool)(defined('DOING_AJAX') && DOING_AJAX);
|
||||||
|
|
||||||
@ -42,20 +46,7 @@ class Changelog {
|
|||||||
// save version number
|
// save version number
|
||||||
Setting::setValue('version', Env::$version);
|
Setting::setValue('version', Env::$version);
|
||||||
|
|
||||||
global $wp;
|
Url::redirectWithReferer($redirect_url);
|
||||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
|
||||||
|
|
||||||
if($redirect_url !== $current_url) {
|
|
||||||
wp_safe_redirect(
|
|
||||||
add_query_arg(
|
|
||||||
array(
|
|
||||||
'mailpoet_redirect' => urlencode($current_url)
|
|
||||||
),
|
|
||||||
$redirect_url
|
|
||||||
)
|
|
||||||
);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
use MailPoet\Cron\Workers\Scheduler;
|
||||||
|
use MailPoet\Cron\Workers\SendingQueue;
|
||||||
use \MailPoet\Models\Setting;
|
use \MailPoet\Models\Setting;
|
||||||
|
|
||||||
class Hooks {
|
class Hooks {
|
||||||
@ -11,6 +13,7 @@ class Hooks {
|
|||||||
$this->setupWPUsers();
|
$this->setupWPUsers();
|
||||||
$this->setupImageSize();
|
$this->setupImageSize();
|
||||||
$this->setupListing();
|
$this->setupListing();
|
||||||
|
$this->setupCronWorkers();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupSubscribe() {
|
function setupSubscribe() {
|
||||||
@ -144,4 +147,19 @@ class Hooks {
|
|||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupCronWorkers() {
|
||||||
|
add_action('mailpoet_cron_worker', array($this, 'runSchedulerWorker'), 10, 1);
|
||||||
|
add_action('mailpoet_cron_worker', array($this, 'runSendingQueueWorker'), 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runSchedulerWorker($timer) {
|
||||||
|
$scheduler = new Scheduler($timer);
|
||||||
|
$scheduler->process();
|
||||||
|
|
||||||
|
}
|
||||||
|
function runSendingQueueWorker($timer) {
|
||||||
|
$sending_queue = new SendingQueue($timer);
|
||||||
|
$sending_queue->process();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@ namespace MailPoet\Config;
|
|||||||
use MailPoet\Models;
|
use MailPoet\Models;
|
||||||
use MailPoet\Cron\Supervisor;
|
use MailPoet\Cron\Supervisor;
|
||||||
use MailPoet\Router;
|
use MailPoet\Router;
|
||||||
use MailPoet\Models\Setting;
|
|
||||||
use MailPoet\Settings\Pages;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@ -26,6 +24,7 @@ class Initializer {
|
|||||||
register_activation_hook(Env::$file, array($this, 'runPopulator'));
|
register_activation_hook(Env::$file, array($this, 'runPopulator'));
|
||||||
|
|
||||||
add_action('plugins_loaded', array($this, 'setup'));
|
add_action('plugins_loaded', array($this, 'setup'));
|
||||||
|
add_action('init', array($this, 'onInit'));
|
||||||
add_action('widgets_init', array($this, 'setupWidget'));
|
add_action('widgets_init', array($this, 'setupWidget'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,16 +33,14 @@ class Initializer {
|
|||||||
$this->setupRenderer();
|
$this->setupRenderer();
|
||||||
$this->setupLocalizer();
|
$this->setupLocalizer();
|
||||||
$this->setupMenu();
|
$this->setupMenu();
|
||||||
$this->setupRouter();
|
|
||||||
$this->setupPermissions();
|
$this->setupPermissions();
|
||||||
$this->setupPublicAPI();
|
|
||||||
$this->setupAnalytics();
|
$this->setupAnalytics();
|
||||||
$this->setupChangelog();
|
$this->setupChangelog();
|
||||||
$this->runQueueSupervisor();
|
|
||||||
$this->setupShortcodes();
|
$this->setupShortcodes();
|
||||||
$this->setupHooks();
|
$this->setupHooks();
|
||||||
$this->setupPages();
|
|
||||||
$this->setupImages();
|
$this->setupImages();
|
||||||
|
$this->setupPublicAPI();
|
||||||
|
$this->runQueueSupervisor();
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
// if anything goes wrong during init
|
// if anything goes wrong during init
|
||||||
// automatically deactivate the plugin
|
// automatically deactivate the plugin
|
||||||
@ -51,11 +48,20 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onInit() {
|
||||||
|
$this->setupRouter();
|
||||||
|
$this->setupPages();
|
||||||
|
$this->runQueueSupervisor();
|
||||||
|
}
|
||||||
|
|
||||||
function setupDB() {
|
function setupDB() {
|
||||||
\ORM::configure(Env::$db_source_name);
|
\ORM::configure(Env::$db_source_name);
|
||||||
\ORM::configure('username', Env::$db_username);
|
\ORM::configure('username', Env::$db_username);
|
||||||
\ORM::configure('password', Env::$db_password);
|
\ORM::configure('password', Env::$db_password);
|
||||||
\ORM::configure('logging', WP_DEBUG);
|
\ORM::configure('logging', WP_DEBUG);
|
||||||
|
\ORM::configure('logger', function($query, $time) {
|
||||||
|
// error_log("\n".$query."\n");
|
||||||
|
});
|
||||||
|
|
||||||
\ORM::configure('driver_options', array(
|
\ORM::configure('driver_options', array(
|
||||||
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
|
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
|
||||||
@ -144,8 +150,11 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupPages() {
|
function setupPages() {
|
||||||
$pages = new Pages();
|
$pages = new \MailPoet\Settings\Pages();
|
||||||
$pages->init();
|
$pages->init();
|
||||||
|
|
||||||
|
$subscription_pages = new \MailPoet\Subscription\Pages();
|
||||||
|
$subscription_pages->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupShortcodes() {
|
function setupShortcodes() {
|
||||||
|
@ -380,6 +380,7 @@ class Menu {
|
|||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'customFields' => $custom_fields,
|
'customFields' => $custom_fields,
|
||||||
|
'settings' => Setting::getAll(),
|
||||||
);
|
);
|
||||||
wp_enqueue_media();
|
wp_enqueue_media();
|
||||||
wp_enqueue_script('tinymce-wplink', includes_url('js/tinymce/plugins/wplink/plugin.js'));
|
wp_enqueue_script('tinymce-wplink', includes_url('js/tinymce/plugins/wplink/plugin.js'));
|
||||||
|
@ -68,4 +68,11 @@ class CronHelper {
|
|||||||
// throw an error if all connection attempts failed
|
// throw an error if all connection attempts failed
|
||||||
throw new \Exception(__('Site URL is unreachable.'));
|
throw new \Exception(__('Site URL is unreachable.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function checkExecutionTimer($timer) {
|
||||||
|
$elapsed_time = microtime(true) - $timer;
|
||||||
|
if($elapsed_time >= self::daemon_execution_limit) {
|
||||||
|
throw new \Exception(__('Maximum execution time reached.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
|
use MailPoet\Cron\Workers\Scheduler;
|
||||||
use MailPoet\Cron\Workers\SendingQueue;
|
use MailPoet\Cron\Workers\SendingQueue;
|
||||||
|
use MailPoet\Models\Newsletter;
|
||||||
|
|
||||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||||
|
|
||||||
@ -35,8 +37,7 @@ class Daemon {
|
|||||||
}
|
}
|
||||||
$this->abortIfStopped($daemon);
|
$this->abortIfStopped($daemon);
|
||||||
try {
|
try {
|
||||||
$sending_queue = new SendingQueue($this->timer);
|
do_action('mailpoet_cron_worker', $this->timer);
|
||||||
$sending_queue->process();
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
}
|
}
|
||||||
$elapsed_time = microtime(true) - $this->timer;
|
$elapsed_time = microtime(true) - $this->timer;
|
||||||
|
27
lib/Cron/Workers/Scheduler.php
Normal file
27
lib/Cron/Workers/Scheduler.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron\Workers;
|
||||||
|
|
||||||
|
use MailPoet\Cron\CronHelper;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Util\Security;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Scheduler {
|
||||||
|
public $timer;
|
||||||
|
|
||||||
|
function __construct($timer = false) {
|
||||||
|
$this->timer = ($timer) ? $timer : microtime(true);
|
||||||
|
CronHelper::checkExecutionTimer($this->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function process() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkExecutionTimer() {
|
||||||
|
$elapsed_time = microtime(true) - $this->timer;
|
||||||
|
if($elapsed_time >= CronHelper::daemon_execution_limit) {
|
||||||
|
throw new \Exception(__('Maximum execution time reached.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ use MailPoet\Models\Subscriber;
|
|||||||
use MailPoet\Newsletter\Renderer\Renderer;
|
use MailPoet\Newsletter\Renderer\Renderer;
|
||||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
|
use MailPoet\Util\Security;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ class SendingQueue {
|
|||||||
'processBulkSubscribers' :
|
'processBulkSubscribers' :
|
||||||
'processIndividualSubscriber';
|
'processIndividualSubscriber';
|
||||||
$this->timer = ($timer) ? $timer : microtime(true);
|
$this->timer = ($timer) ? $timer : microtime(true);
|
||||||
|
CronHelper::checkExecutionTimer($this->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process() {
|
||||||
@ -102,7 +104,7 @@ class SendingQueue {
|
|||||||
}
|
}
|
||||||
$this->updateQueue($queue);
|
$this->updateQueue($queue);
|
||||||
$this->checkSendingLimit();
|
$this->checkSendingLimit();
|
||||||
$this->checkExecutionTimer();
|
CronHelper::checkExecutionTimer($this->timer);
|
||||||
return $queue->subscribers;
|
return $queue->subscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +131,7 @@ class SendingQueue {
|
|||||||
$this->updateNewsletterStatistics($newsletter_statistics);
|
$this->updateNewsletterStatistics($newsletter_statistics);
|
||||||
}
|
}
|
||||||
$this->updateQueue($queue);
|
$this->updateQueue($queue);
|
||||||
$this->checkExecutionTimer();
|
CronHelper::checkExecutionTimer($this->timer);
|
||||||
}
|
}
|
||||||
return $queue->subscribers;
|
return $queue->subscribers;
|
||||||
}
|
}
|
||||||
@ -259,11 +261,4 @@ class SendingQueue {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkExecutionTimer() {
|
|
||||||
$elapsed_time = microtime(true) - $this->timer;
|
|
||||||
if($elapsed_time >= CronHelper::daemon_execution_limit) {
|
|
||||||
throw new \Exception(__('Maximum execution time reached.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -20,18 +20,22 @@ class Checkbox extends Base {
|
|||||||
|
|
||||||
foreach($options as $option) {
|
foreach($options as $option) {
|
||||||
$html .= '<label class="mailpoet_checkbox_label">';
|
$html .= '<label class="mailpoet_checkbox_label">';
|
||||||
|
$html .= '<input type="hidden" name="'.$field_name.'" value="" />';
|
||||||
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
$html .= '<input type="checkbox" class="mailpoet_checkbox" ';
|
||||||
|
|
||||||
$html .= 'name="'.$field_name.'" ';
|
$html .= 'name="'.$field_name.'" ';
|
||||||
|
|
||||||
$html .= 'value="1" ';
|
$html .= 'value="1" ';
|
||||||
|
|
||||||
$html .= (isset($option['is_checked']) && $option['is_checked'])
|
$html .= (
|
||||||
? 'checked="checked"' : '';
|
(isset($option['is_checked']) && $option['is_checked'])
|
||||||
|
||
|
||||||
|
(self::getFieldValue($block))
|
||||||
|
) ? 'checked="checked"' : '';
|
||||||
|
|
||||||
$html .= $field_validation;
|
$html .= $field_validation;
|
||||||
|
|
||||||
$html .= ' />'.$option['value'];
|
$html .= ' /> '.esc_attr($option['value']);
|
||||||
|
|
||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
@ -33,18 +33,37 @@ class Date extends Base {
|
|||||||
// generate an array of selectors based on date format
|
// generate an array of selectors based on date format
|
||||||
$date_selectors = explode('/', $date_format);
|
$date_selectors = explode('/', $date_format);
|
||||||
|
|
||||||
|
// format value if present
|
||||||
|
$value = self::getFieldValue($block);
|
||||||
|
$day = null;
|
||||||
|
$month = null;
|
||||||
|
$year = null;
|
||||||
|
|
||||||
|
if($value) {
|
||||||
|
$day = (int)strftime('%d', $value);
|
||||||
|
$month = (int)strftime('%m', $value);
|
||||||
|
$year = (int)strftime('%Y', $value);
|
||||||
|
} else if(!empty($block['params']['is_default_today'])) {
|
||||||
|
$day = (int)strftime('%d');
|
||||||
|
$month = (int)strftime('%m');
|
||||||
|
$year = (int)strftime('%Y');
|
||||||
|
}
|
||||||
|
|
||||||
foreach($date_selectors as $date_selector) {
|
foreach($date_selectors as $date_selector) {
|
||||||
if($date_selector === 'dd') {
|
if($date_selector === 'dd') {
|
||||||
|
$block['selected'] = $day;
|
||||||
$html .= '<select class="mailpoet_date_day" ';
|
$html .= '<select class="mailpoet_date_day" ';
|
||||||
$html .= 'name="'.$field_name.'[day]" placeholder="'.__('Day').'">';
|
$html .= 'name="'.$field_name.'[day]" placeholder="'.__('Day').'">';
|
||||||
$html .= static::getDays($block);
|
$html .= static::getDays($block);
|
||||||
$html .= '</select>';
|
$html .= '</select>';
|
||||||
} else if($date_selector === 'mm') {
|
} else if($date_selector === 'mm') {
|
||||||
|
$block['selected'] = $month;
|
||||||
$html .= '<select class="mailpoet_date_month" ';
|
$html .= '<select class="mailpoet_date_month" ';
|
||||||
$html .= 'name="'.$field_name.'[month]" placeholder="'.__('Month').'">';
|
$html .= 'name="'.$field_name.'[month]" placeholder="'.__('Month').'">';
|
||||||
$html .= static::getMonths($block);
|
$html .= static::getMonths($block);
|
||||||
$html .= '</select>';
|
$html .= '</select>';
|
||||||
} else if($date_selector === 'yyyy') {
|
} else if($date_selector === 'yyyy') {
|
||||||
|
$block['selected'] = $year;
|
||||||
$html .= '<select class="mailpoet_date_year" ';
|
$html .= '<select class="mailpoet_date_year" ';
|
||||||
$html .= 'name="'.$field_name.'[year]" placeholder="'.__('Year').'">';
|
$html .= 'name="'.$field_name.'[year]" placeholder="'.__('Year').'">';
|
||||||
$html .= static::getYears($block);
|
$html .= static::getYears($block);
|
||||||
@ -84,11 +103,6 @@ class Date extends Base {
|
|||||||
'selected' => null
|
'selected' => null
|
||||||
);
|
);
|
||||||
|
|
||||||
// is default today
|
|
||||||
if(!empty($block['params']['is_default_today'])) {
|
|
||||||
$defaults['selected'] = (int)strftime('%m');
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge block with defaults
|
// merge block with defaults
|
||||||
$block = array_merge($defaults, $block);
|
$block = array_merge($defaults, $block);
|
||||||
|
|
||||||
|
@ -27,11 +27,15 @@ class Radio extends Base {
|
|||||||
|
|
||||||
$html .= 'value="'.esc_attr($option['value']).'" ';
|
$html .= 'value="'.esc_attr($option['value']).'" ';
|
||||||
|
|
||||||
$html .= (isset($option['is_checked']) && $option['is_checked'])
|
$html .= (
|
||||||
? 'checked="checked"' : '';
|
(isset($option['is_checked']) && $option['is_checked'])
|
||||||
|
||
|
||||||
|
(self::getFieldValue($block) === $option['value'])
|
||||||
|
) ? 'checked="checked"' : '';
|
||||||
|
|
||||||
$html .= $field_validation;
|
$html .= $field_validation;
|
||||||
|
|
||||||
$html .= ' /> '.esc_attr($option['value']);
|
$html .= ' /> '.esc_attr($option['value']);
|
||||||
|
|
||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class Segment extends Base {
|
|||||||
$html .= 'name="'.$field_name.'[]" ';
|
$html .= 'name="'.$field_name.'[]" ';
|
||||||
$html .= 'value="'.$option['id'].'" '.$is_checked.' ';
|
$html .= 'value="'.$option['id'].'" '.$is_checked.' ';
|
||||||
$html .= $field_validation;
|
$html .= $field_validation;
|
||||||
$html .= ' />'.$option['name'];
|
$html .= ' /> '.esc_attr($option['name']);
|
||||||
$html .= '</label>';
|
$html .= '</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,7 @@ class Select extends Base {
|
|||||||
$field_validation = static::getInputValidation($block);
|
$field_validation = static::getInputValidation($block);
|
||||||
|
|
||||||
$html .= '<p class="mailpoet_paragraph">';
|
$html .= '<p class="mailpoet_paragraph">';
|
||||||
|
|
||||||
$html .= static::renderLabel($block);
|
$html .= static::renderLabel($block);
|
||||||
|
|
||||||
$html .= '<select class="mailpoet_select" name="'.$field_name.'">';
|
$html .= '<select class="mailpoet_select" name="'.$field_name.'">';
|
||||||
|
|
||||||
if(isset($block['params']['label_within'])
|
if(isset($block['params']['label_within'])
|
||||||
@ -21,10 +19,22 @@ class Select extends Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach($block['params']['values'] as $option) {
|
foreach($block['params']['values'] as $option) {
|
||||||
$is_selected = (isset($option['is_checked']) && $option['is_checked'])
|
$is_selected = (
|
||||||
? 'selected="selected"' : '';
|
(isset($option['is_checked']) && $option['is_checked'])
|
||||||
$html .= '<option value="'.$option['value'].'" '.$is_selected.'>';
|
||
|
||||||
$html .= $option['value'];
|
(self::getFieldValue($block) === $option['value'])
|
||||||
|
) ? 'selected="selected"' : '';
|
||||||
|
|
||||||
|
if(is_array($option['value'])) {
|
||||||
|
$value = key($option['value']);
|
||||||
|
$label = reset($option['value']);
|
||||||
|
} else {
|
||||||
|
$value = $option['value'];
|
||||||
|
$label = $option['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '<option value="'.$value.'" '.$is_selected.'>';
|
||||||
|
$html .= esc_attr($label);
|
||||||
$html .= '</option>';
|
$html .= '</option>';
|
||||||
}
|
}
|
||||||
$html .= '</select>';
|
$html .= '</select>';
|
||||||
|
@ -39,8 +39,7 @@ class Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private: rendering methods
|
static function renderBlocks($blocks = array()) {
|
||||||
private static function renderBlocks($blocks = array()) {
|
|
||||||
$html = '';
|
$html = '';
|
||||||
foreach ($blocks as $key => $block) {
|
foreach ($blocks as $key => $block) {
|
||||||
$html .= static::renderBlock($block)."\n";
|
$html .= static::renderBlock($block)."\n";
|
||||||
@ -49,7 +48,7 @@ class Renderer {
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function renderBlock($block = array()) {
|
static function renderBlock($block = array()) {
|
||||||
$html = '';
|
$html = '';
|
||||||
switch($block['type']) {
|
switch($block['type']) {
|
||||||
case 'html':
|
case 'html':
|
||||||
|
@ -17,7 +17,7 @@ class Styles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* labels */
|
/* labels */
|
||||||
.mailpoet_input_label,
|
.mailpoet_text_label,
|
||||||
.mailpoet_textarea_label,
|
.mailpoet_textarea_label,
|
||||||
.mailpoet_select_label,
|
.mailpoet_select_label,
|
||||||
.mailpoet_radio_label,
|
.mailpoet_radio_label,
|
||||||
@ -28,7 +28,7 @@ class Styles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* inputs */
|
/* inputs */
|
||||||
.mailpoet_input,
|
.mailpoet_text,
|
||||||
.mailpoet_textarea,
|
.mailpoet_textarea,
|
||||||
.mailpoet_select,
|
.mailpoet_select,
|
||||||
.mailpoet_date {
|
.mailpoet_date {
|
||||||
@ -36,9 +36,7 @@ class Styles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet_checkbox {
|
.mailpoet_checkbox {
|
||||||
display:inline;
|
|
||||||
margin-right: 5px;
|
|
||||||
vertical-align:middle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mailpoet_validate_success {
|
.mailpoet_validate_success {
|
||||||
|
@ -93,7 +93,7 @@ class Handler {
|
|||||||
|
|
||||||
return array(
|
return array(
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'filters' => $this->model->filter('filters'),
|
'filters' => $this->model->filter('filters', $this->data['group']),
|
||||||
'groups' => $this->model->filter('groups'),
|
'groups' => $this->model->filter('groups'),
|
||||||
'items' => $items
|
'items' => $items
|
||||||
);
|
);
|
||||||
|
@ -110,7 +110,7 @@ class Model extends \Sudzy\ValidModel {
|
|||||||
$total = $orm->count();
|
$total = $orm->count();
|
||||||
|
|
||||||
if($total > 0) {
|
if($total > 0) {
|
||||||
$models = $orm->select('id')
|
$models = $orm->select(static::$_table.'.id')
|
||||||
->offset(null)
|
->offset(null)
|
||||||
->limit(null)
|
->limit(null)
|
||||||
->findArray();
|
->findArray();
|
||||||
|
@ -73,16 +73,20 @@ class Newsletter extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function withSendingQueue() {
|
function withSendingQueue() {
|
||||||
$this->queue = $this->getQueue();
|
$queue = $this->getQueue();
|
||||||
|
if($queue === false) {
|
||||||
|
$this->queue = false;
|
||||||
|
} else {
|
||||||
|
$this->queue = $queue->asArray();
|
||||||
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static function search($orm, $search = '') {
|
static function search($orm, $search = '') {
|
||||||
return $orm->where_like('subject', '%' . $search . '%');
|
return $orm->where_like('subject', '%' . $search . '%');
|
||||||
}
|
}
|
||||||
|
|
||||||
static function filters() {
|
static function filters($orm, $group = 'all') {
|
||||||
$segments = Segment::orderByAsc('name')->findMany();
|
$segments = Segment::orderByAsc('name')->findMany();
|
||||||
$segment_list = array();
|
$segment_list = array();
|
||||||
$segment_list[] = array(
|
$segment_list[] = array(
|
||||||
@ -91,7 +95,9 @@ class Newsletter extends Model {
|
|||||||
);
|
);
|
||||||
|
|
||||||
foreach($segments as $segment) {
|
foreach($segments as $segment) {
|
||||||
$newsletters_count = $segment->newsletters()->count();
|
$newsletters_count = $segment->newsletters()
|
||||||
|
->filter('groupBy', $group)
|
||||||
|
->count();
|
||||||
if($newsletters_count > 0) {
|
if($newsletters_count > 0) {
|
||||||
$segment_list[] = array(
|
$segment_list[] = array(
|
||||||
'label' => sprintf('%s (%d)', $segment->name, $newsletters_count),
|
'label' => sprintf('%s (%d)', $segment->name, $newsletters_count),
|
||||||
|
@ -35,7 +35,7 @@ class Segment extends Model {
|
|||||||
__NAMESPACE__.'\SubscriberSegment',
|
__NAMESPACE__.'\SubscriberSegment',
|
||||||
'segment_id',
|
'segment_id',
|
||||||
'subscriber_id'
|
'subscriber_id'
|
||||||
);
|
)->where(MP_SUBSCRIBER_SEGMENT_TABLE.'.status', 'subscribed');
|
||||||
}
|
}
|
||||||
|
|
||||||
function duplicate($data = array()) {
|
function duplicate($data = array()) {
|
||||||
@ -186,6 +186,6 @@ class Segment extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function getPublic() {
|
static function getPublic() {
|
||||||
return self::getPublished()->where('type', 'default');
|
return self::getPublished()->where('type', 'default')->orderByAsc('name');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,8 @@ if (!defined('ABSPATH')) exit;
|
|||||||
class Setting extends Model {
|
class Setting extends Model {
|
||||||
public static $_table = MP_SETTINGS_TABLE;
|
public static $_table = MP_SETTINGS_TABLE;
|
||||||
|
|
||||||
|
public static $defaults = null;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
@ -14,8 +16,26 @@ class Setting extends Model {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getDefaults() {
|
||||||
|
if(self::$defaults === null) {
|
||||||
|
self::loadDefaults();
|
||||||
|
}
|
||||||
|
return self::$defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadDefaults() {
|
||||||
|
self::$defaults = array(
|
||||||
|
'signup_confirmation' => array(
|
||||||
|
'enabled' => true,
|
||||||
|
'subject' => sprintf(__('Confirm your subscription to %1$s'), get_option('blogname')),
|
||||||
|
'body' => __("Hello!\n\nHurray! You've subscribed to our site.\nWe need you to activate your subscription to the list(s): [lists_to_confirm] by clicking the link below: \n\n[activation_link]Click here to confirm your subscription.[/activation_link]\n\nThank you,\n\nThe team!")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public static function getValue($key, $default = null) {
|
public static function getValue($key, $default = null) {
|
||||||
$keys = explode('.', $key);
|
$keys = explode('.', $key);
|
||||||
|
$defaults = self::getDefaults();
|
||||||
|
|
||||||
if(count($keys) === 1) {
|
if(count($keys) === 1) {
|
||||||
$setting = Setting::where('name', $key)->findOne();
|
$setting = Setting::where('name', $key)->findOne();
|
||||||
@ -23,9 +43,14 @@ class Setting extends Model {
|
|||||||
return $default;
|
return $default;
|
||||||
} else {
|
} else {
|
||||||
if(is_serialized($setting->value)) {
|
if(is_serialized($setting->value)) {
|
||||||
return unserialize($setting->value);
|
$value = unserialize($setting->value);
|
||||||
} else {
|
} else {
|
||||||
return $setting->value;
|
$value = $setting->value;
|
||||||
|
}
|
||||||
|
if(is_array($value) && array_key_exists($key, $defaults)) {
|
||||||
|
return array_replace_recursive($defaults[$key], $value);
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -93,7 +118,7 @@ class Setting extends Model {
|
|||||||
$settings[$setting->name] = $value;
|
$settings[$setting->name] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $settings;
|
return array_replace_recursive(self::getDefaults(), $settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createOrUpdate($data = array()) {
|
public static function createOrUpdate($data = array()) {
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Models;
|
namespace MailPoet\Models;
|
||||||
|
use MailPoet\Mailer\Mailer;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Subscriber extends Model {
|
class Subscriber extends Model {
|
||||||
public static $_table = MP_SUBSCRIBERS_TABLE;
|
public static $_table = MP_SUBSCRIBERS_TABLE;
|
||||||
|
|
||||||
|
const STATUS_SUBSCRIBED = 'subscribed';
|
||||||
|
const STATUS_UNSUBSCRIBED = 'unsubscribed';
|
||||||
|
const STATUS_UNCONFIRMED = 'unconfirmed';
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
@ -16,13 +21,22 @@ class Subscriber extends Model {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function findOne($id = null) {
|
||||||
|
if(is_int($id) || (string)(int)$id === $id) {
|
||||||
|
return parent::findOne($id);
|
||||||
|
} else {
|
||||||
|
return parent::where('email', $id)->findOne();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function segments() {
|
function segments() {
|
||||||
return $this->has_many_through(
|
return $this->has_many_through(
|
||||||
__NAMESPACE__.'\Segment',
|
__NAMESPACE__.'\Segment',
|
||||||
__NAMESPACE__.'\SubscriberSegment',
|
__NAMESPACE__.'\SubscriberSegment',
|
||||||
'subscriber_id',
|
'subscriber_id',
|
||||||
'segment_id'
|
'segment_id'
|
||||||
);
|
)
|
||||||
|
->where(MP_SUBSCRIBER_SEGMENT_TABLE.'.status', self::STATUS_SUBSCRIBED);
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete() {
|
function delete() {
|
||||||
@ -56,10 +70,116 @@ class Subscriber extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendConfirmationEmail() {
|
function getConfirmationUrl() {
|
||||||
$this->set('status', 'unconfirmed');
|
$post = get_post(Setting::getValue('signup_confirmation.page'));
|
||||||
|
return $this->getSubscriptionUrl($post, 'confirm');
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
function getEditSubscriptionUrl() {
|
||||||
|
$post = get_post(Setting::getValue('subscription.page'));
|
||||||
|
return $this->getSubscriptionUrl($post, 'edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUnsubscribeUrl() {
|
||||||
|
$post = get_post(Setting::getValue('subscription.page'));
|
||||||
|
return $this->getSubscriptionUrl($post, 'unsubscribe');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSubscriptionUrl($post = null, $action = null) {
|
||||||
|
if($post === null || $action === null) return;
|
||||||
|
|
||||||
|
$url = get_permalink($post);
|
||||||
|
|
||||||
|
$params = array(
|
||||||
|
'mailpoet_action='.$action,
|
||||||
|
'mailpoet_token='.self::generateToken($this->email),
|
||||||
|
'mailpoet_email='.$this->email
|
||||||
|
);
|
||||||
|
// add parameters
|
||||||
|
$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?').join('&', $params);
|
||||||
|
|
||||||
|
$url_params = parse_url($url);
|
||||||
|
if(empty($url_params['scheme'])) {
|
||||||
|
$url = get_bloginfo('url').$url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendConfirmationEmail() {
|
||||||
|
if($this->status === self::STATUS_UNCONFIRMED) {
|
||||||
|
$signup_confirmation = Setting::getValue('signup_confirmation');
|
||||||
|
|
||||||
|
$segments = $this->segments()->findMany();
|
||||||
|
$segment_names = array_map(function($segment) {
|
||||||
|
return $segment->name;
|
||||||
|
}, $segments);
|
||||||
|
|
||||||
|
$body = nl2br($signup_confirmation['body']);
|
||||||
|
|
||||||
|
// replace list of segments shortcode
|
||||||
|
$body = str_replace(
|
||||||
|
'[lists_to_confirm]',
|
||||||
|
'<strong>'.join(', ', $segment_names).'</strong>',
|
||||||
|
$body
|
||||||
|
);
|
||||||
|
|
||||||
|
// replace activation link
|
||||||
|
$body = str_replace(
|
||||||
|
array(
|
||||||
|
'[activation_link]',
|
||||||
|
'[/activation_link]'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'<a href="'.htmlentities($this->getConfirmationUrl()).'">',
|
||||||
|
'</a>'
|
||||||
|
),
|
||||||
|
$body
|
||||||
|
);
|
||||||
|
|
||||||
|
// build email data
|
||||||
|
$email = array(
|
||||||
|
'subject' => $signup_confirmation['subject'],
|
||||||
|
'body' => array(
|
||||||
|
'html' => $body,
|
||||||
|
'text' => $body
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// convert subscriber to array
|
||||||
|
$subscriber = $this->asArray();
|
||||||
|
|
||||||
|
// set from
|
||||||
|
$from = (
|
||||||
|
!empty($signup_confirmation['from'])
|
||||||
|
&& !empty($signup_confirmation['from']['email'])
|
||||||
|
) ? $signup_confirmation['from']
|
||||||
|
: false;
|
||||||
|
|
||||||
|
// set reply to
|
||||||
|
$reply_to = (
|
||||||
|
!empty($signup_confirmation['reply_to'])
|
||||||
|
&& !empty($signup_confirmation['reply_to']['email'])
|
||||||
|
) ? $signup_confirmation['reply_to']
|
||||||
|
: false;
|
||||||
|
|
||||||
|
// send email
|
||||||
|
try {
|
||||||
|
$mailer = new Mailer(false, $from, $reply_to);
|
||||||
|
return $mailer->send($email, $subscriber);
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$this->setError($e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function generateToken($email = null) {
|
||||||
|
if($email !== null) {
|
||||||
|
return md5(AUTH_KEY.$email);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function subscribe($subscriber_data = array(), $segment_ids = array()) {
|
static function subscribe($subscriber_data = array(), $segment_ids = array()) {
|
||||||
@ -68,19 +188,22 @@ class Subscriber extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$subscriber = self::createOrUpdate($subscriber_data);
|
$subscriber = self::createOrUpdate($subscriber_data);
|
||||||
|
$errors = $subscriber->getErrors();
|
||||||
|
|
||||||
|
if($errors === false && $subscriber->id > 0) {
|
||||||
|
$subscriber = self::findOne($subscriber->id);
|
||||||
|
|
||||||
if($subscriber !== false && $subscriber->id() > 0) {
|
|
||||||
// restore deleted subscriber
|
// restore deleted subscriber
|
||||||
if($subscriber->deleted_at !== NULL) {
|
if($subscriber->deleted_at !== NULL) {
|
||||||
$subscriber->setExpr('deleted_at', 'NULL');
|
$subscriber->setExpr('deleted_at', 'NULL');
|
||||||
}
|
}
|
||||||
|
|
||||||
if((bool)Setting::getValue('signup_confirmation.enabled')) {
|
if((bool)Setting::getValue('signup_confirmation.enabled')) {
|
||||||
if($subscriber->status !== 'subscribed') {
|
if($subscriber->status !== self::STATUS_SUBSCRIBED) {
|
||||||
$subscriber->sendConfirmationEmail();
|
$subscriber->sendConfirmationEmail();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$subscriber->set('status', 'subscribed');
|
$subscriber->set('status', self::STATUS_SUBSCRIBED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($subscriber->save()) {
|
if($subscriber->save()) {
|
||||||
@ -102,7 +225,7 @@ class Subscriber extends Model {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function filters() {
|
static function filters($orm, $group = 'all') {
|
||||||
$segments = Segment::orderByAsc('name')->findMany();
|
$segments = Segment::orderByAsc('name')->findMany();
|
||||||
$segment_list = array();
|
$segment_list = array();
|
||||||
$segment_list[] = array(
|
$segment_list[] = array(
|
||||||
@ -119,8 +242,9 @@ class Subscriber extends Model {
|
|||||||
|
|
||||||
foreach($segments as $segment) {
|
foreach($segments as $segment) {
|
||||||
$subscribers_count = $segment->subscribers()
|
$subscribers_count = $segment->subscribers()
|
||||||
->whereNull('deleted_at')
|
->filter('groupBy', $group)
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
$segment_list[] = array(
|
$segment_list[] = array(
|
||||||
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
|
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
|
||||||
'value' => $segment->id()
|
'value' => $segment->id()
|
||||||
@ -161,19 +285,19 @@ class Subscriber extends Model {
|
|||||||
'count' => self::getPublished()->count()
|
'count' => self::getPublished()->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'subscribed',
|
'name' => self::STATUS_SUBSCRIBED,
|
||||||
'label' => __('Subscribed'),
|
'label' => __('Subscribed'),
|
||||||
'count' => self::filter('subscribed')->count()
|
'count' => self::filter(self::STATUS_SUBSCRIBED)->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'unconfirmed',
|
'name' => self::STATUS_UNCONFIRMED,
|
||||||
'label' => __('Unconfirmed'),
|
'label' => __('Unconfirmed'),
|
||||||
'count' => self::filter('unconfirmed')->count()
|
'count' => self::filter(self::STATUS_UNCONFIRMED)->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'unsubscribed',
|
'name' => self::STATUS_UNSUBSCRIBED,
|
||||||
'label' => __('Unsubscribed'),
|
'label' => __('Unsubscribed'),
|
||||||
'count' => self::filter('unsubscribed')->count()
|
'count' => self::filter(self::STATUS_UNSUBSCRIBED)->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'trash',
|
'name' => 'trash',
|
||||||
@ -412,21 +536,23 @@ class Subscriber extends Model {
|
|||||||
|
|
||||||
static function bulkConfirmUnconfirmed($orm) {
|
static function bulkConfirmUnconfirmed($orm) {
|
||||||
$subscribers = $orm->findResultSet();
|
$subscribers = $orm->findResultSet();
|
||||||
$subscribers->set('status', 'subscribed')->save();
|
$subscribers->set('status', self::STATUS_SUBSCRIBED)->save();
|
||||||
return $subscribers->count();
|
return $subscribers->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
static function bulkResendConfirmationEmail($orm) {
|
static function bulkSendConfirmationEmail($orm) {
|
||||||
$subscribers = $orm
|
$subscribers = $orm
|
||||||
->where('status', 'unconfirmed')
|
->where('status', self::STATUS_UNCONFIRMED)
|
||||||
->findResultSet();
|
->findMany();
|
||||||
|
|
||||||
|
$emails_sent = 0;
|
||||||
if(!empty($subscribers)) {
|
if(!empty($subscribers)) {
|
||||||
foreach($subscribers as $subscriber) {
|
foreach($subscribers as $subscriber) {
|
||||||
$subscriber->sendConfirmationEmail();
|
if($subscriber->sendConfirmationEmail()) {
|
||||||
|
$emails_sent++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return $emails_sent;
|
||||||
return $subscribers->count();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -467,19 +593,19 @@ class Subscriber extends Model {
|
|||||||
static function subscribed($orm) {
|
static function subscribed($orm) {
|
||||||
return $orm
|
return $orm
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('status', 'subscribed');
|
->where('status', self::STATUS_SUBSCRIBED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function unsubscribed($orm) {
|
static function unsubscribed($orm) {
|
||||||
return $orm
|
return $orm
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('status', 'unsubscribed');
|
->where('status', self::STATUS_UNSUBSCRIBED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function unconfirmed($orm) {
|
static function unconfirmed($orm) {
|
||||||
return $orm
|
return $orm
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('status', 'unconfirmed');
|
->where('status', self::STATUS_UNCONFIRMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function withoutSegments($orm) {
|
static function withoutSegments($orm) {
|
||||||
|
@ -18,7 +18,7 @@ class SubscriberSegment extends Model {
|
|||||||
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
SubscriberSegment::where('subscriber_id', $subscriber->id)
|
||||||
->whereNotIn('segment_id', $segment_ids)
|
->whereNotIn('segment_id', $segment_ids)
|
||||||
->findResultSet()
|
->findResultSet()
|
||||||
->set('status', 'unsubscribed')
|
->set('status', Subscriber::STATUS_UNSUBSCRIBED)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
// subscribe to segments
|
// subscribe to segments
|
||||||
@ -26,7 +26,7 @@ class SubscriberSegment extends Model {
|
|||||||
self::createOrUpdate(array(
|
self::createOrUpdate(array(
|
||||||
'subscriber_id' => $subscriber->id,
|
'subscriber_id' => $subscriber->id,
|
||||||
'segment_id' => $segment_id,
|
'segment_id' => $segment_id,
|
||||||
'status' => 'subscribed'
|
'status' => Subscriber::STATUS_SUBSCRIBED
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,29 +34,8 @@ class SubscriberSegment extends Model {
|
|||||||
return $subscriber;
|
return $subscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function filterWithCustomFields($orm) {
|
|
||||||
$orm = $orm->select(MP_SUBSCRIBERS_TABLE.'.*');
|
|
||||||
$customFields = CustomField::findArray();
|
|
||||||
foreach ($customFields as $customField) {
|
|
||||||
$orm = $orm->select_expr(
|
|
||||||
'CASE WHEN ' .
|
|
||||||
MP_CUSTOM_FIELDS_TABLE . '.id=' . $customField['id'] . ' THEN ' .
|
|
||||||
MP_SUBSCRIBER_CUSTOM_FIELD_TABLE . '.value END as "' . $customField['name'].'"');
|
|
||||||
}
|
|
||||||
$orm = $orm
|
|
||||||
->left_outer_join(
|
|
||||||
MP_SUBSCRIBER_CUSTOM_FIELD_TABLE,
|
|
||||||
array(MP_SUBSCRIBERS_TABLE.'.id', '=',
|
|
||||||
MP_SUBSCRIBER_CUSTOM_FIELD_TABLE.'.subscriber_id'))
|
|
||||||
->left_outer_join(
|
|
||||||
MP_CUSTOM_FIELDS_TABLE,
|
|
||||||
array(MP_CUSTOM_FIELDS_TABLE.'.id','=',
|
|
||||||
MP_SUBSCRIBER_CUSTOM_FIELD_TABLE.'.custom_field_id'));
|
|
||||||
return $orm;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function subscribed($orm) {
|
static function subscribed($orm) {
|
||||||
return $orm->where('status', 'subscribed');
|
return $orm->where('status', Subscriber::STATUS_SUBSCRIBED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function createOrUpdate($data = array()) {
|
static function createOrUpdate($data = array()) {
|
||||||
|
@ -19,7 +19,7 @@ class Footer {
|
|||||||
}
|
}
|
||||||
$template = '
|
$template = '
|
||||||
<tr>
|
<tr>
|
||||||
<td class="mailpoet_padded_header_footer mailpoet_footer" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
<td class="mailpoet_header_footer_padded mailpoet_footer" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
||||||
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||||
' . $DOM->html() . '
|
' . $DOM->html() . '
|
||||||
</td>
|
</td>
|
||||||
|
@ -19,7 +19,7 @@ class Header {
|
|||||||
}
|
}
|
||||||
$template = '
|
$template = '
|
||||||
<tr>
|
<tr>
|
||||||
<td class="mailpoet_padded_header_footer mailpoet_header" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
<td class="mailpoet_header_footer_padded mailpoet_header" bgcolor="' . $element['styles']['block']['backgroundColor'] . '"
|
||||||
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
style="' . StylesHelper::getBlockStyles($element) . StylesHelper::getStyles($element['styles'], 'text') . '">
|
||||||
' . $DOM->html() . '
|
' . $DOM->html() . '
|
||||||
</td>
|
</td>
|
||||||
|
@ -10,7 +10,8 @@ class Renderer {
|
|||||||
$template = ($columns_count === 1) ?
|
$template = ($columns_count === 1) ?
|
||||||
$this->getOneColumnTemplate($styles, $class) :
|
$this->getOneColumnTemplate($styles, $class) :
|
||||||
$this->getMultipleColumnsTemplate($styles, $width, $alignment, $class);
|
$this->getMultipleColumnsTemplate($styles, $width, $alignment, $class);
|
||||||
$result = array_map(function ($content) use ($template) {
|
$result = array_map(function($content) use ($template) {
|
||||||
|
$content = self::removePaddingFromLastElement($content);
|
||||||
return $template['content_start'] . $content . $template['content_end'];
|
return $template['content_start'] . $content . $template['content_end'];
|
||||||
}, $columns_data);
|
}, $columns_data);
|
||||||
$result = implode('', $result);
|
$result = implode('', $result);
|
||||||
@ -75,4 +76,8 @@ class Renderer {
|
|||||||
</tr>';
|
</tr>';
|
||||||
return $template;
|
return $template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removePaddingFromLastElement($element) {
|
||||||
|
return preg_replace('/mailpoet_padded(?!.*mailpoet_padded)/ism', '', $element);
|
||||||
|
}
|
||||||
}
|
}
|
@ -40,7 +40,7 @@
|
|||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
.mailpoet_padded_header_footer {
|
.mailpoet_header_footer_padded {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 599px) and (-webkit-min-device-pixel-ratio: 1) {
|
@media screen and (max-width: 599px) and (-webkit-min-device-pixel-ratio: 1) {
|
||||||
|
@ -15,12 +15,26 @@ class Router {
|
|||||||
);
|
);
|
||||||
add_action(
|
add_action(
|
||||||
'wp_ajax_mailpoet',
|
'wp_ajax_mailpoet',
|
||||||
array($this, 'setup')
|
array($this, 'setupAdmin')
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'wp_ajax_nopriv_mailpoet',
|
||||||
|
array($this, 'setupPublic')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup() {
|
function setupAdmin() {
|
||||||
$this->securityCheck();
|
$this->verifyToken();
|
||||||
|
$this->checkPermissions();
|
||||||
|
return $this->processRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupPublic() {
|
||||||
|
$this->verifyToken();
|
||||||
|
return $this->processRoute();
|
||||||
|
}
|
||||||
|
|
||||||
|
function processRoute() {
|
||||||
$class = ucfirst($_POST['endpoint']);
|
$class = ucfirst($_POST['endpoint']);
|
||||||
$endpoint = __NAMESPACE__ . "\\" . $class;
|
$endpoint = __NAMESPACE__ . "\\" . $class;
|
||||||
$method = $_POST['method'];
|
$method = $_POST['method'];
|
||||||
@ -43,8 +57,11 @@ class Router {
|
|||||||
echo $global;
|
echo $global;
|
||||||
}
|
}
|
||||||
|
|
||||||
function securityCheck() {
|
function checkPermissions() {
|
||||||
if(!current_user_can('manage_options')) { die(); }
|
if(!current_user_can('manage_options')) { die(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyToken() {
|
||||||
if(!wp_verify_nonce($_POST['token'], 'mailpoet_token')) { die(); }
|
if(!wp_verify_nonce($_POST['token'], 'mailpoet_token')) { die(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class Subscribers {
|
|||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function get($id = false) {
|
function get($id = null) {
|
||||||
$subscriber = Subscriber::findOne($id);
|
$subscriber = Subscriber::findOne($id);
|
||||||
if($subscriber !== false) {
|
if($subscriber !== false) {
|
||||||
$subscriber = $subscriber
|
$subscriber = $subscriber
|
||||||
@ -88,18 +88,10 @@ class Subscribers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$subscriber = Subscriber::subscribe($data, $segment_ids);
|
$subscriber = Subscriber::subscribe($data, $segment_ids);
|
||||||
|
if($subscriber->getErrors() !== false) {
|
||||||
$result = false;
|
|
||||||
if($subscriber === false || !$subscriber->id()) {
|
|
||||||
$errors = array_merge($errors, $subscriber->getValidationErrors());
|
|
||||||
} else {
|
|
||||||
$result = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!empty($errors)) {
|
|
||||||
return array(
|
return array(
|
||||||
'result' => false,
|
'result' => false,
|
||||||
'errors' => $errors
|
'errors' => $subscriber->getErrors()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@ class Pages {
|
|||||||
),
|
),
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'has_archive' => false,
|
'has_archive' => false,
|
||||||
'show_ui' => true,
|
'show_ui' => WP_DEBUG,
|
||||||
'show_in_menu' => false,
|
'show_in_menu' => WP_DEBUG,
|
||||||
'rewrite' => false,
|
'rewrite' => false,
|
||||||
'show_in_nav_menus'=>false,
|
'show_in_nav_menus' => false,
|
||||||
'can_export'=>false,
|
'can_export' => false,
|
||||||
'publicly_queryable'=>true,
|
'publicly_queryable' => true,
|
||||||
'exclude_from_search'=>true
|
'exclude_from_search' => true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,9 @@ class Pages {
|
|||||||
return array(
|
return array(
|
||||||
'id' => $page->ID,
|
'id' => $page->ID,
|
||||||
'title' => $page->post_title,
|
'title' => $page->post_title,
|
||||||
'preview_url' => get_permalink($page->ID),
|
'preview_url' => add_query_arg(array(
|
||||||
|
'preview' => 1
|
||||||
|
), get_permalink($page->ID)),
|
||||||
'edit_url' => get_edit_post_link($page->ID)
|
'edit_url' => get_edit_post_link($page->ID)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ class BootStrapMenu {
|
|||||||
Segment::getSegmentsWithSubscriberCount() :
|
Segment::getSegmentsWithSubscriberCount() :
|
||||||
Segment::getSegmentsForExport($with_confirmed_subscribers);
|
Segment::getSegmentsForExport($with_confirmed_subscribers);
|
||||||
return array_map(function($segment) {
|
return array_map(function($segment) {
|
||||||
|
if (!$segment['name']) $segment['name'] = __('Not In Segment');
|
||||||
|
if (!$segment['id']) $segment['id'] = 0;
|
||||||
return array(
|
return array(
|
||||||
'id' => $segment['id'],
|
'id' => $segment['id'],
|
||||||
'name' => $segment['name'],
|
'name' => $segment['name'],
|
||||||
@ -31,7 +33,7 @@ class BootStrapMenu {
|
|||||||
'first_name' => __('First name'),
|
'first_name' => __('First name'),
|
||||||
'last_name' => __('Last name'),
|
'last_name' => __('Last name'),
|
||||||
'status' => __('Status')
|
'status' => __('Status')
|
||||||
// TODO: add additional fiels from MP2
|
// TODO: add additional fields from MP2
|
||||||
/*
|
/*
|
||||||
'confirmed_ip' => __('IP address')
|
'confirmed_ip' => __('IP address')
|
||||||
'confirmed_at' => __('Subscription date')
|
'confirmed_at' => __('Subscription date')
|
||||||
|
@ -17,22 +17,30 @@ class Export {
|
|||||||
public $segments;
|
public $segments;
|
||||||
public $subscribers_without_segment;
|
public $subscribers_without_segment;
|
||||||
public $subscriber_fields;
|
public $subscriber_fields;
|
||||||
|
public $subscriber_custom_fields;
|
||||||
|
public $formatted_subscriber_fields;
|
||||||
public $export_path;
|
public $export_path;
|
||||||
public $export_file;
|
public $export_file;
|
||||||
public $export_file_URL;
|
public $export_file_URL;
|
||||||
public $profiler_start;
|
public $subscriber_batch_size;
|
||||||
|
|
||||||
public function __construct($data) {
|
public function __construct($data) {
|
||||||
|
set_time_limit(0);
|
||||||
$this->export_confirmed_option = $data['export_confirmed_option'];
|
$this->export_confirmed_option = $data['export_confirmed_option'];
|
||||||
$this->export_format_option = $data['export_format_option'];
|
$this->export_format_option = $data['export_format_option'];
|
||||||
$this->group_by_segment_option = $data['group_by_segment_option'];
|
$this->group_by_segment_option = $data['group_by_segment_option'];
|
||||||
$this->segments = $data['segments'];
|
$this->segments = $data['segments'];
|
||||||
$this->subscribers_without_segment = array_search(0, $this->segments);
|
$this->subscribers_without_segment = array_search(0, $this->segments);
|
||||||
$this->subscriber_fields = $data['subscriber_fields'];
|
$this->subscriber_fields = $data['subscriber_fields'];
|
||||||
|
$this->subscriber_custom_fields = $this->getSubscriberCustomFields();
|
||||||
|
$this->formatted_subscriber_fields = $this->formatSubscriberFields(
|
||||||
|
$this->subscriber_fields,
|
||||||
|
$this->subscriber_custom_fields
|
||||||
|
);
|
||||||
$this->export_path = Env::$temp_path;
|
$this->export_path = Env::$temp_path;
|
||||||
$this->export_file = $this->getExportFile($this->export_format_option);
|
$this->export_file = $this->getExportFile($this->export_format_option);
|
||||||
$this->export_file_URL = $this->getExportFileURL($this->export_file);
|
$this->export_file_URL = $this->getExportFileURL($this->export_file);
|
||||||
$this->profiler_start = microtime(true);
|
$this->subscriber_batch_size = 15000;
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process() {
|
||||||
@ -40,75 +48,12 @@ class Export {
|
|||||||
if(is_writable($this->export_path) === false) {
|
if(is_writable($this->export_path) === false) {
|
||||||
throw new \Exception(__("Couldn't save export file on the server."));
|
throw new \Exception(__("Couldn't save export file on the server."));
|
||||||
}
|
}
|
||||||
$subscribers = $this->getSubscribers();
|
$processed_subscribers = call_user_func(
|
||||||
$subscriber_custom_fields = $this->getSubscriberCustomFields();
|
array(
|
||||||
$formatted_subscriber_fields = $this->formatSubscriberFields(
|
$this,
|
||||||
$this->subscriber_fields,
|
'generate' . strtoupper($this->export_format_option)
|
||||||
$subscriber_custom_fields
|
)
|
||||||
);
|
);
|
||||||
if($this->export_format_option === 'csv') {
|
|
||||||
$CSV_file = fopen($this->export_file, 'w');
|
|
||||||
$format_CSV = function($row) {
|
|
||||||
return '"' . str_replace('"', '\"', $row) . '"';
|
|
||||||
};
|
|
||||||
// add UTF-8 BOM (3 bytes, hex EF BB BF) at the start of the file for
|
|
||||||
// Excel to automatically recognize the encoding
|
|
||||||
fwrite($CSV_file, chr(0xEF) . chr(0xBB) . chr(0xBF));
|
|
||||||
if($this->group_by_segment_option) {
|
|
||||||
$formatted_subscriber_fields[] = __('Segment');
|
|
||||||
}
|
|
||||||
fwrite(
|
|
||||||
$CSV_file,
|
|
||||||
implode(
|
|
||||||
',',
|
|
||||||
array_map(
|
|
||||||
$format_CSV,
|
|
||||||
$formatted_subscriber_fields
|
|
||||||
)
|
|
||||||
) . "\n"
|
|
||||||
);
|
|
||||||
foreach($subscribers as $subscriber) {
|
|
||||||
$row = $this->formatSubscriberData($subscriber);
|
|
||||||
if($this->group_by_segment_option) {
|
|
||||||
$row[] = ucwords($subscriber['segment_name']);
|
|
||||||
}
|
|
||||||
fwrite($CSV_file, implode(',', array_map($format_CSV, $row)) . "\n");
|
|
||||||
}
|
|
||||||
fclose($CSV_file);
|
|
||||||
} else {
|
|
||||||
$writer = new XLSXWriter();
|
|
||||||
$writer->setAuthor('MailPoet (www.mailpoet.com)');
|
|
||||||
$header_row = array($formatted_subscriber_fields);
|
|
||||||
$last_segment = false;
|
|
||||||
$rows = array();
|
|
||||||
foreach($subscribers as $subscriber) {
|
|
||||||
if($last_segment && $last_segment !== $subscriber['segment_name'] &&
|
|
||||||
$this->group_by_segment_option
|
|
||||||
) {
|
|
||||||
$writer->writeSheet(
|
|
||||||
array_merge($header_row, $rows), ucwords($last_segment)
|
|
||||||
);
|
|
||||||
$rows = array();
|
|
||||||
}
|
|
||||||
// detect RTL language and set Excel to properly display the sheet
|
|
||||||
$RTL_regex = '/\p{Arabic}|\p{Hebrew}/u';
|
|
||||||
if(!$writer->rtl && (
|
|
||||||
preg_grep($RTL_regex, $subscriber) ||
|
|
||||||
preg_grep($RTL_regex, $formatted_subscriber_fields))
|
|
||||||
) {
|
|
||||||
$writer->rtl = true;
|
|
||||||
}
|
|
||||||
$rows[] = $this->formatSubscriberData($subscriber);
|
|
||||||
$last_segment = $subscriber['segment_name'];
|
|
||||||
}
|
|
||||||
$writer->writeSheet(
|
|
||||||
array_merge($header_row, $rows),
|
|
||||||
($this->group_by_segment_option) ?
|
|
||||||
ucwords($subscriber['segment_name']) :
|
|
||||||
__('All Segments')
|
|
||||||
);
|
|
||||||
$writer->writeToFile($this->export_file);
|
|
||||||
}
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
return array(
|
return array(
|
||||||
'result' => false,
|
'result' => false,
|
||||||
@ -118,14 +63,118 @@ class Export {
|
|||||||
return array(
|
return array(
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'data' => array(
|
'data' => array(
|
||||||
'totalExported' => count($subscribers),
|
'totalExported' => $processed_subscribers,
|
||||||
'exportFileURL' => $this->export_file_URL
|
'exportFileURL' => $this->export_file_URL
|
||||||
),
|
)
|
||||||
'profiler' => $this->timeExecution()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscribers() {
|
function generateCSV() {
|
||||||
|
$processed_subscribers = 0;
|
||||||
|
$offset = 0;
|
||||||
|
$formatted_subscriber_fields = $this->formatted_subscriber_fields;
|
||||||
|
$CSV_file = fopen($this->export_file, 'w');
|
||||||
|
$format_CSV = function($row) {
|
||||||
|
return '"' . str_replace('"', '\"', $row) . '"';
|
||||||
|
};
|
||||||
|
// add UTF-8 BOM (3 bytes, hex EF BB BF) at the start of the file for
|
||||||
|
// Excel to automatically recognize the encoding
|
||||||
|
fwrite($CSV_file, chr(0xEF) . chr(0xBB) . chr(0xBF));
|
||||||
|
if($this->group_by_segment_option) {
|
||||||
|
$formatted_subscriber_fields[] = __('Segment');
|
||||||
|
}
|
||||||
|
fwrite(
|
||||||
|
$CSV_file,
|
||||||
|
implode(
|
||||||
|
',',
|
||||||
|
array_map(
|
||||||
|
$format_CSV,
|
||||||
|
$formatted_subscriber_fields
|
||||||
|
)
|
||||||
|
) . PHP_EOL
|
||||||
|
);
|
||||||
|
do {
|
||||||
|
$subscribers = $this->getSubscribers($offset, $this->subscriber_batch_size);
|
||||||
|
$processed_subscribers += count($subscribers);
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
$row = $this->formatSubscriberData($subscriber);
|
||||||
|
if($this->group_by_segment_option) {
|
||||||
|
$row[] = ucwords($subscriber['segment_name']);
|
||||||
|
}
|
||||||
|
fwrite($CSV_file, implode(',', array_map($format_CSV, $row)) . "\n");
|
||||||
|
}
|
||||||
|
$offset += $this->subscriber_batch_size;
|
||||||
|
} while(count($subscribers) === $this->subscriber_batch_size);
|
||||||
|
fclose($CSV_file);
|
||||||
|
return $processed_subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateXLSX() {
|
||||||
|
$processed_subscribers = 0;
|
||||||
|
$offset = 0;
|
||||||
|
$XLSX_writer = new XLSXWriter();
|
||||||
|
$XLSX_writer->setAuthor('MailPoet (www.mailpoet.com)');
|
||||||
|
$last_segment = false;
|
||||||
|
$processed_segments = array();
|
||||||
|
do {
|
||||||
|
$subscribers = $this->getSubscribers($offset, $this->subscriber_batch_size);
|
||||||
|
$processed_subscribers += count($subscribers);
|
||||||
|
foreach($subscribers as $i => $subscriber) {
|
||||||
|
$current_segment = ucwords($subscriber['segment_name']);
|
||||||
|
// Sheet header (1st row) will be written only if:
|
||||||
|
// * This is the first time we're processing a segment
|
||||||
|
// * "Group by subscriber option" is turned AND the previous subscriber's
|
||||||
|
// segment is different from the current subscriber's segment
|
||||||
|
// Header will NOT be written if:
|
||||||
|
// * We have already processed the segment. Because SQL results are not
|
||||||
|
// sorted by segment name (due to slow queries when using ORDER BY and LIMIT),
|
||||||
|
// we need to keep track of processed segments so that we do not create header
|
||||||
|
// multiple times when switching from one segment to another and back.
|
||||||
|
if((!count($processed_segments) ||
|
||||||
|
($last_segment !== $current_segment && $this->group_by_segment_option)
|
||||||
|
) &&
|
||||||
|
(!in_array($last_segment, $processed_segments) ||
|
||||||
|
!in_array($current_segment, $processed_segments)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
$this->writeXLSX(
|
||||||
|
$XLSX_writer,
|
||||||
|
$subscriber['segment_name'],
|
||||||
|
$this->formatted_subscriber_fields
|
||||||
|
);
|
||||||
|
$processed_segments[] = $current_segment;
|
||||||
|
}
|
||||||
|
$last_segment = ucwords($subscriber['segment_name']);
|
||||||
|
// detect RTL language and set Excel to properly display the sheet
|
||||||
|
$RTL_regex = '/\p{Arabic}|\p{Hebrew}/u';
|
||||||
|
if(!$XLSX_writer->rtl && (
|
||||||
|
preg_grep($RTL_regex, $subscriber) ||
|
||||||
|
preg_grep($RTL_regex, $this->formatted_subscriber_fields))
|
||||||
|
) {
|
||||||
|
$XLSX_writer->rtl = true;
|
||||||
|
}
|
||||||
|
$this->writeXLSX(
|
||||||
|
$XLSX_writer,
|
||||||
|
$last_segment,
|
||||||
|
$this->formatSubscriberData($subscriber)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$offset += $this->subscriber_batch_size;
|
||||||
|
} while(count($subscribers) === $this->subscriber_batch_size);
|
||||||
|
$XLSX_writer->writeToFile($this->export_file);
|
||||||
|
return $processed_subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeXLSX($XLSX_writer, $segment, $data) {
|
||||||
|
return $XLSX_writer->writeSheetRow(
|
||||||
|
($this->group_by_segment_option) ?
|
||||||
|
ucwords($segment) :
|
||||||
|
__('All Segments'),
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubscribers($offset, $limit) {
|
||||||
$subscribers = Subscriber::
|
$subscribers = Subscriber::
|
||||||
left_outer_join(
|
left_outer_join(
|
||||||
SubscriberSegment::$_table,
|
SubscriberSegment::$_table,
|
||||||
@ -141,7 +190,6 @@ class Export {
|
|||||||
'=',
|
'=',
|
||||||
SubscriberSegment::$_table . '.segment_id'
|
SubscriberSegment::$_table . '.segment_id'
|
||||||
))
|
))
|
||||||
->orderByAsc('segment_name')
|
|
||||||
->filter('filterWithCustomFieldsForExport');
|
->filter('filterWithCustomFieldsForExport');
|
||||||
if($this->subscribers_without_segment !== false) {
|
if($this->subscribers_without_segment !== false) {
|
||||||
$subscribers = $subscribers
|
$subscribers = $subscribers
|
||||||
@ -168,9 +216,11 @@ class Export {
|
|||||||
$subscribers =
|
$subscribers =
|
||||||
$subscribers->where(Subscriber::$_table . '.status', 'subscribed');
|
$subscribers->where(Subscriber::$_table . '.status', 'subscribed');
|
||||||
}
|
}
|
||||||
$subscribers = $subscribers->whereNull(Subscriber::$_table . '.deleted_at');
|
$subscribers = $subscribers
|
||||||
|
->whereNull(Subscriber::$_table . '.deleted_at')
|
||||||
return $subscribers->findArray();
|
->limit(sprintf('%d, %d', $offset, $limit))
|
||||||
|
->findArray();
|
||||||
|
return $subscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExportFileURL($file) {
|
function getExportFileURL($file) {
|
||||||
@ -216,9 +266,4 @@ class Export {
|
|||||||
return $subscriber[$field];
|
return $subscriber[$field];
|
||||||
}, $this->subscriber_fields);
|
}, $this->subscriber_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeExecution() {
|
|
||||||
$profiler_end = microtime(true);
|
|
||||||
return ($profiler_end - $this->profiler_start) / 60;
|
|
||||||
}
|
|
||||||
}
|
}
|
344
lib/Subscription/Pages.php
Normal file
344
lib/Subscription/Pages.php
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Subscription;
|
||||||
|
|
||||||
|
use \MailPoet\Router\Subscribers;
|
||||||
|
use \MailPoet\Models\Subscriber;
|
||||||
|
use \MailPoet\Models\CustomField;
|
||||||
|
use \MailPoet\Models\Setting;
|
||||||
|
use \MailPoet\Models\Segment;
|
||||||
|
use \MailPoet\Util\Helpers;
|
||||||
|
use \MailPoet\Util\Url;
|
||||||
|
|
||||||
|
class Pages {
|
||||||
|
const DEMO_EMAIL = 'demo@mailpoet.com';
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if(isset($_GET['mailpoet_page'])) {
|
||||||
|
add_filter('wp_title', array($this,'setWindowTitle'));
|
||||||
|
add_filter('the_title', array($this,'setPageTitle'));
|
||||||
|
add_filter('the_content', array($this,'setPageContent'));
|
||||||
|
}
|
||||||
|
add_action(
|
||||||
|
'admin_post_mailpoet_subscriber_save',
|
||||||
|
array($this, 'subscriberSave')
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'admin_post_nopriv_mailpoet_subscriber_save',
|
||||||
|
array($this, 'subscriberSave')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function subscriberSave() {
|
||||||
|
$action = (isset($_POST['action']) ? $_POST['action'] : null);
|
||||||
|
if($action !== 'mailpoet_subscriber_save') {
|
||||||
|
Url::redirectBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
$reserved_keywords = array('action', 'mailpoet_redirect');
|
||||||
|
$subscriber_data = array_diff_key(
|
||||||
|
$_POST,
|
||||||
|
array_flip($reserved_keywords)
|
||||||
|
);
|
||||||
|
|
||||||
|
$subscriber = Subscriber::createOrUpdate($subscriber_data);
|
||||||
|
$errors = $subscriber->getErrors();
|
||||||
|
|
||||||
|
// TBD: success/error messages (not present in MP2)
|
||||||
|
|
||||||
|
Url::redirectBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPreview() {
|
||||||
|
return (array_key_exists('preview', $_GET));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWindowTitle() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPageTitle($title = null) {
|
||||||
|
$subscriber = $this->getSubscriber();
|
||||||
|
|
||||||
|
switch($this->getAction()) {
|
||||||
|
case 'confirm':
|
||||||
|
return $this->getConfirmTitle($subscriber);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'edit':
|
||||||
|
return $this->getEditTitle($subscriber);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'unsubscribe':
|
||||||
|
if($subscriber !== false) {
|
||||||
|
if($subscriber->status !== Subscriber::STATUS_UNSUBSCRIBED) {
|
||||||
|
$subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
|
||||||
|
$subscriber->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->getUnsubscribeTitle($subscriber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPageContent($page_content = '[mailpoet_page]') {
|
||||||
|
$content = '';
|
||||||
|
$subscriber = $this->getSubscriber();
|
||||||
|
|
||||||
|
switch($this->getAction()) {
|
||||||
|
case 'confirm':
|
||||||
|
$content = $this->getConfirmContent($subscriber);
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
$content = $this->getEditContent($subscriber);
|
||||||
|
break;
|
||||||
|
case 'unsubscribe':
|
||||||
|
$content = $this->getUnsubscribeContent($subscriber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str_replace('[mailpoet_page]', $content, $page_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getConfirmTitle($subscriber) {
|
||||||
|
if($this->isPreview()) {
|
||||||
|
$title = sprintf(
|
||||||
|
__("You've subscribed to: %s"),
|
||||||
|
'demo 1, demo 2'
|
||||||
|
);
|
||||||
|
} else if($subscriber === false) {
|
||||||
|
$title = __('Your confirmation link expired, please subscribe again.');
|
||||||
|
} else {
|
||||||
|
if($subscriber->status !== Subscriber::STATUS_SUBSCRIBED) {
|
||||||
|
$subscriber->status = Subscriber::STATUS_SUBSCRIBED;
|
||||||
|
$subscriber->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$segment_names = array_map(function($segment) {
|
||||||
|
return $segment->name;
|
||||||
|
}, $subscriber->segments()->findMany());
|
||||||
|
|
||||||
|
if(empty($segment_names)) {
|
||||||
|
$title = __("You've subscribed!");
|
||||||
|
} else {
|
||||||
|
$title = sprintf(
|
||||||
|
__("You've subscribed to: %s"),
|
||||||
|
join(', ', $segment_names)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getEditTitle($subscriber) {
|
||||||
|
if($this->isPreview()) {
|
||||||
|
return sprintf(
|
||||||
|
__('Edit your subscriber profile: %s'),
|
||||||
|
self::DEMO_EMAIL
|
||||||
|
);
|
||||||
|
} else if($subscriber !== false) {
|
||||||
|
return sprintf(
|
||||||
|
__('Edit your subscriber profile: %s'),
|
||||||
|
$subscriber->email
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUnsubscribeTitle($subscriber) {
|
||||||
|
if($this->isPreview() || $subscriber !== false) {
|
||||||
|
return __("You've unsubscribed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getConfirmContent($subscriber) {
|
||||||
|
if($this->isPreview() || $subscriber !== false) {
|
||||||
|
return __("Yup, we've added you to our list. You'll hear from us shortly.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getEditContent($subscriber) {
|
||||||
|
if($this->isPreview()) {
|
||||||
|
$subscriber = Subscriber::create();
|
||||||
|
$subscriber->hydrate(array(
|
||||||
|
'email' => self::DEMO_EMAIL
|
||||||
|
));
|
||||||
|
} else if($subscriber !== false) {
|
||||||
|
$subscriber = $subscriber
|
||||||
|
->withCustomFields()
|
||||||
|
->withSubscriptions();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$custom_fields = array_map(function($custom_field) use($subscriber) {
|
||||||
|
$custom_field->id = 'cf_'.$custom_field->id;
|
||||||
|
$custom_field = $custom_field->asArray();
|
||||||
|
$custom_field['params']['value'] = $subscriber->{$custom_field['id']};
|
||||||
|
return $custom_field;
|
||||||
|
}, CustomField::findMany());
|
||||||
|
|
||||||
|
$segment_ids = Setting::getValue('subscription.segments', array());
|
||||||
|
if(!empty($segment_ids)) {
|
||||||
|
$segments = Segment::getPublic()
|
||||||
|
->whereIn('id', $segment_ids)
|
||||||
|
->findMany();
|
||||||
|
} else {
|
||||||
|
$segments = Segment::getPublic()
|
||||||
|
->findMany();
|
||||||
|
}
|
||||||
|
$subscribed_segment_ids = array();
|
||||||
|
if(!empty($subscriber->subscriptions)) {
|
||||||
|
foreach ($subscriber->subscriptions as $subscription) {
|
||||||
|
if($subscription['status'] === Subscriber::STATUS_SUBSCRIBED) {
|
||||||
|
$subscribed_segment_ids[] = $subscription['segment_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$segments = array_map(function($segment) use($subscribed_segment_ids) {
|
||||||
|
return array(
|
||||||
|
'id' => $segment->id,
|
||||||
|
'name' => $segment->name,
|
||||||
|
'is_checked' => in_array($segment->id, $subscribed_segment_ids)
|
||||||
|
);
|
||||||
|
}, $segments);
|
||||||
|
|
||||||
|
$fields = array(
|
||||||
|
array(
|
||||||
|
'id' => 'email',
|
||||||
|
'type' => 'text',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('Email'),
|
||||||
|
'required' => true,
|
||||||
|
'value' => $subscriber->email
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'id' => 'first_name',
|
||||||
|
'type' => 'text',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('First name'),
|
||||||
|
'value' => $subscriber->first_name
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'id' => 'last_name',
|
||||||
|
'type' => 'text',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('Last name'),
|
||||||
|
'value' => $subscriber->last_name
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'id' => 'status',
|
||||||
|
'type' => 'select',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('Status'),
|
||||||
|
'values' => array(
|
||||||
|
array(
|
||||||
|
'value' => array(
|
||||||
|
Subscriber::STATUS_SUBSCRIBED => __('Subscribed')
|
||||||
|
),
|
||||||
|
'is_checked' => (
|
||||||
|
$subscriber->status === Subscriber::STATUS_SUBSCRIBED
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'value' => array(
|
||||||
|
Subscriber::STATUS_UNSUBSCRIBED => __('Unsubscribed')
|
||||||
|
),
|
||||||
|
'is_checked' => (
|
||||||
|
$subscriber->status === Subscriber::STATUS_UNSUBSCRIBED
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'value' => array(
|
||||||
|
Subscriber::STATUS_UNCONFIRMED => __('Unconfirmed')
|
||||||
|
),
|
||||||
|
'is_checked' => (
|
||||||
|
$subscriber->status === Subscriber::STATUS_UNCONFIRMED
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$form = array_merge(
|
||||||
|
$fields,
|
||||||
|
$custom_fields,
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'id' => 'segments',
|
||||||
|
'type' => 'segment',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('Your lists'),
|
||||||
|
'values' => $segments
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'id' => 'submit',
|
||||||
|
'type' => 'submit',
|
||||||
|
'params' => array(
|
||||||
|
'label' => __('Save')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$form_html = '<form method="POST" '.
|
||||||
|
'action="'.admin_url('admin-post.php').'" '.
|
||||||
|
'novalidate>';
|
||||||
|
$form_html .= '<input type="hidden" name="action" '.
|
||||||
|
'value="mailpoet_subscriber_save" />';
|
||||||
|
$form_html .= '<input type="hidden" name="segments" value="" />';
|
||||||
|
$form_html .= '<input type="hidden" name="mailpoet_redirect" '.
|
||||||
|
'value="'.Url::getCurrentUrl().'" />';
|
||||||
|
$form_html .= \MailPoet\Form\Renderer::renderBlocks($form);
|
||||||
|
$form_html .= '</form>';
|
||||||
|
return $form_html;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUnsubscribeContent($subscriber) {
|
||||||
|
$content = '';
|
||||||
|
if($this->isPreview() || $subscriber !== false) {
|
||||||
|
$content = '<p>'.__("Great, you'll never hear from us again!").'</p>';
|
||||||
|
if($subscriber !== false) {
|
||||||
|
$content .= '<p><strong>'.
|
||||||
|
str_replace(
|
||||||
|
array('[link]', '[/link]'),
|
||||||
|
array('<a href="'.$subscriber->getConfirmationUrl().'">', '</a>'),
|
||||||
|
__('You made a mistake? [link]Undo unsubscribe.[/link]')
|
||||||
|
).
|
||||||
|
'</strong></p>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSubscriber() {
|
||||||
|
$token = (isset($_GET['mailpoet_token']))
|
||||||
|
? $_GET['mailpoet_token']
|
||||||
|
: null;
|
||||||
|
$email = (isset($_GET['mailpoet_email']))
|
||||||
|
? $_GET['mailpoet_email']
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if(Subscriber::generateToken($email) === $token) {
|
||||||
|
$subscriber = Subscriber::findOne($email);
|
||||||
|
if($subscriber !== false) {
|
||||||
|
return $subscriber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAction() {
|
||||||
|
return (isset($_GET['mailpoet_action']))
|
||||||
|
? $_GET['mailpoet_action']
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
62
lib/Util/Url.php
Normal file
62
lib/Util/Url.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Util;
|
||||||
|
|
||||||
|
class Url {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getCurrentUrl() {
|
||||||
|
global $wp;
|
||||||
|
return home_url(
|
||||||
|
add_query_arg(
|
||||||
|
$wp->query_string,
|
||||||
|
$wp->request
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function redirectTo($url = null) {
|
||||||
|
wp_safe_redirect($url);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function redirectBack() {
|
||||||
|
// check mailpoet_redirect parameter
|
||||||
|
$referer = (isset($_POST['mailpoet_redirect'])
|
||||||
|
? $_POST['mailpoet_redirect']
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
// fallback: http referer
|
||||||
|
if($referer === null) {
|
||||||
|
if(!empty($_SERVER['HTTP_REFERER'])) {
|
||||||
|
$referer = $_SERVER['HTTP_REFERER'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback: home_url
|
||||||
|
if($referer === null) {
|
||||||
|
$referer = home_url();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($referer !== null) {
|
||||||
|
self::redirectTo($referer);
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function redirectWithReferer($url = null) {
|
||||||
|
$current_url = self::getCurrentUrl();
|
||||||
|
$url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'mailpoet_redirect' => urlencode($current_url)
|
||||||
|
),
|
||||||
|
$url
|
||||||
|
);
|
||||||
|
|
||||||
|
if($url !== $current_url) {
|
||||||
|
self::redirectTo($url);
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
|
|||||||
use \MailPoet\Config\Initializer;
|
use \MailPoet\Config\Initializer;
|
||||||
/*
|
/*
|
||||||
* Plugin Name: MailPoet
|
* Plugin Name: MailPoet
|
||||||
* Version: 0.0.18
|
* Version: 0.0.19
|
||||||
* Plugin URI: http://www.mailpoet.com
|
* Plugin URI: http://www.mailpoet.com
|
||||||
* Description: MailPoet Newsletters.
|
* Description: MailPoet Newsletters.
|
||||||
* Author: MailPoet
|
* Author: MailPoet
|
||||||
@ -22,7 +22,7 @@ use \MailPoet\Config\Initializer;
|
|||||||
|
|
||||||
require 'vendor/autoload.php';
|
require 'vendor/autoload.php';
|
||||||
|
|
||||||
define('MAILPOET_VERSION', '0.0.18');
|
define('MAILPOET_VERSION', '0.0.19');
|
||||||
|
|
||||||
$initializer = new Initializer(array(
|
$initializer = new Initializer(array(
|
||||||
'file' => __FILE__,
|
'file' => __FILE__,
|
||||||
|
@ -19,7 +19,13 @@ class SettingCest {
|
|||||||
expect($errors[0])->equals('You need to specify a name.');
|
expect($errors[0])->equals('You need to specify a name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanGetAllSettings() {
|
function itHasDefaultSettings() {
|
||||||
|
$default_settings = Setting::getDefaults();
|
||||||
|
expect($default_settings)->notEmpty();
|
||||||
|
expect($default_settings['signup_confirmation']['enabled'])->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function itCanGetAllSettingsIncludingDefaults() {
|
||||||
Setting::setValue('key_1', 'value_1');
|
Setting::setValue('key_1', 'value_1');
|
||||||
Setting::setValue('key_2', 'value_2');
|
Setting::setValue('key_2', 'value_2');
|
||||||
Setting::setValue('key_3', array(
|
Setting::setValue('key_3', array(
|
||||||
@ -28,13 +34,17 @@ class SettingCest {
|
|||||||
));
|
));
|
||||||
|
|
||||||
$settings = Setting::getAll();
|
$settings = Setting::getAll();
|
||||||
expect(array_keys($settings))->count(3);
|
|
||||||
expect($settings['key_1'])->equals('value_1');
|
expect($settings['key_1'])->equals('value_1');
|
||||||
expect($settings['key_2'])->equals('value_2');
|
expect($settings['key_2'])->equals('value_2');
|
||||||
expect($settings['key_3'])->equals(array(
|
expect($settings['key_3'])->equals(array(
|
||||||
'subkey_1' => 'subvalue_1',
|
'subkey_1' => 'subvalue_1',
|
||||||
'subkey_2' => 'subvalue_2'
|
'subkey_2' => 'subvalue_2'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// default settings
|
||||||
|
$default_settings = Setting::getDefaults();
|
||||||
|
expect($settings['signup_confirmation'])
|
||||||
|
->equals($default_settings['signup_confirmation']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function itReturnsDefaultValueIfNotSet() {
|
function itReturnsDefaultValueIfNotSet() {
|
||||||
|
@ -105,6 +105,26 @@ class NewsletterRendererCest {
|
|||||||
expect($rendered_column_content)->equals($column_content);
|
expect($rendered_column_content)->equals($column_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function itRemovesPaddingFromLastColumnElement() {
|
||||||
|
$column_content = array('
|
||||||
|
<tr><td class="mailpoet_padded"></td></tr>
|
||||||
|
<tr><td class="mailpoet_padded"></td></tr>
|
||||||
|
<tr><td class="mailpoet_padded"></td></tr>
|
||||||
|
<tr><td class="mailpoet_padded"></td></tr>'
|
||||||
|
);
|
||||||
|
$column_styles = array(
|
||||||
|
'block' => array(
|
||||||
|
'backgroundColor' => "#999999"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$rendered_column_content = $this->column_renderer->render(
|
||||||
|
$column_styles,
|
||||||
|
count($column_content),
|
||||||
|
$column_content
|
||||||
|
);
|
||||||
|
expect(substr_count($rendered_column_content, 'mailpoet_padded'))->equals(3);
|
||||||
|
}
|
||||||
|
|
||||||
function itRendersHeader() {
|
function itRendersHeader() {
|
||||||
$newsletter = json_decode($this->newsletter['body'], true);
|
$newsletter = json_decode($this->newsletter['body'], true);
|
||||||
$template = $newsletter['content']['blocks'][0]['blocks'][0]['blocks'][0];
|
$template = $newsletter['content']['blocks'][0]['blocks'][0]['blocks'][0];
|
||||||
|
@ -16,7 +16,7 @@ class SettingsCest {
|
|||||||
|
|
||||||
Setting::deleteMany();
|
Setting::deleteMany();
|
||||||
$settings = $router->get();
|
$settings = $router->get();
|
||||||
expect($settings)->isEmpty();
|
expect($settings)->equals(Setting::getDefaults());
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanSetSettings() {
|
function itCanSetSettings() {
|
||||||
|
@ -122,6 +122,15 @@ class ExportCest {
|
|||||||
'1'
|
'1'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
expect($this->export->subscriber_custom_fields)
|
||||||
|
->equals($this->export->getSubscriberCustomFields());
|
||||||
|
expect($this->export->formatted_subscriber_fields)
|
||||||
|
->equals(
|
||||||
|
$this->export->formatSubscriberFields(
|
||||||
|
$this->export->subscriber_fields,
|
||||||
|
$this->export->subscriber_custom_fields
|
||||||
|
)
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
preg_match(
|
preg_match(
|
||||||
'|' .
|
'|' .
|
||||||
@ -137,6 +146,7 @@ class ExportCest {
|
|||||||
'|'
|
'|'
|
||||||
, $this->export->export_file_URL)
|
, $this->export->export_file_URL)
|
||||||
)->equals(1);
|
)->equals(1);
|
||||||
|
expect($this->export->subscriber_batch_size)->notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanGetSubscriberCustomFields() {
|
function itCanGetSubscriberCustomFields() {
|
||||||
@ -156,7 +166,7 @@ class ExportCest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function itProperlyReturnsSubscriberCustomFields() {
|
function itProperlyReturnsSubscriberCustomFields() {
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
foreach($subscribers as $subscriber) {
|
foreach($subscribers as $subscriber) {
|
||||||
if($subscriber['email'] === $this->subscribers_data[1]) {
|
if($subscriber['email'] === $this->subscribers_data[1]) {
|
||||||
expect($subscriber['Country'])
|
expect($subscriber['Country'])
|
||||||
@ -167,37 +177,37 @@ class ExportCest {
|
|||||||
|
|
||||||
function itCanGetSubscribers() {
|
function itCanGetSubscribers() {
|
||||||
$this->export->segments = array(1);
|
$this->export->segments = array(1);
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(2);
|
expect(count($subscribers))->equals(2);
|
||||||
$this->export->segments = array(2);
|
$this->export->segments = array(2);
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(2);
|
expect(count($subscribers))->equals(2);
|
||||||
$this->export->segments = array(
|
$this->export->segments = array(
|
||||||
1,
|
1,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(3);
|
expect(count($subscribers))->equals(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanGroupSubscribersBySegments() {
|
function itCanGroupSubscribersBySegments() {
|
||||||
$this->export->group_by_segment_option = true;
|
$this->export->group_by_segment_option = true;
|
||||||
$this->export->subscribers_without_segment = true;
|
$this->export->subscribers_without_segment = true;
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(5);
|
expect(count($subscribers))->equals(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanGetSubscribersOnlyWithoutSegments() {
|
function itCanGetSubscribersOnlyWithoutSegments() {
|
||||||
$this->export->segments = array(0);
|
$this->export->segments = array(0);
|
||||||
$this->export->subscribers_without_segment = true;
|
$this->export->subscribers_without_segment = true;
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(1);
|
expect(count($subscribers))->equals(1);
|
||||||
expect($subscribers[0]['segment_name'])->equals('Not In Segment');
|
expect($subscribers[0]['segment_name'])->equals('Not In Segment');
|
||||||
}
|
}
|
||||||
|
|
||||||
function itCanGetOnlyConfirmedSubscribers() {
|
function itCanGetOnlyConfirmedSubscribers() {
|
||||||
$this->export->export_confirmed_option = true;
|
$this->export->export_confirmed_option = true;
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(1);
|
expect(count($subscribers))->equals(1);
|
||||||
expect($subscribers[0]['email'])
|
expect($subscribers[0]['email'])
|
||||||
->equals($this->subscribers_data[1]['email']);
|
->equals($this->subscribers_data[1]['email']);
|
||||||
@ -207,7 +217,7 @@ class ExportCest {
|
|||||||
SubscriberSegment::where('subscriber_id', 3)
|
SubscriberSegment::where('subscriber_id', 3)
|
||||||
->findOne()
|
->findOne()
|
||||||
->delete();
|
->delete();
|
||||||
$subscribers = $this->export->getSubscribers();
|
$subscribers = $this->export->getSubscribers(0, 10);
|
||||||
expect(count($subscribers))->equals(2);
|
expect(count($subscribers))->equals(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,8 +233,8 @@ class ExportCest {
|
|||||||
$this->export->export_format_option = 'csv';
|
$this->export->export_format_option = 'csv';
|
||||||
$this->export->process();
|
$this->export->process();
|
||||||
$CSV_file_size = filesize($this->export->export_file);
|
$CSV_file_size = filesize($this->export->export_file);
|
||||||
$this->export->export_file = $this->export->getExportFile('xls');
|
$this->export->export_file = $this->export->getExportFile('xlsx');
|
||||||
$this->export->export_format_option = 'xls';
|
$this->export->export_format_option = 'xlsx';
|
||||||
$this->export->process();
|
$this->export->process();
|
||||||
$XLS_file_size = filesize($this->export->export_file);
|
$XLS_file_size = filesize($this->export->export_file);
|
||||||
expect($CSV_file_size)->greaterThan(0);
|
expect($CSV_file_size)->greaterThan(0);
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
'admin.js'
|
'admin.js'
|
||||||
)%>
|
)%>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var mailpoet_date_format = "<%= get_option('date_format') %>";
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
HS.beacon.config({
|
HS.beacon.config({
|
||||||
icon: 'message',
|
icon: 'message',
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -522,7 +522,7 @@
|
|||||||
],
|
],
|
||||||
fonts: [
|
fonts: [
|
||||||
'Arial',
|
'Arial',
|
||||||
'Comic Sans',
|
'Comic Sans MS',
|
||||||
'Courier New',
|
'Courier New',
|
||||||
'Georgia',
|
'Georgia',
|
||||||
'Lucida',
|
'Lucida',
|
||||||
@ -976,10 +976,10 @@
|
|||||||
backgroundColor: '#2ea1cd',
|
backgroundColor: '#2ea1cd',
|
||||||
borderColor: '#0074a2',
|
borderColor: '#0074a2',
|
||||||
borderWidth: '1px',
|
borderWidth: '1px',
|
||||||
borderRadius: '7px',
|
borderRadius: '5px',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
width: '120px',
|
width: '180px',
|
||||||
lineHeight: '35px',
|
lineHeight: '40px',
|
||||||
fontColor: '#ffffff',
|
fontColor: '#ffffff',
|
||||||
fontFamily: 'Verdana',
|
fontFamily: 'Verdana',
|
||||||
fontSize: '18px',
|
fontSize: '18px',
|
||||||
@ -1241,7 +1241,9 @@
|
|||||||
customFieldsWindowTitle:
|
customFieldsWindowTitle:
|
||||||
'<%= __('Select a shortcode') %>',
|
'<%= __('Select a shortcode') %>',
|
||||||
unsubscribeLinkMissing:
|
unsubscribeLinkMissing:
|
||||||
'<%= __('Please include an unsubscribe link to continue.') %>',
|
'<%= __('All newsletter must include an "unsubscribe" link. Add a footer widget to your newsletter to continue.') %>',
|
||||||
|
newsletterPreviewEmailMissing:
|
||||||
|
'<%= __('Please enter an email where newsletter preview should be sent to.') %>',
|
||||||
newsletterPreviewSent:
|
newsletterPreviewSent:
|
||||||
'<%= __('Newsletter preview email has been successfully sent!') %>',
|
'<%= __('Newsletter preview email has been successfully sent!') %>',
|
||||||
newsletterPreviewFailedToSend:
|
newsletterPreviewFailedToSend:
|
||||||
@ -1264,7 +1266,7 @@
|
|||||||
imageMissing: '<%= image_url(
|
imageMissing: '<%= image_url(
|
||||||
"newsletter_editor/image-missing.svg"
|
"newsletter_editor/image-missing.svg"
|
||||||
) %>',
|
) %>',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
var editor = null;
|
var editor = null;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<div class="mailpoet_form_field">
|
<div class="mailpoet_form_field">
|
||||||
<label>
|
<label>
|
||||||
<%= __('Send preview to') %><br />
|
<%= __('Send preview to') %><br />
|
||||||
<input id="mailpoet_preview_to_email" class="mailpoet_input mailpoet_input_full" type="text" name="to_email" value="{{ from_email }}" />
|
<input id="mailpoet_preview_to_email" class="mailpoet_input mailpoet_input_full" type="text" name="to_email" value="<%= settings.sender.address %>" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -194,14 +194,13 @@
|
|||||||
<% endif %>
|
<% endif %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- manage subscriptions-->
|
<!-- edit subscription-->
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<label for="settings[subscription_edit]">
|
<label for="subscription_edit_page">
|
||||||
<%= __('Unsubscribe & Manage Subscription page') %>
|
<%= __('Manage Subscription page') %>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
<%= __('The page your subscribers see when they click to
|
<%= __('The page your subscribers see when they click on "Manage your subscription" in your emails.') %>
|
||||||
"Unsubscribe" or "Manage your subscription" in your emails.') %>
|
|
||||||
</p>
|
</p>
|
||||||
</label>
|
</label>
|
||||||
</th>
|
</th>
|
||||||
@ -209,14 +208,15 @@
|
|||||||
<p>
|
<p>
|
||||||
<select
|
<select
|
||||||
class="mailpoet_page_selection"
|
class="mailpoet_page_selection"
|
||||||
name="subscription[page]"
|
id="subscription_edit_page"
|
||||||
|
name="subscription[edit_page]"
|
||||||
>
|
>
|
||||||
<% for page in pages %>
|
<% for page in pages %>
|
||||||
<option
|
<option
|
||||||
value="<%= page.id %>"
|
value="<%= page.id %>"
|
||||||
data-preview-url="<%= page.preview_url|raw %>"
|
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=edit"
|
||||||
data-edit-url="<%= page.edit_url|raw %>"
|
data-edit-url="<%= page.edit_url|raw %>"
|
||||||
<% if(page.id == settings.subscription.page) %>
|
<% if(page.id == settings.subscription.edit_page) %>
|
||||||
selected="selected"
|
selected="selected"
|
||||||
<% endif %>
|
<% endif %>
|
||||||
><%= page.title %></option>
|
><%= page.title %></option>
|
||||||
@ -254,6 +254,46 @@
|
|||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<!-- unsubscribe-->
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<label for="subscription_unsubscribe_page">
|
||||||
|
<%= __('Unsubscribe page') %>
|
||||||
|
<p class="description">
|
||||||
|
<%= __('The page your subscribers see when they click on "Unsubscribe" in your emails.') %>
|
||||||
|
</p>
|
||||||
|
</label>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<p>
|
||||||
|
<select
|
||||||
|
class="mailpoet_page_selection"
|
||||||
|
id="subscription_unsubscribe_page"
|
||||||
|
name="subscription[unsubscribe_page]"
|
||||||
|
>
|
||||||
|
<% for page in pages %>
|
||||||
|
<option
|
||||||
|
value="<%= page.id %>"
|
||||||
|
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=unsubscribe"
|
||||||
|
data-edit-url="<%= page.edit_url|raw %>"
|
||||||
|
<% if(page.id == settings.subscription.unsubscribe_page) %>
|
||||||
|
selected="selected"
|
||||||
|
<% endif %>
|
||||||
|
><%= page.title %></option>
|
||||||
|
<% endfor %>
|
||||||
|
</select>
|
||||||
|
<a
|
||||||
|
class="mailpoet_page_preview"
|
||||||
|
href="javascript:;"
|
||||||
|
title="<%= __('Preview page') %>"
|
||||||
|
><%= __('Preview') %></a> | <a
|
||||||
|
class="mailpoet_page_edit"
|
||||||
|
href="javascript:;"
|
||||||
|
title="<%= __('Edit page') %>"
|
||||||
|
><%= __('Edit') %></a>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<!-- shortcode: archive page -->
|
<!-- shortcode: archive page -->
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
|
@ -112,11 +112,6 @@
|
|||||||
name="signup_confirmation[subject]"
|
name="signup_confirmation[subject]"
|
||||||
<% if(settings.signup_confirmation.subject) %>
|
<% if(settings.signup_confirmation.subject) %>
|
||||||
value="<%= settings.signup_confirmation.subject %>"
|
value="<%= settings.signup_confirmation.subject %>"
|
||||||
<% else %>
|
|
||||||
value="<%=
|
|
||||||
__('Confirm your subscription to %1$s')
|
|
||||||
| format(get_option('blogname'))
|
|
||||||
%>"
|
|
||||||
<% endif %>
|
<% endif %>
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
@ -139,8 +134,6 @@
|
|||||||
name="signup_confirmation[body]"
|
name="signup_confirmation[body]"
|
||||||
><% if(settings.signup_confirmation.body) %>
|
><% if(settings.signup_confirmation.body) %>
|
||||||
<%=- settings.signup_confirmation.body -%>
|
<%=- settings.signup_confirmation.body -%>
|
||||||
<% else %>
|
|
||||||
<%=- __("Hello!\n\nHurray! You've subscribed to our site.\nWe need you to activate your subscription to the list(s): [lists_to_confirm] by clicking the link below: \n\n[activation_link]Click here to confirm your subscription.[/activation_link]\n\nThank you,\n\nThe team!") -%>
|
|
||||||
<% endif %></textarea>
|
<% endif %></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -163,7 +156,7 @@
|
|||||||
<% for page in pages %>
|
<% for page in pages %>
|
||||||
<option
|
<option
|
||||||
value="<%= page.id %>"
|
value="<%= page.id %>"
|
||||||
data-preview-url="<%= page.preview_url|raw %>"
|
data-preview-url="<%= page.preview_url|raw %>&mailpoet_action=confirm"
|
||||||
data-edit-url="<%= page.edit_url|raw %>"
|
data-edit-url="<%= page.edit_url|raw %>"
|
||||||
<% if(page.id == settings.signup_confirmation.page) %>
|
<% if(page.id == settings.signup_confirmation.page) %>
|
||||||
selected="selected"
|
selected="selected"
|
||||||
|
@ -20,7 +20,5 @@
|
|||||||
var mailpoet_segments = <%= json_encode(segments) %>;
|
var mailpoet_segments = <%= json_encode(segments) %>;
|
||||||
var mailpoet_custom_fields = <%= json_encode(custom_fields) %>;
|
var mailpoet_custom_fields = <%= json_encode(custom_fields) %>;
|
||||||
var mailpoet_month_names = <%= json_encode(month_names) %>;
|
var mailpoet_month_names = <%= json_encode(month_names) %>;
|
||||||
var mailpoet_date_format = "<%= get_option('date_format') %>";
|
|
||||||
var mailpoet_date_offset = "<%= get_option('gmt_offset') %>";
|
|
||||||
</script>
|
</script>
|
||||||
<% endblock %>
|
<% endblock %>
|
||||||
|
@ -91,10 +91,14 @@ baseConfig = {
|
|||||||
config.push(_.extend({}, baseConfig, {
|
config.push(_.extend({}, baseConfig, {
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
entry: {
|
entry: {
|
||||||
vendor: ['handlebars', 'handlebars_helpers'],
|
vendor: [
|
||||||
|
'handlebars',
|
||||||
|
'handlebars_helpers'
|
||||||
|
],
|
||||||
mailpoet: [
|
mailpoet: [
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'ajax',
|
'ajax',
|
||||||
|
'date',
|
||||||
'modal',
|
'modal',
|
||||||
'notice',
|
'notice',
|
||||||
'jquery.serialize_object',
|
'jquery.serialize_object',
|
||||||
@ -129,7 +133,6 @@ config.push(_.extend({}, baseConfig, {
|
|||||||
'blob',
|
'blob',
|
||||||
'filesaver',
|
'filesaver',
|
||||||
'velocity-animate',
|
'velocity-animate',
|
||||||
|
|
||||||
'newsletter_editor/communicationsFix.js',
|
'newsletter_editor/communicationsFix.js',
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
'newsletter_editor/components/config.js',
|
'newsletter_editor/components/config.js',
|
||||||
@ -156,11 +159,11 @@ config.push(_.extend({}, baseConfig, {
|
|||||||
'newsletter_editor/blocks/header.js',
|
'newsletter_editor/blocks/header.js',
|
||||||
'newsletter_editor/blocks/automatedLatestContent.js',
|
'newsletter_editor/blocks/automatedLatestContent.js',
|
||||||
'newsletter_editor/blocks/posts.js',
|
'newsletter_editor/blocks/posts.js',
|
||||||
'newsletter_editor/blocks/social.js',
|
'newsletter_editor/blocks/social.js'
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'),
|
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
|
||||||
],
|
],
|
||||||
externals: {
|
externals: {
|
||||||
'jquery': 'jQuery',
|
'jquery': 'jQuery',
|
||||||
|
Reference in New Issue
Block a user