Use separate scheduler for welcome emails

[MAILPOET-2321]
This commit is contained in:
Pavel Dohnal
2019-08-28 14:06:49 +02:00
committed by M. Shull
parent 10e374ca60
commit c90a2e41a1
11 changed files with 437 additions and 337 deletions

View File

@ -12,7 +12,7 @@ use MailPoet\Models\Form;
use MailPoet\Models\StatisticsForms;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Segments\BulkAction;
use MailPoet\Segments\SubscribersListings;
use MailPoet\Settings\SettingsController;
@ -343,7 +343,8 @@ class Subscribers extends APIEndpoint {
}
if (!empty($new_segments)) {
Scheduler::scheduleSubscriberWelcomeNotification($subscriber->id, $new_segments);
$scheduler = new WelcomeScheduler();
$scheduler->scheduleSubscriberWelcomeNotification($subscriber->id, $new_segments);
}
return $this->successResponse(

View File

@ -6,7 +6,7 @@ use MailPoet\Models\CustomField;
use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Subscribers\RequiredCustomFieldValidator;
use MailPoet\Subscribers\ConfirmationEmailMailer;
use MailPoet\Subscribers\NewSubscriberNotificationMailer;
@ -30,16 +30,21 @@ class API {
/** @var ApiDataSanitizer */
private $custom_fields_data_sanitizer;
/** @var WelcomeScheduler */
private $welcome_scheduler;
public function __construct(
NewSubscriberNotificationMailer $new_subscriber_notification_mailer,
ConfirmationEmailMailer $confirmation_email_mailer,
RequiredCustomFieldValidator $required_custom_field_validator,
ApiDataSanitizer $custom_fields_data_sanitizer
ApiDataSanitizer $custom_fields_data_sanitizer,
WelcomeScheduler $welcome_scheduler
) {
$this->new_subscriber_notification_mailer = $new_subscriber_notification_mailer;
$this->confirmation_email_mailer = $confirmation_email_mailer;
$this->required_custom_field_validator = $required_custom_field_validator;
$this->custom_fields_data_sanitizer = $custom_fields_data_sanitizer;
$this->welcome_scheduler = $welcome_scheduler;
}
function getSubscriberFields() {
@ -361,7 +366,7 @@ class API {
}
protected function _scheduleWelcomeNotification(Subscriber $subscriber, array $segments) {
$result = Scheduler::scheduleSubscriberWelcomeNotification($subscriber->id, $segments);
$result = $this->welcome_scheduler->scheduleSubscriberWelcomeNotification($subscriber->id, $segments);
if (is_array($result)) {
foreach ($result as $queue) {
if ($queue instanceof Sending && $queue->getErrors()) {

View File

@ -183,6 +183,7 @@ class ContainerConfigurator implements IContainerConfigurator {
// Newsletter
$container->autowire(\MailPoet\Newsletter\AutomatedLatestContent::class)->setPublic(true);
$container->autowire(\MailPoet\Newsletter\NewslettersRepository::class);
$container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class);
// Util
$container->autowire(\MailPoet\Util\Cookies::class);
$container->autowire(\MailPoet\Util\Url::class)->setPublic(true);

View File

@ -59,20 +59,6 @@ class Scheduler {
}
}
static function scheduleSubscriberWelcomeNotification($subscriber_id, $segments) {
$newsletters = self::getNewsletters(Newsletter::TYPE_WELCOME);
if (empty($newsletters)) return false;
$result = [];
foreach ($newsletters as $newsletter) {
if ($newsletter->event === 'segment' &&
in_array($newsletter->segment, $segments)
) {
$result[] = self::createWelcomeNotificationSendingTask($newsletter, $subscriber_id);
}
}
return $result;
}
static function scheduleAutomaticEmail($group, $event, $scheduling_condition = false, $subscriber_id = false, $meta = false) {
$newsletters = self::getNewsletters(Newsletter::TYPE_AUTOMATIC, $group);
if (empty($newsletters)) return false;
@ -144,52 +130,6 @@ class Scheduler {
}
}
static function scheduleWPUserWelcomeNotification(
$subscriber_id,
$wp_user,
$old_user_data = false
) {
$newsletters = self::getNewsletters(Newsletter::TYPE_WELCOME);
if (empty($newsletters)) return false;
foreach ($newsletters as $newsletter) {
if ($newsletter->event === 'user') {
if (!empty($old_user_data['roles'])) {
// do not schedule welcome newsletter if roles have not changed
$old_role = $old_user_data['roles'];
$new_role = $wp_user['roles'];
if ($newsletter->role === self::WORDPRESS_ALL_ROLES ||
!array_diff($old_role, $new_role)
) {
continue;
}
}
if ($newsletter->role === self::WORDPRESS_ALL_ROLES ||
in_array($newsletter->role, $wp_user['roles'])
) {
self::createWelcomeNotificationSendingTask($newsletter, $subscriber_id);
}
}
}
}
static function createWelcomeNotificationSendingTask($newsletter, $subscriber_id) {
$previously_scheduled_notification = SendingQueue::joinWithSubscribers()
->where('queues.newsletter_id', $newsletter->id)
->where('subscribers.subscriber_id', $subscriber_id)
->findOne();
if (!empty($previously_scheduled_notification)) return;
$sending_task = SendingTask::create();
$sending_task->newsletter_id = $newsletter->id;
$sending_task->setSubscribers([$subscriber_id]);
$sending_task->status = SendingQueue::STATUS_SCHEDULED;
$sending_task->priority = SendingQueue::PRIORITY_HIGH;
$sending_task->scheduled_at = self::getScheduledTimeWithDelay(
$newsletter->afterTimeType,
$newsletter->afterTimeNumber
);
return $sending_task->save();
}
static function createAutomaticEmailSendingTask($newsletter, $subscriber_id, $meta) {
$sending_task = SendingTask::create();
$sending_task->newsletter_id = $newsletter->id;

View File

@ -0,0 +1,71 @@
<?php
namespace MailPoet\Newsletter\Scheduler;
use MailPoet\Models\Newsletter;
use MailPoet\Models\SendingQueue;
use MailPoet\Tasks\Sending as SendingTask;
class WelcomeScheduler {
function scheduleSubscriberWelcomeNotification($subscriber_id, $segments) {
$newsletters = Scheduler::getNewsletters(Newsletter::TYPE_WELCOME);
if (empty($newsletters)) return false;
$result = [];
foreach ($newsletters as $newsletter) {
if ($newsletter->event === 'segment' &&
in_array($newsletter->segment, $segments)
) {
$result[] = $this->createWelcomeNotificationSendingTask($newsletter, $subscriber_id);
}
}
return $result;
}
function scheduleWPUserWelcomeNotification(
$subscriber_id,
$wp_user,
$old_user_data = false
) {
$newsletters = Scheduler::getNewsletters(Newsletter::TYPE_WELCOME);
if (empty($newsletters)) return false;
foreach ($newsletters as $newsletter) {
if ($newsletter->event === 'user') {
if (!empty($old_user_data['roles'])) {
// do not schedule welcome newsletter if roles have not changed
$old_role = $old_user_data['roles'];
$new_role = $wp_user['roles'];
if ($newsletter->role === Scheduler::WORDPRESS_ALL_ROLES ||
!array_diff($old_role, $new_role)
) {
continue;
}
}
if ($newsletter->role === Scheduler::WORDPRESS_ALL_ROLES ||
in_array($newsletter->role, $wp_user['roles'])
) {
$this->createWelcomeNotificationSendingTask($newsletter, $subscriber_id);
}
}
}
}
function createWelcomeNotificationSendingTask($newsletter, $subscriber_id) {
$previously_scheduled_notification = SendingQueue::joinWithSubscribers()
->where('queues.newsletter_id', $newsletter->id)
->where('subscribers.subscriber_id', $subscriber_id)
->findOne();
if (!empty($previously_scheduled_notification)) return;
$sending_task = SendingTask::create();
$sending_task->newsletter_id = $newsletter->id;
$sending_task->setSubscribers([$subscriber_id]);
$sending_task->status = SendingQueue::STATUS_SCHEDULED;
$sending_task->priority = SendingQueue::PRIORITY_HIGH;
$sending_task->scheduled_at = Scheduler::getScheduledTimeWithDelay(
$newsletter->afterTimeType,
$newsletter->afterTimeNumber
);
return $sending_task->save();
}
}

View File

@ -7,7 +7,7 @@ use MailPoet\Models\StatisticsOpens;
use MailPoet\Models\Subscriber;
use MailPoet\Models\Segment;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscribers\Source;
@ -73,7 +73,8 @@ class WP {
// welcome email
if ($schedule_welcome_newsletter === true) {
Scheduler::scheduleWPUserWelcomeNotification(
$scheduler = new WelcomeScheduler();
$scheduler->scheduleWPUserWelcomeNotification(
$subscriber->id,
(array)$wp_user,
(array)$old_wp_user_data

View File

@ -7,6 +7,7 @@ use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Settings\SettingsController;
use MailPoet\Util\Helpers;
@ -24,17 +25,22 @@ class SubscriberActions {
/** @var BulkActionFactory */
private $bulk_action_factory;
/** @var WelcomeScheduler */
private $welcome_scheduler;
public function __construct(
SettingsController $settings,
NewSubscriberNotificationMailer $new_subscriber_notification_mailer,
ConfirmationEmailMailer $confirmation_email_mailer,
BulkActionFactory $bulk_action_factory
BulkActionFactory $bulk_action_factory,
WelcomeScheduler $welcome_scheduler
) {
$this->settings = $settings;
$this->new_subscriber_notification_mailer = $new_subscriber_notification_mailer;
$this->confirmation_email_mailer = $confirmation_email_mailer;
$this->bulk_action_factory = $bulk_action_factory;
$this->bulk_action_factory->registerAction('\MailPoet\Models\Subscriber', 'bulkSendConfirmationEmail', $this);
$this->welcome_scheduler = $welcome_scheduler;
}
function subscribe($subscriber_data = [], $segment_ids = []) {
@ -91,7 +97,7 @@ class SubscriberActions {
if ($subscriber->status === Subscriber::STATUS_SUBSCRIBED) {
$this->new_subscriber_notification_mailer->send($subscriber, Segment::whereIn('id', $segment_ids)->findMany());
Scheduler::scheduleSubscriberWelcomeNotification(
$this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$subscriber->id,
$segment_ids
);

View File

@ -2,12 +2,11 @@
namespace MailPoet\Subscription;
use MailPoet\Models\Form as FormModel;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Models\CustomField;
use MailPoet\Models\Segment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscribers\NewSubscriberNotificationMailer;
use MailPoet\Util\Helpers;
@ -42,18 +41,23 @@ class Pages {
/** @var CaptchaRenderer */
private $captcha_renderer;
/** @var WelcomeScheduler */
private $welcome_scheduler;
function __construct(
NewSubscriberNotificationMailer $new_subscriber_notification_sender,
WPFunctions $wp,
SettingsController $settings,
UrlHelper $url_helper,
CaptchaRenderer $captcha_renderer
CaptchaRenderer $captcha_renderer,
WelcomeScheduler $welcome_scheduler
) {
$this->wp = $wp;
$this->new_subscriber_notification_sender = $new_subscriber_notification_sender;
$this->settings = $settings;
$this->url_helper = $url_helper;
$this->captcha_renderer = $captcha_renderer;
$this->welcome_scheduler = $welcome_scheduler;
}
function init($action = false, $data = [], $init_shortcodes = false, $init_page_filters = false) {
@ -122,7 +126,7 @@ class Pages {
// send welcome notification
$subscriber_segments = $this->subscriber->segments()->findMany();
if ($subscriber_segments) {
Scheduler::scheduleSubscriberWelcomeNotification(
$this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$this->subscriber->id,
array_map(function ($segment) {
return $segment->get('id');

View File

@ -2,7 +2,6 @@
namespace MailPoet\Test\API\MP;
use AspectMock\Test as Mock;
use Codeception\Util\Fixtures;
use Codeception\Stub;
use Codeception\Stub\Expected;
@ -12,6 +11,7 @@ use MailPoet\Models\ScheduledTask;
use MailPoet\Models\Segment;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\Subscriber;
use MailPoet\Newsletter\Scheduler\WelcomeScheduler;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscribers\ConfirmationEmailMailer;
use MailPoet\Subscribers\NewSubscriberNotificationMailer;
@ -26,7 +26,8 @@ class APITest extends \MailPoetTest {
Stub::makeEmpty(NewSubscriberNotificationMailer::class, ['send']),
Stub::makeEmpty(ConfirmationEmailMailer::class, ['sendConfirmationEmail']),
Stub::makeEmptyExcept(RequiredCustomFieldValidator::class, 'validate'),
Stub::makeEmpty(ApiDataSanitizer::class)
Stub::makeEmpty(ApiDataSanitizer::class),
Stub::makeEmpty(WelcomeScheduler::class)
);
}
@ -280,7 +281,8 @@ class APITest extends \MailPoetTest {
$notificationMailer,
$this->makeEmpty(ConfirmationEmailMailer::class),
$this->makeEmpty(RequiredCustomFieldValidator::class),
$this->makeEmpty(ApiDataSanitizer::class)
$this->makeEmpty(ApiDataSanitizer::class),
Stub::makeEmpty(WelcomeScheduler::class)
);
$API->subscribeToLists($subscriber->email, $segments, ['send_confirmation_email' => false, 'skip_subscriber_notification' => true]);
@ -291,7 +293,8 @@ class APITest extends \MailPoetTest {
$notificationMailer,
$this->makeEmpty(ConfirmationEmailMailer::class),
$this->makeEmpty(RequiredCustomFieldValidator::class),
$this->makeEmpty(ApiDataSanitizer::class)
$this->makeEmpty(ApiDataSanitizer::class),
Stub::makeEmpty(WelcomeScheduler::class)
);
$API->subscribeToLists($subscriber->email, $segments, ['send_confirmation_email' => false, 'skip_subscriber_notification' => false]);
}
@ -532,7 +535,7 @@ class APITest extends \MailPoetTest {
$task->type = 'sending';
$task->setError("Big Error");
$sendingStub = Sending::create($task, SendingQueue::create());
Mock::double('MailPoet\Newsletter\Scheduler\Scheduler', [
$welcome_scheduler = $this->make('MailPoet\Newsletter\Scheduler\WelcomeScheduler', [
'scheduleSubscriberWelcomeNotification' => [$sendingStub],
]);
$segment = Segment::createOrUpdate(
@ -541,7 +544,13 @@ class APITest extends \MailPoetTest {
'type' => Segment::TYPE_DEFAULT,
]
);
$API = $this->getApi();
$API = new \MailPoet\API\MP\v1\API(
Stub::makeEmpty(NewSubscriberNotificationMailer::class, ['send']),
Stub::makeEmpty(ConfirmationEmailMailer::class, ['sendConfirmationEmail']),
Stub::makeEmptyExcept(RequiredCustomFieldValidator::class, 'validate'),
Stub::makeEmpty(ApiDataSanitizer::class),
$welcome_scheduler
);
$subscriber = [
'email' => 'test@example.com',
];
@ -857,7 +866,6 @@ class APITest extends \MailPoetTest {
}
function _after() {
Mock::clean();
\ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
\ORM::raw_execute('TRUNCATE ' . CustomField::$_table);
\ORM::raw_execute('TRUNCATE ' . Segment::$_table);

View File

@ -117,102 +117,6 @@ class SchedulerTest extends \MailPoetTest {
expect(SendingQueue::findMany())->count(2);
}
function testItDoesNotCreateDuplicateWelcomeNotificationSendingTasks() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
'afterTimeType' => 'hours',
];
$existing_subscriber = 678;
$existing_queue = SendingTask::create();
$existing_queue->newsletter_id = $newsletter->id;
$existing_queue->setSubscribers([$existing_subscriber]);
$existing_queue->save();
// queue is not scheduled
Scheduler::createWelcomeNotificationSendingTask($newsletter, $existing_subscriber);
expect(SendingQueue::findMany())->count(1);
// queue is not scheduled
Scheduler::createWelcomeNotificationSendingTask($newsletter, 1);
expect(SendingQueue::findMany())->count(2);
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInHours() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled delivery in 2 hours
$newsletter->afterTimeType = 'hours';
Scheduler::createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addHours(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInDays() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for delivery in 2 days
$newsletter->afterTimeType = 'days';
Scheduler::createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDays(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInWeeks() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for delivery in 2 weeks
$newsletter->afterTimeType = 'weeks';
Scheduler::createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addWeeks(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendImmediately() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for immediate delivery
$newsletter->afterTimeType = null;
Scheduler::createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->format('Y-m-d H:i'));
}
function tesIttDoesNotSchedulePostNotificationWhenNotificationWasAlreadySentForPost() {
$newsletter = $this->_createNewsletter();
$newsletter_post = NewsletterPost::create();
@ -249,167 +153,6 @@ class SchedulerTest extends \MailPoetTest {
expect($queue->scheduled_at)->startsWith($next_run_date->format('Y-m-d 05:00'));
}
function testItDoesNotSchedulesSubscriberWelcomeNotificationWhenSubscriberIsNotInSegment() {
// do not schedule when subscriber is not in segment
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
Scheduler::scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItSchedulesSubscriberWelcomeNotification() {
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
$this->_createNewsletterOptions(
$newsletter->id,
Newsletter::TYPE_WELCOME,
[
'event' => 'segment',
'segment' => 2,
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
// queue is created and scheduled for delivery one day later
$result = Scheduler::scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = [
3,
2,
1,
]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
expect($result[0]->id())->equals($queue->id());
}
function itDoesNotScheduleAnythingWhenNewsletterDoesNotExist() {
// post notification is not scheduled
expect(Scheduler::schedulePostNotification($post_id = 10))->false();
// subscriber welcome notification is not scheduled
$result = Scheduler::scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
expect($result)->false();
// WP user welcome notification is not scheduled
$result = Scheduler::scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
expect($result)->false();
}
function testItDoesNotScheduleWPUserWelcomeNotificationWhenRoleHasNotChanged() {
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
$this->_createNewsletterOptions(
$newsletter->id,
Newsletter::TYPE_WELCOME,
[
'event' => 'user',
'role' => 'editor',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
Scheduler::scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['editor']],
$old_user_data = ['roles' => ['editor']]
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItDoesNotScheduleWPUserWelcomeNotificationWhenUserRoleDoesNotMatch() {
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
$this->_createNewsletterOptions(
$newsletter->id,
Newsletter::TYPE_WELCOME,
[
'event' => 'user',
'role' => 'editor',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
Scheduler::scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItSchedulesWPUserWelcomeNotificationWhenUserRolesMatches() {
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
$this->_createNewsletterOptions(
$newsletter->id,
Newsletter::TYPE_WELCOME,
[
'event' => 'user',
'role' => 'administrator',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
Scheduler::scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
// queue is created and scheduled for delivery one day later
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
}
function testItSchedulesWPUserWelcomeNotificationWhenUserHasAnyRole() {
$newsletter = $this->_createNewsletter(Newsletter::TYPE_WELCOME);
$this->_createNewsletterOptions(
$newsletter->id,
Newsletter::TYPE_WELCOME,
[
'event' => 'user',
'role' => Scheduler::WORDPRESS_ALL_ROLES,
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
Scheduler::scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
// queue is created and scheduled for delivery one day later
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
}
function testItProcessesPostNotificationScheduledForDailyDelivery() {
$newsletter_option_field = NewsletterOptionField::create();
$newsletter_option_field->name = 'schedule';

View File

@ -0,0 +1,320 @@
<?php
namespace MailPoet\Newsletter\Scheduler;
use Carbon\Carbon;
use MailPoet\Models\Newsletter;
use MailPoet\Models\NewsletterOption;
use MailPoet\Models\NewsletterOptionField;
use MailPoet\Models\NewsletterPost;
use MailPoet\Models\ScheduledTask;
use MailPoet\Models\ScheduledTaskSubscriber;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\Subscriber;
use MailPoet\Tasks\Sending as SendingTask;
class WelcomeTest extends \MailPoetTest {
/** @var WelcomeScheduler */
private $welcome_scheduler;
function _before() {
parent::_before();
$this->welcome_scheduler = new WelcomeScheduler;
}
function testItDoesNotCreateDuplicateWelcomeNotificationSendingTasks() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
'afterTimeType' => 'hours',
];
$existing_subscriber = 678;
$existing_queue = SendingTask::create();
$existing_queue->newsletter_id = $newsletter->id;
$existing_queue->setSubscribers([$existing_subscriber]);
$existing_queue->save();
// queue is not scheduled
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, $existing_subscriber);
expect(SendingQueue::findMany())->count(1);
// queue is not scheduled
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, 1);
expect(SendingQueue::findMany())->count(2);
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInHours() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled delivery in 2 hours
$newsletter->afterTimeType = 'hours';
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addHours(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInDays() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for delivery in 2 days
$newsletter->afterTimeType = 'days';
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDays(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendInWeeks() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for delivery in 2 weeks
$newsletter->afterTimeType = 'weeks';
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)
->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addWeeks(2)->format('Y-m-d H:i'));
}
function testItCreatesWelcomeNotificationSendingTaskScheduledToSendImmediately() {
$newsletter = (object)[
'id' => 1,
'afterTimeNumber' => 2,
];
// queue is scheduled for immediate delivery
$newsletter->afterTimeType = null;
$this->welcome_scheduler->createWelcomeNotificationSendingTask($newsletter, $subscriber_id = 1);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId(1)->findOne();
expect($queue->id)->greaterOrEquals(1);
expect($queue->priority)->equals(SendingQueue::PRIORITY_HIGH);
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->format('Y-m-d H:i'));
}
function testItDoesNotSchedulesSubscriberWelcomeNotificationWhenSubscriberIsNotInSegment() {
// do not schedule when subscriber is not in segment
$newsletter = $this->_createNewsletter();
$this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItSchedulesSubscriberWelcomeNotification() {
$newsletter = $this->_createNewsletter();
$this->_createNewsletterOptions(
$newsletter->id,
[
'event' => 'segment',
'segment' => 2,
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
// queue is created and scheduled for delivery one day later
$result = $this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = [
3,
2,
1,
]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
expect($result[0]->id())->equals($queue->id());
}
function itDoesNotScheduleAnythingWhenNewsletterDoesNotExist() {
// subscriber welcome notification is not scheduled
$result = $this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
expect($result)->false();
// WP user welcome notification is not scheduled
$result = $this->welcome_scheduler->scheduleSubscriberWelcomeNotification(
$subscriber_id = 10,
$segments = []
);
expect($result)->false();
}
function testItDoesNotScheduleWPUserWelcomeNotificationWhenRoleHasNotChanged() {
$newsletter = $this->_createNewsletter();
$this->_createNewsletterOptions(
$newsletter->id,
[
'event' => 'user',
'role' => 'editor',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
$this->welcome_scheduler->scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['editor']],
$old_user_data = ['roles' => ['editor']]
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItDoesNotScheduleWPUserWelcomeNotificationWhenUserRoleDoesNotMatch() {
$newsletter = $this->_createNewsletter();
$this->_createNewsletterOptions(
$newsletter->id,
[
'event' => 'user',
'role' => 'editor',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
$this->welcome_scheduler->scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
// queue is not created
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect($queue)->false();
}
function testItSchedulesWPUserWelcomeNotificationWhenUserRolesMatches() {
$newsletter = $this->_createNewsletter();
$this->_createNewsletterOptions(
$newsletter->id,
[
'event' => 'user',
'role' => 'administrator',
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
$this->welcome_scheduler->scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
// queue is created and scheduled for delivery one day later
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
}
function testItSchedulesWPUserWelcomeNotificationWhenUserHasAnyRole() {
$newsletter = $this->_createNewsletter();
$this->_createNewsletterOptions(
$newsletter->id,
[
'event' => 'user',
'role' => Scheduler::WORDPRESS_ALL_ROLES,
'afterTimeType' => 'days',
'afterTimeNumber' => 1,
]
);
$this->welcome_scheduler->scheduleWPUserWelcomeNotification(
$subscriber_id = 10,
$wp_user = ['roles' => ['administrator']]
);
$current_time = Carbon::createFromTimestamp(current_time('timestamp'));
Carbon::setTestNow($current_time); // mock carbon to return current time
// queue is created and scheduled for delivery one day later
$queue = SendingQueue::findTaskByNewsletterId($newsletter->id)
->findOne();
expect(Carbon::parse($queue->scheduled_at)->format('Y-m-d H:i'))
->equals($current_time->addDay()->format('Y-m-d H:i'));
}
function _createNewsletter(
$status = Newsletter::STATUS_ACTIVE
) {
$newsletter = Newsletter::create();
$newsletter->type = Newsletter::TYPE_WELCOME;
$newsletter->status = $status;
$newsletter->save();
expect($newsletter->getErrors())->false();
return $newsletter;
}
function _createNewsletterOptions($newsletter_id, $options) {
foreach ($options as $option => $value) {
$newsletter_option_field = NewsletterOptionField::where('name', $option)->findOne();
if (!$newsletter_option_field) {
$newsletter_option_field = NewsletterOptionField::create();
$newsletter_option_field->name = $option;
$newsletter_option_field->newsletter_type = Newsletter::TYPE_WELCOME;
$newsletter_option_field->save();
expect($newsletter_option_field->getErrors())->false();
}
$newsletter_option = NewsletterOption::create();
$newsletter_option->option_field_id = $newsletter_option_field->id;
$newsletter_option->newsletter_id = $newsletter_id;
$newsletter_option->value = $value;
$newsletter_option->save();
expect($newsletter_option->getErrors())->false();
}
}
function _after() {
Carbon::setTestNow();
\ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);
\ORM::raw_execute('TRUNCATE ' . NewsletterOption::$_table);
\ORM::raw_execute('TRUNCATE ' . NewsletterOptionField::$_table);
\ORM::raw_execute('TRUNCATE ' . NewsletterPost::$_table);
\ORM::raw_execute('TRUNCATE ' . ScheduledTask::$_table);
\ORM::raw_execute('TRUNCATE ' . ScheduledTaskSubscriber::$_table);
\ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
\ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
}
}