diff --git a/assets/js/src/cron.jsx b/assets/js/src/cron.jsx
index 0691489352..1f3dcb3183 100644
--- a/assets/js/src/cron.jsx
+++ b/assets/js/src/cron.jsx
@@ -21,8 +21,6 @@ define(
action: 'getStatus'
})
.done(function(response) {
- jQuery('.button-primary')
- .removeClass('disabled');
if(response.status !== undefined) {
this.setState(response);
} else {
@@ -36,55 +34,26 @@ define(
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() {
- if(this.state.status === 'loading') {
- return(
{MailPoet.I18n.t('loadingDaemonStatus')}
);
- }
switch(this.state.status) {
- case 'started':
+ case 'loading':
return(
);
- break;
- case 'starting':
- case 'stopping':
+ case false:
+ return(
+
+ {MailPoet.I18n.t('daemonNotRunning')}
+
+ );
+ default:
return(
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
);
- break;
- case 'stopped':
- return(
-
- );
- break;
}
}
});
@@ -97,4 +66,4 @@ define(
container
);
}
-});
+});
\ No newline at end of file
diff --git a/lib/API/Endpoints/Cron.php b/lib/API/Endpoints/Cron.php
index a2ee3941b4..700a8ce5ff 100644
--- a/lib/API/Endpoints/Cron.php
+++ b/lib/API/Endpoints/Cron.php
@@ -2,35 +2,15 @@
namespace MailPoet\API\Endpoints;
use MailPoet\Cron\CronHelper;
-use MailPoet\Cron\Supervisor;
use MailPoet\Models\Setting;
if(!defined('ABSPATH')) exit;
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() {
- $daemon = Setting::where('name', 'cron_daemon')
- ->findOne();
+ $daemon = Setting::getValue(CronHelper::DAEMON_SETTING);
return ($daemon) ?
- unserialize($daemon->value) :
- false;
+ $daemon :
+ array('status' => false);
}
}
\ No newline at end of file
diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php
index 77bcd7e5a9..01b47b9ba9 100644
--- a/lib/Config/Initializer.php
+++ b/lib/Config/Initializer.php
@@ -2,7 +2,7 @@
namespace MailPoet\Config;
use MailPoet\Models;
-use MailPoet\Cron\Supervisor;
+use MailPoet\Cron\CronTrigger;
use MailPoet\Router;
use MailPoet\API;
use MailPoet\WP\Notice as WPNotice;
@@ -107,7 +107,7 @@ class Initializer {
$this->setupShortcodes();
$this->setupHooks();
$this->setupImages();
- $this->runQueueSupervisor();
+ $this->setupCronTrigger();
$this->plugin_initialized = true;
} catch(\Exception $e) {
@@ -192,14 +192,9 @@ class Initializer {
$router->init();
}
- function runQueueSupervisor() {
- if(php_sapi_name() === 'cli') return;
- try {
- $supervisor = new Supervisor();
- $supervisor->checkDaemon();
- } catch(\Exception $e) {
- // Prevent Daemon exceptions from breaking out and breaking UI
- }
+ function setupCronTrigger() {
+ $cron_trigger = new CronTrigger();
+ $cron_trigger->init();
}
function setupImages() {
diff --git a/lib/Config/Menu.php b/lib/Config/Menu.php
index 88850296b1..9aef4eff9b 100644
--- a/lib/Config/Menu.php
+++ b/lib/Config/Menu.php
@@ -1,6 +1,7 @@
$settings,
'segments' => Segment::getPublic()->findArray(),
+ 'cron_trigger' => CronTrigger::getAvailableMethods(),
'pages' => Pages::getAll(),
'flags' => $flags,
'current_user' => wp_get_current_user(),
@@ -433,4 +435,4 @@ class Menu {
? (int)$listing_per_page
: Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
}
-}
+}
\ No newline at end of file
diff --git a/lib/Config/Populator.php b/lib/Config/Populator.php
index 65ae2bd54a..9d7231337c 100644
--- a/lib/Config/Populator.php
+++ b/lib/Config/Populator.php
@@ -10,6 +10,7 @@ use MailPoet\Config\PopulatorData\Templates\PostNotificationsBlank1Column;
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank1Column;
use MailPoet\Config\PopulatorData\Templates\WelcomeBlank12Column;
use MailPoet\Config\PopulatorData\Templates\SimpleText;
+use MailPoet\Cron\CronTrigger;
use \MailPoet\Models\Segment;
use \MailPoet\Segments\WP;
use \MailPoet\Models\Setting;
@@ -74,6 +75,13 @@ class Populator {
private function createDefaultSettings() {
$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
$sender = array(
'name' => $current_user->display_name,
diff --git a/lib/Cron/CronHelper.php b/lib/Cron/CronHelper.php
index d78d5b122c..91a6566e82 100644
--- a/lib/Cron/CronHelper.php
+++ b/lib/Cron/CronHelper.php
@@ -1,9 +1,9 @@
false,
+ 'sslverify' => false,
'timeout' => $timeout,
'user-agent' => 'MailPoet (www.mailpoet.com) Cron'
);
@@ -70,7 +87,7 @@ class CronHelper {
throw new \Exception(__('Site URL is unreachable.'));
}
- static function checkExecutionTimer($timer) {
+ static function enforceExecutionLimit($timer) {
$elapsed_time = microtime(true) - $timer;
if($elapsed_time >= self::DAEMON_EXECUTION_LIMIT) {
throw new \Exception(__('Maximum execution time has been reached.'));
diff --git a/lib/Cron/CronTrigger.php b/lib/Cron/CronTrigger.php
new file mode 100644
index 0000000000..9d5f88aec8
--- /dev/null
+++ b/lib/Cron/CronTrigger.php
@@ -0,0 +1,41 @@
+ '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');
+ }
+}
\ No newline at end of file
diff --git a/lib/Cron/Daemon.php b/lib/Cron/Daemon.php
index 3cdcdd0696..aaeada8b45 100644
--- a/lib/Cron/Daemon.php
+++ b/lib/Cron/Daemon.php
@@ -78,15 +78,16 @@ class Daemon {
}
}
- function abortWithError($message) {
- exit('[mailpoet_cron_error:' . base64_encode($message) . ']');
- }
-
function callSelf() {
CronHelper::accessDaemon($this->token, self::REQUEST_TIMEOUT);
$this->terminateRequest();
}
+ function abortWithError($message) {
+ status_header(404, $message);
+ exit;
+ }
+
function terminateRequest() {
exit;
}
diff --git a/lib/Cron/Supervisor.php b/lib/Cron/Supervisor.php
index 9490bd159a..92d51ec2f9 100644
--- a/lib/Cron/Supervisor.php
+++ b/lib/Cron/Supervisor.php
@@ -6,87 +6,35 @@ if(!defined('ABSPATH')) exit;
class Supervisor {
public $daemon;
public $token;
- public $force_run;
- function __construct($force_run = false) {
- $this->daemon = CronHelper::getDaemon();
+ function __construct() {
$this->token = CronHelper::createToken();
- $this->force_run = $force_run;
+ $this->daemon = $this->getDaemon();
}
function checkDaemon() {
$daemon = $this->daemon;
- if(!$daemon) {
- $daemon = CronHelper::createDaemon($this->token);
- return $this->runDaemon($daemon);
+ $execution_timeout_exceeded =
+ (time() - (int)$daemon['updated_at']) > CronHelper::DAEMON_EXECUTION_TIMEOUT;
+ if($execution_timeout_exceeded) {
+ CronHelper::restartDaemon($this->token);
+ return $this->runDaemon();
}
- // 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 $daemon;
}
function runDaemon() {
- $request = CronHelper::accessDaemon($this->token);
- preg_match('/\[(mailpoet_cron_error:.*?)\]/i', $request, $status);
+ CronHelper::accessDaemon($this->token);
$daemon = CronHelper::getDaemon();
- if(!empty($status) || !$daemon) {
- if(!$daemon) {
- $message = __('Daemon failed to run.');
- } else {
- list(, $message) = explode(':', $status[0]);
- $message = base64_decode($message);
- }
- return $this->formatResultMessage(
- false,
- $message
- );
- }
- return $this->formatDaemonStatusMessage($daemon['status']);
+ return $daemon;
}
- 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;
+ function getDaemon() {
+ $daemon = CronHelper::getDaemon();
+ if(!$daemon) {
+ CronHelper::createDaemon($this->token);
+ return $this->runDaemon();
}
- return $formattedResult;
+ return $daemon;
}
-}
+}
\ No newline at end of file
diff --git a/lib/Cron/Triggers/MailPoet.php b/lib/Cron/Triggers/MailPoet.php
new file mode 100644
index 0000000000..ab9d8cf01a
--- /dev/null
+++ b/lib/Cron/Triggers/MailPoet.php
@@ -0,0 +1,13 @@
+checkDaemon();
+ }
+}
\ No newline at end of file
diff --git a/lib/Cron/Triggers/WordPress.php b/lib/Cron/Triggers/WordPress.php
new file mode 100644
index 0000000000..5885cfa9fc
--- /dev/null
+++ b/lib/Cron/Triggers/WordPress.php
@@ -0,0 +1,31 @@
+timer = ($timer) ? $timer : microtime(true);
- CronHelper::checkExecutionTimer($this->timer);
+ // abort if execution limit is reached
+ CronHelper::enforceExecutionLimit($this->timer);
}
function process() {
- $scheduled_queues = SendingQueue::where('status', 'scheduled')
- ->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
- ->findMany();
+ $scheduled_queues = self::getScheduledQueues();
if(!count($scheduled_queues)) return;
foreach($scheduled_queues as $i => $queue) {
$newsletter = Newsletter::filter('filterWithOptions')
@@ -40,7 +39,7 @@ class Scheduler {
} elseif($newsletter->type === 'standard') {
$this->processScheduledStandardNewsletter($newsletter, $queue);
}
- CronHelper::checkExecutionTimer($this->timer);
+ CronHelper::enforceExecutionLimit($this->timer);
}
}
@@ -185,4 +184,10 @@ class Scheduler {
$notification_history :
false;
}
+
+ static function getScheduledQueues() {
+ return SendingQueue::where('status', 'scheduled')
+ ->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
+ ->findMany();
+ }
}
\ No newline at end of file
diff --git a/lib/Cron/Workers/SendingQueue/SendingQueue.php b/lib/Cron/Workers/SendingQueue/SendingQueue.php
index 25fc18551a..55fdbc889a 100644
--- a/lib/Cron/Workers/SendingQueue/SendingQueue.php
+++ b/lib/Cron/Workers/SendingQueue/SendingQueue.php
@@ -5,7 +5,7 @@ use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
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\StatisticsNewsletters as StatisticsNewslettersModel;
use MailPoet\Models\Subscriber as SubscriberModel;
@@ -23,11 +23,14 @@ class SendingQueue {
$this->mailer_task = new MailerTask();
$this->newsletter_task = new NewsletterTask();
$this->timer = ($timer) ? $timer : microtime(true);
+ // abort if execution or sending limit are reached
+ CronHelper::enforceExecutionLimit($this->timer);
}
function process() {
- $this->mailer_task->checkSendingLimit();
- foreach($this->getQueues() as $queue) {
+ foreach(self::getRunningQueues() as $queue) {
+ // abort if sending limit is reached
+ MailerLog::enforceSendingLimit();
// get and pre-process newsletter (render, replace shortcodes/links, etc.)
$newsletter = $this->newsletter_task->getAndPreProcess($queue->asArray());
if(!$newsletter) {
@@ -67,6 +70,11 @@ class SendingQueue {
$newsletter,
$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,
$queue->subscribers
);
+ $queue = $this->updateQueue($queue);
} else {
// update processed/to process list
$queue->subscribers = SubscribersTask::updateProcessedList(
@@ -149,19 +158,18 @@ class SendingQueue {
);
// log statistics
StatisticsNewslettersModel::createMultiple($statistics);
- // keep track of sent items
- $this->mailer_task->updateMailerLog();
- $subscribers_to_process_count = count($queue->subscribers['to_process']);
+ // update the sent count
+ $this->mailer_task->updateSentCount();
+ $queue = $this->updateQueue($queue);
+ // enforce sending limit if there are still subscribers left to process
+ if($queue->count_to_process) {
+ MailerLog::enforceSendingLimit();
+ }
}
- $queue = $this->updateQueue($queue);
- if($subscribers_to_process_count) {
- $this->mailer_task->checkSendingLimit();
- }
- CronHelper::checkExecutionTimer($this->timer);
return $queue;
}
- function getQueues() {
+ static function getRunningQueues() {
return SendingQueueModel::orderByDesc('priority')
->whereNull('deleted_at')
->whereNull('status')
@@ -178,13 +186,6 @@ class SendingQueue {
if(!$queue->count_to_process) {
$queue->processed_at = current_time('mysql');
$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();
}
diff --git a/lib/Cron/Workers/SendingQueue/Tasks/Mailer.php b/lib/Cron/Workers/SendingQueue/Tasks/Mailer.php
index 9563ff9361..c2a105166d 100644
--- a/lib/Cron/Workers/SendingQueue/Tasks/Mailer.php
+++ b/lib/Cron/Workers/SendingQueue/Tasks/Mailer.php
@@ -2,18 +2,14 @@
namespace MailPoet\Cron\Workers\SendingQueue\Tasks;
use MailPoet\Mailer\Mailer as MailerFactory;
-use MailPoet\Models\Setting;
+use MailPoet\Mailer\MailerLog;
if(!defined('ABSPATH')) exit;
class Mailer {
- public $mta_config;
- public $mta_log;
public $mailer;
function __construct() {
- $this->mta_config = $this->getMailerConfig();
- $this->mta_log = $this->getMailerLog();
$this->mailer = $this->configureMailer();
}
@@ -40,33 +36,16 @@ class 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() {
- $mta_log = Setting::getValue('mta_log');
- if(!$mta_log) {
- $mta_log = array(
- 'sent' => 0,
- 'started' => time()
- );
- Setting::setValue('mta_log', $mta_log);
- }
- return $mta_log;
+ return MailerLog::getMailerLog();
}
- function updateMailerLog() {
- $this->mta_log['sent']++;
- Setting::setValue('mta_log', $this->mta_log);
+ function updateSentCount() {
+ return MailerLog::incrementSentCount();
}
function getProcessingMethod() {
- return ($this->mta_config['method'] === 'MailPoet') ?
+ return ($this->mailer->mailer_config['method'] === MailerFactory::METHOD_MAILPOET) ?
'bulk' :
'individual';
}
@@ -81,23 +60,4 @@ class Mailer {
$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);
- }
- }
-}
+}
\ No newline at end of file
diff --git a/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php b/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php
index 6944812bf5..7f34771315 100644
--- a/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php
+++ b/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php
@@ -62,7 +62,7 @@ class Newsletter {
return $newsletter;
}
- function render($newsletter) {
+ function render(array $newsletter) {
$renderer = new Renderer($newsletter);
$newsletter['rendered_body'] = $renderer->render();
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);
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/Cron/Workers/SendingQueue/Tasks/Posts.php b/lib/Cron/Workers/SendingQueue/Tasks/Posts.php
index a61f60aeb2..6cbd102c71 100644
--- a/lib/Cron/Workers/SendingQueue/Tasks/Posts.php
+++ b/lib/Cron/Workers/SendingQueue/Tasks/Posts.php
@@ -1,7 +1,7 @@
mailer = $this->getMailer($mailer);
+ $this->mailer_config = self::getMailerConfig($mailer);
$this->sender = $this->getSender($sender);
$this->reply_to = $this->getReplyTo($reply_to);
$this->mailer_instance = $this->buildMailer();
@@ -26,59 +35,59 @@ class Mailer {
}
function buildMailer() {
- switch($this->mailer['method']) {
- case 'AmazonSES':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['region'],
- $this->mailer['access_key'],
- $this->mailer['secret_key'],
+ switch($this->mailer_config['method']) {
+ case self::METHOD_AMAZONSES:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['region'],
+ $this->mailer_config['access_key'],
+ $this->mailer_config['secret_key'],
$this->sender,
$this->reply_to
);
break;
- case 'ElasticEmail':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['api_key'],
+ case self::METHOD_ELASTICEMAIL:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['api_key'],
$this->sender,
$this->reply_to
);
break;
- case 'MailGun':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['domain'],
- $this->mailer['api_key'],
+ case self::METHOD_MAILGUN:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['domain'],
+ $this->mailer_config['api_key'],
$this->sender,
$this->reply_to
);
break;
- case 'MailPoet':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['mailpoet_api_key'],
+ case self::METHOD_MAILPOET:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['mailpoet_api_key'],
$this->sender,
$this->reply_to
);
break;
- case 'SendGrid':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['api_key'],
+ case self::METHOD_SENDGRID:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['api_key'],
$this->sender,
$this->reply_to
);
break;
- case 'PHPMail':
- $mailer_instance = new $this->mailer['class'](
+ case self::METHOD_PHPMAIL:
+ $mailer_instance = new $this->mailer_config['class'](
$this->sender,
$this->reply_to
);
break;
- case 'SMTP':
- $mailer_instance = new $this->mailer['class'](
- $this->mailer['host'],
- $this->mailer['port'],
- $this->mailer['authentication'],
- $this->mailer['login'],
- $this->mailer['password'],
- $this->mailer['encryption'],
+ case self::METHOD_SMTP:
+ $mailer_instance = new $this->mailer_config['class'](
+ $this->mailer_config['host'],
+ $this->mailer_config['port'],
+ $this->mailer_config['authentication'],
+ $this->mailer_config['login'],
+ $this->mailer_config['password'],
+ $this->mailer_config['encryption'],
$this->sender,
$this->reply_to
);
@@ -89,12 +98,20 @@ class Mailer {
return $mailer_instance;
}
- function getMailer($mailer = false) {
+ static function getMailerConfig($mailer = false) {
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(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['frequency_interval'] =
+ (int)$mailer['frequency']['interval'] * self::SENDING_LIMIT_INTERVAL_MULTIPLIER;
+ $mailer['frequency_limit'] = (int)$mailer['frequency']['emails'];
return $mailer;
}
@@ -140,4 +157,4 @@ class Mailer {
$subscriber = trim(preg_replace('!\s\s+!', ' ', $subscriber));
return $subscriber;
}
-}
+}
\ No newline at end of file
diff --git a/lib/Mailer/MailerLog.php b/lib/Mailer/MailerLog.php
new file mode 100644
index 0000000000..4e273fd524
--- /dev/null
+++ b/lib/Mailer/MailerLog.php
@@ -0,0 +1,60 @@
+ 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'));
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/Models/Setting.php b/lib/Models/Setting.php
index e94f084149..bf19a03e2d 100644
--- a/lib/Models/Setting.php
+++ b/lib/Models/Setting.php
@@ -1,6 +1,8 @@
self::DEFAULT_SENDING_FREQUENCY_INTERVAL
)
),
- 'task_scheduler' => array(
- 'method' => 'WordPress'
+ CronTrigger::SETTING_NAME => array(
+ 'method' => CronTrigger::DEFAULT_METHOD
),
'signup_confirmation' => array(
'enabled' => true,
@@ -160,4 +162,9 @@ class Setting extends Model {
return $setting->save();
}
-}
+
+ public static function deleteValue($value) {
+ $value = self::where('name', $value)->findOne();
+ return ($value) ? $value->delete() : false;
+ }
+}
\ No newline at end of file
diff --git a/lib/Newsletter/Links/Links.php b/lib/Newsletter/Links/Links.php
index 912f44aa8a..13ca2a7704 100644
--- a/lib/Newsletter/Links/Links.php
+++ b/lib/Newsletter/Links/Links.php
@@ -130,7 +130,7 @@ class Links {
static function save(array $links, $newsletter_id, $queue_id) {
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->newsletter_id = $newsletter_id;
$newsletter_link->queue_id = $queue_id;
diff --git a/lib/Subscribers/ImportExport/Import/MailChimp.php b/lib/Subscribers/ImportExport/Import/MailChimp.php
index bae4d9877c..1aae5c4377 100644
--- a/lib/Subscribers/ImportExport/Import/MailChimp.php
+++ b/lib/Subscribers/ImportExport/Import/MailChimp.php
@@ -66,44 +66,40 @@ class MailChimp {
$connection = @fopen($url, 'r');
if(!$connection) {
return $this->processError('connection');
- } else {
- $i = 0;
- $header = array();
- while(!feof($connection)) {
- $buffer = fgets($connection, 4096);
- if(trim($buffer) !== '') {
- $obj = json_decode($buffer);
- if($i === 0) {
- $header = $obj;
- if(is_object($header) && isset($header->error)) {
- return $this->processError('lists');
- }
- if(!isset($header_hash)) {
- $header_hash = md5(implode(',', $header));
- } else {
- if(md5(implode(',', $header) !== $header_hash)) {
- return $this->processError('headers');
- }
- }
- } else {
- $subscribers[] = $obj;
- }
- $i++;
- }
-
- $bytes_fetched += strlen($buffer);
- if($bytes_fetched > $this->max_post_size) {
- return $this->processError('size');
-
- }
- }
- fclose($connection);
}
+ $i = 0;
+ $header = array();
+ while(!feof($connection)) {
+ $buffer = fgets($connection, 4096);
+ if(trim($buffer) !== '') {
+ $obj = json_decode($buffer);
+ if($i === 0) {
+ $header = $obj;
+ if(is_object($header) && isset($header->error)) {
+ return $this->processError('lists');
+ }
+ if(!isset($header_hash)) {
+ $header_hash = md5(implode(',', $header));
+ } else {
+ if(md5(implode(',', $header) !== $header_hash)) {
+ return $this->processError('headers');
+ }
+ }
+ } else {
+ $subscribers[] = $obj;
+ }
+ $i++;
+ }
+ $bytes_fetched += strlen($buffer);
+ if($bytes_fetched > $this->max_post_size) {
+ return $this->processError('size');
+ }
+ }
+ fclose($connection);
}
if(!count($subscribers)) {
return $this->processError('subscribers');
-
}
return array(
@@ -130,7 +126,7 @@ class MailChimp {
}
function processError($error) {
- switch ($error) {
+ switch($error) {
case 'API':
$errorMessage = __('Invalid API Key.');
break;
diff --git a/views/cron.html b/views/cron.html
index 22660da728..4b964c3248 100644
--- a/views/cron.html
+++ b/views/cron.html
@@ -6,11 +6,10 @@
<% block translations %>
<%= localize({
+ 'daemonNotRunning': __('Daemon is not running'),
'daemonControlError': __('Cron daemon error'),
'loadingDaemonStatus': __('Loading daemon status...'),
- 'cronDaemonIsRunning': __('Cron daemon is running.'),
- 'stop': __('Stop'),
- 'start': __('Start'),
+ 'cronDaemonIsRunning': __('Cron daemon is running'),
'cronDaemonState': __('Cron is %$1s')
}) %>
<% endblock %>
diff --git a/views/settings/advanced.html b/views/settings/advanced.html
index 6e1e555f11..35852c3efc 100644
--- a/views/settings/advanced.html
+++ b/views/settings/advanced.html
@@ -39,10 +39,9 @@