Add check for orphaned newsletter links

[MAILPOET-1587]
This commit is contained in:
Rostislav Wolny
2024-08-01 14:02:38 +02:00
committed by Aschepikov
parent fe66e31b5f
commit 45114e4da2
4 changed files with 62 additions and 0 deletions

View File

@@ -28,6 +28,7 @@ export function DataInconsistencies({ dataInconsistencies }: Props) {
'mailpoet',
),
orphaned_subscriptions: __('Orphaned Subscriptions', 'mailpoet'),
orphaned_links: __('Orphaned Links', 'mailpoet'),
}),
[],
);

View File

@@ -9,12 +9,14 @@ class DataInconsistencyController {
const ORPHANED_SENDING_TASK_SUBSCRIBERS = 'orphaned_sending_task_subscribers';
const SENDING_QUEUE_WITHOUT_NEWSLETTER = 'sending_queue_without_newsletter';
const ORPHANED_SUBSCRIPTIONS = 'orphaned_subscriptions';
const ORPHANED_LINKS = 'orphaned_links';
const SUPPORTED_INCONSISTENCY_CHECKS = [
self::ORPHANED_SENDING_TASKS,
self::ORPHANED_SENDING_TASK_SUBSCRIBERS,
self::SENDING_QUEUE_WITHOUT_NEWSLETTER,
self::ORPHANED_SUBSCRIPTIONS,
self::ORPHANED_LINKS,
];
private DataInconsistencyRepository $repository;
@@ -31,6 +33,7 @@ class DataInconsistencyController {
self::ORPHANED_SENDING_TASK_SUBSCRIBERS => $this->repository->getOrphanedScheduledTasksSubscribersCount(),
self::SENDING_QUEUE_WITHOUT_NEWSLETTER => $this->repository->getSendingQueuesWithoutNewsletterCount(),
self::ORPHANED_SUBSCRIPTIONS => $this->repository->getOrphanedSubscriptionsCount(),
self::ORPHANED_LINKS => $this->repository->getOrphanedNewsletterLinksCount(),
];
$result['total'] = array_sum($result);
return $result;
@@ -48,6 +51,8 @@ class DataInconsistencyController {
$this->repository->cleanupSendingQueuesWithoutNewsletter();
} elseif ($inconsistency === self::ORPHANED_SUBSCRIPTIONS) {
$this->repository->cleanupOrphanedSubscriptions();
} elseif ($inconsistency === self::ORPHANED_LINKS) {
$this->repository->cleanupOrphanedNewsletterLinks();
}
}
}

View File

@@ -4,6 +4,7 @@ namespace MailPoet\Util\DataInconsistency;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterLinkEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\ScheduledTaskSubscriberEntity;
use MailPoet\Entities\SegmentEntity;
@@ -64,6 +65,19 @@ class DataInconsistencyRepository {
return intval($count);
}
public function getOrphanedNewsletterLinksCount(): int {
$newsletterTable = $this->entityManager->getClassMetadata(NewsletterEntity::class)->getTableName();
$sendingQueueTable = $this->entityManager->getClassMetadata(SendingQueueEntity::class)->getTableName();
$newsletterLinkTable = $this->entityManager->getClassMetadata(NewsletterLinkEntity::class)->getTableName();
$count = $this->entityManager->getConnection()->executeQuery("
SELECT count(distinct nl.`id`) FROM $newsletterLinkTable nl
LEFT JOIN $newsletterTable n ON n.`id` = nl.`newsletter_id`
LEFT JOIN $sendingQueueTable sq ON sq.`id` = nl.`queue_id`
WHERE n.`id` IS NULL OR sq.`id` IS NULL
")->fetchOne();
return intval($count);
}
public function cleanupOrphanedSendingTasks(): int {
$ids = $this->buildOrphanedSendingTasksQuery(
$this->entityManager->createQueryBuilder()
@@ -128,6 +142,18 @@ class DataInconsistencyRepository {
");
}
public function cleanupOrphanedNewsletterLinks(): int {
$newsletterTable = $this->entityManager->getClassMetadata(NewsletterEntity::class)->getTableName();
$sendingQueueTable = $this->entityManager->getClassMetadata(SendingQueueEntity::class)->getTableName();
$newsletterLinkTable = $this->entityManager->getClassMetadata(NewsletterLinkEntity::class)->getTableName();
return (int)$this->entityManager->getConnection()->executeStatement("
DELETE nl FROM $newsletterLinkTable nl
LEFT JOIN $newsletterTable n ON n.`id` = nl.`newsletter_id`
LEFT JOIN $sendingQueueTable sq ON sq.`id` = nl.`queue_id`
WHERE n.`id` IS NULL OR sq.`id` IS NULL
");
}
private function buildOrphanedSendingTasksQuery(QueryBuilder $queryBuilder): Query {
return $queryBuilder
->from(ScheduledTaskEntity::class, 'st')

View File

@@ -8,6 +8,7 @@ use MailPoet\Entities\ScheduledTaskSubscriberEntity;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Test\DataFactories\NewsletterLink;
use MailPoet\Test\DataFactories\ScheduledTask;
use MailPoet\Test\DataFactories\ScheduledTaskSubscriber;
use MailPoet\Test\DataFactories\Segment;
@@ -129,4 +130,33 @@ class DataInconsistencyRepositoryTest extends \MailPoetTest {
$segmentToKeep = $this->entityManager->find(SegmentEntity::class, $segmentToKeep->getId());
$this->assertInstanceOf(SegmentEntity::class, $segmentToKeep);
}
public function testItHandlesOrphanedLinks(): void {
$newsletterToDelete = (new Newsletter())->create();
$task1 = (new ScheduledTask())->create(SendingQueueWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED);
(new SendingQueue())->create($task1, $newsletterToDelete);
$this->entityManager->refresh($newsletterToDelete);
$newsletterToKeep = (new Newsletter())->create();
$task2 = (new ScheduledTask())->create(SendingQueueWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED);
$queueToDelete = (new SendingQueue())->create($task2, $newsletterToKeep);
$this->entityManager->refresh($newsletterToKeep);
$newsletterToKeep2 = (new Newsletter())->create();
$task3 = (new ScheduledTask())->create(SendingQueueWorker::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED);
(new SendingQueue())->create($task3, $newsletterToKeep2);
$this->entityManager->refresh($newsletterToKeep2);
(new NewsletterLink($newsletterToDelete))->create();
(new NewsletterLink($newsletterToKeep))->create();
(new NewsletterLink($newsletterToKeep2))->create();
$this->entityManager->remove($newsletterToDelete);
$this->entityManager->remove($queueToDelete);
$this->entityManager->flush();
verify($this->repository->getOrphanedNewsletterLinksCount())->equals(2);
$this->repository->cleanupOrphanedNewsletterLinks();
verify($this->repository->getOrphanedNewsletterLinksCount())->equals(0);
}
}