Use doctrine in stats notifications for auto emails

[MAILPOET-2439]
This commit is contained in:
Pavel Dohnal
2019-10-28 12:42:21 +01:00
committed by Jack Kitterhing
parent 5a2edff9fe
commit 95564cfa32
4 changed files with 138 additions and 92 deletions

View File

@ -5,11 +5,14 @@ namespace MailPoet\Cron\Workers\StatsNotifications;
use Carbon\Carbon;
use MailPoet\Config\Renderer;
use MailPoet\Cron\Workers\SimpleWorker;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Features\FeaturesController;
use MailPoet\Mailer\Mailer;
use MailPoet\Mailer\MetaInfo;
use MailPoet\Models\Newsletter;
use MailPoet\Models\ScheduledTask;
use MailPoet\Newsletter\Statistics\NewsletterStatistics;
use MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository;
use MailPoet\Settings\SettingsController;
use MailPoet\WooCommerce\Helper as WCHelper;
use MailPoet\WP\Functions as WPFunctions;
@ -26,20 +29,24 @@ class AutomatedEmails extends SimpleWorker {
/** @var Renderer */
private $renderer;
/** @var WCHelper */
private $woocommerce_helper;
/** @var MetaInfo */
private $mailerMetaInfo;
/** @var float */
public $timer;
/** @var StatsNotificationsRepository */
private $repository;
/** @var NewsletterStatisticsRepository */
private $newsletter_statistics_repository;
function __construct(
Mailer $mailer,
Renderer $renderer,
SettingsController $settings,
WCHelper $woocommerce_helper,
StatsNotificationsRepository $repository,
NewsletterStatisticsRepository $newsletter_statistics_repository,
MetaInfo $mailerMetaInfo,
$timer = false
) {
@ -47,9 +54,10 @@ class AutomatedEmails extends SimpleWorker {
$this->mailer = $mailer;
$this->settings = $settings;
$this->renderer = $renderer;
$this->woocommerce_helper = $woocommerce_helper;
$this->mailerMetaInfo = $mailerMetaInfo;
$this->timer = $timer ?: microtime(true);
$this->repository = $repository;
$this->newsletter_statistics_repository = $newsletter_statistics_repository;
}
function checkProcessingRequirements() {
@ -107,44 +115,37 @@ class AutomatedEmails extends SimpleWorker {
}
protected function getNewsletters() {
$newsletters = Newsletter
::whereNull('deleted_at')
->whereIn('type', [Newsletter::TYPE_AUTOMATIC, Newsletter::TYPE_WELCOME])
->where('status', Newsletter::STATUS_ACTIVE)
->orderByAsc('subject')
->findMany();
foreach ($newsletters as $newsletter) {
$newsletter
->withSendingQueue()
->withTotalSent()
->withStatistics($this->woocommerce_helper);
}
$result = [];
$newsletters = $this->repository->getDueAutomatedNewsletters();
foreach ($newsletters as $newsletter) {
if ($newsletter->total_sent) {
$result[] = $newsletter;
$statistics = $this->newsletter_statistics_repository->getStatistics($newsletter);
if ($statistics->getTotalSentCount()) {
$result[] = [
'statistics' => $statistics,
'newsletter' => $newsletter,
];
}
}
return $result;
}
/**
* @param Newsletter[] $newsletters
* @return array
*/
private function prepareContext(array $newsletters) {
$context = [
'linkSettings' => WPFunctions::get()->getSiteUrl(null, '/wp-admin/admin.php?page=mailpoet-settings#basics'),
'newsletters' => [],
];
foreach ($newsletters as $newsletter) {
$clicked = ($newsletter->statistics['clicked'] * 100) / $newsletter->total_sent;
$opened = ($newsletter->statistics['opened'] * 100) / $newsletter->total_sent;
foreach ($newsletters as $row) {
/** @var NewsletterStatistics $statistics */
$statistics = $row['statistics'];
/** @var NewsletterEntity $newsletter */
$newsletter = $row['newsletter'];
$clicked = ($statistics->getClickCount() * 100) / $statistics->getTotalSentCount();
$opened = ($statistics->getOpenCount() * 100) / $statistics->getTotalSentCount();
$context['newsletters'][] = [
'linkStats' => WPFunctions::get()->getSiteUrl(null, '/wp-admin/admin.php?page=mailpoet-newsletters#/stats/' . $newsletter->id),
'linkStats' => WPFunctions::get()->getSiteUrl(null, '/wp-admin/admin.php?page=mailpoet-newsletters#/stats/' . $newsletter->getId()),
'clicked' => $clicked,
'opened' => $opened,
'subject' => $newsletter->subject,
'subject' => $newsletter->getSubject(),
];
}
return $context;

View File

@ -4,6 +4,7 @@ namespace MailPoet\Cron\Workers\StatsNotifications;
use Carbon\Carbon;
use MailPoet\Doctrine\Repository;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\StatsNotificationEntity;
@ -56,5 +57,24 @@ class StatsNotificationsRepository extends Repository {
}
return $query->getQuery()->getResult();
}
/**
* @return NewsletterEntity[]
*/
public function getDueAutomatedNewsletters() {
return $this->entity_manager
->createQueryBuilder()
->select('n')
->from(NewsletterEntity::class, 'n')
->where('n.status = :status')
->setParameter(':status', NewsletterEntity::STATUS_ACTIVE)
->andWhere('n.deleted_at is null')
->andWhere('n.type IN (:types)')
->setParameter('types', [NewsletterEntity::TYPE_AUTOMATIC, NewsletterEntity::TYPE_WELCOME])
->orderBy('n.subject')
->getQuery()
->getResult();
}
}

View File

@ -162,7 +162,15 @@ class WorkersFactory {
/** @return StatsNotificationsWorkerForAutomatedEmails */
function createStatsNotificationsWorkerForAutomatedEmails($timer) {
return new StatsNotificationsWorkerForAutomatedEmails($this->mailer, $this->renderer, $this->settings, $this->woocommerce_helper, $this->mailerMetaInfo, $timer);
return new StatsNotificationsWorkerForAutomatedEmails(
$this->mailer,
$this->renderer,
$this->settings,
$this->stats_notifications_repository,
$this->newsletter_statistics_repository,
$this->mailerMetaInfo,
$timer
);
}
/** @return SendingServiceKeyCheckWorker */

View File

@ -3,10 +3,15 @@
namespace MailPoet\Cron\Workers\StatsNotifications;
use MailPoet\Config\Renderer;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Mailer\Mailer;
use MailPoet\Mailer\MetaInfo;
use MailPoet\Models\Newsletter;
use MailPoet\Models\ScheduledTask;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\StatisticsClicks;
use MailPoet\Models\StatisticsOpens;
use MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository;
use MailPoet\Settings\SettingsController;
use MailPoet\WooCommerce\Helper as WCHelper;
use PHPUnit\Framework\MockObject\MockObject;
@ -28,6 +33,7 @@ class AutomatedEmailsTest extends \MailPoetTest {
function _before() {
parent::_before();
\ORM::raw_execute('TRUNCATE ' . ScheduledTask::$_table);
\ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);
ScheduledTask::createOrUpdate([
'type' => AutomatedEmails::TASK_TYPE,
'status' => null,
@ -37,17 +43,15 @@ class AutomatedEmailsTest extends \MailPoetTest {
$this->mailer = $this->createMock(Mailer::class);
$this->renderer = $this->createMock(Renderer::class);
$this->settings = new SettingsController();
$this->stats_notifications = $this->getMockBuilder(AutomatedEmails::class)
->enableOriginalConstructor()
->setConstructorArgs([
$this->mailer,
$this->renderer,
$this->settings,
$this->makeEmpty(WCHelper::class),
new MetaInfo,
])
->setMethods(['getNewsletters'])
->getMock();
$this->stats_notifications = new AutomatedEmails(
$this->mailer,
$this->renderer,
$this->settings,
ContainerWrapper::getInstance()->get(StatsNotificationsRepository::class),
ContainerWrapper::getInstance()->get(NewsletterStatisticsRepository::class),
new MetaInfo
);
$this->settings->set(Worker::SETTINGS_KEY, [
'automated' => true,
'address' => 'email@example.com',
@ -76,15 +80,11 @@ class AutomatedEmailsTest extends \MailPoetTest {
expect($this->stats_notifications->checkProcessingRequirements())->equals(false);
}
function testItDoesntWorkIfEnabled() {
function testItDoesWorkIfEnabled() {
expect($this->stats_notifications->checkProcessingRequirements())->equals(true);
}
function testItDoesntRenderIfNoNewslettersFound() {
$this->stats_notifications
->expects($this->once())
->method('getNewsletters')
->will($this->returnValue([]));
$this->renderer->expects($this->never())
->method('render');
$this->mailer->expects($this->never())
@ -96,20 +96,15 @@ class AutomatedEmailsTest extends \MailPoetTest {
}
function testItRenders() {
$newsletter1 = Newsletter::create();
$newsletter1->hydrate([
'id' => 8765,
Newsletter::createOrUpdate([
'id' => 8763,
'subject' => 'Subject',
'total_sent' => 10,
'statistics' => [
'clicked' => 5,
'opened' => 2,
],
'type' => 'welcome',
'status' => 'active',
]);
$this->stats_notifications
->expects($this->once())
->method('getNewsletters')
->will($this->returnValue([$newsletter1]));
$this->createQueue(8763, 10);
$this->createClicks(8763, 5);
$this->createOpens(8763, 2);
$this->renderer->expects($this->exactly(2))
->method('render');
$this->renderer->expects($this->at(0))
@ -129,20 +124,16 @@ class AutomatedEmailsTest extends \MailPoetTest {
}
function testItSends() {
$newsletter1 = Newsletter::create();
$newsletter1->hydrate([
'id' => 8765,
Newsletter::createOrUpdate([
'id' => 8763,
'subject' => 'Subject',
'total_sent' => 10,
'statistics' => [
'clicked' => 5,
'opened' => 2,
],
'type' => 'welcome',
'status' => 'active',
]);
$this->stats_notifications
->expects($this->once())
->method('getNewsletters')
->will($this->returnValue([$newsletter1]));
$this->createQueue(8763, 10);
$this->createClicks(8763, 5);
$this->createOpens(8763, 2);
$this->renderer->expects($this->exactly(2))
->method('render');
@ -163,20 +154,15 @@ class AutomatedEmailsTest extends \MailPoetTest {
}
function testItPreparesContext() {
$newsletter1 = Newsletter::create();
$newsletter1->hydrate([
'id' => 8765,
Newsletter::createOrUpdate([
'id' => 8764,
'subject' => 'Subject',
'total_sent' => 10,
'statistics' => [
'clicked' => 5,
'opened' => 2,
],
'type' => 'welcome',
'status' => 'active',
]);
$this->stats_notifications
->expects($this->once())
->method('getNewsletters')
->will($this->returnValue([$newsletter1]));
$this->createClicks(8764, 5);
$this->createOpens(8764, 2);
$this->createQueue(8764, 10);
$this->renderer->expects($this->exactly(2)) // html + text template
->method('render')
->with(
@ -189,20 +175,16 @@ class AutomatedEmailsTest extends \MailPoetTest {
}
function testItAddsNewsletterStatsToContext() {
$newsletter1 = Newsletter::create();
$newsletter1->hydrate([
Newsletter::createOrUpdate([
'id' => 8765,
'subject' => 'Subject',
'total_sent' => 10,
'statistics' => [
'clicked' => 5,
'opened' => 2,
],
'type' => 'welcome',
'status' => 'active',
]);
$this->stats_notifications
->expects($this->once())
->method('getNewsletters')
->will($this->returnValue([$newsletter1]));
$this->createClicks(8765, 5);
$this->createOpens(8765, 2);
$this->createQueue(8765, 10);
$this->renderer->expects($this->exactly(2)) // html + text template
->method('render')
->with(
@ -217,4 +199,39 @@ class AutomatedEmailsTest extends \MailPoetTest {
$this->stats_notifications->process();
}
private function createClicks($newsletter_id, $count) {
for ($i = 0; $i < $count; $i++) {
StatisticsClicks::createOrUpdate([
'newsletter_id' => $newsletter_id,
'subscriber_id' => $i + 1,
'queue_id' => 5,
'link_id' => 4,
'count' => 1,
]);
}
}
private function createOpens($newsletter_id, $count) {
for ($i = 0; $i < $count; $i++) {
StatisticsOpens::createOrUpdate([
'newsletter_id' => $newsletter_id,
'subscriber_id' => $i + 1,
'queue_id' => 5,
]);
}
}
private function createQueue($newsletter_id, $count_processed) {
$sending_task = ScheduledTask::createOrUpdate([
'type' => 'sending',
'status' => ScheduledTask::STATUS_COMPLETED,
]);
SendingQueue::createOrUpdate([
'newsletter_rendered_subject' => 'Email Subject',
'task_id' => $sending_task->id,
'newsletter_id' => $newsletter_id,
'count_processed' => $count_processed,
]);
}
}