diff --git a/mailpoet/lib/API/JSON/v1/Newsletters.php b/mailpoet/lib/API/JSON/v1/Newsletters.php index a9cb483f94..ab077ce508 100644 --- a/mailpoet/lib/API/JSON/v1/Newsletters.php +++ b/mailpoet/lib/API/JSON/v1/Newsletters.php @@ -15,6 +15,7 @@ use MailPoet\Entities\SendingQueueEntity; use MailPoet\InvalidStateException; use MailPoet\Listing; use MailPoet\Newsletter\Listing\NewsletterListingRepository; +use MailPoet\Newsletter\NewsletterDeleteController; use MailPoet\Newsletter\NewsletterSaveController; use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\NewsletterValidator; @@ -73,6 +74,8 @@ class Newsletters extends APIEndpoint { /** @var NewsletterSaveController */ private $newsletterSaveController; + private NewsletterDeleteController $newsletterDeleteController; + /** @var NewsletterUrl */ private $newsletterUrl; @@ -98,6 +101,7 @@ class Newsletters extends APIEndpoint { Emoji $emoji, SendPreviewController $sendPreviewController, NewsletterSaveController $newsletterSaveController, + NewsletterDeleteController $newsletterDeleteController, NewsletterUrl $newsletterUrl, Scheduler $scheduler, NewsletterValidator $newsletterValidator, @@ -115,6 +119,7 @@ class Newsletters extends APIEndpoint { $this->emoji = $emoji; $this->sendPreviewController = $sendPreviewController; $this->newsletterSaveController = $newsletterSaveController; + $this->newsletterDeleteController = $newsletterDeleteController; $this->newsletterUrl = $newsletterUrl; $this->scheduler = $scheduler; $this->newsletterValidator = $newsletterValidator; @@ -291,7 +296,7 @@ class Newsletters extends APIEndpoint { $newsletter = $this->getNewsletter($data); if ($newsletter instanceof NewsletterEntity) { $this->wp->doAction('mailpoet_api_newsletters_delete_before', [$newsletter->getId()]); - $this->newslettersRepository->bulkDelete([$newsletter->getId()]); + $this->newsletterDeleteController->bulkDelete([(int)$newsletter->getId()]); $this->wp->doAction('mailpoet_api_newsletters_delete_after', [$newsletter->getId()]); return $this->successResponse(null, ['count' => 1]); } else { @@ -401,7 +406,7 @@ class Newsletters extends APIEndpoint { $this->newslettersRepository->bulkRestore($ids); } elseif ($data['action'] === 'delete') { $this->wp->doAction('mailpoet_api_newsletters_delete_before', $ids); - $this->newslettersRepository->bulkDelete($ids); + $this->newsletterDeleteController->bulkDelete($ids); $this->wp->doAction('mailpoet_api_newsletters_delete_after', $ids); } else { throw UnexpectedValueException::create() diff --git a/mailpoet/lib/Automation/Integrations/MailPoet/Hooks/AutomationEditorLoadingHooks.php b/mailpoet/lib/Automation/Integrations/MailPoet/Hooks/AutomationEditorLoadingHooks.php index 97b5b5580f..c01e3c0196 100644 --- a/mailpoet/lib/Automation/Integrations/MailPoet/Hooks/AutomationEditorLoadingHooks.php +++ b/mailpoet/lib/Automation/Integrations/MailPoet/Hooks/AutomationEditorLoadingHooks.php @@ -7,6 +7,7 @@ use MailPoet\Automation\Engine\Data\Step; use MailPoet\Automation\Engine\Hooks; use MailPoet\Automation\Engine\Storage\AutomationStorage; use MailPoet\Automation\Engine\WordPress; +use MailPoet\Newsletter\NewsletterDeleteController; use MailPoet\Newsletter\NewslettersRepository; class AutomationEditorLoadingHooks { @@ -20,14 +21,18 @@ class AutomationEditorLoadingHooks { /** @var NewslettersRepository */ private $newslettersRepository; + private NewsletterDeleteController $newsletterDeleteController; + public function __construct( WordPress $wp, AutomationStorage $automationStorage, - NewslettersRepository $newslettersRepository + NewslettersRepository $newslettersRepository, + NewsletterDeleteController $newsletterDeleteController ) { $this->wp = $wp; $this->automationStorage = $automationStorage; $this->newslettersRepository = $newslettersRepository; + $this->newsletterDeleteController = $newsletterDeleteController; } public function init(): void { @@ -59,7 +64,7 @@ class AutomationEditorLoadingHooks { continue; } - $this->newslettersRepository->bulkDelete([$emailId]); + $this->newsletterDeleteController->bulkDelete([$emailId]); $args = $step->getArgs(); unset($args['email_id']); $updatedStep = new Step( diff --git a/mailpoet/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php b/mailpoet/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php index dadac4d564..ede089f0a8 100644 --- a/mailpoet/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php +++ b/mailpoet/lib/Cron/Workers/SendingQueue/Tasks/Newsletter.php @@ -14,6 +14,7 @@ use MailPoet\Entities\SubscriberEntity; use MailPoet\Logging\LoggerFactory; use MailPoet\Mailer\MailerLog; use MailPoet\Newsletter\Links\Links as NewsletterLinks; +use MailPoet\Newsletter\NewsletterDeleteController; use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\Renderer\PostProcess\OpenTracking; use MailPoet\Newsletter\Renderer\Renderer; @@ -51,6 +52,9 @@ class Newsletter { /** @var NewslettersRepository */ private $newslettersRepository; + /** @var NewsletterDeleteController */ + private $newsletterDeleteController; + /** @var Emoji */ private $emoji; @@ -96,6 +100,7 @@ class Newsletter { $this->emoji = $emoji; $this->renderer = ContainerWrapper::getInstance()->get(Renderer::class); $this->newslettersRepository = ContainerWrapper::getInstance()->get(NewslettersRepository::class); + $this->newsletterDeleteController = ContainerWrapper::getInstance()->get(NewsletterDeleteController::class); $this->linksTask = ContainerWrapper::getInstance()->get(LinksTask::class); $this->newsletterLinks = ContainerWrapper::getInstance()->get(NewsletterLinks::class); $this->sendingQueuesRepository = ContainerWrapper::getInstance()->get(SendingQueuesRepository::class); @@ -191,7 +196,7 @@ class Newsletter { 'no posts in post notification, deleting it', ['newsletter_id' => $newsletter->getId(), 'task_id' => $task->getId()] ); - $this->newslettersRepository->bulkDelete([(int)$newsletter->getId()]); + $this->newsletterDeleteController->bulkDelete([(int)$newsletter->getId()]); return false; } // extract and save newsletter posts diff --git a/mailpoet/lib/DI/ContainerConfigurator.php b/mailpoet/lib/DI/ContainerConfigurator.php index b221867fad..2b13462c72 100644 --- a/mailpoet/lib/DI/ContainerConfigurator.php +++ b/mailpoet/lib/DI/ContainerConfigurator.php @@ -543,6 +543,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Newsletter\ApiDataSanitizer::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\AutomatedLatestContent::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\NewsletterSaveController::class)->setPublic(true); + $container->autowire(\MailPoet\Newsletter\NewsletterDeleteController::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); diff --git a/mailpoet/lib/Models/Newsletter.php b/mailpoet/lib/Models/Newsletter.php index ffb6bae1d4..46db38c3b3 100644 --- a/mailpoet/lib/Models/Newsletter.php +++ b/mailpoet/lib/Models/Newsletter.php @@ -4,6 +4,7 @@ namespace MailPoet\Models; use MailPoet\DI\ContainerWrapper; use MailPoet\Entities\NewsletterEntity; +use MailPoet\Newsletter\NewsletterDeleteController; use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Settings\SettingsController; @@ -141,7 +142,7 @@ class Newsletter extends Model { public function delete() { trigger_error('Calling Newsletter::delete() is deprecated and will be removed. Use \MailPoet\Newsletter\NewslettersRepository instead.', E_USER_DEPRECATED); - ContainerWrapper::getInstance()->get(NewslettersRepository::class)->bulkDelete([$this->id]); + ContainerWrapper::getInstance()->get(NewsletterDeleteController::class)->bulkDelete([$this->id]); return null; } diff --git a/mailpoet/lib/Newsletter/NewsletterDeleteController.php b/mailpoet/lib/Newsletter/NewsletterDeleteController.php new file mode 100644 index 0000000000..6b7558b6e9 --- /dev/null +++ b/mailpoet/lib/Newsletter/NewsletterDeleteController.php @@ -0,0 +1,156 @@ +entityManager = $entityManager; + $this->newslettersRepository = $newslettersRepository; + $this->newsletterLinkRepository = $newsletterLinkRepository; + $this->newsletterOptionsRepository = $newsletterOptionsRepository; + $this->newsletterPostsRepository = $newsletterPostsRepository; + $this->newsletterSegmentRepository = $newsletterSegmentRepository; + $this->scheduledTasksRepository = $scheduledTasksRepository; + $this->scheduledTaskSubscribersRepository = $scheduledTaskSubscribersRepository; + $this->sendingQueuesRepository = $sendingQueuesRepository; + $this->statisticsClicksRepository = $statisticsClicksRepository; + $this->statisticsNewslettersRepository = $statisticsNewslettersRepository; + $this->statisticsOpensRepository = $statisticsOpensRepository; + $this->statisticsWooCommercePurchasesRepository = $statisticsWooCommercePurchasesRepository; + $this->statsNotificationsRepository = $statsNotificationsRepository; + $this->wp = $wp; + } + + /** @param int[] $ids */ + public function bulkDelete(array $ids): int { + if (!$ids) { + return 0; + } + + // Fetch children ids for deleting + $childrenIds = $this->newslettersRepository->fetchChildrenIds($ids); + $ids = array_merge($ids, $childrenIds); + + $this->entityManager->beginTransaction(); + try { + // Delete statistics data + $this->statisticsNewslettersRepository->deleteByNewsletterIds($ids); + $this->statisticsOpensRepository->deleteByNewsletterIds($ids); + $this->statisticsClicksRepository->deleteByNewsletterIds($ids); + + // Update WooCommerce statistics and remove newsletter and click id + $this->statisticsWooCommercePurchasesRepository->removeNewsletterDataByNewsletterIds($ids); + + // Delete newsletter posts, options, links, and segments + $this->newsletterPostsRepository->deleteByNewsletterIds($ids); + $this->newsletterOptionsRepository->deleteByNewsletterIds($ids); + $this->newsletterLinkRepository->deleteByNewsletterIds($ids); + $this->newsletterSegmentRepository->deleteByNewsletterIds($ids); + + // Delete stats notifications and related tasks + /** @var string[] $taskIds */ + $taskIds = $this->entityManager->createQueryBuilder() + ->select('IDENTITY(sn.task)') + ->from(StatsNotificationEntity::class, 'sn') + ->where('sn.newsletter IN (:ids)') + ->setParameter('ids', $ids) + ->getQuery() + ->getSingleColumnResult(); + $taskIds = array_map('intval', $taskIds); + + $this->scheduledTasksRepository->deleteByIds($taskIds); + $this->statsNotificationsRepository->deleteByNewsletterIds($ids); + + // Delete scheduled task subscribers, scheduled tasks, and sending queues + /** @var string[] $taskIds */ + $taskIds = $this->entityManager->createQueryBuilder() + ->select('IDENTITY(q.task)') + ->from(SendingQueueEntity::class, 'q') + ->where('q.newsletter IN (:ids)') + ->setParameter('ids', $ids) + ->getQuery() + ->getSingleColumnResult(); + $taskIds = array_map('intval', $taskIds); + + $this->scheduledTaskSubscribersRepository->deleteByTaskIds($taskIds); + $this->scheduledTasksRepository->deleteByIds($taskIds); + $this->sendingQueuesRepository->deleteByNewsletterIds($ids); + + // Fetch WP Posts IDs and delete them + /** @var string[] $wpPostIds */ + $wpPostIds = $this->entityManager->createQueryBuilder() + ->select('IDENTITY(n.wpPost) AS id') + ->from(NewsletterEntity::class, 'n') + ->where('n.id IN (:ids)') + ->andWhere('n.wpPost IS NOT NULL') + ->setParameter('ids', $ids) + ->getQuery() + ->getSingleColumnResult(); + $wpPostIds = array_map('intval', $wpPostIds); + + foreach ($wpPostIds as $wpPostId) { + $this->wp->wpDeletePost($wpPostId, true); + } + + // Delete newsletter entities + $this->newslettersRepository->deleteByIds($ids); + + $this->entityManager->commit(); + } catch (Throwable $e) { + $this->entityManager->rollback(); + throw $e; + } + + return count($ids); + } +} diff --git a/mailpoet/lib/Newsletter/NewslettersRepository.php b/mailpoet/lib/Newsletter/NewslettersRepository.php index 12ca36c7f1..330cd33860 100644 --- a/mailpoet/lib/Newsletter/NewslettersRepository.php +++ b/mailpoet/lib/Newsletter/NewslettersRepository.php @@ -7,83 +7,30 @@ use MailPoet\AutomaticEmails\WooCommerce\Events\AbandonedCart; use MailPoet\AutomaticEmails\WooCommerce\Events\FirstPurchase; use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedInCategory; use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedProduct; -use MailPoet\Cron\Workers\StatsNotifications\NewsletterLinkRepository; -use MailPoet\Cron\Workers\StatsNotifications\StatsNotificationsRepository; use MailPoet\Doctrine\Repository; use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\NewsletterOptionFieldEntity; use MailPoet\Entities\NewsletterSegmentEntity; use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Entities\SendingQueueEntity; -use MailPoet\Entities\StatsNotificationEntity; use MailPoet\Logging\LoggerFactory; -use MailPoet\Newsletter\Options\NewsletterOptionsRepository; -use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; -use MailPoet\Newsletter\Sending\ScheduledTasksRepository; -use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository; -use MailPoet\Newsletter\Sending\SendingQueuesRepository; -use MailPoet\Statistics\StatisticsClicksRepository; -use MailPoet\Statistics\StatisticsNewslettersRepository; -use MailPoet\Statistics\StatisticsOpensRepository; -use MailPoet\Statistics\StatisticsWooCommercePurchasesRepository; use MailPoet\Util\Helpers; -use MailPoet\WP\Functions as WPFunctions; use MailPoetVendor\Carbon\Carbon; use MailPoetVendor\Doctrine\DBAL\Connection; use MailPoetVendor\Doctrine\ORM\EntityManager; use MailPoetVendor\Doctrine\ORM\Query\Expr\Join; -use Throwable; /** * @extends Repository */ class NewslettersRepository extends Repository { private LoggerFactory $loggerFactory; - private NewsletterLinkRepository $newsletterLinkRepository; - private NewsletterOptionsRepository $newsletterOptionsRepository; - private NewsletterPostsRepository $newsletterPostsRepository; - private NewsletterSegmentRepository $newsletterSegmentRepository; - private ScheduledTasksRepository $scheduledTasksRepository; - private ScheduledTaskSubscribersRepository $scheduledTaskSubscribersRepository; - private SendingQueuesRepository $sendingQueuesRepository; - private StatisticsClicksRepository $statisticsClicksRepository; - private StatisticsNewslettersRepository $statisticsNewslettersRepository; - private StatisticsOpensRepository $statisticsOpensRepository; - private StatisticsWooCommercePurchasesRepository $statisticsWooCommercePurchasesRepository; - private StatsNotificationsRepository $statsNotificationsRepository; - private WPFunctions $wp; public function __construct( - EntityManager $entityManager, - NewsletterLinkRepository $newsletterLinkRepository, - NewsletterOptionsRepository $newsletterOptionsRepository, - NewsletterPostsRepository $newsletterPostsRepository, - NewsletterSegmentRepository $newsletterSegmentRepository, - ScheduledTasksRepository $scheduledTasksRepository, - ScheduledTaskSubscribersRepository $scheduledTaskSubscribersRepository, - SendingQueuesRepository $sendingQueuesRepository, - StatisticsClicksRepository $statisticsClicksRepository, - StatisticsNewslettersRepository $statisticsNewslettersRepository, - StatisticsOpensRepository $statisticsOpensRepository, - StatisticsWooCommercePurchasesRepository $statisticsWooCommercePurchasesRepository, - StatsNotificationsRepository $statsNotificationsRepository, - WPFunctions $wp + EntityManager $entityManager ) { parent::__construct($entityManager); $this->loggerFactory = LoggerFactory::getInstance(); - $this->newsletterLinkRepository = $newsletterLinkRepository; - $this->newsletterOptionsRepository = $newsletterOptionsRepository; - $this->newsletterPostsRepository = $newsletterPostsRepository; - $this->newsletterSegmentRepository = $newsletterSegmentRepository; - $this->scheduledTasksRepository = $scheduledTasksRepository; - $this->scheduledTaskSubscribersRepository = $scheduledTaskSubscribersRepository; - $this->sendingQueuesRepository = $sendingQueuesRepository; - $this->statisticsClicksRepository = $statisticsClicksRepository; - $this->statisticsNewslettersRepository = $statisticsNewslettersRepository; - $this->statisticsOpensRepository = $statisticsOpensRepository; - $this->statisticsWooCommercePurchasesRepository = $statisticsWooCommercePurchasesRepository; - $this->statsNotificationsRepository = $statsNotificationsRepository; - $this->wp = $wp; } protected function getEntityClassName() { @@ -397,88 +344,6 @@ class NewslettersRepository extends Repository { return count($ids); } - public function bulkDelete(array $ids) { - if (empty($ids)) { - return 0; - } - // Fetch children ids for deleting - $childrenIds = $this->fetchChildrenIds($ids); - $ids = array_merge($ids, $childrenIds); - - $this->entityManager->beginTransaction(); - try { - // Delete statistics data - $this->statisticsNewslettersRepository->deleteByNewsletterIds($ids); - $this->statisticsOpensRepository->deleteByNewsletterIds($ids); - $this->statisticsClicksRepository->deleteByNewsletterIds($ids); - - // Update WooCommerce statistics and remove newsletter and click id - $this->statisticsWooCommercePurchasesRepository->removeNewsletterDataByNewsletterIds($ids); - - // Delete newsletter posts, options, links, and segments - $this->newsletterPostsRepository->deleteByNewsletterIds($ids); - $this->newsletterOptionsRepository->deleteByNewsletterIds($ids); - $this->newsletterLinkRepository->deleteByNewsletterIds($ids); - $this->newsletterSegmentRepository->deleteByNewsletterIds($ids); - - // Delete stats notifications and related tasks - /** @var string[] $taskIds */ - $taskIds = $this->entityManager->createQueryBuilder() - ->select('IDENTITY(sn.task)') - ->from(StatsNotificationEntity::class, 'sn') - ->where('sn.newsletter IN (:ids)') - ->setParameter('ids', $ids) - ->getQuery() - ->getSingleColumnResult(); - $taskIds = array_map('intval', $taskIds); - - $this->scheduledTasksRepository->deleteByIds($taskIds); - $this->statsNotificationsRepository->deleteByNewsletterIds($ids); - - // Delete scheduled task subscribers, scheduled tasks, and sending queues - /** @var string[] $taskIds */ - $taskIds = $this->entityManager->createQueryBuilder() - ->select('IDENTITY(q.task)') - ->from(SendingQueueEntity::class, 'q') - ->where('q.newsletter IN (:ids)') - ->setParameter('ids', $ids) - ->getQuery() - ->getSingleColumnResult(); - $taskIds = array_map('intval', $taskIds); - - $this->scheduledTaskSubscribersRepository->deleteByTaskIds($taskIds); - $this->scheduledTasksRepository->deleteByIds($taskIds); - $this->sendingQueuesRepository->deleteByNewsletterIds($ids); - - // Fetch WP Posts IDs and delete them - /** @var string[] $wpPostIds */ - $wpPostIds = $this->entityManager->createQueryBuilder() - ->select('IDENTITY(n.wpPost) AS id') - ->from(NewsletterEntity::class, 'n') - ->where('n.id IN (:ids)') - ->andWhere('n.wpPost IS NOT NULL') - ->setParameter('ids', $ids) - ->getQuery() - ->getSingleColumnResult(); - $wpPostIds = array_map('intval', $wpPostIds); - - foreach ($wpPostIds as $wpPostId) { - $this->wp->wpDeletePost($wpPostId, true); - } - - // Delete newsletter entities - $this->deleteByIds($ids); - - $this->entityManager->commit(); - } catch (Throwable $e) { - $this->entityManager->rollback(); - throw $e; - } - - return count($ids); - } - - /** @param int[] $ids */ public function deleteByIds(array $ids): void { $this->entityManager->createQueryBuilder() @@ -665,12 +530,19 @@ class NewslettersRepository extends Repository { $this->flush(); } - private function fetchChildrenIds(array $parentIds) { - $ids = $this->entityManager->createQueryBuilder()->select('n.id') + /** + * @param int[] $parentIds + * @return int[] + */ + public function fetchChildrenIds(array $parentIds): array { + /** @var string[] $ids */ + $ids = $this->entityManager->createQueryBuilder() + ->select('n.id') ->from(NewsletterEntity::class, 'n') ->where('n.parent IN (:ids)') ->setParameter('ids', $parentIds) - ->getQuery()->getScalarResult(); - return array_column($ids, 'id'); + ->getQuery() + ->getSingleColumnResult(); + return array_map('intval', $ids); } } diff --git a/mailpoet/tests/integration/Newsletter/NewsletterDeleteControllerTest.php b/mailpoet/tests/integration/Newsletter/NewsletterDeleteControllerTest.php new file mode 100644 index 0000000000..463f24914f --- /dev/null +++ b/mailpoet/tests/integration/Newsletter/NewsletterDeleteControllerTest.php @@ -0,0 +1,317 @@ +controller = $this->diContainer->get(NewsletterDeleteController::class); + $this->repository = $this->diContainer->get(NewslettersRepository::class); + $this->taskSubscribersRepository = $this->diContainer->get(ScheduledTaskSubscribersRepository::class); + $this->wp = $this->diContainer->get(WPFunctions::class); + } + + public function testItBulkDeleteNewslettersAndChildren() { + $standardNewsletter = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); + $standardQueue = $this->createQueueWithTaskAndSegmentAndSubscribers($standardNewsletter, null); // Null for scheduled task being processed + $notification = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE); + $notificationHistory = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION_HISTORY, NewsletterEntity::STATUS_SCHEDULED, $notification); + $notificationHistoryQueue = $this->createQueueWithTaskAndSegmentAndSubscribers($notificationHistory); + + $standardSegment = $standardNewsletter->getNewsletterSegments()->first(); + $this->assertInstanceOf(NewsletterSegmentEntity::class, $standardSegment); + $standardScheduledTaks = $standardQueue->getTask(); + $this->assertInstanceOf(ScheduledTaskEntity::class, $standardScheduledTaks); + $standardScheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $standardScheduledTaks]); + $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $standardScheduledTaskSubscriber); + $notificationHistoryScheduledTask = $notificationHistoryQueue->getTask(); + $this->assertInstanceOf(ScheduledTaskEntity::class, $notificationHistoryScheduledTask); + $notificationHistorySegment = $notificationHistory->getNewsletterSegments()->first(); + $this->assertInstanceOf(NewsletterSegmentEntity::class, $notificationHistorySegment); + $notificationHistoryScheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $notificationHistoryScheduledTask]); + $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $notificationHistoryScheduledTaskSubscriber); + $standardStatsNotification = $this->createStatNotification($standardNewsletter); + $standardStatsNotificationScheduledTask = $standardStatsNotification->getTask(); + $this->assertInstanceOf(ScheduledTaskEntity::class, $standardStatsNotificationScheduledTask); + $notificationHistoryStatsNotification = $this->createStatNotification($notificationHistory); + $notificationHistoryStatsNotificationScheduledTask = $notificationHistoryStatsNotification->getTask(); + $this->assertInstanceOf(ScheduledTaskEntity::class, $notificationHistoryStatsNotificationScheduledTask); + $standardLink = $this->createNewsletterLink($standardNewsletter, $standardQueue); + $notificationHistoryLink = $this->createNewsletterLink($notificationHistory, $notificationHistoryQueue); + $optionField = (new NewsletterOptionField())->findOrCreate('name', NewsletterEntity::TYPE_NOTIFICATION); + $optionValue = $this->createNewsletterOption($notificationHistory, $optionField, 'value'); + $newsletterPost = $this->createNewsletterPost($notification, 1); + + $subscriber = $standardScheduledTaskSubscriber->getSubscriber(); + $this->assertInstanceOf(SubscriberEntity::class, $subscriber); + $statisticsNewsletter = $this->createNewsletterStatistics($standardNewsletter, $standardQueue, $subscriber); + $statisticsOpen = $this->createOpenStatistics($standardNewsletter, $standardQueue, $subscriber); + $statisticsClick = $this->createClickStatistics($standardNewsletter, $standardQueue, $subscriber, $standardLink); + $statisticsPurchase = $this->createPurchaseStatistics($standardNewsletter, $standardQueue, $statisticsClick, $subscriber); + + // Trash + $this->repository->bulkTrash([(int)$standardNewsletter->getId(), (int)$notification->getId()]); + // Delete + $this->controller->bulkDelete([(int)$standardNewsletter->getId(), (int)$notification->getId()]); + + // Clear entity manager to forget all entities + $this->entityManager->clear(); + + // Check they were all deleted + // Newsletters + verify($this->repository->findOneById($standardNewsletter->getId()))->null(); + verify($this->repository->findOneById($notification->getId()))->null(); + verify($this->repository->findOneById($notificationHistory->getId()))->null(); + + // Sending queues + verify($this->entityManager->find(SendingQueueEntity::class, $standardQueue->getId()))->null(); + verify($this->entityManager->find(SendingQueueEntity::class, $notificationHistoryQueue->getId()))->null(); + + // Scheduled tasks subscribers + verify($this->taskSubscribersRepository->findOneBy(['task' => $standardScheduledTaks]))->null(); + verify($this->taskSubscribersRepository->findOneBy(['task' => $notificationHistoryScheduledTask]))->null(); + + // Scheduled tasks + verify($this->entityManager->find(ScheduledTaskEntity::class, $standardScheduledTaks->getId()))->null(); + verify($this->entityManager->find(ScheduledTaskEntity::class, $notificationHistoryScheduledTask->getId()))->null(); + + // Newsletter segments + verify($this->entityManager->find(NewsletterSegmentEntity::class, $standardSegment->getId()))->null(); + verify($this->entityManager->find(NewsletterSegmentEntity::class, $notificationHistorySegment->getId()))->null(); + + // Newsletter stats notifications + verify($this->entityManager->find(StatsNotificationEntity::class, $standardStatsNotificationScheduledTask->getId()))->null(); + verify($this->entityManager->find(StatsNotificationEntity::class, $notificationHistoryStatsNotification->getId()))->null(); + + // Newsletter stats notifications scheduled tasks + verify($this->entityManager->find(ScheduledTaskEntity::class, $standardStatsNotificationScheduledTask->getId()))->null(); + verify($this->entityManager->find(ScheduledTaskEntity::class, $notificationHistoryStatsNotificationScheduledTask->getId()))->null(); + + // Newsletter links + verify($this->entityManager->find(NewsletterLinkEntity::class, $standardLink->getId()))->null(); + verify($this->entityManager->find(NewsletterLinkEntity::class, $notificationHistoryLink->getId()))->null(); + + // Option fields values + verify($this->entityManager->find(NewsletterOptionEntity::class, $optionValue->getId()))->null(); + + // Newsletter post + verify($this->entityManager->find(NewsletterPostEntity::class, $newsletterPost->getId()))->null(); + + // Statistics data + verify($this->entityManager->find(StatisticsNewsletterEntity::class, $statisticsNewsletter->getId()))->null(); + verify($this->entityManager->find(StatisticsOpenEntity::class, $statisticsOpen->getId()))->null(); + verify($this->entityManager->find(StatisticsClickEntity::class, $statisticsClick->getId()))->null(); + $statisticsPurchase = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase->getId()); + $this->assertNotNull($statisticsPurchase); + verify($statisticsPurchase->getNewsletter())->null(); + } + + public function testItDeletesMultipleNewslettersWithPurchaseStatsAndKeepsStats() { + $standardNewsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENT); + $statisticsPurchase1 = $this->createPurchaseStatsForNewsletter($standardNewsletter1); + $standardNewsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENT); + $statisticsPurchase2 = $this->createPurchaseStatsForNewsletter($standardNewsletter2); + + // Delete + $this->controller->bulkDelete([(int)$standardNewsletter1->getId(), (int)$standardNewsletter2->getId()]); + + // Clear entity manager to forget all entities + $this->entityManager->clear(); + + // Check Newsletters were deleted + verify($this->repository->findOneById($standardNewsletter1->getId()))->null(); + verify($this->repository->findOneById($standardNewsletter2->getId()))->null(); + + // Check purchase stats were not deleted + $statisticsPurchase1 = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase1->getId()); + $statisticsPurchase2 = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase2->getId()); + $this->assertNotNull($statisticsPurchase1); + verify($statisticsPurchase1->getNewsletter())->null(); + $this->assertNotNull($statisticsPurchase2); + verify($statisticsPurchase2->getNewsletter())->null(); + } + + public function testItDeletesWpPostsBulkDelete() { + $newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); + $post1Id = $this->wp->wpInsertPost(['post_title' => 'Post 1']); + $newsletter1->setWpPost($this->entityManager->getReference(WpPostEntity::class, $post1Id)); + $newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_WELCOME, NewsletterEntity::STATUS_SENDING); + $post2Id = $this->wp->wpInsertPost(['post_title' => 'Post 2']); + $newsletter2->setWpPost($this->entityManager->getReference(WpPostEntity::class, $post2Id)); + $newsletter3 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); + + $blogPost = $this->wp->wpInsertPost(['post_title' => 'Regular blog post']); + + verify($this->wp->getPost($post1Id))->instanceOf(\WP_Post::class); + verify($this->wp->getPost($post2Id))->instanceOf(\WP_Post::class); + + $this->entityManager->flush(); + $this->entityManager->clear(); + + $this->controller->bulkDelete([(int)$newsletter1->getId(), (int)$newsletter2->getId(), (int)$newsletter3->getId()]); + verify($this->wp->getPost($post1Id))->null(); + verify($this->wp->getPost($post2Id))->null(); + verify($this->wp->getPost($blogPost))->instanceOf(\WP_Post::class); + } + + private function createNewsletter(string $type, string $status = NewsletterEntity::STATUS_DRAFT, $parent = null): NewsletterEntity { + $newsletter = new NewsletterEntity(); + $newsletter->setType($type); + $newsletter->setSubject('My Standard Newsletter'); + $newsletter->setBody(Fixtures::get('newsletter_body_template')); + $newsletter->setStatus($status); + $newsletter->setParent($parent); + $this->entityManager->persist($newsletter); + $this->entityManager->flush(); + return $newsletter; + } + + private function createQueueWithTaskAndSegmentAndSubscribers(NewsletterEntity $newsletter, $status = ScheduledTaskEntity::STATUS_SCHEDULED): SendingQueueEntity { + $task = new ScheduledTaskEntity(); + $task->setType(SendingQueue::TASK_TYPE); + $task->setStatus($status); + $this->entityManager->persist($task); + + $queue = new SendingQueueEntity(); + $queue->setNewsletter($newsletter); + $queue->setTask($task); + $this->entityManager->persist($queue); + $newsletter->getQueues()->add($queue); + + $segment = new SegmentEntity("List for newsletter id {$newsletter->getId()}", SegmentEntity::TYPE_DEFAULT, 'Description'); + $this->entityManager->persist($segment); + + $subscriber = new SubscriberEntity(); + $subscriber->setEmail("sub{$newsletter->getId()}@mailpoet.com"); + $subscriber->setStatus(SubscriberEntity::STATUS_SUBSCRIBED); + $this->entityManager->persist($subscriber); + $this->entityManager->flush(); + $scheduledTaskSubscriber = new ScheduledTaskSubscriberEntity($task, $subscriber); + $this->entityManager->persist($scheduledTaskSubscriber); + + $newsletterSegment = new NewsletterSegmentEntity($newsletter, $segment); + $newsletter->getNewsletterSegments()->add($newsletterSegment); + $this->entityManager->persist($newsletterSegment); + $this->entityManager->flush(); + return $queue; + } + + private function createStatNotification(NewsletterEntity $newsletter): StatsNotificationEntity { + $task = new ScheduledTaskEntity(); + $task->setType('stats_notification'); + $task->setStatus(ScheduledTaskEntity::STATUS_SCHEDULED); + $this->entityManager->persist($task); + $statsNotification = new StatsNotificationEntity($newsletter, $task); + $this->entityManager->persist($statsNotification); + $this->entityManager->flush(); + return $statsNotification; + } + + private function createNewsletterLink(NewsletterEntity $newsletter, SendingQueueEntity $queue): NewsletterLinkEntity { + $link = new NewsletterLinkEntity($newsletter, $queue, 'http://example.com', 'abcd'); + $this->entityManager->persist($link); + $this->entityManager->flush(); + return $link; + } + + private function createNewsletterOption(NewsletterEntity $newsletter, NewsletterOptionFieldEntity $field, $value): NewsletterOptionEntity { + $option = new NewsletterOptionEntity($newsletter, $field); + $option->setValue($value); + $this->entityManager->persist($option); + $this->entityManager->flush(); + return $option; + } + + private function createNewsletterPost(NewsletterEntity $newsletter, int $postId): NewsletterPostEntity { + $post = new NewsletterPostEntity($newsletter, $postId); + $this->entityManager->persist($post); + $this->entityManager->flush(); + return $post; + } + + private function createNewsletterStatistics(NewsletterEntity $newsletter, SendingQueueEntity $queue, SubscriberEntity $subscriber): StatisticsNewsletterEntity { + $statisticsNewsletter = new StatisticsNewsletterEntity($newsletter, $queue, $subscriber); + $this->entityManager->persist($statisticsNewsletter); + $this->entityManager->flush(); + return $statisticsNewsletter; + } + + private function createOpenStatistics(NewsletterEntity $newsletter, SendingQueueEntity $queue, SubscriberEntity $subscriber): StatisticsOpenEntity { + $statistics = new StatisticsOpenEntity($newsletter, $queue, $subscriber); + $this->entityManager->persist($statistics); + $this->entityManager->flush(); + return $statistics; + } + + private function createClickStatistics( + NewsletterEntity $newsletter, + SendingQueueEntity $queue, + SubscriberEntity $subscriber, + NewsletterLinkEntity $link + ): StatisticsClickEntity { + $statistics = new StatisticsClickEntity($newsletter, $queue, $subscriber, $link, 1); + $this->entityManager->persist($statistics); + $this->entityManager->flush(); + return $statistics; + } + + private function createPurchaseStatistics( + NewsletterEntity $newsletter, + SendingQueueEntity $queue, + StatisticsClickEntity $click, + SubscriberEntity $subscriber + ): StatisticsWooCommercePurchaseEntity { + $statistics = new StatisticsWooCommercePurchaseEntity($newsletter, $queue, $click, 1, 'EUR', 100, 'completed'); + $statistics->setSubscriber($subscriber); + $this->entityManager->persist($statistics); + $this->entityManager->flush(); + return $statistics; + } + + private function createPurchaseStatsForNewsletter(NewsletterEntity $newsletter): StatisticsWooCommercePurchaseEntity { + $queue = $this->createQueueWithTaskAndSegmentAndSubscribers($newsletter, NewsletterEntity::STATUS_SENT); // Null for scheduled task being processed + $segment = $newsletter->getNewsletterSegments()->first(); + $this->assertInstanceOf(NewsletterSegmentEntity::class, $segment); + $scheduledTask = $queue->getTask(); + $this->assertInstanceOf(ScheduledTaskEntity::class, $scheduledTask); + $scheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $scheduledTask]); + $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $scheduledTaskSubscriber); + $link = $this->createNewsletterLink($newsletter, $queue); + $this->assertInstanceOf(NewsletterLinkEntity::class, $link); + $subscriber = $scheduledTaskSubscriber->getSubscriber(); + $this->assertInstanceOf(SubscriberEntity::class, $subscriber); + $statisticsClick = $this->createClickStatistics($newsletter, $queue, $subscriber, $link); + $this->assertInstanceOf(StatisticsClickEntity::class, $statisticsClick); + return $this->createPurchaseStatistics($newsletter, $queue, $statisticsClick, $subscriber); + } +} diff --git a/mailpoet/tests/integration/Newsletter/NewsletterRepositoryTest.php b/mailpoet/tests/integration/Newsletter/NewsletterRepositoryTest.php index 4bf877151e..408abd6aea 100644 --- a/mailpoet/tests/integration/Newsletter/NewsletterRepositoryTest.php +++ b/mailpoet/tests/integration/Newsletter/NewsletterRepositoryTest.php @@ -5,44 +5,23 @@ namespace MailPoet\Newsletter; use Codeception\Util\Fixtures; use MailPoet\Cron\Workers\SendingQueue\SendingQueue; use MailPoet\Entities\NewsletterEntity; -use MailPoet\Entities\NewsletterLinkEntity; -use MailPoet\Entities\NewsletterOptionEntity; -use MailPoet\Entities\NewsletterOptionFieldEntity; -use MailPoet\Entities\NewsletterPostEntity; use MailPoet\Entities\NewsletterSegmentEntity; use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Entities\ScheduledTaskSubscriberEntity; use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SendingQueueEntity; -use MailPoet\Entities\StatisticsClickEntity; -use MailPoet\Entities\StatisticsNewsletterEntity; -use MailPoet\Entities\StatisticsOpenEntity; -use MailPoet\Entities\StatisticsWooCommercePurchaseEntity; -use MailPoet\Entities\StatsNotificationEntity; use MailPoet\Entities\SubscriberEntity; -use MailPoet\Entities\WpPostEntity; -use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository; -use MailPoet\Test\DataFactories\NewsletterOptionField; use MailPoet\Test\DataFactories\ScheduledTask as ScheduledTaskFactory; use MailPoet\Test\DataFactories\SendingQueue as SendingQueueFactory; -use MailPoet\WP\Functions as WPFunctions; use MailPoetVendor\Carbon\Carbon; class NewsletterRepositoryTest extends \MailPoetTest { /** @var NewslettersRepository */ private $repository; - /** @var ScheduledTaskSubscribersRepository */ - private $taskSubscribersRepository; - - /** @var WPFunctions */ - private $wp; - public function _before() { parent::_before(); $this->repository = $this->diContainer->get(NewslettersRepository::class); - $this->taskSubscribersRepository = $this->diContainer->get(ScheduledTaskSubscribersRepository::class); - $this->wp = $this->diContainer->get(WPFunctions::class); } public function testItBulkTrashNewslettersAndChildren() { @@ -127,149 +106,6 @@ class NewsletterRepositoryTest extends \MailPoetTest { verify($scheduledTask->getStatus())->equals(ScheduledTaskEntity::STATUS_SCHEDULED); } - public function testItBulkDeleteNewslettersAndChildren() { - $standardNewsletter = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); - $standardQueue = $this->createQueueWithTaskAndSegmentAndSubscribers($standardNewsletter, null); // Null for scheduled task being processed - $notification = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE); - $notificationHistory = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION_HISTORY, NewsletterEntity::STATUS_SCHEDULED, $notification); - $notificationHistoryQueue = $this->createQueueWithTaskAndSegmentAndSubscribers($notificationHistory); - - $standardSegment = $standardNewsletter->getNewsletterSegments()->first(); - $this->assertInstanceOf(NewsletterSegmentEntity::class, $standardSegment); - $standardScheduledTaks = $standardQueue->getTask(); - $this->assertInstanceOf(ScheduledTaskEntity::class, $standardScheduledTaks); - $standardScheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $standardScheduledTaks]); - $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $standardScheduledTaskSubscriber); - $notificationHistoryScheduledTask = $notificationHistoryQueue->getTask(); - $this->assertInstanceOf(ScheduledTaskEntity::class, $notificationHistoryScheduledTask); - $notificationHistorySegment = $notificationHistory->getNewsletterSegments()->first(); - $this->assertInstanceOf(NewsletterSegmentEntity::class, $notificationHistorySegment); - $notificationHistoryScheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $notificationHistoryScheduledTask]); - $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $notificationHistoryScheduledTaskSubscriber); - $standardStatsNotification = $this->createStatNotification($standardNewsletter); - $standardStatsNotificationScheduledTask = $standardStatsNotification->getTask(); - $this->assertInstanceOf(ScheduledTaskEntity::class, $standardStatsNotificationScheduledTask); - $notificationHistoryStatsNotification = $this->createStatNotification($notificationHistory); - $notificationHistoryStatsNotificationScheduledTask = $notificationHistoryStatsNotification->getTask(); - $this->assertInstanceOf(ScheduledTaskEntity::class, $notificationHistoryStatsNotificationScheduledTask); - $standardLink = $this->createNewsletterLink($standardNewsletter, $standardQueue); - $notificationHistoryLink = $this->createNewsletterLink($notificationHistory, $notificationHistoryQueue); - $optionField = (new NewsletterOptionField())->findOrCreate('name', NewsletterEntity::TYPE_NOTIFICATION); - $optionValue = $this->createNewsletterOption($notificationHistory, $optionField, 'value'); - $newsletterPost = $this->createNewsletterPost($notification, 1); - - $subscriber = $standardScheduledTaskSubscriber->getSubscriber(); - $this->assertInstanceOf(SubscriberEntity::class, $subscriber); - $statisticsNewsletter = $this->createNewsletterStatistics($standardNewsletter, $standardQueue, $subscriber); - $statisticsOpen = $this->createOpenStatistics($standardNewsletter, $standardQueue, $subscriber); - $statisticsClick = $this->createClickStatistics($standardNewsletter, $standardQueue, $subscriber, $standardLink); - $statisticsPurchase = $this->createPurchaseStatistics($standardNewsletter, $standardQueue, $statisticsClick, $subscriber); - - // Trash - $this->repository->bulkTrash([$standardNewsletter->getId(), $notification->getId()]); - // Delete - $this->repository->bulkDelete([$standardNewsletter->getId(), $notification->getId()]); - - // Clear entity manager to forget all entities - $this->entityManager->clear(); - - // Check they were all deleted - // Newsletters - verify($this->repository->findOneById($standardNewsletter->getId()))->null(); - verify($this->repository->findOneById($notification->getId()))->null(); - verify($this->repository->findOneById($notificationHistory->getId()))->null(); - - // Sending queues - verify($this->entityManager->find(SendingQueueEntity::class, $standardQueue->getId()))->null(); - verify($this->entityManager->find(SendingQueueEntity::class, $notificationHistoryQueue->getId()))->null(); - - // Scheduled tasks subscribers - verify($this->taskSubscribersRepository->findOneBy(['task' => $standardScheduledTaks]))->null(); - verify($this->taskSubscribersRepository->findOneBy(['task' => $notificationHistoryScheduledTask]))->null(); - - // Scheduled tasks - verify($this->entityManager->find(ScheduledTaskEntity::class, $standardScheduledTaks->getId()))->null(); - verify($this->entityManager->find(ScheduledTaskEntity::class, $notificationHistoryScheduledTask->getId()))->null(); - - // Newsletter segments - verify($this->entityManager->find(NewsletterSegmentEntity::class, $standardSegment->getId()))->null(); - verify($this->entityManager->find(NewsletterSegmentEntity::class, $notificationHistorySegment->getId()))->null(); - - // Newsletter stats notifications - verify($this->entityManager->find(StatsNotificationEntity::class, $standardStatsNotificationScheduledTask->getId()))->null(); - verify($this->entityManager->find(StatsNotificationEntity::class, $notificationHistoryStatsNotification->getId()))->null(); - - // Newsletter stats notifications scheduled tasks - verify($this->entityManager->find(ScheduledTaskEntity::class, $standardStatsNotificationScheduledTask->getId()))->null(); - verify($this->entityManager->find(ScheduledTaskEntity::class, $notificationHistoryStatsNotificationScheduledTask->getId()))->null(); - - // Newsletter links - verify($this->entityManager->find(NewsletterLinkEntity::class, $standardLink->getId()))->null(); - verify($this->entityManager->find(NewsletterLinkEntity::class, $notificationHistoryLink->getId()))->null(); - - // Option fields values - verify($this->entityManager->find(NewsletterOptionEntity::class, $optionValue->getId()))->null(); - - // Newsletter post - verify($this->entityManager->find(NewsletterPostEntity::class, $newsletterPost->getId()))->null(); - - // Statistics data - verify($this->entityManager->find(StatisticsNewsletterEntity::class, $statisticsNewsletter->getId()))->null(); - verify($this->entityManager->find(StatisticsOpenEntity::class, $statisticsOpen->getId()))->null(); - verify($this->entityManager->find(StatisticsClickEntity::class, $statisticsClick->getId()))->null(); - $statisticsPurchase = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase->getId()); - $this->assertNotNull($statisticsPurchase); - verify($statisticsPurchase->getNewsletter())->null(); - } - - public function testItDeletesMultipleNewslettersWithPurchaseStatsAndKeepsStats() { - $standardNewsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENT); - $statisticsPurchase1 = $this->createPurchaseStatsForNewsletter($standardNewsletter1); - $standardNewsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENT); - $statisticsPurchase2 = $this->createPurchaseStatsForNewsletter($standardNewsletter2); - - // Delete - $this->repository->bulkDelete([$standardNewsletter1->getId(), $standardNewsletter2->getId()]); - - // Clear entity manager to forget all entities - $this->entityManager->clear(); - - // Check Newsletters were deleted - verify($this->repository->findOneById($standardNewsletter1->getId()))->null(); - verify($this->repository->findOneById($standardNewsletter2->getId()))->null(); - - // Check purchase stats were not deleted - $statisticsPurchase1 = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase1->getId()); - $statisticsPurchase2 = $this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase2->getId()); - $this->assertNotNull($statisticsPurchase1); - verify($statisticsPurchase1->getNewsletter())->null(); - $this->assertNotNull($statisticsPurchase2); - verify($statisticsPurchase2->getNewsletter())->null(); - } - - public function testItDeletesWpPostsBulkDelete() { - $newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); - $post1Id = $this->wp->wpInsertPost(['post_title' => 'Post 1']); - $newsletter1->setWpPost($this->entityManager->getReference(WpPostEntity::class, $post1Id)); - $newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_WELCOME, NewsletterEntity::STATUS_SENDING); - $post2Id = $this->wp->wpInsertPost(['post_title' => 'Post 2']); - $newsletter2->setWpPost($this->entityManager->getReference(WpPostEntity::class, $post2Id)); - $newsletter3 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING); - - $blogPost = $this->wp->wpInsertPost(['post_title' => 'Regular blog post']); - - verify($this->wp->getPost($post1Id))->instanceOf(\WP_Post::class); - verify($this->wp->getPost($post2Id))->instanceOf(\WP_Post::class); - - $this->entityManager->flush(); - $this->entityManager->clear(); - - $this->repository->bulkDelete([$newsletter1->getId(), $newsletter2->getId(), $newsletter3->getId()]); - verify($this->wp->getPost($post1Id))->null(); - verify($this->wp->getPost($post2Id))->null(); - verify($this->wp->getPost($blogPost))->instanceOf(\WP_Post::class); - } - public function testItGetsArchiveNewslettersForSegments() { $types = [ NewsletterEntity::TYPE_STANDARD, @@ -386,93 +222,4 @@ class NewsletterRepositoryTest extends \MailPoetTest { $this->entityManager->flush(); return $queue; } - - private function createStatNotification(NewsletterEntity $newsletter): StatsNotificationEntity { - $task = new ScheduledTaskEntity(); - $task->setType('stats_notification'); - $task->setStatus(ScheduledTaskEntity::STATUS_SCHEDULED); - $this->entityManager->persist($task); - $statsNotification = new StatsNotificationEntity($newsletter, $task); - $this->entityManager->persist($statsNotification); - $this->entityManager->flush(); - return $statsNotification; - } - - private function createNewsletterLink(NewsletterEntity $newsletter, SendingQueueEntity $queue): NewsletterLinkEntity { - $link = new NewsletterLinkEntity($newsletter, $queue, 'http://example.com', 'abcd'); - $this->entityManager->persist($link); - $this->entityManager->flush(); - return $link; - } - - private function createNewsletterOption(NewsletterEntity $newsletter, NewsletterOptionFieldEntity $field, $value): NewsletterOptionEntity { - $option = new NewsletterOptionEntity($newsletter, $field); - $option->setValue($value); - $this->entityManager->persist($option); - $this->entityManager->flush(); - return $option; - } - - private function createNewsletterPost(NewsletterEntity $newsletter, int $postId): NewsletterPostEntity { - $post = new NewsletterPostEntity($newsletter, $postId); - $this->entityManager->persist($post); - $this->entityManager->flush(); - return $post; - } - - private function createNewsletterStatistics(NewsletterEntity $newsletter, SendingQueueEntity $queue, SubscriberEntity $subscriber): StatisticsNewsletterEntity { - $statisticsNewsletter = new StatisticsNewsletterEntity($newsletter, $queue, $subscriber); - $this->entityManager->persist($statisticsNewsletter); - $this->entityManager->flush(); - return $statisticsNewsletter; - } - - private function createOpenStatistics(NewsletterEntity $newsletter, SendingQueueEntity $queue, SubscriberEntity $subscriber): StatisticsOpenEntity { - $statistics = new StatisticsOpenEntity($newsletter, $queue, $subscriber); - $this->entityManager->persist($statistics); - $this->entityManager->flush(); - return $statistics; - } - - private function createClickStatistics( - NewsletterEntity $newsletter, - SendingQueueEntity $queue, - SubscriberEntity $subscriber, - NewsletterLinkEntity $link - ): StatisticsClickEntity { - $statistics = new StatisticsClickEntity($newsletter, $queue, $subscriber, $link, 1); - $this->entityManager->persist($statistics); - $this->entityManager->flush(); - return $statistics; - } - - private function createPurchaseStatistics( - NewsletterEntity $newsletter, - SendingQueueEntity $queue, - StatisticsClickEntity $click, - SubscriberEntity $subscriber - ): StatisticsWooCommercePurchaseEntity { - $statistics = new StatisticsWooCommercePurchaseEntity($newsletter, $queue, $click, 1, 'EUR', 100, 'completed'); - $statistics->setSubscriber($subscriber); - $this->entityManager->persist($statistics); - $this->entityManager->flush(); - return $statistics; - } - - private function createPurchaseStatsForNewsletter(NewsletterEntity $newsletter): StatisticsWooCommercePurchaseEntity { - $queue = $this->createQueueWithTaskAndSegmentAndSubscribers($newsletter, NewsletterEntity::STATUS_SENT); // Null for scheduled task being processed - $segment = $newsletter->getNewsletterSegments()->first(); - $this->assertInstanceOf(NewsletterSegmentEntity::class, $segment); - $scheduledTask = $queue->getTask(); - $this->assertInstanceOf(ScheduledTaskEntity::class, $scheduledTask); - $scheduledTaskSubscriber = $this->taskSubscribersRepository->findOneBy(['task' => $scheduledTask]); - $this->assertInstanceOf(ScheduledTaskSubscriberEntity::class, $scheduledTaskSubscriber); - $link = $this->createNewsletterLink($newsletter, $queue); - $this->assertInstanceOf(NewsletterLinkEntity::class, $link); - $subscriber = $scheduledTaskSubscriber->getSubscriber(); - $this->assertInstanceOf(SubscriberEntity::class, $subscriber); - $statisticsClick = $this->createClickStatistics($newsletter, $queue, $subscriber, $link); - $this->assertInstanceOf(StatisticsClickEntity::class, $statisticsClick); - return $this->createPurchaseStatistics($newsletter, $queue, $statisticsClick, $subscriber); - } } diff --git a/mailpoet/tests/integration/WooCommerce/TrackerTest.php b/mailpoet/tests/integration/WooCommerce/TrackerTest.php index 5fedc98415..fa19366bda 100644 --- a/mailpoet/tests/integration/WooCommerce/TrackerTest.php +++ b/mailpoet/tests/integration/WooCommerce/TrackerTest.php @@ -8,7 +8,7 @@ use MailPoet\Entities\NewsletterOptionEntity; use MailPoet\Entities\NewsletterOptionFieldEntity; use MailPoet\Entities\StatisticsWooCommercePurchaseEntity; use MailPoet\Entities\SubscriberEntity; -use MailPoet\Newsletter\NewslettersRepository; +use MailPoet\Newsletter\NewsletterDeleteController; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Test\DataFactories\Newsletter; @@ -200,8 +200,8 @@ class TrackerTest extends \MailPoetTest { $this->createRevenueRecord($newsletter2, $this->createOrderData(2, 'USD', 10)); $this->createRevenueRecord($newsletter3, $this->createOrderData(3, 'USD', 10)); - $newsletterRepository = $this->diContainer->get(NewslettersRepository::class); - $newsletterRepository->bulkDelete([$newsletter1->getId(), $newsletter2->getId()]); + $newsletterDeleteController = $this->diContainer->get(NewsletterDeleteController::class); + $newsletterDeleteController->bulkDelete([$newsletter1->getId(), $newsletter2->getId()]); $tracker = $this->diContainer->get(Tracker::class); $mailPoetData = $tracker->addTrackingData(['extensions' => []])['extensions']['mailpoet'];