Extract newsletter bulk delete logic to a controller

Repositories shouldn't inject other repositories. Also, this solves circular DI dependency.

[MAILPOET-5845]
This commit is contained in:
Jan Jakes
2024-01-18 17:31:34 +01:00
committed by Aschepikov
parent 82d5621caf
commit d6da2af55b
10 changed files with 511 additions and 402 deletions

View File

@@ -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()

View File

@@ -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(

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -0,0 +1,156 @@
<?php declare(strict_types = 1);
namespace MailPoet\Newsletter;
use MailPoet\Cron\Workers\StatsNotifications\NewsletterLinkRepository;
use MailPoet\Cron\Workers\StatsNotifications\StatsNotificationsRepository;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\StatsNotificationEntity;
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\WP\Functions as WPFunctions;
use MailPoetVendor\Doctrine\ORM\EntityManager;
use Throwable;
class NewsletterDeleteController {
private EntityManager $entityManager;
private NewslettersRepository $newslettersRepository;
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,
NewslettersRepository $newslettersRepository,
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
) {
$this->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);
}
}

View File

@@ -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<NewsletterEntity>
*/
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);
}
}

View File

@@ -0,0 +1,317 @@
<?php declare(strict_types = 1);
namespace MailPoet\Test\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\NewsletterDeleteController;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository;
use MailPoet\Test\DataFactories\NewsletterOptionField;
use MailPoet\WP\Functions as WPFunctions;
class NewsletterDeleteControllerTest extends \MailPoetTest {
private NewsletterDeleteController $controller;
private NewslettersRepository $repository;
private ScheduledTaskSubscribersRepository $taskSubscribersRepository;
private WPFunctions $wp;
public function _before() {
parent::_before();
$this->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);
}
}

View File

@@ -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);
}
}

View File

@@ -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'];