Refactor \MailPoet\Models\Newsletter::getArchives() to Doctrine

[MAILPOET-3629]
This commit is contained in:
Rodrigo Primo
2021-09-09 16:08:52 -03:00
committed by Veljko V
parent 3ca95ed4da
commit 97d177013f
6 changed files with 162 additions and 143 deletions

View File

@@ -2,10 +2,13 @@
namespace MailPoet\Config;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\ScheduledTaskEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Form\Widget;
use MailPoet\Models\Newsletter;
use MailPoet\Models\Subscriber;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Url as NewsletterUrl;
use MailPoet\Segments\SegmentSubscribersRepository;
use MailPoet\Subscribers\SubscribersRepository;
@@ -28,18 +31,23 @@ class Shortcodes {
/** @var NewsletterUrl */
private $newsletterUrl;
/** @var NewslettersRepository */
private $newslettersRepository;
public function __construct(
Pages $subscriptionPages,
WPFunctions $wp,
SegmentSubscribersRepository $segmentSubscribersRepository,
SubscribersRepository $subscribersRepository,
NewsletterUrl $newsletterUrl
NewsletterUrl $newsletterUrl,
NewslettersRepository $newslettersRepository
) {
$this->subscriptionPages = $subscriptionPages;
$this->wp = $wp;
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
$this->subscribersRepository = $subscribersRepository;
$this->newsletterUrl = $newsletterUrl;
$this->newslettersRepository = $newslettersRepository;
}
public function init() {
@@ -110,7 +118,7 @@ class Shortcodes {
$html = '';
$newsletters = Newsletter::getArchives($segmentIds);
$newsletters = $this->newslettersRepository->getArchives($segmentIds);
$subscriber = $this->subscribersRepository->getCurrentWPUser();
$subscriber = $subscriber ? Subscriber::findOne($subscriber->getId()) : null;
@@ -127,10 +135,17 @@ class Shortcodes {
}
$html .= '<ul class="mailpoet_archive">';
foreach ($newsletters as $newsletter) {
$queue = $newsletter->queue()->findOne();
$queue = $newsletter->getQueues()->first();
if ($queue instanceof SendingQueueEntity) {
$task = $queue->getTask();
} else {
$task = null;
}
$html .= '<li>' .
'<span class="mailpoet_archive_date">' .
$this->wp->applyFilters('mailpoet_archive_date', $newsletter) .
$this->wp->applyFilters('mailpoet_archive_date', $task) .
'</span>
<span class="mailpoet_archive_subject">' .
$this->wp->applyFilters('mailpoet_archive_subject', $newsletter, $subscriber, $queue) .
@@ -142,18 +157,27 @@ class Shortcodes {
return $html;
}
public function renderArchiveDate($newsletter) {
public function renderArchiveDate($task) {
$timestamp = null;
if ($task instanceof ScheduledTaskEntity) {
$processedAt = $task->getProcessedAt();
if (!is_null($processedAt)) {
$timestamp = $processedAt->getTimestamp();
}
}
return $this->wp->dateI18n(
$this->wp->getOption('date_format'),
strtotime($newsletter->processedAt)
$timestamp
);
}
public function renderArchiveSubject($newsletter, $subscriber, $queue) {
public function renderArchiveSubject(NewsletterEntity $newsletter, $subscriber, SendingQueueEntity $queue) {
$previewUrl = $this->newsletterUrl->getViewInBrowserUrl($newsletter, $subscriber, $queue);
return '<a href="' . esc_attr($previewUrl) . '" target="_blank" title="'
. esc_attr(__('Preview in a new tab', 'mailpoet')) . '">'
. esc_attr($newsletter->newsletterRenderedSubject) .
. esc_attr((string)$queue->getNewsletterRenderedSubject()) .
'</a>';
}
}

View File

@@ -506,42 +506,6 @@ class Newsletter extends Model {
->findMany();
}
public static function getArchives($segmentIds = []) {
$orm = self::tableAlias('newsletters')
->distinct()->select('newsletters.*')
->select('newsletter_rendered_subject')
->select('task_id')
->whereIn('newsletters.type', [
self::TYPE_STANDARD,
self::TYPE_NOTIFICATION_HISTORY,
])
->join(
MP_SENDING_QUEUES_TABLE,
'queues.newsletter_id = newsletters.id',
'queues'
)
->join(
MP_SCHEDULED_TASKS_TABLE,
'queues.task_id = tasks.id',
'tasks'
)
->where('tasks.status', SendingQueue::STATUS_COMPLETED)
->whereNull('newsletters.deleted_at')
->select('tasks.processed_at')
->orderByDesc('tasks.processed_at')
->orderByAsc('task_id');
if (!empty($segmentIds)) {
$orm->join(
MP_NEWSLETTER_SEGMENT_TABLE,
'newsletter_segments.newsletter_id = newsletters.id',
'newsletter_segments'
)
->whereIn('newsletter_segments.segment_id', $segmentIds);
}
return $orm->findMany();
}
public static function getByHash($hash) {
return parent::where('hash', $hash)
->findOne();

View File

@@ -129,6 +129,40 @@ class NewslettersRepository extends Repository {
];
}
/**
* @param array $segmentIds
* @return NewsletterEntity[]
*/
public function getArchives(array $segmentIds = []) {
$types = [
NewsletterEntity::TYPE_STANDARD,
NewsletterEntity::TYPE_NOTIFICATION_HISTORY,
];
$queryBuilder = $this->entityManager
->createQueryBuilder()
->select('n')
->distinct()
->from(NewsletterEntity::class, 'n')
->innerJoin(SendingQueueEntity::class, 'sq', Join::WITH, 'sq.newsletter = n.id')
->innerJoin(ScheduledTaskEntity::class, 'st', Join::WITH, 'st.id = sq.task')
->where('n.type IN (:types)')
->andWhere('st.status = :statusCompleted')
->andWhere('n.deletedAt IS NULL')
->orderBy('st.processedAt', 'DESC')
->addOrderBy('st.id', 'ASC')
->setParameter('types', $types)
->setParameter('statusCompleted', SendingQueueEntity::STATUS_COMPLETED);
if (!empty($segmentIds)) {
$queryBuilder->innerJoin(NewsletterSegmentEntity::class, 'ns', Join::WITH, 'ns.newsletter = n.id')
->andWhere('ns.segment IN (:segmentIds)')
->setParameter('segmentIds', $segmentIds);
}
return $queryBuilder->getQuery()->getResult();
}
/**
* @return int - number of processed ids
*/

View File

@@ -2,6 +2,8 @@
namespace MailPoet\Newsletter;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Models\Subscriber as SubscriberModel;
use MailPoet\Router\Endpoints\ViewInBrowser as ViewInBrowserEndpoint;
@@ -45,22 +47,30 @@ class Url {
}
public function createUrlDataObject($newsletter, $subscriber, $queue, $preview) {
if ($newsletter instanceof NewsletterEntity) {
$newsletterId = (!empty($newsletter->getId())) ? (int)$newsletter->getId() : 0;
$newsletterHash = (!empty($newsletter->getHash())) ? $newsletter->getHash() : 0;
} else {
$newsletterId = (!empty($newsletter->id)) ? (int)$newsletter->id : 0;
$newsletterHash = (!empty($newsletter->hash)) ? $newsletter->hash : 0;
}
if ($queue instanceof SendingQueueEntity) {
$sendingQueueId = (!empty($queue->getId())) ? (int)$queue->getId() : 0;
} else {
$sendingQueueId = (!empty($queue->id)) ? (int)$queue->id : 0;
}
return [
(!empty($newsletter->id)) ?
(int)$newsletter->id :
0,
(!empty($newsletter->hash)) ?
$newsletter->hash :
0,
$newsletterId,
$newsletterHash,
(!empty($subscriber->id)) ?
(int)$subscriber->id :
0,
(!empty($subscriber->token)) ?
$subscriber->token :
0,
(!empty($queue->id)) ?
(int)$queue->id :
0,
$sendingQueueId,
(int)$preview,
];
}

View File

@@ -204,93 +204,6 @@ class NewsletterTest extends \MailPoetTest {
expect($newsletter->event)->equals($association->value);
}
public function testItGetsArchiveNewslettersForSegments() {
// clear the DB
$this->_after();
$types = [
Newsletter::TYPE_STANDARD,
Newsletter::TYPE_NOTIFICATION_HISTORY,
];
$newsletters = [];
$sendingQueues[] = [];
for ($i = 0; $i < count($types); $i++) {
$newsletters[$i] = Newsletter::createOrUpdate(
[
'subject' => 'My Standard Newsletter',
'preheader' => 'Pre Header',
'type' => $types[$i],
]
);
$sendingQueues[$i] = SendingTask::create();
$sendingQueues[$i]->newsletter_id = $newsletters[$i]->id;
$sendingQueues[$i]->status = SendingQueue::STATUS_COMPLETED;
$sendingQueues[$i]->save();
}
// set segment association for the last newsletter
$newsletterSegment = NewsletterSegment::create();
$newsletterSegment->newsletterId = end($newsletters[1])->id;
$newsletterSegment->segmentId = 123;
$newsletterSegment->save();
expect(Newsletter::findMany())->count(2);
// return archives in segment 123
$results = Newsletter::getArchives([123]);
expect($results)->count(1);
expect($results[0]->id)->equals($newsletters[1]->id);
expect($results[0]->type)->equals(Newsletter::TYPE_NOTIFICATION_HISTORY);
}
public function testItGetsAllArchiveNewsletters() {
// clear the DB
$this->_after();
$types = [
Newsletter::TYPE_STANDARD,
Newsletter::TYPE_STANDARD, // should be returned
Newsletter::TYPE_WELCOME,
Newsletter::TYPE_AUTOMATIC,
Newsletter::TYPE_NOTIFICATION,
Newsletter::TYPE_NOTIFICATION_HISTORY, // should be returned
Newsletter::TYPE_NOTIFICATION_HISTORY,
];
$newsletters = [];
$sendingQueues[] = [];
for ($i = 0; $i < count($types); $i++) {
$newsletters[$i] = Newsletter::createOrUpdate(
[
'subject' => 'My Standard Newsletter',
'preheader' => 'Pre Header',
'type' => $types[$i],
]
);
$sendingQueues[$i] = SendingTask::create();
$sendingQueues[$i]->newsletter_id = $newsletters[$i]->id;
$sendingQueues[$i]->status = SendingQueue::STATUS_COMPLETED;
$sendingQueues[$i]->save();
}
// set the sending queue status of the first newsletter to null
$sendingQueues[0]->status = null;
$sendingQueues[0]->save();
// trash the last newsletter
end($newsletters)->trash();
expect(Newsletter::findMany())->count(7);
// archives return only:
// 1. STANDARD and NOTIFICATION HISTORY newsletters
// 2. active newsletters (i.e., not trashed)
// 3. with sending queue records that are COMPLETED
$results = Newsletter::getArchives();
expect($results)->count(2);
expect($results[0]->id)->equals($newsletters[1]->id);
expect($results[0]->type)->equals(Newsletter::TYPE_STANDARD);
expect($results[1]->id)->equals($newsletters[5]->id);
expect($results[1]->type)->equals(Newsletter::TYPE_NOTIFICATION_HISTORY);
}
public function testItGeneratesHashOnNewsletterSave() {
expect(strlen($this->newsletter->hash))
->equals(Security::HASH_LENGTH);

View File

@@ -19,8 +19,10 @@ use MailPoet\Entities\StatisticsOpenEntity;
use MailPoet\Entities\StatisticsWooCommercePurchaseEntity;
use MailPoet\Entities\StatsNotificationEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Models\Newsletter;
use MailPoet\Newsletter\Sending\ScheduledTaskSubscribersRepository;
use MailPoet\Tasks\Sending as SendingTask;
use MailPoetVendor\Carbon\Carbon;
class NewsletterRepositoryTest extends \MailPoetTest {
/** @var NewslettersRepository */
@@ -211,8 +213,65 @@ class NewsletterRepositoryTest extends \MailPoetTest {
expect($this->entityManager->find(StatisticsWooCommercePurchaseEntity::class, $statisticsPurchase->getId()))->null();
}
public function _after() {
$this->cleanup();
public function testItGetsArchiveNewslettersForSegments() {
$types = [
NewsletterEntity::TYPE_STANDARD,
NewsletterEntity::TYPE_NOTIFICATION_HISTORY,
];
list($newsletters) = $this->createNewslettersAndSendingTasks($types);
// set segment association for the last newsletter
$segment = new SegmentEntity('Segment', SegmentEntity::TYPE_DEFAULT, 'description');
$this->entityManager->persist($segment);
$newsletterSegment = new NewsletterSegmentEntity($newsletters[1], $segment);
$this->entityManager->persist($newsletterSegment);
$this->entityManager->flush();
expect($this->repository->findAll())->count(2);
// return archives in a given segment
$results = $this->repository->getArchives([$segment->getId()]);
expect($results)->count(1);
expect($results[0]->getId())->equals($newsletters[1]->getId());
expect($results[0]->getType())->equals(NewsletterEntity::TYPE_NOTIFICATION_HISTORY);
}
public function testItGetsAllArchiveNewsletters() {
$types = [
Newsletter::TYPE_STANDARD,
Newsletter::TYPE_STANDARD, // should be returned
Newsletter::TYPE_WELCOME,
Newsletter::TYPE_AUTOMATIC,
Newsletter::TYPE_NOTIFICATION,
Newsletter::TYPE_NOTIFICATION_HISTORY, // should be returned
Newsletter::TYPE_NOTIFICATION_HISTORY,
];
list($newsletters, $sendingQueues) = $this->createNewslettersAndSendingTasks($types);
// set the sending queue status of the first newsletter to null
$sendingQueues[0]->status = null;
$sendingQueues[0]->save();
// trash the last newsletter
end($newsletters)->setDeletedAt(new Carbon());
$this->entityManager->flush();
expect($this->repository->findAll())->count(7);
// archives return only:
// 1. STANDARD and NOTIFICATION HISTORY newsletters
// 2. active newsletters (i.e., not trashed)
// 3. with sending queue records that are COMPLETED
$results = $this->repository->getArchives();
expect($results)->count(2);
expect($results[0]->getId())->equals($newsletters[1]->getId());
expect($results[0]->getType())->equals(NewsletterEntity::TYPE_STANDARD);
expect($results[1]->getId())->equals($newsletters[5]->getId());
expect($results[1]->getType())->equals(NewsletterEntity::TYPE_NOTIFICATION_HISTORY);
}
private function createNewsletter(string $type, string $status = NewsletterEntity::STATUS_DRAFT, $parent = null): NewsletterEntity {
@@ -227,6 +286,21 @@ class NewsletterRepositoryTest extends \MailPoetTest {
return $newsletter;
}
private function createNewslettersAndSendingTasks(array $types): array {
$newsletters = [];
$sendingQueues = [];
for ($i = 0; $i < count($types); $i++) {
$newsletters[$i] = $this->createNewsletter($types[$i]);
$sendingQueues[$i] = SendingTask::create();
$sendingQueues[$i]->newsletter_id = $newsletters[$i]->getId();
$sendingQueues[$i]->status = SendingQueueEntity::STATUS_COMPLETED;
$sendingQueues[$i]->save();
}
return [$newsletters, $sendingQueues];
}
private function createQueueWithTaskAndSegmentAndSubscribers(NewsletterEntity $newsletter, $status = ScheduledTaskEntity::STATUS_SCHEDULED): SendingQueueEntity {
$task = new ScheduledTaskEntity();
$task->setType(SendingTask::TASK_TYPE);