Reschedules past due scheduled queues when reactivating notification
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\API\JSON\v1;
|
namespace MailPoet\API\JSON\v1;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use MailPoet\API\JSON\Endpoint as APIEndpoint;
|
use MailPoet\API\JSON\Endpoint as APIEndpoint;
|
||||||
use MailPoet\API\JSON\Error as APIError;
|
use MailPoet\API\JSON\Error as APIError;
|
||||||
use MailPoet\Listing;
|
use MailPoet\Listing;
|
||||||
@ -134,7 +135,7 @@ class Newsletters extends APIEndpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
$id = (isset($data['id'])) ? (int)$data['id'] : false;
|
||||||
$newsletter = Newsletter::findOne($id);
|
$newsletter = Newsletter::filter('filterWithOptions')->findOne($id);
|
||||||
|
|
||||||
if($newsletter === false) {
|
if($newsletter === false) {
|
||||||
return $this->errorResponse(array(
|
return $this->errorResponse(array(
|
||||||
@ -147,11 +148,22 @@ class Newsletters extends APIEndpoint {
|
|||||||
|
|
||||||
if(!empty($errors)) {
|
if(!empty($errors)) {
|
||||||
return $this->errorResponse($errors);
|
return $this->errorResponse($errors);
|
||||||
} else {
|
|
||||||
return $this->successResponse(
|
|
||||||
Newsletter::findOne($newsletter->id)->asArray()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there are past due notifications, reschedule them for the next send date
|
||||||
|
if($newsletter->type === Newsletter::TYPE_NOTIFICATION && $status === Newsletter::STATUS_ACTIVE) {
|
||||||
|
$next_run_date = Scheduler::getNextRunDate($newsletter->schedule);
|
||||||
|
$newsletter->queue()
|
||||||
|
->whereLte('scheduled_at', Carbon::createFromTimestamp(current_time('timestamp')))
|
||||||
|
->where('status', SendingQueue::STATUS_SCHEDULED)
|
||||||
|
->findResultSet()
|
||||||
|
->set('scheduled_at', $next_run_date)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->successResponse(
|
||||||
|
Newsletter::findOne($newsletter->id)->asArray()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function restore($data = array()) {
|
function restore($data = array()) {
|
||||||
|
@ -176,6 +176,18 @@ class Scheduler {
|
|||||||
return $next_run_date;
|
return $next_run_date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function getPreviousRunDate($schedule, $from_timestamp = false) {
|
||||||
|
$from_timestamp = ($from_timestamp) ? $from_timestamp : current_time('timestamp');
|
||||||
|
try {
|
||||||
|
$schedule = \Cron\CronExpression::factory($schedule);
|
||||||
|
$previous_run_date = $schedule->getPreviousRunDate(Carbon::createFromTimestamp($from_timestamp))
|
||||||
|
->format('Y-m-d H:i:s');
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
$previous_run_date = false;
|
||||||
|
}
|
||||||
|
return $previous_run_date;
|
||||||
|
}
|
||||||
|
|
||||||
static function getNewsletters($type) {
|
static function getNewsletters($type) {
|
||||||
return Newsletter::getPublished()
|
return Newsletter::getPublished()
|
||||||
->filter('filterType', $type)
|
->filter('filterType', $type)
|
||||||
|
@ -8,6 +8,7 @@ use Helper\WordPressHooks as WPHooksHelper;
|
|||||||
use MailPoet\API\JSON\v1\Newsletters;
|
use MailPoet\API\JSON\v1\Newsletters;
|
||||||
use MailPoet\API\JSON\Response as APIResponse;
|
use MailPoet\API\JSON\Response as APIResponse;
|
||||||
use MailPoet\Models\Newsletter;
|
use MailPoet\Models\Newsletter;
|
||||||
|
use MailPoet\Models\NewsletterOption;
|
||||||
use MailPoet\Models\NewsletterOptionField;
|
use MailPoet\Models\NewsletterOptionField;
|
||||||
use MailPoet\Models\NewsletterSegment;
|
use MailPoet\Models\NewsletterSegment;
|
||||||
use MailPoet\Models\Segment;
|
use MailPoet\Models\Segment;
|
||||||
@ -140,7 +141,6 @@ class NewslettersTest extends \MailPoetTest {
|
|||||||
expect(WPHooksHelper::isActionDone($hook_name))->true();
|
expect(WPHooksHelper::isActionDone($hook_name))->true();
|
||||||
expect(WPHooksHelper::getActionDone($hook_name)[0] instanceof Newsletter)->true();
|
expect(WPHooksHelper::getActionDone($hook_name)[0] instanceof Newsletter)->true();
|
||||||
|
|
||||||
|
|
||||||
$invalid_data = array(
|
$invalid_data = array(
|
||||||
'subject' => 'Missing newsletter type'
|
'subject' => 'Missing newsletter type'
|
||||||
);
|
);
|
||||||
@ -357,6 +357,51 @@ class NewslettersTest extends \MailPoetTest {
|
|||||||
->equals('This newsletter does not exist.');
|
->equals('This newsletter does not exist.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testItReschedulesPastDuePostNotificationsWhenStatusIsSetBackToActive() {
|
||||||
|
$newsletter_option_field = NewsletterOptionField::create();
|
||||||
|
$newsletter_option_field->name = 'schedule';
|
||||||
|
$newsletter_option_field->newsletter_type = Newsletter::TYPE_NOTIFICATION;
|
||||||
|
$newsletter_option_field->save();
|
||||||
|
$schedule = sprintf('0 %d * * *', Carbon::createFromTimestamp(current_time('timestamp'))->hour); // every day at current hour
|
||||||
|
$random_future_date = Carbon::createFromTimestamp(current_time('timestamp'))->addDays(10)->format('Y-m-d H:i:s'); // 10 days from now
|
||||||
|
$newsletter_option = NewsletterOption::createOrUpdate(
|
||||||
|
array(
|
||||||
|
'newsletter_id' => $this->post_notification->id,
|
||||||
|
'option_field_id' => $newsletter_option_field->id,
|
||||||
|
'value' => $schedule
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$sending_queue_1 = SendingQueue::create();
|
||||||
|
$sending_queue_1->newsletter_id = $this->post_notification->id;
|
||||||
|
$sending_queue_1->scheduled_at = Scheduler::getPreviousRunDate($schedule);
|
||||||
|
$sending_queue_1->status = SendingQueue::STATUS_SCHEDULED;
|
||||||
|
$sending_queue_1->save();
|
||||||
|
$sending_queue_2 = SendingQueue::create();
|
||||||
|
$sending_queue_2->newsletter_id = $this->post_notification->id;
|
||||||
|
$sending_queue_2->scheduled_at = $random_future_date;
|
||||||
|
$sending_queue_2->status = SendingQueue::STATUS_SCHEDULED;
|
||||||
|
$sending_queue_2->save();
|
||||||
|
$sending_queue_3 = SendingQueue::create();
|
||||||
|
$sending_queue_3->newsletter_id = $this->post_notification->id;
|
||||||
|
$sending_queue_3->scheduled_at = Scheduler::getPreviousRunDate($schedule);
|
||||||
|
$sending_queue_3->save();
|
||||||
|
|
||||||
|
$router = new Newsletters();
|
||||||
|
$response = $router->setStatus(
|
||||||
|
array(
|
||||||
|
'id' => $this->post_notification->id,
|
||||||
|
'status' => Newsletter::STATUS_ACTIVE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$sending_queues = SendingQueue::findMany();
|
||||||
|
// previously scheduled notification is rescheduled for future date
|
||||||
|
expect($sending_queues[0]->scheduled_at)->equals(Scheduler::getNextRunDate($schedule));
|
||||||
|
// future scheduled notifications are left intact
|
||||||
|
expect($sending_queues[1]->scheduled_at)->equals($random_future_date);
|
||||||
|
// previously unscheduled (e.g., sent/sending) notifications are left intact
|
||||||
|
expect($sending_queues[2]->scheduled_at)->equals(Scheduler::getPreviousRunDate($schedule));
|
||||||
|
}
|
||||||
|
|
||||||
function testItCanRestoreANewsletter() {
|
function testItCanRestoreANewsletter() {
|
||||||
$this->newsletter->trash();
|
$this->newsletter->trash();
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class SchedulerTest extends \MailPoetTest {
|
|||||||
function testItGetsActiveNewslettersFilteredByType() {
|
function testItGetsActiveNewslettersFilteredByType() {
|
||||||
$newsletter = $this->_createNewsletter($type = Newsletter::TYPE_WELCOME);
|
$newsletter = $this->_createNewsletter($type = Newsletter::TYPE_WELCOME);
|
||||||
|
|
||||||
// no newsletters wtih type "notification" should be found
|
// no newsletters with type "notification" should be found
|
||||||
expect(Scheduler::getNewsletters(Newsletter::TYPE_NOTIFICATION))->isEmpty();
|
expect(Scheduler::getNewsletters(Newsletter::TYPE_NOTIFICATION))->isEmpty();
|
||||||
|
|
||||||
// one newsletter with type "welcome" should be found
|
// one newsletter with type "welcome" should be found
|
||||||
@ -41,6 +41,15 @@ class SchedulerTest extends \MailPoetTest {
|
|||||||
expect(Scheduler::getNextRunDate('invalid CRON expression'))->false();
|
expect(Scheduler::getNextRunDate('invalid CRON expression'))->false();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testItCanGetPreviousRunDate() {
|
||||||
|
// it accepts cron syntax and returns previous run date
|
||||||
|
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||||
|
expect(Scheduler::getPreviousRunDate('* * * * *'))
|
||||||
|
->equals($current_time->subMinute()->format('Y-m-d H:i:00'));
|
||||||
|
// when invalid CRON expression is used, false response is returned
|
||||||
|
expect(Scheduler::getPreviousRunDate('invalid CRON expression'))->false();
|
||||||
|
}
|
||||||
|
|
||||||
function testItFormatsDatetimeString() {
|
function testItFormatsDatetimeString() {
|
||||||
expect(Scheduler::formatDatetimeString('April 20, 2016 4pm'))
|
expect(Scheduler::formatDatetimeString('April 20, 2016 4pm'))
|
||||||
->equals('2016-04-20 16:00:00');
|
->equals('2016-04-20 16:00:00');
|
||||||
|
Reference in New Issue
Block a user