- Refactors Mailer class
- Refactors SendingQueue worker class - Adds Maier router with a send() method + ability to specify sending method - Updates tests - Introduces 'stopping' and 'starting' cron states - Improves cron control mechanism Closes #276
This commit is contained in:
@ -15,10 +15,10 @@ define(
|
||||
status: 'loading'
|
||||
};
|
||||
},
|
||||
getDaemonData: function() {
|
||||
getCronData: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'getDaemonStatus'
|
||||
action: 'getStatus'
|
||||
})
|
||||
.done(function(response) {
|
||||
jQuery('.button-primary')
|
||||
@ -32,25 +32,23 @@ define(
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
this.getDaemonData();
|
||||
setInterval(this.getDaemonData, 5000);
|
||||
this.getCronData();
|
||||
setInterval(this.getCronData, 5000);
|
||||
}
|
||||
},
|
||||
controlDaemon: function(action) {
|
||||
controlCron: function(action) {
|
||||
if (jQuery('.button-primary').hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
jQuery('.button-primary')
|
||||
.addClass('disabled');
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'cron',
|
||||
action: 'controlDaemon',
|
||||
data: {
|
||||
'action': action
|
||||
}
|
||||
action: action,
|
||||
})
|
||||
.done(function(response) {
|
||||
if(!response.result) {
|
||||
//this.replaceState();
|
||||
} else {
|
||||
//this.setState(response);
|
||||
MailPoet.Notice.error(MailPoetI18n.daemonControlError);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
@ -71,19 +69,25 @@ define(
|
||||
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||
<br />
|
||||
<br />
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'stop')}>Stop</a>
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'pause')}>Pause</a>
|
||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>Stop</a>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case 'starting':
|
||||
case 'stopping':
|
||||
return(
|
||||
<div>
|
||||
Daemon is {this.state.status}
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
case 'paused':
|
||||
case 'stopped':
|
||||
return(
|
||||
<div>
|
||||
Daemon is {this.state.status}
|
||||
<br />
|
||||
<br />
|
||||
<a href="#" className="button-primary" onClick={this.controlDaemon.bind(null, 'start')}>Start</a>
|
||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>Start</a>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
|
@ -16,7 +16,7 @@ define(
|
||||
Breadcrumb
|
||||
) {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
{
|
||||
@ -24,14 +24,17 @@ define(
|
||||
label: 'Subject line',
|
||||
tip: "Be creative! It's the first thing your subscribers see."+
|
||||
"Tempt them to open your email.",
|
||||
type: 'text'
|
||||
type: 'text',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'segments',
|
||||
label: 'Lists',
|
||||
tip: "The subscriber list that will be used for this campaign.",
|
||||
label: 'Segments',
|
||||
tip: "The subscriber segment that will be used for this campaign.",
|
||||
type: 'selection',
|
||||
placeholder: "Select a list",
|
||||
placeholder: "Select a segment",
|
||||
id: "mailpoet_segments",
|
||||
endpoint: "segments",
|
||||
multiple: true,
|
||||
@ -111,12 +114,19 @@ define(
|
||||
action: 'add',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id,
|
||||
segments: jQuery('#mailpoet_segments').val()
|
||||
segments: jQuery('#mailpoet_segments').val(),
|
||||
sender: {
|
||||
'name': jQuery('#mailpoet_newsletter [name="sender_name"]').val(),
|
||||
'address': jQuery('#mailpoet_newsletter [name="sender_address"]').val()
|
||||
},
|
||||
reply_to: {
|
||||
'name': jQuery('#mailpoet_newsletter [name="reply_to_name"]').val(),
|
||||
'address': jQuery('#mailpoet_newsletter [name="reply_to_address"]').val()
|
||||
}
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
this.history.pushState(null, '/');
|
||||
|
||||
MailPoet.Notice.success(
|
||||
'The newsletter is being sent...'
|
||||
);
|
||||
|
@ -75,7 +75,7 @@ class Initializer {
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||
define('MP_SENDING_QUEUE_TABLE', $sending_queues);
|
||||
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||
}
|
||||
|
||||
@ -113,7 +113,6 @@ class Initializer {
|
||||
}
|
||||
|
||||
function setupAnalytics() {
|
||||
|
||||
$widget = new Analytics();
|
||||
$widget->init();
|
||||
}
|
||||
@ -143,10 +142,12 @@ class Initializer {
|
||||
}
|
||||
|
||||
function runQueueSupervisor() {
|
||||
if (php_sapi_name() === 'cli') return;
|
||||
try {
|
||||
$supervisor = new Supervisor();
|
||||
$supervisor->checkDaemon();
|
||||
} catch (\Exception $e) {}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
function setupImages() {
|
||||
|
@ -8,14 +8,14 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
class PublicAPI {
|
||||
function __construct() {
|
||||
# http://example.com/?mailpoet-api§ion=&action=&payload=
|
||||
# http://example.com/?mailpoet-api§ion=&action=&request_payload=
|
||||
$this->api = isset($_GET['mailpoet-api']) ? true : false;
|
||||
$this->section = isset($_GET['section']) ? $_GET['section'] : false;
|
||||
$this->action = isset($_GET['action']) ?
|
||||
Helpers::underscoreToCamelCase($_GET['action']) :
|
||||
false;
|
||||
$this->payload = isset($_GET['payload']) ?
|
||||
json_decode(urldecode($_GET['payload']), true) :
|
||||
$this->requestPayload = isset($_GET['request_payload']) ?
|
||||
json_decode(urldecode($_GET['request_payload']), true) :
|
||||
false;
|
||||
}
|
||||
|
||||
@ -26,10 +26,9 @@ class PublicAPI {
|
||||
|
||||
function queue() {
|
||||
try {
|
||||
$queue = new Daemon($this->payload);
|
||||
$queue = new Daemon($this->requestPayload);
|
||||
$this->_checkAndCallMethod($queue, $this->action);
|
||||
} catch(\Exception $e) {
|
||||
// mailer configuration error
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,18 +10,18 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Daemon {
|
||||
function __construct($payload = array()) {
|
||||
function __construct($requestPayload = array()) {
|
||||
set_time_limit(0);
|
||||
ignore_user_abort();
|
||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
||||
$this->refreshedToken = $this->refreshToken();
|
||||
$this->payload = $payload;
|
||||
$this->requestPayload = $requestPayload;
|
||||
$this->timer = microtime(true);
|
||||
}
|
||||
|
||||
function start() {
|
||||
if(!isset($this->payload['session'])) {
|
||||
$this->abortWithError('missing session ID');
|
||||
if(!isset($this->requestPayload['session'])) {
|
||||
$this->abortWithError(__('Missing session ID.'));
|
||||
}
|
||||
$this->manageSession('start');
|
||||
$daemon = $this->daemon;
|
||||
@ -30,58 +30,63 @@ class Daemon {
|
||||
$daemon = Setting::create();
|
||||
$daemon->name = 'cron_daemon';
|
||||
$daemonData = array(
|
||||
'status' => null,
|
||||
'status' => 'starting',
|
||||
'counter' => 0
|
||||
);
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
}
|
||||
if($daemonData['status'] !== 'started') {
|
||||
if($daemonData['status'] === 'started') {
|
||||
$_SESSION['cron_daemon'] = array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Daemon already running.'))
|
||||
);
|
||||
}
|
||||
if($daemonData['status'] === 'starting') {
|
||||
$_SESSION['cron_daemon'] = 'started';
|
||||
$_SESSION['cron_daemon'] = array('result' => true);
|
||||
$daemonData['status'] = 'started';
|
||||
$daemonData['token'] = $this->refreshedToken;
|
||||
$_SESSION['cron_daemon'] = array('result' => true);
|
||||
$this->manageSession('end');
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
$this->callSelf();
|
||||
} else {
|
||||
$_SESSION['cron_daemon'] = array(
|
||||
'result' => false,
|
||||
'error' => 'already started'
|
||||
);
|
||||
}
|
||||
$this->manageSession('end');
|
||||
}
|
||||
|
||||
function run() {
|
||||
if(!$this->daemon || $this->daemonData['status'] !== 'started') {
|
||||
$this->abortWithError('not running');
|
||||
$allowedStatuses = array(
|
||||
'stopping',
|
||||
'starting',
|
||||
'started'
|
||||
);
|
||||
if(!$this->daemon || !in_array($this->daemonData['status'], $allowedStatuses)) {
|
||||
$this->abortWithError(__('Invalid daemon status.'));
|
||||
}
|
||||
if(!isset($this->payload['token']) ||
|
||||
$this->payload['token'] !== $this->daemonData['token']
|
||||
if(!isset($this->requestPayload['token']) ||
|
||||
$this->requestPayload['token'] !== $this->daemonData['token']
|
||||
) {
|
||||
$this->abortWithError('invalid token');
|
||||
$this->abortWithError('Invalid token.');
|
||||
}
|
||||
|
||||
try {
|
||||
$sendingQueue = new SendingQueue($this->timer);
|
||||
$sendingQueue->process();
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if($elapsedTime < 30) {
|
||||
sleep(30 - $elapsedTime);
|
||||
}
|
||||
|
||||
// after each execution, read daemon in case it's status was modified
|
||||
list($daemon, $daemonData) = $this->getDaemon();
|
||||
$daemonData['counter']++;
|
||||
if($daemonData['status'] === 'stopping') $daemonData['status'] = 'stopped';
|
||||
if($daemonData['status'] === 'starting') $daemonData['status'] = 'started';
|
||||
$daemonData['token'] = $this->refreshedToken;
|
||||
$daemonData['counter']++;
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
if($daemonData['status'] === 'strated') $this->callSelf();
|
||||
if($daemonData['status'] === 'started') $this->callSelf();
|
||||
}
|
||||
|
||||
function getDaemon() {
|
||||
@ -103,7 +108,7 @@ class Daemon {
|
||||
if(session_id()) {
|
||||
session_write_close();
|
||||
}
|
||||
session_id($this->payload['session']);
|
||||
session_id($this->requestPayload['session']);
|
||||
session_start();
|
||||
break;
|
||||
case 'end':
|
||||
@ -114,9 +119,8 @@ class Daemon {
|
||||
|
||||
function callSelf() {
|
||||
$payload = json_encode(array('token' => $this->refreshedToken));
|
||||
Supervisor::getRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=run&payload=' . urlencode($payload)
|
||||
|
||||
Supervisor::accessRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=run&request_payload=' . urlencode($payload)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
@ -125,7 +129,7 @@ class Daemon {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => $error
|
||||
'errors' => array($error)
|
||||
));
|
||||
exit;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class Supervisor {
|
||||
function __construct($forceStart = false) {
|
||||
$this->forceStart = $forceStart;
|
||||
if(!Env::isPluginActivated()) {
|
||||
throw new \Exception('Database has not been configured.');
|
||||
throw new \Exception(__('MailPoet is not activated.'));
|
||||
}
|
||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
||||
}
|
||||
@ -20,17 +20,24 @@ class Supervisor {
|
||||
if(!$this->daemon) {
|
||||
return $this->startDaemon();
|
||||
}
|
||||
if(!$this->forceStart && $this->daemonData['status'] === 'stopped') {
|
||||
if(!$this->forceStart && (
|
||||
$this->daemonData['status'] === 'stopped' ||
|
||||
$this->daemonData['status'] === 'stopping')
|
||||
) {
|
||||
return $this->daemonData['status'];
|
||||
}
|
||||
$timeSinceLastRun = $this->getDaemonLastRunTime();
|
||||
if($timeSinceLastRun < 40) {
|
||||
if(!$this->forceStart) {
|
||||
return;
|
||||
}
|
||||
$currentTime = Carbon::now('UTC');
|
||||
$lastUpdateTime = Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at, 'UTC'
|
||||
);
|
||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
||||
if($timeSinceLastStart < 40) return;
|
||||
$this->daemonData['status'] = null;
|
||||
if($this->daemonData['status'] === 'stopping' ||
|
||||
$this->daemonData['status'] === 'starting'
|
||||
) {
|
||||
return $this->daemonData['status'];
|
||||
}
|
||||
}
|
||||
$this->daemonData['status'] = 'starting';
|
||||
$this->daemon->value = json_encode($this->daemonData);
|
||||
$this->daemon->save();
|
||||
return $this->startDaemon();
|
||||
@ -41,9 +48,9 @@ class Supervisor {
|
||||
$sessionId = session_id();
|
||||
session_write_close();
|
||||
$_SESSION['cron_daemon'] = null;
|
||||
$payload = json_encode(array('session' => $sessionId));
|
||||
self::getRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=start&payload=' . urlencode($payload)
|
||||
$requestPayload = json_encode(array('session' => $sessionId));
|
||||
self::accessRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=start&request_payload=' . urlencode($requestPayload)
|
||||
);
|
||||
session_start();
|
||||
$daemonStatus = $_SESSION['cron_daemon'];
|
||||
@ -62,10 +69,10 @@ class Supervisor {
|
||||
);
|
||||
}
|
||||
|
||||
static function getRemoteUrl($url) {
|
||||
static function accessRemoteUrl($url) {
|
||||
$args = array(
|
||||
'timeout' => 1,
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com)'
|
||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||
);
|
||||
wp_remote_get(
|
||||
self::getSiteUrl() . $url,
|
||||
@ -74,11 +81,28 @@ class Supervisor {
|
||||
}
|
||||
|
||||
static function getSiteUrl() {
|
||||
if(preg_match('!:\d+/!', site_url())) return site_url();
|
||||
preg_match('!http://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
||||
// additional check for some sites running on a virtual machine or behind
|
||||
// proxy where there could be different ports (e.g., host:8080 => guest:80)
|
||||
|
||||
// if the site URL does not contain a port, return the URL
|
||||
if(!preg_match('!^https?://.*?:\d+!', site_url())) return site_url();
|
||||
preg_match('!://(?P<host>.*?):(?P<port>\d+)!', site_url(), $server);
|
||||
// connect to the URL with port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
return ($fp) ?
|
||||
site_url() :
|
||||
preg_replace('/(?=:\d+):\d+/', '$1', site_url());
|
||||
if($fp) return site_url();
|
||||
// connect to the URL without port
|
||||
$fp = @fsockopen($server['host'], $server['port'], $errno, $errstr, 1);
|
||||
if($fp) return preg_replace('!(?=:\d+):\d+!', '$1', site_url());
|
||||
// throw an error if all connections fail
|
||||
throw new \Exception(__('Site URL is unreachable.'));
|
||||
}
|
||||
|
||||
function getDaemonLastRunTime() {
|
||||
$currentTime = Carbon::now('UTC');
|
||||
$lastUpdateTime = Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->daemon->updated_at, 'UTC'
|
||||
);
|
||||
return $currentTime->diffInSeconds($lastUpdateTime);
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace MailPoet\Cron\Workers;
|
||||
|
||||
use MailPoet\Mailer\Mailer;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\NewsletterStatistics;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Newsletter\Renderer\Renderer;
|
||||
use MailPoet\Router\Mailer;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -15,75 +15,58 @@ class SendingQueue {
|
||||
}
|
||||
|
||||
function process() {
|
||||
$queues =
|
||||
\MailPoet\Models\SendingQueue::orderByDesc('priority')
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
->findResultSet();
|
||||
foreach($queues as $queue) {
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id);
|
||||
foreach($this->getQueues() as $queue) {
|
||||
$newsletter = Newsletter::findOne($queue->newsletter_id)
|
||||
->asArray();
|
||||
if(!$newsletter) {
|
||||
continue;
|
||||
};
|
||||
$newsletter = $newsletter->asArray();
|
||||
$mailer = new Mailer($httpRequest = false);
|
||||
if(!empty($newsletter['sender_address']) &&
|
||||
!empty($newsletter['sender_name'])
|
||||
) {
|
||||
$mailer->fromName = $newsletter['sender_name'];
|
||||
$mailer->fromEmail = $newsletter['sender_address'];
|
||||
$mailer->fromNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->fromName,
|
||||
$mailer->fromEmail
|
||||
);
|
||||
}
|
||||
if(!empty($newsletter['reply_to_address']) &&
|
||||
!empty($newsletter['reply_to_name'])
|
||||
) {
|
||||
$mailer->replyToName = $newsletter['reply_to_name'];
|
||||
$mailer->replyToEmail = $newsletter['reply_to_address'];
|
||||
$mailer->replyToNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->replyToName,
|
||||
$mailer->replyToEmail
|
||||
);
|
||||
}
|
||||
$mailer->mailer = $mailer->buildMailer();
|
||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
||||
$newsletter = array(
|
||||
'subject' => $newsletter['subject'],
|
||||
'id' => $newsletter['id'],
|
||||
'body' => array(
|
||||
'html' => $renderer->renderAll(),
|
||||
'text' => ''
|
||||
// TODO: add text body
|
||||
)
|
||||
);
|
||||
$newsletter = $this->renderNewsletter($newsletter);
|
||||
$mailer = $this->configureMailerForNewsletter($newsletter);
|
||||
$subscribers = json_decode($queue->subscribers, true);
|
||||
$subscribersToProcess = $subscribers['to_process'];
|
||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
||||
if(!isset($subscribers['failed'])) $subscribers['failed'] = array();
|
||||
foreach(array_chunk($subscribersToProcess, 200) as $subscriberIds) {
|
||||
$dbSubscribers = Subscriber::whereIn('id', $subscriberIds)
|
||||
->findArray();
|
||||
foreach($dbSubscribers as $i => $dbSubscriber) {
|
||||
foreach($dbSubscribers as $dbSubscriber) {
|
||||
$this->checkExecutionTimer();
|
||||
// TODO: replace shortcodes in the newsletter
|
||||
$result = $mailer->mailer->send(
|
||||
$newsletter,
|
||||
$mailer->transformSubscriber($dbSubscriber)
|
||||
);
|
||||
$newsletterStatistics = NewsletterStatistics::create();
|
||||
$newsletterStatistics->subscriber_id = $dbSubscriber['id'];
|
||||
$newsletterStatistics->newsletter_id = $newsletter['id'];
|
||||
$newsletterStatistics->queue_id = $queue->id;
|
||||
$newsletterStatistics->save();
|
||||
$result = $this->sendNewsletter(
|
||||
$mailer,
|
||||
$this->processNewsletter($newsletter),
|
||||
$dbSubscriber);
|
||||
if($result) {
|
||||
$this->updateStatistics($newsletter['id'], $dbSubscriber['id'], $queue->id);
|
||||
$subscribers['processed'][] = $dbSubscriber['id'];
|
||||
} else {
|
||||
$subscribers['failed'][] = $dbSubscriber['id'];
|
||||
} else $subscribers['failed'][] = $dbSubscriber['id'];
|
||||
$this->updateQueue($queue, $subscribers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processNewsletter($newsletter) {
|
||||
// TODO: replace shortcodes, etc..
|
||||
return $newsletter;
|
||||
}
|
||||
|
||||
function sendNewsletter($mailer, $newsletter, $subscriber) {
|
||||
return $mailer->mailerInstance->send(
|
||||
$newsletter,
|
||||
$mailer->transformSubscriber($subscriber)
|
||||
);
|
||||
}
|
||||
|
||||
function updateStatistics($newsletterId, $subscriberId, $queueId) {
|
||||
$newsletterStatistics = NewsletterStatistics::create();
|
||||
$newsletterStatistics->subscriber_id = $newsletterId;
|
||||
$newsletterStatistics->newsletter_id = $subscriberId;
|
||||
$newsletterStatistics->queue_id = $queueId;
|
||||
$newsletterStatistics->save();
|
||||
}
|
||||
|
||||
function updateQueue($queue, $subscribers) {
|
||||
$subscribers['to_process'] = array_values(
|
||||
array_diff(
|
||||
$subscribers['to_process'],
|
||||
@ -103,12 +86,39 @@ class SendingQueue {
|
||||
$queue->subscribers = json_encode($subscribers);
|
||||
$queue->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function configureMailerForNewsletter($newsletter) {
|
||||
if(!empty($newsletter['sender_address']) && !empty($newsletter['sender_name'])) {
|
||||
$sender = array(
|
||||
'name' => $newsletter['sender_name'],
|
||||
'address' => $newsletter['sender_address']
|
||||
);
|
||||
} else $sender = false;
|
||||
if(!empty($newsletter['reply_to_address']) && !empty($newsletter['reply_to_name'])) {
|
||||
$replyTo = array(
|
||||
'name' => $newsletter['reply_to_name'],
|
||||
'address' => $newsletter['reply_to_address']
|
||||
);
|
||||
} else $replyTo = false;
|
||||
$mailer = new Mailer($method = false, $sender, $replyTo);
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
function checkExecutionTimer() {
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if($elapsedTime >= 28) throw new \Exception('Maximum execution time reached.');
|
||||
if($elapsedTime >= 30) throw new \Exception('Maximum execution time reached.');
|
||||
}
|
||||
|
||||
function getQueues() {
|
||||
return \MailPoet\Models\SendingQueue::orderByDesc('priority')
|
||||
->whereNull('deleted_at')
|
||||
->whereNull('status')
|
||||
->findResultSet();
|
||||
}
|
||||
|
||||
function renderNewsletter($newsletter) {
|
||||
$renderer = new Renderer(json_decode($newsletter['body'], true));
|
||||
$newsletter['body'] = $renderer->renderAll();
|
||||
return $newsletter;
|
||||
}
|
||||
}
|
141
lib/Mailer/Mailer.php
Normal file
141
lib/Mailer/Mailer.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
function __construct($mailer = false, $sender = false, $reply_to = false) {
|
||||
$this->mailer = $this->getMailer($mailer);
|
||||
$this->sender = $this->getSender($sender);
|
||||
$this->replyTo = $this->getReplyTo($reply_to);
|
||||
$this->mailerInstance = $this->buildMailer();
|
||||
}
|
||||
|
||||
function send($newsletter, $subscriber) {
|
||||
$subscriber = $this->transformSubscriber($subscriber);
|
||||
return $this->mailerInstance->send($newsletter, $subscriber);
|
||||
}
|
||||
|
||||
function buildMailer() {
|
||||
switch($this->mailer['method']) {
|
||||
case 'AmazonSES':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['region'],
|
||||
$this->mailer['access_key'],
|
||||
$this->mailer['secret_key'],
|
||||
$this->sender['fromNameEmail']
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['domain'],
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['fromNameEmail']
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['mailpoet_api_key'],
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
case 'Mandrill':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['api_key'],
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
case 'WPMail':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
case 'SMTP':
|
||||
$mailerInstance = new $this->mailer['class'](
|
||||
$this->mailer['host'],
|
||||
$this->mailer['port'],
|
||||
$this->mailer['authentication'],
|
||||
$this->mailer['login'],
|
||||
$this->mailer['password'],
|
||||
$this->mailer['encryption'],
|
||||
$this->sender['fromEmail'],
|
||||
$this->sender['fromName']
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception(__('Mailing method does not exist.'));
|
||||
break;
|
||||
}
|
||||
return $mailerInstance;
|
||||
}
|
||||
|
||||
function getMailer($mailer = false) {
|
||||
if(!$mailer) {
|
||||
$mailer = Setting::getValue('mta', null);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured.'));
|
||||
}
|
||||
$mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method'];
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
function getSender($sender = false) {
|
||||
if(!$sender) {
|
||||
$sender = Setting::getValue('sender', null);
|
||||
if(!$sender) throw new \Exception(__('Sender name and email are not configured.'));
|
||||
}
|
||||
return array(
|
||||
'fromName' => $sender['name'],
|
||||
'fromEmail' => $sender['address'],
|
||||
'fromNameEmail' => sprintf('%s <%s>', $sender['name'], $sender['address'])
|
||||
);
|
||||
}
|
||||
|
||||
function getReplyTo($replyTo = false) {
|
||||
if(!$replyTo) {
|
||||
$replyTo = Setting::getValue('replyTo', null);
|
||||
if(!$replyTo) {
|
||||
$replyTo = array(
|
||||
'name' => $this->sender['fromName'],
|
||||
'address' => $this->sender['fromEmail']
|
||||
);
|
||||
}
|
||||
}
|
||||
return array(
|
||||
'replyToName' => $replyTo['name'],
|
||||
'replyToEmail' => $replyTo['address'],
|
||||
'replyToNameEmail' => sprintf('%s <%s>', $replyTo['name'], $replyTo['address'])
|
||||
);
|
||||
}
|
||||
|
||||
function transformSubscriber($subscriber) {
|
||||
if(!is_array($subscriber)) return $subscriber;
|
||||
if(isset($subscriber['address'])) $subscriber['email'] = $subscriber['address'];
|
||||
$first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : '';
|
||||
$last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : '';
|
||||
if(!$first_name && !$last_name) return $subscriber['email'];
|
||||
$subscriber = sprintf('%s %s <%s>', $first_name, $last_name, $subscriber['email']);
|
||||
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
|
||||
return $subscriber;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\API;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\API;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\API;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\API;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer\API;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Mailer;
|
||||
namespace MailPoet\Mailer\Methods;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
@ -4,7 +4,7 @@ namespace MailPoet\Models;
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue extends Model {
|
||||
public static $_table = MP_SENDING_QUEUE_TABLE;
|
||||
public static $_table = MP_SENDING_QUEUES_TABLE;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
@ -1,36 +1,29 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoet\Cron\Daemon;
|
||||
use MailPoet\Cron\Supervisor;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Cron {
|
||||
function controlDaemon($data) {
|
||||
switch($data['action']) {
|
||||
case 'start':
|
||||
$supervisor = new \MailPoet\Cron\Supervisor($forceStart = true);
|
||||
function start() {
|
||||
$supervisor = new Supervisor($forceStart = true);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $supervisor->checkDaemon()
|
||||
'result' => $supervisor->checkDaemon() ? true : false
|
||||
)
|
||||
);
|
||||
exit;
|
||||
break;
|
||||
case 'stop':
|
||||
$status = 'stopped';
|
||||
break;
|
||||
default:
|
||||
$status = 'paused';
|
||||
break;
|
||||
}
|
||||
$daemon = new \MailPoet\Cron\Daemon();
|
||||
if(!$daemon->daemon || $daemon->daemonData['status'] !== 'started') {
|
||||
|
||||
function stop() {
|
||||
$daemon = new Daemon();
|
||||
if(!$daemon->daemon ||
|
||||
$daemon->daemonData['status'] !== 'started'
|
||||
) {
|
||||
$result = false;
|
||||
} else {
|
||||
$daemon->daemonData['status'] = $status;
|
||||
$daemon->daemonData['status'] = 'stopping';
|
||||
$daemon->daemon->value = json_encode($daemon->daemonData);
|
||||
$result = $daemon->daemon->save();
|
||||
}
|
||||
@ -41,153 +34,8 @@ class Cron {
|
||||
);
|
||||
}
|
||||
|
||||
function getDaemonStatus() {
|
||||
function getStatus() {
|
||||
$daemon = new \MailPoet\Cron\BootStrapMenu();
|
||||
wp_send_json($daemon->bootStrap());
|
||||
}
|
||||
|
||||
function addQueue($data) {
|
||||
$queue = SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
|
||||
!d($queue);
|
||||
exit;
|
||||
$queue = SendingQueue::create();
|
||||
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
|
||||
|
||||
$subscriber_ids = array();
|
||||
$segments = Segment::whereIn('id', $data['segments'])
|
||||
->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
}
|
||||
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $subscriber_ids
|
||||
)
|
||||
);
|
||||
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$queue->save();
|
||||
wp_send_json(
|
||||
!$queue->save() ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => 'Queue could not be created.'
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function addQueues($data) {
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $queueData['newsletter_id'];
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $queueData['subscribers']
|
||||
)
|
||||
);
|
||||
$queue->count_total = $queue->count_to_process = count($queueData['subscribers']);
|
||||
$queue->save();
|
||||
return array(
|
||||
'newsletter_id' => $queue->newsletter_id,
|
||||
'queue_id' => $queue->id
|
||||
);
|
||||
}, $data);
|
||||
$result = Helpers::arrayColumn($result, 'queue_id', 'newsletter_id');
|
||||
wp_send_json(
|
||||
count($data) != count($result) ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Some queues could not be created.'),
|
||||
'data' => $result
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteQueue($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id']);
|
||||
if(!$queue) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function deleteQueues($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findResultSet();
|
||||
if(!$queues->count()) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queues not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
foreach($queues as $queue) {
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
}
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function getQueueStatus($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id'])
|
||||
->asArray();
|
||||
wp_send_json(
|
||||
!$queue ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueuesStatus($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findArray();
|
||||
wp_send_json(
|
||||
!$queues ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queues
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -1,191 +1,20 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
require_once(ABSPATH . 'wp-includes/pluggable.php');
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Mailer {
|
||||
function __construct($httpRequest = true) {
|
||||
$this->mailerType = array(
|
||||
'AmazonSES' => 'API',
|
||||
'ElasticEmail' => 'API',
|
||||
'MailGun' => 'API',
|
||||
'Mandrill' => 'API',
|
||||
'SendGrid' => 'API',
|
||||
'MailPoet' => null,
|
||||
'SMTP' => null,
|
||||
'WPMail' => null
|
||||
);
|
||||
if(!$httpRequest) {
|
||||
list($this->fromName, $this->fromEmail, $this->fromNameEmail)
|
||||
= $this->getSetting('sender');
|
||||
$this->mailer = $this->getSetting('mailer');
|
||||
}
|
||||
}
|
||||
|
||||
function send($data) {
|
||||
$subscriber = $this->transformSubscriber($data['subscriber']);
|
||||
list($fromName, $fromEmail, $fromNameEmail)
|
||||
= $this->getSetting('sender');
|
||||
if(!$fromName && !$fromEmail) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Please configure your name and e-mail address.'))
|
||||
)
|
||||
$mailer = new \MailPoet\Mailer\Mailer(
|
||||
(isset($data['mailer'])) ? $data['mailer'] : false,
|
||||
(isset($data['sender'])) ? $data['sender'] : false,
|
||||
(isset($data['reply_to'])) ? $data['reply_to'] : false
|
||||
);
|
||||
}
|
||||
$data['mailer']['class'] = 'MailPoet\\Mailer\\' .
|
||||
(($this->mailerType[$data['mailer']['method']]) ?
|
||||
$this->mailerType[$data['mailer']['method']] . '\\' . $data['mailer']['method'] :
|
||||
$data['mailer']['method']
|
||||
);
|
||||
$mailer = $this->buildMailer(
|
||||
$data['mailer'],
|
||||
$fromName,
|
||||
$fromEmail,
|
||||
$fromNameEmail
|
||||
);
|
||||
if(!empty($newsletter['sender_address']) &&
|
||||
!empty($newsletter['sender_name'])
|
||||
) {
|
||||
$mailer->fromName = $newsletter['sender_name'];
|
||||
$mailer->fromEmail = $newsletter['sender_address'];
|
||||
$mailer->fromNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->fromName,
|
||||
$mailer->fromEmail
|
||||
);
|
||||
}
|
||||
if(!empty($newsletter['reply_to_address']) &&
|
||||
!empty($newsletter['reply_to_name'])
|
||||
) {
|
||||
$mailer->replyToName = $newsletter['reply_to_name'];
|
||||
$mailer->replyToEmail = $newsletter['reply_to_address'];
|
||||
$mailer->replyToNameEmail = sprintf(
|
||||
'%s <%s>',
|
||||
$mailer->replyToName,
|
||||
$mailer->replyToEmail
|
||||
);
|
||||
}
|
||||
$result = $mailer->send($data['newsletter'], $subscriber);
|
||||
$result = $mailer->send($data['newsletter'], $data['subscriber']);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => ($result) ? true : false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function buildMailer($mailer = false, $fromName = false, $fromEmail = false, $fromNameEmail = false) {
|
||||
if(!$mailer) $mailer = $this->mailer;
|
||||
if(!$fromName) $fromName = $this->fromName;
|
||||
if(!$fromEmail) $fromEmail = $this->fromEmail;
|
||||
if(!$fromNameEmail) $fromNameEmail = $this->fromNameEmail;
|
||||
switch($mailer['method']) {
|
||||
case 'AmazonSES':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['region'],
|
||||
$mailer['access_key'],
|
||||
$mailer['secret_key'],
|
||||
$fromNameEmail
|
||||
);
|
||||
break;
|
||||
case 'ElasticEmail':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail, $fromName
|
||||
);
|
||||
break;
|
||||
case 'MailGun':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['domain'],
|
||||
$mailer['api_key'],
|
||||
$fromNameEmail
|
||||
);
|
||||
break;
|
||||
case 'MailPoet':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['mailpoet_api_key'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'Mandrill':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail, $fromName
|
||||
);
|
||||
break;
|
||||
case 'SendGrid':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['api_key'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'WPMail':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
case 'SMTP':
|
||||
$mailerInstance = new $mailer['class'](
|
||||
$mailer['host'],
|
||||
$mailer['port'],
|
||||
$mailer['authentication'],
|
||||
$mailer['login'],
|
||||
$mailer['password'],
|
||||
$mailer['encryption'],
|
||||
$fromEmail,
|
||||
$fromName
|
||||
);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Mailing method does not exist.');
|
||||
break;
|
||||
}
|
||||
return $mailerInstance;
|
||||
}
|
||||
|
||||
function transformSubscriber($subscriber) {
|
||||
if(!is_array($subscriber)) return $subscriber;
|
||||
if(isset($subscriber['address'])) $subscriber['email'] = $subscriber['address'];
|
||||
$first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : '';
|
||||
$last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : '';
|
||||
if(!$first_name && !$last_name) return $subscriber['email'];
|
||||
$subscriber = sprintf('%s %s <%s>', $first_name, $last_name, $subscriber['email']);
|
||||
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
|
||||
return $subscriber;
|
||||
}
|
||||
|
||||
function getSetting($setting) {
|
||||
switch($setting) {
|
||||
case 'mailer':
|
||||
$mailer = Setting::getValue('mta', null);
|
||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception('Mailing method is not configured.');
|
||||
$mailer['class'] = 'MailPoet\\Mailer\\' .
|
||||
(($this->mailerType[$mailer['method']]) ?
|
||||
$this->mailerType[$mailer['method']] . '\\' . $mailer['method'] :
|
||||
$mailer['method']
|
||||
);
|
||||
return $mailer;
|
||||
break;
|
||||
case 'sender':
|
||||
$sender = Setting::getValue($setting, null);
|
||||
if(!$sender) throw new \Exception('Sender name and email are not configured.');
|
||||
return array(
|
||||
$sender['name'],
|
||||
$sender['address'],
|
||||
sprintf('%s <%s>', $sender['name'], $sender['address'])
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return Setting::getValue($setting, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,196 +0,0 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\SendingQueue;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class Queue {
|
||||
function controlDaemon($data) {
|
||||
switch($data['action']) {
|
||||
case 'start':
|
||||
$supervisor = new Supervisor($forceStart = true);
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $supervisor->checkDaemon() ?
|
||||
true :
|
||||
false
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'stop':
|
||||
$status = 'stopped';
|
||||
break;
|
||||
default:
|
||||
$status = 'paused';
|
||||
break;
|
||||
}
|
||||
$daemon = new Daemon();
|
||||
if(!$daemon->daemon || $daemon->daemonData['status'] !== 'started') {
|
||||
$result = false;
|
||||
} else {
|
||||
$daemon->daemonData['status'] = $status;
|
||||
$daemon->daemon->value = json_encode($daemon->daemonData);
|
||||
$result = $daemon->daemon->save();
|
||||
}
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getDaemonStatus() {
|
||||
$daemon = new \MailPoet\Cron\BootStrapMenu();
|
||||
wp_send_json($daemon->bootStrap());
|
||||
}
|
||||
|
||||
function addQueue($data) {
|
||||
$queue = SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
|
||||
!d($queue);
|
||||
exit;
|
||||
$queue = SendingQueue::create();
|
||||
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
|
||||
|
||||
$subscriber_ids = array();
|
||||
$segments = Segment::whereIn('id', $data['segments'])
|
||||
->findMany();
|
||||
foreach($segments as $segment) {
|
||||
$subscriber_ids = array_merge($subscriber_ids, Helpers::arrayColumn(
|
||||
$segment->subscribers()
|
||||
->findArray(),
|
||||
'id'
|
||||
));
|
||||
}
|
||||
|
||||
$subscriber_ids = array_unique($subscriber_ids);
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $subscriber_ids
|
||||
)
|
||||
);
|
||||
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$queue->save();
|
||||
wp_send_json(
|
||||
!$queue->save() ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => 'Queue could not be created.'
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addQueues($data) {
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = SendingQueue::create();
|
||||
$queue->newsletter_id = $queueData['newsletter_id'];
|
||||
$queue->subscribers = json_encode(
|
||||
array(
|
||||
'to_process' => $queueData['subscribers']
|
||||
)
|
||||
);
|
||||
$queue->count_total = $queue->count_to_process = count($queueData['subscribers']);
|
||||
$queue->save();
|
||||
return array(
|
||||
'newsletter_id' => $queue->newsletter_id,
|
||||
'queue_id' => $queue->id
|
||||
);
|
||||
}, $data);
|
||||
$result = Helpers::arrayColumn($result, 'queue_id', 'newsletter_id');
|
||||
wp_send_json(
|
||||
count($data) != count($result) ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Some queues could not be created.'),
|
||||
'data' => $result
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteQueue($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id']);
|
||||
if(!$queue) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function deleteQueues($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findResultSet();
|
||||
if(!$queues->count()) {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queues not found.')
|
||||
)
|
||||
);
|
||||
}
|
||||
foreach($queues as $queue) {
|
||||
$queue->deleted_at = 'Y-m-d H:i:s';
|
||||
$queue->save();
|
||||
}
|
||||
wp_send_json(array('result' => true));
|
||||
}
|
||||
|
||||
function getQueueStatus($data) {
|
||||
$queue = SendingQueue::whereNull('deleted_at')
|
||||
->findOne($data['queue_id'])
|
||||
->asArray();
|
||||
wp_send_json(
|
||||
!$queue ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queue
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueuesStatus($data) {
|
||||
$queues = SendingQueue::whereNull('deleted_at')
|
||||
->whereIn('id', $data['queue_ids'])
|
||||
->findArray();
|
||||
wp_send_json(
|
||||
!$queues ?
|
||||
array(
|
||||
'result' => false,
|
||||
'error' => __('Queue not found.')
|
||||
) :
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => $queues
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@ class SendingQueue {
|
||||
'errors' => array($e->getMessage())
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
$queue = \MailPoet\Models\SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
|
100
tests/unit/Mailer/MailerCest.php
Normal file
100
tests/unit/Mailer/MailerCest.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
use MailPoet\Mailer\Mailer;
|
||||
|
||||
class MailerCest {
|
||||
function _before() {
|
||||
$this->sender = array(
|
||||
'name' => 'Sender',
|
||||
'address' => 'staff@mailinator.com'
|
||||
);
|
||||
$this->replyTo = array(
|
||||
'name' => 'Reply To',
|
||||
'address' => 'staff@mailinator.com'
|
||||
);
|
||||
$this->mailer = array(
|
||||
'method' => 'MailPoet',
|
||||
'mailpoet_api_key' => 'dhNSqj1XHkVltIliyQDvMiKzQShOA5rs0m_DdRUVZHU'
|
||||
);
|
||||
$this->subscriber = 'Recipient <mailpoet-phoenix-test@mailinator.com>';
|
||||
$this->newsletter = array(
|
||||
'subject' => 'testing Mailer',
|
||||
'body' => array(
|
||||
'html' => 'HTML body',
|
||||
'text' => 'TEXT body'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function itRequiresMailerMethod() {
|
||||
try {
|
||||
$mailer = new Mailer();
|
||||
} catch (Exception $e) {
|
||||
expect($e->getMessage())->equals('Mailer is not configured.');
|
||||
}
|
||||
}
|
||||
|
||||
function itRequiresSender() {
|
||||
try {
|
||||
$mailer = new Mailer($mailer = $this->mailer);
|
||||
} catch (Exception $e) {
|
||||
expect($e->getMessage())->equals('Sender name and email are not configured.');
|
||||
}
|
||||
}
|
||||
|
||||
function itCanConstruct() {
|
||||
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo);
|
||||
expect($mailer->sender['fromName'])->equals($this->sender['name']);
|
||||
expect($mailer->sender['fromEmail'])->equals($this->sender['address']);
|
||||
expect($mailer->replyTo['replyToName'])->equals($this->replyTo['name']);
|
||||
expect($mailer->replyTo['replyToEmail'])->equals($this->replyTo['address']);
|
||||
}
|
||||
|
||||
function itCanBuildMailerInstance() {
|
||||
$mailer = new Mailer($this->mailer, $this->sender);
|
||||
expect(get_class($mailer->mailerInstance))
|
||||
->equals('MailPoet\Mailer\Methods\MailPoet');
|
||||
}
|
||||
|
||||
function itCanAbortWhenMethodDoesNotExist() {
|
||||
try {
|
||||
$mailer = new Mailer(array('method' => 'test'), $this->sender);
|
||||
} catch (Exception $e) {
|
||||
expect($e->getMessage())->equals('Mailing method does not exist.');
|
||||
}
|
||||
}
|
||||
|
||||
function itCanTransformSubscriber() {
|
||||
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo);
|
||||
expect($mailer->transformSubscriber('test@email.com'))
|
||||
->equals('test@email.com');
|
||||
expect($mailer->transformSubscriber(
|
||||
array(
|
||||
'email' => 'test@email.com'
|
||||
))
|
||||
)->equals('test@email.com');
|
||||
expect($mailer->transformSubscriber(
|
||||
array(
|
||||
'first_name' => 'First',
|
||||
'email' => 'test@email.com'
|
||||
))
|
||||
)->equals('First <test@email.com>');
|
||||
expect($mailer->transformSubscriber(
|
||||
array(
|
||||
'last_name' => 'Last',
|
||||
'email' => 'test@email.com'
|
||||
))
|
||||
)->equals('Last <test@email.com>');
|
||||
expect($mailer->transformSubscriber(
|
||||
array(
|
||||
'first_name' => 'First',
|
||||
'last_name' => 'Last',
|
||||
'email' => 'test@email.com'
|
||||
))
|
||||
)->equals('First Last <test@email.com>');
|
||||
}
|
||||
|
||||
function itCanSend() {
|
||||
$mailer = new Mailer($this->mailer, $this->sender, $this->replyTo);
|
||||
expect($mailer->send($this->newsletter, $this->subscriber))->true();
|
||||
}
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\API\AmazonSES;
|
||||
use MailPoet\Mailer\Methods\AmazonSES;
|
||||
|
||||
class AmazonSESCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'method' => 'AmazonSES',
|
||||
'type' => 'API',
|
||||
'access_key' => 'AKIAJM6Y5HMGXBLDNSRA',
|
||||
'secret_key' => 'P3EbTbVx7U0LXKQ9nTm2eIrP+9aPiLyvaRDsFxXh',
|
||||
'region' => 'us-east-1',
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\API\ElasticEmail;
|
||||
use MailPoet\Mailer\Methods\ElasticEmail;
|
||||
|
||||
class ElasticEmailCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'method' => 'ElasticEmail',
|
||||
'type' => 'API',
|
||||
'api_key' => '997f1f7f-41de-4d7f-a8cb-86c8481370fa'
|
||||
);
|
||||
$this->fromEmail = 'staff@mailpoet.com';
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\API\MailGun;
|
||||
use MailPoet\Mailer\Methods\MailGun;
|
||||
|
||||
class MailGunCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'method' => 'MailGun',
|
||||
'type' => 'API',
|
||||
'api_key' => 'key-6cf5g5qjzenk-7nodj44gdt8phe6vam2',
|
||||
'domain' => 'mrcasual.com'
|
||||
);
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\MailPoet;
|
||||
use MailPoet\Mailer\Methods\MailPoet;
|
||||
|
||||
class MailPoetCest {
|
||||
function _before() {
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\API\Mandrill;
|
||||
use MailPoet\Mailer\Methods\Mandrill;
|
||||
|
||||
class MandrillCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'method' => 'Mandrill',
|
||||
'type' => 'API',
|
||||
'api_key' => '692ys1B7REEoZN7R-dYwNA'
|
||||
);
|
||||
$this->fromEmail = 'staff@mailpoet.com';
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\SMTP;
|
||||
use MailPoet\Mailer\Methods\SMTP;
|
||||
|
||||
class SMTPCest {
|
||||
function _before() {
|
@ -1,12 +1,11 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\API\SendGrid;
|
||||
use MailPoet\Mailer\Methods\SendGrid;
|
||||
|
||||
class SendGridCest {
|
||||
function _before() {
|
||||
$this->settings = array(
|
||||
'method' => 'SendGrid',
|
||||
'type' => 'API',
|
||||
'api_key' => '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'
|
||||
);
|
||||
$this->fromEmail = 'staff@mailpoet.com';
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MailPoet\Mailer\WPMail;
|
||||
use MailPoet\Mailer\Methods\WPMail;
|
||||
|
||||
class WPMailCest {
|
||||
function _before() {
|
Reference in New Issue
Block a user