settings = SettingsController::getInstance(); $this->settings->set('cron_trigger', [ 'method' => 'none', ]); $future = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp', true) + 600); $this->addScheduledTask(Beamer::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); $this->addScheduledTask(SubscribersStatsReport::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); $this->wordpressTrigger = $this->diContainer->get(WordPress::class); } public function testItDoesNotRunIfRunIntervalIsNotElapsed() { $runInterval = 10; WPFunctions::get()->addFilter('mailpoet_cron_trigger_wordpress_run_interval', function () use ($runInterval) { return $runInterval; }); $currentTime = time(); $this->settings->set(WordPress::LAST_RUN_AT_SETTING, $currentTime); $this->addQueue(SendingQueueEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->run())->equals(false); verify($this->settings->get(WordPress::LAST_RUN_AT_SETTING))->equals($currentTime); WPFunctions::get()->removeAllFilters('mailpoet_cron_trigger_wordpress_run_interval'); } public function testItRunsIfRunIntervalIsElapsed() { $runInterval = 10; WPFunctions::get()->addFilter('mailpoet_cron_trigger_wordpress_run_interval', function () use ($runInterval) { return $runInterval; }); $timeInThePast = (time() - $runInterval) - 1; $this->settings->set(WordPress::LAST_RUN_AT_SETTING, $timeInThePast); $this->addQueue(SendingQueueEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->run())->notEmpty(); verify($this->settings->get(WordPress::LAST_RUN_AT_SETTING))->greaterThan($timeInThePast); WPFunctions::get()->removeAllFilters('mailpoet_cron_trigger_wordpress_run_interval'); } public function testItCanResetRunInterval() { $currentTime = time(); $this->settings->set(WordPress::LAST_RUN_AT_SETTING, $currentTime); $this->addQueue(SendingQueueEntity::STATUS_SCHEDULED); WordPress::resetRunInterval(); verify($this->settings->get(WordPress::LAST_RUN_AT_SETTING))->empty(); verify($this->wordpressTrigger->run())->notEmpty(); } public function testItRequiresScheduledQueuesToExecute() { verify($this->wordpressTrigger->checkExecutionRequirements())->false(); $this->addQueue(SendingQueueEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItRequiresRunningQueuesToExecute() { verify($this->wordpressTrigger->checkExecutionRequirements())->false(); // status of 'null' indicates that queue is running $this->addQueue(null); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItFailsExecutionRequiremenetsCheckWhenQueueStatusIsCompleted() { verify($this->wordpressTrigger->checkExecutionRequirements())->false(); $this->addQueue(ScheduledTaskEntity::STATUS_COMPLETED); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItRequiresSendingLimitNotToBeReachedToExecute() { $this->addQueue(null); $this->addMTAConfigAndLog(null); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); $this->addMTAConfigAndLog(1); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItRequiresSendingNotToBePausedToExecute() { $this->addQueue(null); $this->addMTAConfigAndLog(null); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); $this->addMTAConfigAndLog(0, MailerLog::STATUS_PAUSED); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItDoesNotExecuteWhenWeAreWaitingForRetry() { $this->addQueue(null); $this->addMTAConfigAndLog(null); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); $this->addMTAConfigAndLog(null, null, time() - 1); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); $this->addMTAConfigAndLog(null, null, time() + 120); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItExecutesWhenAuthorizedEmailsCheckIsDue() { $this->addScheduledTask(AuthorizedSendingEmailsCheck::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenBeamerTaskIsDue() { $this->addScheduledTask(Beamer::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenBounceIsActive() { $this->settings->set(Mailer::MAILER_CONFIG_SETTING_NAME, [ 'method' => Mailer::METHOD_MAILPOET, 'frequency' => [ 'emails' => SettingsController::DEFAULT_SENDING_FREQUENCY_EMAILS, 'interval' => SettingsController::DEFAULT_SENDING_FREQUENCY_INTERVAL, ], ]); $this->addScheduledTask(BounceWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItCanDeactivateRunningDaemon() { $this->settings->set(CronHelper::DAEMON_SETTING, ['status' => CronHelper::DAEMON_STATUS_ACTIVE]); verify($this->settings->get(CronHelper::DAEMON_SETTING)['status'])->equals(CronHelper::DAEMON_STATUS_ACTIVE); $this->wordpressTrigger->stop(); verify($this->settings->get(CronHelper::DAEMON_SETTING)['status'])->equals(CronHelper::DAEMON_STATUS_INACTIVE); } public function testItRunsWhenExecutionRequirementsAreMet() { // status of 'null' indicates that queue is running $this->addQueue(null); // check that cron daemon does not exist verify($this->settings->get(CronHelper::DAEMON_SETTING))->null(); $this->wordpressTrigger->run(); verify($this->settings->get(CronHelper::DAEMON_SETTING))->notNull(); } public function testItDeactivatesCronDaemonWhenExecutionRequirementsAreNotMet() { $this->settings->set(CronHelper::DAEMON_SETTING, ['status' => CronHelper::DAEMON_STATUS_ACTIVE]); verify($this->settings->get(CronHelper::DAEMON_SETTING)['status'])->equals(CronHelper::DAEMON_STATUS_ACTIVE); $this->wordpressTrigger->run(); verify($this->settings->get(CronHelper::DAEMON_SETTING)['status'])->equals(CronHelper::DAEMON_STATUS_INACTIVE); } public function testItDoesNotTriggerCronWhenFutureStatsReportIsScheduled() { $future = Carbon::now()->addHour(); $statsJobType = SubscribersStatsReport::TASK_TYPE; verify($this->settings->get(CronHelper::DAEMON_SETTING))->null(); $scheduledTaskTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName(); $this->entityManager->getConnection()->executeStatement("DELETE FROM $scheduledTaskTable WHERE type = '$statsJobType';"); $this->settings->set(Bridge::API_KEY_SETTING_NAME, 'asdfgh'); $this->settings->set(Bridge::API_KEY_STATE_SETTING_NAME, ['state' => 'valid']); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); $this->addScheduledTask(SubscribersStatsReport::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItDoesNotTriggerCronForStatsReportIfThereIsNoValidKey() { $statsJobType = SubscribersStatsReport::TASK_TYPE; verify($this->settings->get(CronHelper::DAEMON_SETTING))->null(); $scheduledTaskTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName(); $this->entityManager->getConnection()->executeStatement("DELETE FROM $scheduledTaskTable WHERE type = '$statsJobType';"); $this->settings->set(Bridge::API_KEY_SETTING_NAME, 'somekey'); $this->settings->set(Bridge::API_KEY_STATE_SETTING_NAME, ['state' => 'invalid']); $this->settings->set(Bridge::PREMIUM_KEY_SETTING_NAME, null); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } public function testItTriggersCronIfThereIsValidKeyAndNoStatsReportJobScheduled() { $statsJobType = SubscribersStatsReport::TASK_TYPE; verify($this->settings->get(CronHelper::DAEMON_SETTING))->null(); $scheduledTaskTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName(); $this->entityManager->getConnection()->executeStatement("DELETE FROM $scheduledTaskTable WHERE type = '$statsJobType';"); $this->settings->set(Bridge::API_KEY_SETTING_NAME, 'somekey'); $this->settings->set(Bridge::API_KEY_STATE_SETTING_NAME, ['state' => 'valid']); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenStatsNotificationsWorkerTaskIsDue() { $this->addScheduledTask(StatsNotificationsWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenAutomatedEmailsTaskIsDue() { $this->addScheduledTask(AutomatedEmails::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenSubscribersEmailCountTaskIsDue() { $this->addScheduledTask(SubscribersEmailCount::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenInactiveSubscribersTaskIsDue() { $this->addScheduledTask(InactiveSubscribers::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenUnsubscribeTokensTaskIsDue() { $this->addScheduledTask(UnsubscribeTokens::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenSubscriberLinkTokensTaskIsDue() { $this->addScheduledTask(SubscriberLinkTokens::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenWooCommerceSyncWorkerTaskIsDue() { $this->addScheduledTask(WooCommerceSyncWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenAuthorizedSendingEmailsCheckTaskIsDue() { $this->addScheduledTask(AuthorizedSendingEmailsCheck::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenWooCommercePastOrdersTaskIsDue() { $this->addScheduledTask(WooCommercePastOrders::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenSubscribersEngagementScoreTaskIsDue() { $this->addScheduledTask(SubscribersEngagementScore::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenSubscribersCountCacheRecalculationTaskIsDue() { $this->addScheduledTask(SubscribersCountCacheRecalculation::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenSubscribersLastEngagementTaskIsDue() { $this->addScheduledTask(SubscribersLastEngagement::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenReEngagementEmailsSchedulerTaskIsDue() { $this->addScheduledTask(ReEngagementEmailsScheduler::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItExecutesWhenNewsletterTemplateThumbnailsTaskIsDue() { $this->addScheduledTask(NewsletterTemplateThumbnails::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED); verify($this->wordpressTrigger->checkExecutionRequirements())->true(); } public function testItDoesNotExecuteWhenTasksAreScheduledInFuture() { $future = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp', true) + 600); $this->addScheduledTask(NewsletterTemplateThumbnails::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); $this->addScheduledTask(SubscribersLastEngagement::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); $this->addScheduledTask(SubscribersCountCacheRecalculation::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $future); verify($this->wordpressTrigger->checkExecutionRequirements())->false(); } private function addMTAConfigAndLog($sent, $status = null, int $retryAt = null) { $mtaConfig = [ 'frequency' => [ 'emails' => 1, 'interval' => 1, ], ]; $this->settings->set( Mailer::MAILER_CONFIG_SETTING_NAME, $mtaConfig ); $mtaLog = [ 'sent' => $sent, 'started' => time(), 'status' => $status, ]; if ($retryAt) { $mtaLog['retry_at'] = $retryAt; } $this->settings->set( MailerLog::SETTING_NAME, $mtaLog ); } private function addQueue($status): SendingQueueEntity { $scheduledAt = ($status === SendingQueueEntity::STATUS_SCHEDULED) ? Carbon::now() : null; $newsletter = (new NewsletterFactory())->create(); $scheduledTask = (new ScheduledTaskFactory())->create(SendingQueue::TASK_TYPE, $status, $scheduledAt); $sendingQueue = (new SendingQueueFactory())->create($scheduledTask, $newsletter); return $sendingQueue; } private function addScheduledTask($type, $status, $scheduledAt = null) { if (!$scheduledAt && $status === ScheduledTaskEntity::STATUS_SCHEDULED) { $scheduledAt = Carbon::now(); } $task = new ScheduledTaskEntity(); $task->setType($type); $task->setStatus($status); $task->setScheduledAt($scheduledAt); $this->entityManager->persist($task); $this->entityManager->flush(); } }