diff --git a/lib/API/JSON/v1/Subscribers.php b/lib/API/JSON/v1/Subscribers.php index c515932c38..48423400e3 100644 --- a/lib/API/JSON/v1/Subscribers.php +++ b/lib/API/JSON/v1/Subscribers.php @@ -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( diff --git a/lib/API/MP/v1/API.php b/lib/API/MP/v1/API.php index a8a9b452e9..243b2ee9d0 100644 --- a/lib/API/MP/v1/API.php +++ b/lib/API/MP/v1/API.php @@ -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()) { diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index e1ec836371..35728b3be5 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -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); diff --git a/lib/Newsletter/Scheduler/Scheduler.php b/lib/Newsletter/Scheduler/Scheduler.php index 3c83c89a29..413c1277dc 100644 --- a/lib/Newsletter/Scheduler/Scheduler.php +++ b/lib/Newsletter/Scheduler/Scheduler.php @@ -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; diff --git a/lib/Newsletter/Scheduler/WelcomeScheduler.php b/lib/Newsletter/Scheduler/WelcomeScheduler.php new file mode 100644 index 0000000000..ac6a313a92 --- /dev/null +++ b/lib/Newsletter/Scheduler/WelcomeScheduler.php @@ -0,0 +1,71 @@ +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(); + } + +} diff --git a/lib/Segments/WP.php b/lib/Segments/WP.php index f5aca9b710..2babfe940e 100644 --- a/lib/Segments/WP.php +++ b/lib/Segments/WP.php @@ -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 diff --git a/lib/Subscribers/SubscriberActions.php b/lib/Subscribers/SubscriberActions.php index 5601488c69..aa23a7f461 100644 --- a/lib/Subscribers/SubscriberActions.php +++ b/lib/Subscribers/SubscriberActions.php @@ -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 ); diff --git a/lib/Subscription/Pages.php b/lib/Subscription/Pages.php index 54d02a0f49..2de5e398d0 100644 --- a/lib/Subscription/Pages.php +++ b/lib/Subscription/Pages.php @@ -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'); diff --git a/tests/integration/API/MP/APITest.php b/tests/integration/API/MP/APITest.php index fa41c77c84..df33ef89cb 100644 --- a/tests/integration/API/MP/APITest.php +++ b/tests/integration/API/MP/APITest.php @@ -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); diff --git a/tests/integration/Newsletter/Scheduler/SchedulerTest.php b/tests/integration/Newsletter/Scheduler/SchedulerTest.php index 183759f3b8..1df9e29c67 100644 --- a/tests/integration/Newsletter/Scheduler/SchedulerTest.php +++ b/tests/integration/Newsletter/Scheduler/SchedulerTest.php @@ -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'; diff --git a/tests/integration/Newsletter/Scheduler/WelcomeTest.php b/tests/integration/Newsletter/Scheduler/WelcomeTest.php new file mode 100644 index 0000000000..1d459dbbf2 --- /dev/null +++ b/tests/integration/Newsletter/Scheduler/WelcomeTest.php @@ -0,0 +1,320 @@ +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); + } + +}