@ -21,8 +21,6 @@ define(
|
|||||||
action: 'getStatus'
|
action: 'getStatus'
|
||||||
})
|
})
|
||||||
.done(function(response) {
|
.done(function(response) {
|
||||||
jQuery('.button-primary')
|
|
||||||
.removeClass('disabled');
|
|
||||||
if(response.status !== undefined) {
|
if(response.status !== undefined) {
|
||||||
this.setState(response);
|
this.setState(response);
|
||||||
} else {
|
} else {
|
||||||
@ -36,55 +34,26 @@ define(
|
|||||||
setInterval(this.getCronData, 5000);
|
setInterval(this.getCronData, 5000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controlCron: function(action) {
|
|
||||||
if(jQuery('.button-primary').hasClass('disabled')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
jQuery('.button-primary')
|
|
||||||
.addClass('disabled');
|
|
||||||
MailPoet.Ajax.post({
|
|
||||||
endpoint: 'cron',
|
|
||||||
action: action,
|
|
||||||
})
|
|
||||||
.done(function(response) {
|
|
||||||
if(!response.result) {
|
|
||||||
MailPoet.Notice.error(MailPoet.I18n.t('daemonControlError'));
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
render: function() {
|
render: function() {
|
||||||
if(this.state.status === 'loading') {
|
|
||||||
return(<div>{MailPoet.I18n.t('loadingDaemonStatus')}</div>);
|
|
||||||
}
|
|
||||||
switch(this.state.status) {
|
switch(this.state.status) {
|
||||||
case 'started':
|
case 'loading':
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
{MailPoet.I18n.t('cronDaemonIsRunning')}
|
{MailPoet.I18n.t('loadingDaemonStatus')}
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>{MailPoet.I18n.t('stop')}</a>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
break;
|
case false:
|
||||||
case 'starting':
|
return(
|
||||||
case 'stopping':
|
<div>
|
||||||
|
{MailPoet.I18n.t('daemonNotRunning')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
default:
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
case 'stopped':
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>{MailPoet.I18n.t('start')}</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,35 +2,15 @@
|
|||||||
namespace MailPoet\API\Endpoints;
|
namespace MailPoet\API\Endpoints;
|
||||||
|
|
||||||
use MailPoet\Cron\CronHelper;
|
use MailPoet\Cron\CronHelper;
|
||||||
use MailPoet\Cron\Supervisor;
|
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Cron {
|
class Cron {
|
||||||
function start() {
|
|
||||||
$supervisor = new Supervisor($force_run = true);
|
|
||||||
return $supervisor->checkDaemon();
|
|
||||||
}
|
|
||||||
|
|
||||||
function stop() {
|
|
||||||
$daemon = CronHelper::getDaemon();
|
|
||||||
if(!$daemon || $daemon['status'] !== 'started') {
|
|
||||||
$result = false;
|
|
||||||
} else {
|
|
||||||
$daemon['status'] = 'stopping';
|
|
||||||
$result = CronHelper::saveDaemon($daemon);
|
|
||||||
}
|
|
||||||
return array(
|
|
||||||
'result' => $result
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatus() {
|
function getStatus() {
|
||||||
$daemon = Setting::where('name', 'cron_daemon')
|
$daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
|
||||||
->findOne();
|
|
||||||
return ($daemon) ?
|
return ($daemon) ?
|
||||||
unserialize($daemon->value) :
|
$daemon :
|
||||||
false;
|
array('status' => false);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
use MailPoet\Models;
|
use MailPoet\Models;
|
||||||
use MailPoet\Cron\Supervisor;
|
use MailPoet\Cron\CronTrigger;
|
||||||
use MailPoet\Router;
|
use MailPoet\Router;
|
||||||
use MailPoet\API;
|
use MailPoet\API;
|
||||||
use MailPoet\WP\Notice as WPNotice;
|
use MailPoet\WP\Notice as WPNotice;
|
||||||
@ -107,7 +107,7 @@ class Initializer {
|
|||||||
$this->setupShortcodes();
|
$this->setupShortcodes();
|
||||||
$this->setupHooks();
|
$this->setupHooks();
|
||||||
$this->setupImages();
|
$this->setupImages();
|
||||||
$this->runQueueSupervisor();
|
$this->setupCronTrigger();
|
||||||
|
|
||||||
$this->plugin_initialized = true;
|
$this->plugin_initialized = true;
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
@ -192,14 +192,9 @@ class Initializer {
|
|||||||
$router->init();
|
$router->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
function runQueueSupervisor() {
|
function setupCronTrigger() {
|
||||||
if(php_sapi_name() === 'cli') return;
|
$cron_trigger = new CronTrigger();
|
||||||
try {
|
$cron_trigger->init();
|
||||||
$supervisor = new Supervisor();
|
|
||||||
$supervisor->checkDaemon();
|
|
||||||
} catch(\Exception $e) {
|
|
||||||
// Prevent Daemon exceptions from breaking out and breaking UI
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupImages() {
|
function setupImages() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
|
use MailPoet\Cron\CronTrigger;
|
||||||
use MailPoet\Form\Block;
|
use MailPoet\Form\Block;
|
||||||
use MailPoet\Form\Renderer as FormRenderer;
|
use MailPoet\Form\Renderer as FormRenderer;
|
||||||
use MailPoet\Models\CustomField;
|
use MailPoet\Models\CustomField;
|
||||||
@ -255,6 +256,7 @@ class Menu {
|
|||||||
$data = array(
|
$data = array(
|
||||||
'settings' => $settings,
|
'settings' => $settings,
|
||||||
'segments' => Segment::getPublic()->findArray(),
|
'segments' => Segment::getPublic()->findArray(),
|
||||||
|
'cron_trigger' => CronTrigger::getAvailableMethods(),
|
||||||
'pages' => Pages::getAll(),
|
'pages' => Pages::getAll(),
|
||||||
'flags' => $flags,
|
'flags' => $flags,
|
||||||
'current_user' => wp_get_current_user(),
|
'current_user' => wp_get_current_user(),
|
||||||
|
@ -10,6 +10,7 @@ use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlank1Column;
|
|||||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank1Column;
|
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank1Column;
|
||||||
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank12Column;
|
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank12Column;
|
||||||
use MailPoet\Config\PopulatorData\Templates\SimpleText;
|
use MailPoet\Config\PopulatorData\Templates\SimpleText;
|
||||||
|
use MailPoet\Cron\CronTrigger;
|
||||||
use \MailPoet\Models\Segment;
|
use \MailPoet\Models\Segment;
|
||||||
use \MailPoet\Segments\WP;
|
use \MailPoet\Segments\WP;
|
||||||
use \MailPoet\Models\Setting;
|
use \MailPoet\Models\Setting;
|
||||||
@ -74,6 +75,13 @@ class Populator {
|
|||||||
private function createDefaultSettings() {
|
private function createDefaultSettings() {
|
||||||
$current_user = wp_get_current_user();
|
$current_user = wp_get_current_user();
|
||||||
|
|
||||||
|
if(!Setting::getValue(CronTrigger::SETTING_NAME)) {
|
||||||
|
// disable task scheduler (cron) be default
|
||||||
|
Setting::setValue(CronTrigger::SETTING_NAME, array(
|
||||||
|
'method' => CronTrigger::DEFAULT_METHOD
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// default sender info based on current user
|
// default sender info based on current user
|
||||||
$sender = array(
|
$sender = array(
|
||||||
'name' => $current_user->display_name,
|
'name' => $current_user->display_name,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
use MailPoet\Router\Front as FrontRouter;
|
|
||||||
use MailPoet\Router\Endpoints\Queue as QueueEndpoint;
|
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Router\Endpoints\Queue as QueueEndpoint;
|
||||||
|
use MailPoet\Router\Front as FrontRouter;
|
||||||
use MailPoet\Util\Security;
|
use MailPoet\Util\Security;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
@ -12,6 +12,7 @@ class CronHelper {
|
|||||||
const DAEMON_EXECUTION_LIMIT = 20;
|
const DAEMON_EXECUTION_LIMIT = 20;
|
||||||
const DAEMON_EXECUTION_TIMEOUT = 35;
|
const DAEMON_EXECUTION_TIMEOUT = 35;
|
||||||
const DAEMON_REQUEST_TIMEOUT = 2;
|
const DAEMON_REQUEST_TIMEOUT = 2;
|
||||||
|
const DAEMON_SETTING = 'cron_daemon';
|
||||||
|
|
||||||
static function createDaemon($token) {
|
static function createDaemon($token) {
|
||||||
$daemon = array(
|
$daemon = array(
|
||||||
@ -22,18 +23,32 @@ class CronHelper {
|
|||||||
return $daemon;
|
return $daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function restartDaemon($token) {
|
||||||
|
return self::createDaemon($token);
|
||||||
|
}
|
||||||
|
|
||||||
static function getDaemon() {
|
static function getDaemon() {
|
||||||
return Setting::getValue('cron_daemon');
|
return Setting::getValue(self::DAEMON_SETTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function saveDaemon($daemon) {
|
static function saveDaemon($daemon) {
|
||||||
$daemon['updated_at'] = time();
|
$daemon['updated_at'] = time();
|
||||||
return Setting::setValue(
|
return Setting::setValue(
|
||||||
'cron_daemon',
|
self::DAEMON_SETTING,
|
||||||
$daemon
|
$daemon
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function stopDaemon() {
|
||||||
|
$daemon = self::getDaemon();
|
||||||
|
$daemon['status'] = Daemon::STATUS_STOPPED;
|
||||||
|
return self::saveDaemon($daemon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function deleteDaemon() {
|
||||||
|
return Setting::deleteValue(self::DAEMON_SETTING);
|
||||||
|
}
|
||||||
|
|
||||||
static function createToken() {
|
static function createToken() {
|
||||||
return Security::generateRandomString();
|
return Security::generateRandomString();
|
||||||
}
|
}
|
||||||
@ -46,6 +61,8 @@ class CronHelper {
|
|||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
$args = array(
|
$args = array(
|
||||||
|
'blocking' => false,
|
||||||
|
'sslverify' => false,
|
||||||
'timeout' => $timeout,
|
'timeout' => $timeout,
|
||||||
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
|
||||||
);
|
);
|
||||||
@ -70,7 +87,7 @@ class CronHelper {
|
|||||||
throw new \Exception(__('Site URL is unreachable.'));
|
throw new \Exception(__('Site URL is unreachable.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static function checkExecutionTimer($timer) {
|
static function enforceExecutionLimit($timer) {
|
||||||
$elapsed_time = microtime(true) - $timer;
|
$elapsed_time = microtime(true) - $timer;
|
||||||
if($elapsed_time >= self::DAEMON_EXECUTION_LIMIT) {
|
if($elapsed_time >= self::DAEMON_EXECUTION_LIMIT) {
|
||||||
throw new \Exception(__('Maximum execution time has been reached.'));
|
throw new \Exception(__('Maximum execution time has been reached.'));
|
||||||
|
41
lib/Cron/CronTrigger.php
Normal file
41
lib/Cron/CronTrigger.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class CronTrigger {
|
||||||
|
public $current_method;
|
||||||
|
public static $available_methods = array(
|
||||||
|
'mailpoet' => 'MailPoet',
|
||||||
|
'wordpress' => 'WordPress'
|
||||||
|
);
|
||||||
|
const DEFAULT_METHOD = 'WordPress';
|
||||||
|
const SETTING_NAME = 'cron_trigger';
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->current_method = self::getCurrentMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
try {
|
||||||
|
// configure cron trigger only outside of cli environment
|
||||||
|
if(php_sapi_name() === 'cli') return;
|
||||||
|
$trigger_class = __NAMESPACE__ . '\Triggers\\' . $this->current_method;
|
||||||
|
return (class_exists($trigger_class)) ?
|
||||||
|
$trigger_class::run() :
|
||||||
|
false;
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
// cron exceptions should not prevent the rest of the site from loading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getAvailableMethods() {
|
||||||
|
return self::$available_methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getCurrentMethod() {
|
||||||
|
return Setting::getValue(self::SETTING_NAME . '.method');
|
||||||
|
}
|
||||||
|
}
|
@ -78,15 +78,16 @@ class Daemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function abortWithError($message) {
|
|
||||||
exit('[mailpoet_cron_error:' . base64_encode($message) . ']');
|
|
||||||
}
|
|
||||||
|
|
||||||
function callSelf() {
|
function callSelf() {
|
||||||
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
|
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
|
||||||
$this->terminateRequest();
|
$this->terminateRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function abortWithError($message) {
|
||||||
|
status_header(404, $message);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
function terminateRequest() {
|
function terminateRequest() {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -6,87 +6,35 @@ if(!defined('ABSPATH')) exit;
|
|||||||
class Supervisor {
|
class Supervisor {
|
||||||
public $daemon;
|
public $daemon;
|
||||||
public $token;
|
public $token;
|
||||||
public $force_run;
|
|
||||||
|
|
||||||
function __construct($force_run = false) {
|
function __construct() {
|
||||||
$this->daemon = CronHelper::getDaemon();
|
|
||||||
$this->token = CronHelper::createToken();
|
$this->token = CronHelper::createToken();
|
||||||
$this->force_run = $force_run;
|
$this->daemon = $this->getDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDaemon() {
|
function checkDaemon() {
|
||||||
$daemon = $this->daemon;
|
$daemon = $this->daemon;
|
||||||
if(!$daemon) {
|
$execution_timeout_exceeded =
|
||||||
$daemon = CronHelper::createDaemon($this->token);
|
(time() - (int)$daemon['updated_at']) > CronHelper::DAEMON_EXECUTION_TIMEOUT;
|
||||||
return $this->runDaemon($daemon);
|
if($execution_timeout_exceeded) {
|
||||||
}
|
CronHelper::restartDaemon($this->token);
|
||||||
// if the daemon is stopped, return its status and do nothing
|
|
||||||
if(!$this->force_run &&
|
|
||||||
isset($daemon['status']) &&
|
|
||||||
$daemon['status'] === Daemon::STATUS_STOPPED
|
|
||||||
) {
|
|
||||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
|
||||||
}
|
|
||||||
$elapsed_time = time() - (int)$daemon['updated_at'];
|
|
||||||
// if it's been less than 40 seconds since last execution and we're not
|
|
||||||
// force-running the daemon, return its status and do nothing
|
|
||||||
if($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT && !$this->force_run) {
|
|
||||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
|
||||||
} elseif($elapsed_time < CronHelper::DAEMON_EXECUTION_TIMEOUT &&
|
|
||||||
$this->force_run &&
|
|
||||||
in_array($daemon['status'], array(
|
|
||||||
Daemon::STATUS_STOPPING,
|
|
||||||
Daemon::STATUS_STARTING
|
|
||||||
))
|
|
||||||
) {
|
|
||||||
// if it's been less than 40 seconds since last execution, we are
|
|
||||||
// force-running the daemon and it's either being started or stopped,
|
|
||||||
// return its status and do nothing
|
|
||||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
|
||||||
}
|
|
||||||
// re-create (restart) daemon
|
|
||||||
CronHelper::createDaemon($this->token);
|
|
||||||
return $this->runDaemon();
|
return $this->runDaemon();
|
||||||
}
|
}
|
||||||
|
return $daemon;
|
||||||
|
}
|
||||||
|
|
||||||
function runDaemon() {
|
function runDaemon() {
|
||||||
$request = CronHelper::accessDaemon($this->token);
|
CronHelper::accessDaemon($this->token);
|
||||||
preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
|
$daemon = CronHelper::getDaemon();
|
||||||
|
return $daemon;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDaemon() {
|
||||||
$daemon = CronHelper::getDaemon();
|
$daemon = CronHelper::getDaemon();
|
||||||
if(!empty($status) || !$daemon) {
|
|
||||||
if(!$daemon) {
|
if(!$daemon) {
|
||||||
$message = __('Daemon failed to run.');
|
CronHelper::createDaemon($this->token);
|
||||||
} else {
|
return $this->runDaemon();
|
||||||
list(, $message) = explode(':', $status[0]);
|
|
||||||
$message = base64_decode($message);
|
|
||||||
}
|
}
|
||||||
return $this->formatResultMessage(
|
return $daemon;
|
||||||
false,
|
|
||||||
$message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $this->formatDaemonStatusMessage($daemon['status']);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function formatDaemonStatusMessage($status) {
|
|
||||||
return $this->formatResultMessage(
|
|
||||||
true,
|
|
||||||
sprintf(
|
|
||||||
__('Daemon is currently %s.'),
|
|
||||||
__($status)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function formatResultMessage($result, $message) {
|
|
||||||
$formattedResult = array(
|
|
||||||
'result' => $result
|
|
||||||
);
|
|
||||||
if(!$result) {
|
|
||||||
$formattedResult['errors'] = array($message);
|
|
||||||
} else {
|
|
||||||
$formattedResult['message'] = $message;
|
|
||||||
}
|
|
||||||
return $formattedResult;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
13
lib/Cron/Triggers/MailPoet.php
Normal file
13
lib/Cron/Triggers/MailPoet.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron\Triggers;
|
||||||
|
|
||||||
|
use MailPoet\Cron\Supervisor;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class MailPoet {
|
||||||
|
static function run() {
|
||||||
|
$supervisor = new Supervisor();
|
||||||
|
return $supervisor->checkDaemon();
|
||||||
|
}
|
||||||
|
}
|
31
lib/Cron/Triggers/WordPress.php
Normal file
31
lib/Cron/Triggers/WordPress.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron\Triggers;
|
||||||
|
|
||||||
|
use MailPoet\Cron\CronHelper;
|
||||||
|
use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
|
||||||
|
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
|
||||||
|
use MailPoet\Mailer\MailerLog;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class WordPress {
|
||||||
|
static function run() {
|
||||||
|
return (self::checkExecutionRequirements()) ?
|
||||||
|
MailPoet::run() :
|
||||||
|
self::cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function checkExecutionRequirements() {
|
||||||
|
$scheduled_queues = SchedulerWorker::getScheduledQueues();
|
||||||
|
$running_queues = SendingQueueWorker::getRunningQueues();
|
||||||
|
$sending_limit_reached = MailerLog::isSendingLimitReached();
|
||||||
|
return (($scheduled_queues || $running_queues) && !$sending_limit_reached);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function cleanup() {
|
||||||
|
$cron_daemon = CronHelper::getDaemon();
|
||||||
|
if($cron_daemon) {
|
||||||
|
CronHelper::deleteDaemon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,13 +20,12 @@ class Scheduler {
|
|||||||
|
|
||||||
function __construct($timer = false) {
|
function __construct($timer = false) {
|
||||||
$this->timer = ($timer) ? $timer : microtime(true);
|
$this->timer = ($timer) ? $timer : microtime(true);
|
||||||
CronHelper::checkExecutionTimer($this->timer);
|
// abort if execution limit is reached
|
||||||
|
CronHelper::enforceExecutionLimit($this->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process() {
|
||||||
$scheduled_queues = SendingQueue::where('status', 'scheduled')
|
$scheduled_queues = self::getScheduledQueues();
|
||||||
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
|
||||||
->findMany();
|
|
||||||
if(!count($scheduled_queues)) return;
|
if(!count($scheduled_queues)) return;
|
||||||
foreach($scheduled_queues as $i => $queue) {
|
foreach($scheduled_queues as $i => $queue) {
|
||||||
$newsletter = Newsletter::filter('filterWithOptions')
|
$newsletter = Newsletter::filter('filterWithOptions')
|
||||||
@ -40,7 +39,7 @@ class Scheduler {
|
|||||||
} elseif($newsletter->type === 'standard') {
|
} elseif($newsletter->type === 'standard') {
|
||||||
$this->processScheduledStandardNewsletter($newsletter, $queue);
|
$this->processScheduledStandardNewsletter($newsletter, $queue);
|
||||||
}
|
}
|
||||||
CronHelper::checkExecutionTimer($this->timer);
|
CronHelper::enforceExecutionLimit($this->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,4 +184,10 @@ class Scheduler {
|
|||||||
$notification_history :
|
$notification_history :
|
||||||
false;
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function getScheduledQueues() {
|
||||||
|
return SendingQueue::where('status', 'scheduled')
|
||||||
|
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||||
|
->findMany();
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ use MailPoet\Cron\CronHelper;
|
|||||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
|
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
|
||||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
|
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
|
||||||
use MailPoet\Cron\Workers\SendingQueue\Tasks\Subscribers as SubscribersTask;
|
use MailPoet\Cron\Workers\SendingQueue\Tasks\Subscribers as SubscribersTask;
|
||||||
use MailPoet\Models\Newsletter as NewsletterModel;
|
use MailPoet\Mailer\MailerLog;
|
||||||
use MailPoet\Models\SendingQueue as SendingQueueModel;
|
use MailPoet\Models\SendingQueue as SendingQueueModel;
|
||||||
use MailPoet\Models\StatisticsNewsletters as StatisticsNewslettersModel;
|
use MailPoet\Models\StatisticsNewsletters as StatisticsNewslettersModel;
|
||||||
use MailPoet\Models\Subscriber as SubscriberModel;
|
use MailPoet\Models\Subscriber as SubscriberModel;
|
||||||
@ -23,11 +23,14 @@ class SendingQueue {
|
|||||||
$this->mailer_task = new MailerTask();
|
$this->mailer_task = new MailerTask();
|
||||||
$this->newsletter_task = new NewsletterTask();
|
$this->newsletter_task = new NewsletterTask();
|
||||||
$this->timer = ($timer) ? $timer : microtime(true);
|
$this->timer = ($timer) ? $timer : microtime(true);
|
||||||
|
// abort if execution or sending limit are reached
|
||||||
|
CronHelper::enforceExecutionLimit($this->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function process() {
|
function process() {
|
||||||
$this->mailer_task->checkSendingLimit();
|
foreach(self::getRunningQueues() as $queue) {
|
||||||
foreach($this->getQueues() as $queue) {
|
// abort if sending limit is reached
|
||||||
|
MailerLog::enforceSendingLimit();
|
||||||
// get and pre-process newsletter (render, replace shortcodes/links, etc.)
|
// get and pre-process newsletter (render, replace shortcodes/links, etc.)
|
||||||
$newsletter = $this->newsletter_task->getAndPreProcess($queue->asArray());
|
$newsletter = $this->newsletter_task->getAndPreProcess($queue->asArray());
|
||||||
if(!$newsletter) {
|
if(!$newsletter) {
|
||||||
@ -67,6 +70,11 @@ class SendingQueue {
|
|||||||
$newsletter,
|
$newsletter,
|
||||||
$found_subscribers
|
$found_subscribers
|
||||||
);
|
);
|
||||||
|
if($queue->status === SendingQueueModel::STATUS_COMPLETED) {
|
||||||
|
$this->newsletter_task->markNewsletterAsSent($queue->newsletter_id);
|
||||||
|
}
|
||||||
|
// abort if execution limit is reached
|
||||||
|
CronHelper::enforceExecutionLimit($this->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,6 +149,7 @@ class SendingQueue {
|
|||||||
$prepared_subscribers_ids,
|
$prepared_subscribers_ids,
|
||||||
$queue->subscribers
|
$queue->subscribers
|
||||||
);
|
);
|
||||||
|
$queue = $this->updateQueue($queue);
|
||||||
} else {
|
} else {
|
||||||
// update processed/to process list
|
// update processed/to process list
|
||||||
$queue->subscribers = SubscribersTask::updateProcessedList(
|
$queue->subscribers = SubscribersTask::updateProcessedList(
|
||||||
@ -149,19 +158,18 @@ class SendingQueue {
|
|||||||
);
|
);
|
||||||
// log statistics
|
// log statistics
|
||||||
StatisticsNewslettersModel::createMultiple($statistics);
|
StatisticsNewslettersModel::createMultiple($statistics);
|
||||||
// keep track of sent items
|
// update the sent count
|
||||||
$this->mailer_task->updateMailerLog();
|
$this->mailer_task->updateSentCount();
|
||||||
$subscribers_to_process_count = count($queue->subscribers['to_process']);
|
|
||||||
}
|
|
||||||
$queue = $this->updateQueue($queue);
|
$queue = $this->updateQueue($queue);
|
||||||
if($subscribers_to_process_count) {
|
// enforce sending limit if there are still subscribers left to process
|
||||||
$this->mailer_task->checkSendingLimit();
|
if($queue->count_to_process) {
|
||||||
|
MailerLog::enforceSendingLimit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CronHelper::checkExecutionTimer($this->timer);
|
|
||||||
return $queue;
|
return $queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQueues() {
|
static function getRunningQueues() {
|
||||||
return SendingQueueModel::orderByDesc('priority')
|
return SendingQueueModel::orderByDesc('priority')
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->whereNull('status')
|
->whereNull('status')
|
||||||
@ -178,13 +186,6 @@ class SendingQueue {
|
|||||||
if(!$queue->count_to_process) {
|
if(!$queue->count_to_process) {
|
||||||
$queue->processed_at = current_time('mysql');
|
$queue->processed_at = current_time('mysql');
|
||||||
$queue->status = SendingQueueModel::STATUS_COMPLETED;
|
$queue->status = SendingQueueModel::STATUS_COMPLETED;
|
||||||
// if it's a standard or post notificaiton newsletter, update its status to sent
|
|
||||||
$newsletter = NewsletterModel::findOne($queue->newsletter_id);
|
|
||||||
if($newsletter->type === NewsletterModel::TYPE_STANDARD ||
|
|
||||||
$newsletter->type === NewsletterModel::TYPE_NOTIFICATION_HISTORY
|
|
||||||
) {
|
|
||||||
$newsletter->setStatus(NewsletterModel::STATUS_SENT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $queue->save();
|
return $queue->save();
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,14 @@
|
|||||||
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
||||||
|
|
||||||
use MailPoet\Mailer\Mailer as MailerFactory;
|
use MailPoet\Mailer\Mailer as MailerFactory;
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Mailer\MailerLog;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Mailer {
|
class Mailer {
|
||||||
public $mta_config;
|
|
||||||
public $mta_log;
|
|
||||||
public $mailer;
|
public $mailer;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
$this->mta_config = $this->getMailerConfig();
|
|
||||||
$this->mta_log = $this->getMailerLog();
|
|
||||||
$this->mailer = $this->configureMailer();
|
$this->mailer = $this->configureMailer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,33 +36,16 @@ class Mailer {
|
|||||||
return $this->mailer;
|
return $this->mailer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMailerConfig() {
|
|
||||||
$mta_config = Setting::getValue('mta');
|
|
||||||
if(!$mta_config) {
|
|
||||||
throw new \Exception(__('Mailer is not configured'));
|
|
||||||
}
|
|
||||||
return $mta_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMailerLog() {
|
function getMailerLog() {
|
||||||
$mta_log = Setting::getValue('mta_log');
|
return MailerLog::getMailerLog();
|
||||||
if(!$mta_log) {
|
|
||||||
$mta_log = array(
|
|
||||||
'sent' => 0,
|
|
||||||
'started' => time()
|
|
||||||
);
|
|
||||||
Setting::setValue('mta_log', $mta_log);
|
|
||||||
}
|
|
||||||
return $mta_log;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMailerLog() {
|
function updateSentCount() {
|
||||||
$this->mta_log['sent']++;
|
return MailerLog::incrementSentCount();
|
||||||
Setting::setValue('mta_log', $this->mta_log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProcessingMethod() {
|
function getProcessingMethod() {
|
||||||
return ($this->mta_config['method'] === 'MailPoet') ?
|
return ($this->mailer->mailer_config['method'] === MailerFactory::METHOD_MAILPOET) ?
|
||||||
'bulk' :
|
'bulk' :
|
||||||
'individual';
|
'individual';
|
||||||
}
|
}
|
||||||
@ -81,23 +60,4 @@ class Mailer {
|
|||||||
$prepared_subscribers
|
$prepared_subscribers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkSendingLimit() {
|
|
||||||
if($this->mta_config['method'] === 'MailPoet') return;
|
|
||||||
$frequency_interval = (int)$this->mta_config['frequency']['interval'] * 60;
|
|
||||||
$frequency_limit = (int)$this->mta_config['frequency']['emails'];
|
|
||||||
$elapsed_time = time() - (int)$this->mta_log['started'];
|
|
||||||
if($this->mta_log['sent'] === $frequency_limit &&
|
|
||||||
$elapsed_time <= $frequency_interval
|
|
||||||
) {
|
|
||||||
throw new \Exception(__('Sending frequency limit has been reached'));
|
|
||||||
}
|
|
||||||
if($elapsed_time > $frequency_interval) {
|
|
||||||
$this->mta_log = array(
|
|
||||||
'sent' => 0,
|
|
||||||
'started' => time()
|
|
||||||
);
|
|
||||||
Setting::setValue('mta_log', $this->mta_log);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -62,7 +62,7 @@ class Newsletter {
|
|||||||
return $newsletter;
|
return $newsletter;
|
||||||
}
|
}
|
||||||
|
|
||||||
function render($newsletter) {
|
function render(array $newsletter) {
|
||||||
$renderer = new Renderer($newsletter);
|
$renderer = new Renderer($newsletter);
|
||||||
$newsletter['rendered_body'] = $renderer->render();
|
$newsletter['rendered_body'] = $renderer->render();
|
||||||
return $newsletter;
|
return $newsletter;
|
||||||
@ -103,4 +103,12 @@ class Newsletter {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function markNewsletterAsSent($newsletter_id) {
|
||||||
|
$newsletter = NewsletterModel::findOne($newsletter_id);
|
||||||
|
// if it's a standard newsletter, update its status
|
||||||
|
if($newsletter->type === NewsletterModel::TYPE_STANDARD) {
|
||||||
|
$newsletter->setStatus(NewsletterModel::STATUS_SENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
|
||||||
|
|
||||||
use MailPoet\Models\Newsletter;
|
use MailPoet\Models\Newsletter as NewsletterModel;
|
||||||
use MailPoet\Models\NewsletterPost;
|
use MailPoet\Models\NewsletterPost;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
@ -19,7 +19,7 @@ class Posts {
|
|||||||
if(!count($matched_posts_ids)) {
|
if(!count($matched_posts_ids)) {
|
||||||
return $newsletter;
|
return $newsletter;
|
||||||
}
|
}
|
||||||
$newsletter_id = ($newsletter['type'] === Newsletter::TYPE_NOTIFICATION_HISTORY) ?
|
$newsletter_id = ($newsletter['type'] === NewsletterModel::TYPE_NOTIFICATION_HISTORY) ?
|
||||||
$newsletter['parent_id'] :
|
$newsletter['parent_id'] :
|
||||||
$newsletter['id'];
|
$newsletter['id'];
|
||||||
foreach($matched_posts_ids as $post_id) {
|
foreach($matched_posts_ids as $post_id) {
|
||||||
|
@ -8,13 +8,22 @@ require_once(ABSPATH . 'wp-includes/pluggable.php');
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Mailer {
|
class Mailer {
|
||||||
public $mailer;
|
public $mailer_config;
|
||||||
public $sender;
|
public $sender;
|
||||||
public $reply_to;
|
public $reply_to;
|
||||||
public $mailer_instance;
|
public $mailer_instance;
|
||||||
|
const MAILER_CONFIG = 'mta';
|
||||||
|
const SENDING_LIMIT_INTERVAL_MULTIPLIER = 60;
|
||||||
|
const METHOD_MAILPOET = 'MailPoet';
|
||||||
|
const METHOD_MAILGUN = 'MailGun';
|
||||||
|
const METHOD_ELASTICEMAIL = 'ElasticEmail';
|
||||||
|
const METHOD_AMAZONSES = 'AmazonSES';
|
||||||
|
const METHOD_SENDGRID = 'SendGrid';
|
||||||
|
const METHOD_PHPMAIL = 'PHPMail';
|
||||||
|
const METHOD_SMTP = 'SMTP';
|
||||||
|
|
||||||
function __construct($mailer = false, $sender = false, $reply_to = false) {
|
function __construct($mailer = false, $sender = false, $reply_to = false) {
|
||||||
$this->mailer = $this->getMailer($mailer);
|
$this->mailer_config = self::getMailerConfig($mailer);
|
||||||
$this->sender = $this->getSender($sender);
|
$this->sender = $this->getSender($sender);
|
||||||
$this->reply_to = $this->getReplyTo($reply_to);
|
$this->reply_to = $this->getReplyTo($reply_to);
|
||||||
$this->mailer_instance = $this->buildMailer();
|
$this->mailer_instance = $this->buildMailer();
|
||||||
@ -26,59 +35,59 @@ class Mailer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildMailer() {
|
function buildMailer() {
|
||||||
switch($this->mailer['method']) {
|
switch($this->mailer_config['method']) {
|
||||||
case 'AmazonSES':
|
case self::METHOD_AMAZONSES:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['region'],
|
$this->mailer_config['region'],
|
||||||
$this->mailer['access_key'],
|
$this->mailer_config['access_key'],
|
||||||
$this->mailer['secret_key'],
|
$this->mailer_config['secret_key'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'ElasticEmail':
|
case self::METHOD_ELASTICEMAIL:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['api_key'],
|
$this->mailer_config['api_key'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'MailGun':
|
case self::METHOD_MAILGUN:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['domain'],
|
$this->mailer_config['domain'],
|
||||||
$this->mailer['api_key'],
|
$this->mailer_config['api_key'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'MailPoet':
|
case self::METHOD_MAILPOET:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['mailpoet_api_key'],
|
$this->mailer_config['mailpoet_api_key'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'SendGrid':
|
case self::METHOD_SENDGRID:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['api_key'],
|
$this->mailer_config['api_key'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'PHPMail':
|
case self::METHOD_PHPMAIL:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'SMTP':
|
case self::METHOD_SMTP:
|
||||||
$mailer_instance = new $this->mailer['class'](
|
$mailer_instance = new $this->mailer_config['class'](
|
||||||
$this->mailer['host'],
|
$this->mailer_config['host'],
|
||||||
$this->mailer['port'],
|
$this->mailer_config['port'],
|
||||||
$this->mailer['authentication'],
|
$this->mailer_config['authentication'],
|
||||||
$this->mailer['login'],
|
$this->mailer_config['login'],
|
||||||
$this->mailer['password'],
|
$this->mailer_config['password'],
|
||||||
$this->mailer['encryption'],
|
$this->mailer_config['encryption'],
|
||||||
$this->sender,
|
$this->sender,
|
||||||
$this->reply_to
|
$this->reply_to
|
||||||
);
|
);
|
||||||
@ -89,12 +98,20 @@ class Mailer {
|
|||||||
return $mailer_instance;
|
return $mailer_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMailer($mailer = false) {
|
static function getMailerConfig($mailer = false) {
|
||||||
if(!$mailer) {
|
if(!$mailer) {
|
||||||
$mailer = Setting::getValue('mta');
|
$mailer = Setting::getValue(self::MAILER_CONFIG);
|
||||||
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured'));
|
if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured'));
|
||||||
}
|
}
|
||||||
|
if(empty($mailer['frequency'])) {
|
||||||
|
$default_settings = Setting::getDefaults();
|
||||||
|
$mailer['frequency'] = $default_settings['mta']['frequency'];
|
||||||
|
}
|
||||||
|
// add additional variables to the mailer object
|
||||||
$mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method'];
|
$mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method'];
|
||||||
|
$mailer['frequency_interval'] =
|
||||||
|
(int)$mailer['frequency']['interval'] * self::SENDING_LIMIT_INTERVAL_MULTIPLIER;
|
||||||
|
$mailer['frequency_limit'] = (int)$mailer['frequency']['emails'];
|
||||||
return $mailer;
|
return $mailer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
lib/Mailer/MailerLog.php
Normal file
60
lib/Mailer/MailerLog.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Mailer;
|
||||||
|
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class MailerLog {
|
||||||
|
const SETTING_NAME = 'mta_log';
|
||||||
|
|
||||||
|
static function getMailerLog() {
|
||||||
|
$mailer_log = Setting::getValue(self::SETTING_NAME);
|
||||||
|
if(!$mailer_log) {
|
||||||
|
$mailer_log = self::createMailerLog();
|
||||||
|
}
|
||||||
|
return $mailer_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function createMailerLog() {
|
||||||
|
$mailer_log = array(
|
||||||
|
'sent' => 0,
|
||||||
|
'started' => time()
|
||||||
|
);
|
||||||
|
Setting::setValue(self::SETTING_NAME, $mailer_log);
|
||||||
|
return $mailer_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function resetMailerLog() {
|
||||||
|
return self::createMailerLog();
|
||||||
|
}
|
||||||
|
|
||||||
|
static function updateMailerLog($mailer_log) {
|
||||||
|
Setting::setValue(self::SETTING_NAME, $mailer_log);
|
||||||
|
return $mailer_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function incrementSentCount($mailer_log = false) {
|
||||||
|
$mailer_log = ($mailer_log) ? $mailer_log : self::getMailerLog();
|
||||||
|
(int)$mailer_log['sent']++;
|
||||||
|
return self::updateMailerLog($mailer_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function isSendingLimitReached() {
|
||||||
|
$mailer_config = Mailer::getMailerConfig();
|
||||||
|
$mailer_log = self::getMailerLog();
|
||||||
|
$elapsed_time = time() - (int)$mailer_log['started'];
|
||||||
|
if($mailer_log['sent'] === $mailer_config['frequency_limit']) {
|
||||||
|
if($elapsed_time <= $mailer_config['frequency_interval']) return true;
|
||||||
|
// reset mailer log if enough time has passed since the limit was reached
|
||||||
|
self::resetMailerLog();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function enforceSendingLimit() {
|
||||||
|
if(self::isSendingLimitReached()) {
|
||||||
|
throw new \Exception(__('Sending frequency limit has been reached'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Models;
|
namespace MailPoet\Models;
|
||||||
|
|
||||||
|
use MailPoet\Cron\CronTrigger;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Setting extends Model {
|
class Setting extends Model {
|
||||||
@ -38,8 +40,8 @@ class Setting extends Model {
|
|||||||
'interval' => self::DEFAULT_SENDING_FREQUENCY_INTERVAL
|
'interval' => self::DEFAULT_SENDING_FREQUENCY_INTERVAL
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'task_scheduler' => array(
|
CronTrigger::SETTING_NAME => array(
|
||||||
'method' => 'WordPress'
|
'method' => CronTrigger::DEFAULT_METHOD
|
||||||
),
|
),
|
||||||
'signup_confirmation' => array(
|
'signup_confirmation' => array(
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
@ -160,4 +162,9 @@ class Setting extends Model {
|
|||||||
|
|
||||||
return $setting->save();
|
return $setting->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function deleteValue($value) {
|
||||||
|
$value = self::where('name', $value)->findOne();
|
||||||
|
return ($value) ? $value->delete() : false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -130,7 +130,7 @@ class Links {
|
|||||||
|
|
||||||
static function save(array $links, $newsletter_id, $queue_id) {
|
static function save(array $links, $newsletter_id, $queue_id) {
|
||||||
foreach($links as $link) {
|
foreach($links as $link) {
|
||||||
if(empty($link['hash'] || empty($link['url']))) continue;
|
if(empty($link['hash']) || empty($link['url'])) continue;
|
||||||
$newsletter_link = NewsletterLink::create();
|
$newsletter_link = NewsletterLink::create();
|
||||||
$newsletter_link->newsletter_id = $newsletter_id;
|
$newsletter_link->newsletter_id = $newsletter_id;
|
||||||
$newsletter_link->queue_id = $queue_id;
|
$newsletter_link->queue_id = $queue_id;
|
||||||
|
@ -66,7 +66,7 @@ class MailChimp {
|
|||||||
$connection = @fopen($url, 'r');
|
$connection = @fopen($url, 'r');
|
||||||
if(!$connection) {
|
if(!$connection) {
|
||||||
return $this->processError('connection');
|
return $this->processError('connection');
|
||||||
} else {
|
}
|
||||||
$i = 0;
|
$i = 0;
|
||||||
$header = array();
|
$header = array();
|
||||||
while(!feof($connection)) {
|
while(!feof($connection)) {
|
||||||
@ -90,20 +90,16 @@ class MailChimp {
|
|||||||
}
|
}
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$bytes_fetched += strlen($buffer);
|
$bytes_fetched += strlen($buffer);
|
||||||
if($bytes_fetched > $this->max_post_size) {
|
if($bytes_fetched > $this->max_post_size) {
|
||||||
return $this->processError('size');
|
return $this->processError('size');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose($connection);
|
fclose($connection);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!count($subscribers)) {
|
if(!count($subscribers)) {
|
||||||
return $this->processError('subscribers');
|
return $this->processError('subscribers');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
|
|
||||||
<% block translations %>
|
<% block translations %>
|
||||||
<%= localize({
|
<%= localize({
|
||||||
|
'daemonNotRunning': __('Daemon is not running'),
|
||||||
'daemonControlError': __('Cron daemon error'),
|
'daemonControlError': __('Cron daemon error'),
|
||||||
'loadingDaemonStatus': __('Loading daemon status...'),
|
'loadingDaemonStatus': __('Loading daemon status...'),
|
||||||
'cronDaemonIsRunning': __('Cron daemon is running.'),
|
'cronDaemonIsRunning': __('Cron daemon is running'),
|
||||||
'stop': __('Stop'),
|
|
||||||
'start': __('Start'),
|
|
||||||
'cronDaemonState': __('Cron is %$1s')
|
'cronDaemonState': __('Cron is %$1s')
|
||||||
}) %>
|
}) %>
|
||||||
<% endblock %>
|
<% endblock %>
|
||||||
|
@ -39,10 +39,9 @@
|
|||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="task_scheduler[method]"
|
name="cron_trigger[method]"
|
||||||
value="WordPress"
|
value="<%= cron_trigger.wordpress %>"
|
||||||
<% if not(settings.task_scheduler.method)
|
<% if (settings.cron_trigger.method == cron_trigger.wordpress) %>
|
||||||
or (settings.task_scheduler.method == 'WordPress') %>
|
|
||||||
checked="checked"
|
checked="checked"
|
||||||
<% endif %>
|
<% endif %>
|
||||||
/><%= __('Visitors to your website (recommended)') %>
|
/><%= __('Visitors to your website (recommended)') %>
|
||||||
@ -52,9 +51,9 @@
|
|||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="task_scheduler[method]"
|
name="cron_trigger[method]"
|
||||||
value="MailPoet"
|
value="<%= cron_trigger.mailpoet %>"
|
||||||
<% if (settings.task_scheduler.method == 'MailPoet') %>
|
<% if (settings.cron_trigger.method == cron_trigger.mailpoet) %>
|
||||||
checked="checked"
|
checked="checked"
|
||||||
<% endif %>
|
<% endif %>
|
||||||
/><%= __("MailPoet's own script. Doesn't work with [link]these hosts[/link].")
|
/><%= __("MailPoet's own script. Doesn't work with [link]these hosts[/link].")
|
||||||
|
Reference in New Issue
Block a user