Add check for orphaned newsletter posts

[MAILPOET-1587]
This commit is contained in:
Rostislav Wolny
2024-08-01 14:50:18 +02:00
committed by Aschepikov
parent 45114e4da2
commit 9b8af4cafd
5 changed files with 92 additions and 0 deletions

View File

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

View File

@@ -10,6 +10,7 @@ class DataInconsistencyController {
const SENDING_QUEUE_WITHOUT_NEWSLETTER = 'sending_queue_without_newsletter'; const SENDING_QUEUE_WITHOUT_NEWSLETTER = 'sending_queue_without_newsletter';
const ORPHANED_SUBSCRIPTIONS = 'orphaned_subscriptions'; const ORPHANED_SUBSCRIPTIONS = 'orphaned_subscriptions';
const ORPHANED_LINKS = 'orphaned_links'; const ORPHANED_LINKS = 'orphaned_links';
const ORPHANED_NEWSLETTER_POSTS = 'orphaned_newsletter_posts';
const SUPPORTED_INCONSISTENCY_CHECKS = [ const SUPPORTED_INCONSISTENCY_CHECKS = [
self::ORPHANED_SENDING_TASKS, self::ORPHANED_SENDING_TASKS,
@@ -17,6 +18,7 @@ class DataInconsistencyController {
self::SENDING_QUEUE_WITHOUT_NEWSLETTER, self::SENDING_QUEUE_WITHOUT_NEWSLETTER,
self::ORPHANED_SUBSCRIPTIONS, self::ORPHANED_SUBSCRIPTIONS,
self::ORPHANED_LINKS, self::ORPHANED_LINKS,
self::ORPHANED_NEWSLETTER_POSTS,
]; ];
private DataInconsistencyRepository $repository; private DataInconsistencyRepository $repository;
@@ -34,6 +36,7 @@ class DataInconsistencyController {
self::SENDING_QUEUE_WITHOUT_NEWSLETTER => $this->repository->getSendingQueuesWithoutNewsletterCount(), self::SENDING_QUEUE_WITHOUT_NEWSLETTER => $this->repository->getSendingQueuesWithoutNewsletterCount(),
self::ORPHANED_SUBSCRIPTIONS => $this->repository->getOrphanedSubscriptionsCount(), self::ORPHANED_SUBSCRIPTIONS => $this->repository->getOrphanedSubscriptionsCount(),
self::ORPHANED_LINKS => $this->repository->getOrphanedNewsletterLinksCount(), self::ORPHANED_LINKS => $this->repository->getOrphanedNewsletterLinksCount(),
self::ORPHANED_NEWSLETTER_POSTS => $this->repository->getOrphanedNewsletterPostsCount(),
]; ];
$result['total'] = array_sum($result); $result['total'] = array_sum($result);
return $result; return $result;
@@ -53,6 +56,8 @@ class DataInconsistencyController {
$this->repository->cleanupOrphanedSubscriptions(); $this->repository->cleanupOrphanedSubscriptions();
} elseif ($inconsistency === self::ORPHANED_LINKS) { } elseif ($inconsistency === self::ORPHANED_LINKS) {
$this->repository->cleanupOrphanedNewsletterLinks(); $this->repository->cleanupOrphanedNewsletterLinks();
} elseif ($inconsistency === self::ORPHANED_NEWSLETTER_POSTS) {
$this->repository->cleanupOrphanedNewsletterPosts();
} }
} }
} }

View File

@@ -5,6 +5,7 @@ namespace MailPoet\Util\DataInconsistency;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue; use MailPoet\Cron\Workers\SendingQueue\SendingQueue;
use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterLinkEntity; use MailPoet\Entities\NewsletterLinkEntity;
use MailPoet\Entities\NewsletterPostEntity;
use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\ScheduledTaskSubscriberEntity; use MailPoet\Entities\ScheduledTaskSubscriberEntity;
use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SegmentEntity;
@@ -78,6 +79,17 @@ class DataInconsistencyRepository {
return intval($count); return intval($count);
} }
public function getOrphanedNewsletterPostsCount(): int {
$newsletterTable = $this->entityManager->getClassMetadata(NewsletterEntity::class)->getTableName();
$newsletterPostTable = $this->entityManager->getClassMetadata(NewsletterPostEntity::class)->getTableName();
$count = $this->entityManager->getConnection()->executeQuery("
SELECT count(distinct np.`id`) FROM $newsletterPostTable np
LEFT JOIN $newsletterTable n ON n.`id` = np.`newsletter_id`
WHERE n.`id` IS NULL
")->fetchOne();
return intval($count);
}
public function cleanupOrphanedSendingTasks(): int { public function cleanupOrphanedSendingTasks(): int {
$ids = $this->buildOrphanedSendingTasksQuery( $ids = $this->buildOrphanedSendingTasksQuery(
$this->entityManager->createQueryBuilder() $this->entityManager->createQueryBuilder()
@@ -154,6 +166,16 @@ class DataInconsistencyRepository {
"); ");
} }
public function cleanupOrphanedNewsletterPosts(): int {
$newsletterTable = $this->entityManager->getClassMetadata(NewsletterEntity::class)->getTableName();
$newsletterPostTable = $this->entityManager->getClassMetadata(NewsletterPostEntity::class)->getTableName();
return (int)$this->entityManager->getConnection()->executeStatement("
DELETE np FROM $newsletterPostTable np
LEFT JOIN $newsletterTable n ON n.`id` = np.`newsletter_id`
WHERE n.`id` IS NULL
");
}
private function buildOrphanedSendingTasksQuery(QueryBuilder $queryBuilder): Query { private function buildOrphanedSendingTasksQuery(QueryBuilder $queryBuilder): Query {
return $queryBuilder return $queryBuilder
->from(ScheduledTaskEntity::class, 'st') ->from(ScheduledTaskEntity::class, 'st')

View File

@@ -0,0 +1,49 @@
<?php declare(strict_types = 1);
namespace MailPoet\Test\DataFactories;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterPostEntity;
use MailPoetVendor\Doctrine\ORM\EntityManager;
class NewsletterPost {
protected $data;
/** @var NewsletterEntity */
private $newsletter;
public function __construct(
NewsletterEntity $newsletter
) {
$this->data = [
'post_id' => 1,
];
$this->newsletter = $newsletter;
}
public function withPostId($id) {
$this->data['post_id'] = $id;
return $this;
}
/**
* @param string $createdAt in format Y-m-d H:i:s
* @return self
*/
public function withCreatedAt($createdAt) {
$this->data['created_at'] = $createdAt;
return $this;
}
public function create(): NewsletterPostEntity {
$entityManager = ContainerWrapper::getInstance()->get(EntityManager::class);
$entity = new NewsletterPostEntity(
$this->newsletter,
$this->data['post_id'],
);
$entityManager->persist($entity);
$entityManager->flush();
return $entity;
}
}

View File

@@ -9,6 +9,7 @@ use MailPoet\Entities\SegmentEntity;
use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberEntity;
use MailPoet\Test\DataFactories\Newsletter; use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Test\DataFactories\NewsletterLink; use MailPoet\Test\DataFactories\NewsletterLink;
use MailPoet\Test\DataFactories\NewsletterPost;
use MailPoet\Test\DataFactories\ScheduledTask; use MailPoet\Test\DataFactories\ScheduledTask;
use MailPoet\Test\DataFactories\ScheduledTaskSubscriber; use MailPoet\Test\DataFactories\ScheduledTaskSubscriber;
use MailPoet\Test\DataFactories\Segment; use MailPoet\Test\DataFactories\Segment;
@@ -159,4 +160,18 @@ class DataInconsistencyRepositoryTest extends \MailPoetTest {
$this->repository->cleanupOrphanedNewsletterLinks(); $this->repository->cleanupOrphanedNewsletterLinks();
verify($this->repository->getOrphanedNewsletterLinksCount())->equals(0); verify($this->repository->getOrphanedNewsletterLinksCount())->equals(0);
} }
public function testItHandlesOrphanedNewsletterPosts(): void {
$newsletterToDelete = (new Newsletter())->create();
$newsletterToKeep = (new Newsletter())->create();
(new NewsletterPost($newsletterToDelete))->create();
(new NewsletterPost($newsletterToKeep))->create();
$this->entityManager->remove($newsletterToDelete);
$this->entityManager->flush();
verify($this->repository->getOrphanedNewsletterPostsCount())->equals(1);
$this->repository->cleanupOrphanedNewsletterPosts();
verify($this->repository->getOrphanedNewsletterPostsCount())->equals(0);
}
} }