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:
@@ -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()
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
156
mailpoet/lib/Newsletter/NewsletterDeleteController.php
Normal file
156
mailpoet/lib/Newsletter/NewsletterDeleteController.php
Normal 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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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'];
|
||||
|
Reference in New Issue
Block a user