diff --git a/lib/AutomaticEmails/WooCommerce/Events/FirstPurchase.php b/lib/AutomaticEmails/WooCommerce/Events/FirstPurchase.php index 31e753375b..e1b2caec66 100644 --- a/lib/AutomaticEmails/WooCommerce/Events/FirstPurchase.php +++ b/lib/AutomaticEmails/WooCommerce/Events/FirstPurchase.php @@ -3,10 +3,12 @@ namespace MailPoet\AutomaticEmails\WooCommerce\Events; use MailPoet\AutomaticEmails\WooCommerce\WooCommerce; +use MailPoet\DI\ContainerWrapper; use MailPoet\Logging\LoggerFactory; use MailPoet\Models\Newsletter; use MailPoet\Models\SendingQueue; use MailPoet\Models\Subscriber; +use MailPoet\Newsletter\AutomaticEmailsRepository; use MailPoet\Newsletter\Scheduler\AutomaticEmailScheduler; use MailPoet\WooCommerce\Helper as WCHelper; use MailPoet\WP\Functions as WPFunctions; @@ -26,6 +28,9 @@ class FirstPurchase { /** @var LoggerFactory */ private $loggerFactory; + /** @var AutomaticEmailsRepository */ + private $repository; + public function __construct(WCHelper $helper = null) { if ($helper === null) { $helper = new WCHelper(); @@ -33,6 +38,7 @@ class FirstPurchase { $this->helper = $helper; $this->scheduler = new AutomaticEmailScheduler(); $this->loggerFactory = LoggerFactory::getInstance(); + $this->repository = ContainerWrapper::getInstance()->get(AutomaticEmailsRepository::class); } public function init() { @@ -165,7 +171,7 @@ class FirstPurchase { } $checkEmailWasNotScheduled = function (Newsletter $newsletter) use ($subscriber) { - return !$newsletter->wasScheduledForSubscriber($subscriber->id); + return !$this->repository->wasScheduledForSubscriber($newsletter->id, $subscriber->id); }; $this->loggerFactory->getLogger(self::SLUG)->addInfo( diff --git a/lib/AutomaticEmails/WooCommerce/Events/PurchasedInCategory.php b/lib/AutomaticEmails/WooCommerce/Events/PurchasedInCategory.php index 26cf8b1ef2..febe22144a 100644 --- a/lib/AutomaticEmails/WooCommerce/Events/PurchasedInCategory.php +++ b/lib/AutomaticEmails/WooCommerce/Events/PurchasedInCategory.php @@ -3,8 +3,10 @@ namespace MailPoet\AutomaticEmails\WooCommerce\Events; use MailPoet\AutomaticEmails\WooCommerce\WooCommerce; +use MailPoet\DI\ContainerWrapper; use MailPoet\Logging\LoggerFactory; use MailPoet\Models\Subscriber; +use MailPoet\Newsletter\AutomaticEmailsRepository; use MailPoet\Newsletter\Scheduler\AutomaticEmailScheduler; use MailPoet\WooCommerce\Helper as WCHelper; use MailPoet\WP\Functions as WPFunctions; @@ -21,6 +23,9 @@ class PurchasedInCategory { /** @var LoggerFactory */ private $loggerFactory; + /** @var AutomaticEmailsRepository */ + private $repository; + public function __construct(WCHelper $woocommerceHelper = null) { if ($woocommerceHelper === null) { $woocommerceHelper = new WCHelper(); @@ -28,6 +33,7 @@ class PurchasedInCategory { $this->woocommerceHelper = $woocommerceHelper; $this->scheduler = new AutomaticEmailScheduler(); $this->loggerFactory = LoggerFactory::getInstance(); + $this->repository = ContainerWrapper::getInstance()->get(AutomaticEmailsRepository::class); } public function getEventDetails() { @@ -118,8 +124,8 @@ class PurchasedInCategory { $meta = $automaticEmail->getMeta(); if (empty($meta['option'])) return false; - if ($automaticEmail->wasScheduledForSubscriber($subscriber->id)) { - $sentAllProducts = $automaticEmail->alreadySentAllProducts($subscriber->id, 'orderedProductCategories', $orderedProductCategories); + if ($this->repository->wasScheduledForSubscriber($automaticEmail->id, $subscriber->id)) { + $sentAllProducts = $this->repository->alreadySentAllProducts($automaticEmail->id, $subscriber->id, 'orderedProductCategories', $orderedProductCategories); if ($sentAllProducts) return false; } diff --git a/lib/AutomaticEmails/WooCommerce/Events/PurchasedProduct.php b/lib/AutomaticEmails/WooCommerce/Events/PurchasedProduct.php index c5532badc0..fd4519df57 100644 --- a/lib/AutomaticEmails/WooCommerce/Events/PurchasedProduct.php +++ b/lib/AutomaticEmails/WooCommerce/Events/PurchasedProduct.php @@ -3,9 +3,11 @@ namespace MailPoet\AutomaticEmails\WooCommerce\Events; use MailPoet\AutomaticEmails\WooCommerce\WooCommerce; +use MailPoet\DI\ContainerWrapper; use MailPoet\Logging\LoggerFactory; use MailPoet\Models\Newsletter; use MailPoet\Models\Subscriber; +use MailPoet\Newsletter\AutomaticEmailsRepository; use MailPoet\Newsletter\Scheduler\AutomaticEmailScheduler; use MailPoet\WooCommerce\Helper as WCHelper; use MailPoet\WP\Functions as WPFunctions; @@ -23,6 +25,9 @@ class PurchasedProduct { /** @var LoggerFactory */ private $loggerFactory; + /** @var AutomaticEmailsRepository */ + private $repository; + public function __construct(WCHelper $helper = null) { if ($helper === null) { $helper = new WCHelper(); @@ -30,6 +35,7 @@ class PurchasedProduct { $this->helper = $helper; $this->scheduler = new AutomaticEmailScheduler(); $this->loggerFactory = LoggerFactory::getInstance(); + $this->repository = ContainerWrapper::getInstance()->get(AutomaticEmailsRepository::class); } public function init() { @@ -125,8 +131,8 @@ class PurchasedProduct { $meta = $automaticEmail->getMeta(); if (empty($meta['option'])) return false; - if ($automaticEmail->wasScheduledForSubscriber($subscriber->id)) { - $sentAllProducts = $automaticEmail->alreadySentAllProducts($subscriber->id, 'orderedProducts', $orderedProducts); + if ($this->repository->wasScheduledForSubscriber($automaticEmail->id, $subscriber->id)) { + $sentAllProducts = $this->repository->alreadySentAllProducts($automaticEmail->id, $subscriber->id, 'orderedProducts', $orderedProducts); if ($sentAllProducts) return false; } diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 94c75c9b8e..9fdb62953d 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -286,6 +286,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Newsletter\NewsletterSaveController::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\NewsletterPostsRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\NewslettersRepository::class)->setPublic(true); + $container->autowire(\MailPoet\Newsletter\AutomaticEmailsRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Listing\NewsletterListingRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Options\NewsletterOptionsRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository::class)->setPublic(true); diff --git a/lib/Entities/ScheduledTaskEntity.php b/lib/Entities/ScheduledTaskEntity.php index 3f7560ff5f..2f8432b821 100644 --- a/lib/Entities/ScheduledTaskEntity.php +++ b/lib/Entities/ScheduledTaskEntity.php @@ -63,6 +63,11 @@ class ScheduledTaskEntity { */ private $meta; + /** + * @ORM\OneToMany(targetEntity="MailPoet\Entities\ScheduledTaskSubscriberEntity", mappedBy="task", fetch="EXTRA_LAZY") + */ + public $subscribers; + /** * @return string|null */ diff --git a/lib/Models/Newsletter.php b/lib/Models/Newsletter.php index e965319886..cf9b813fcd 100644 --- a/lib/Models/Newsletter.php +++ b/lib/Models/Newsletter.php @@ -368,42 +368,6 @@ class Newsletter extends Model { return $this; } - public function wasScheduledForSubscriber($subscriberId) { - $query = SendingQueue::selectExpr('COUNT(*)', 'count'); - $query = $this->getAllQueuesForSubscscriberQuery($query, $subscriberId); - /** @var \stdClass */ - $queue = $query->findOne(); - - return ((int)$queue->count) > 0; - } - - private function getAllQueuesForSubscscriberQuery($orm, $subscriberId) { - return $orm->tableAlias('queue') - ->join(ScheduledTask::$_table, ['queue.task_id', '=', 'task.id'], 'task') - ->join(ScheduledTaskSubscriber::$_table, ['subscriber.task_id', '=', 'task.id'], 'subscriber') - ->where('queue.newsletter_id', $this->id) - ->where('subscriber.subscriber_id', $subscriberId); - } - - /** - * Check for automatic emails. - * Search products/categories in meta if all of the ordered products have already been sent to the subscriber. - */ - public function alreadySentAllProducts(int $subscriberId, string $orderedKey, array $ordered): bool { - $query = SendingQueue::select('queue.*'); - $queues = $this->getAllQueuesForSubscscriberQuery($query, $subscriberId)->findMany(); - $sent = []; - foreach ($queues as $queue) { - $meta = $queue->getMeta(); - if (isset($meta[$orderedKey])) { - $sent = array_merge($sent, $meta[$orderedKey]); - } - } - $notSentProducts = array_diff($ordered, $sent); - - return empty($notSentProducts); - } - public static function filterWithOptions($orm, $type) { $orm = $orm->select(MP_NEWSLETTERS_TABLE . '.*'); $optionFields = NewsletterOptionField::findArray(); diff --git a/lib/Newsletter/AutomaticEmailsRepository.php b/lib/Newsletter/AutomaticEmailsRepository.php new file mode 100644 index 0000000000..05046e32b3 --- /dev/null +++ b/lib/Newsletter/AutomaticEmailsRepository.php @@ -0,0 +1,59 @@ + + */ +class AutomaticEmailsRepository extends Repository { + protected function getEntityClassName() { + return NewsletterEntity::class; + } + + public function wasScheduledForSubscriber(int $newsletterId, int $subscriberId): bool { + $query = $this->doctrineRepository->createQueryBuilder('n') + ->select('COUNT(q)') + ->from(SendingQueueEntity::class, 'q'); + $query = $this->getAllQueuesForSubscscriberQuery($query, $newsletterId, $subscriberId); + $count = $query->getQuery() + ->getSingleScalarResult() ?: 0; + return ((int)$count) > 0; + } + + private function getAllQueuesForSubscscriberQuery(QueryBuilder $query, int $newsletterId, int $subscriberId): QueryBuilder { + return $query + ->join('q.task', 't') + ->join('t.subscribers', 's') + ->andWhere('q.newsletter = :newsletterId') + ->andWhere('s.subscriber = :subscriberId') + ->setParameter('newsletterId', $newsletterId) + ->setParameter('subscriberId', $subscriberId); + } + + /** + * Search products/categories in meta if all of the ordered products have already been sent to the subscriber. + */ + public function alreadySentAllProducts(int $newsletterId, int $subscriberId, string $orderedKey, array $ordered): bool { + $query = $this->doctrineRepository->createQueryBuilder('n') + ->select('q') + ->from(SendingQueueEntity::class, 'q'); + $queues = $this->getAllQueuesForSubscscriberQuery($query, $newsletterId, $subscriberId) + ->getQuery() + ->getResult(); + $sent = []; + foreach ($queues as $queue) { + $meta = $queue->getMeta(); + if (isset($meta[$orderedKey])) { + $sent = array_merge($sent, $meta[$orderedKey]); + } + } + $notSentProducts = array_diff($ordered, $sent); + + return empty($notSentProducts); + } +}