Skip to content

Commit e85d520

Browse files
committed
Campaign processor
1 parent 2f92e74 commit e85d520

File tree

6 files changed

+426
-207
lines changed

6 files changed

+426
-207
lines changed

config/services/services.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ services:
2929
autowire: true
3030
autoconfigure: true
3131
public: true
32+
33+
PhpList\Core\Domain\Messaging\Service\CampaignProcessor:
34+
autowire: true
35+
autoconfigure: true
36+
public: true

src/Domain/Messaging/Command/ProcessQueueCommand.php

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,38 @@
44

55
namespace PhpList\Core\Domain\Messaging\Command;
66

7+
use PhpList\Core\Domain\Messaging\Service\CampaignProcessor;
78
use Symfony\Component\Console\Command\Command;
89
use Symfony\Component\Console\Input\InputInterface;
910
use Symfony\Component\Console\Output\OutputInterface;
10-
use Doctrine\ORM\EntityManagerInterface;
11-
use PhpList\Core\Domain\Messaging\Model\Message;
1211
use PhpList\Core\Domain\Messaging\Repository\MessageRepository;
1312
use PhpList\Core\Domain\Messaging\Service\MessageProcessingPreparator;
14-
use PhpList\Core\Domain\Subscription\Service\Provider\SubscriberProvider;
1513
use Symfony\Component\Lock\LockFactory;
16-
use Symfony\Component\Mailer\MailerInterface;
17-
use Symfony\Component\Mime\Email;
14+
use Symfony\Component\Console\Attribute\AsCommand;
1815
use Throwable;
1916

17+
#[AsCommand(
18+
name: 'phplist:process-queue',
19+
description: 'Processes the email campaign queue.'
20+
)]
2021
class ProcessQueueCommand extends Command
2122
{
22-
protected static $defaultName = 'phplist:process-queue';
23-
2423
private MessageRepository $messageRepository;
25-
private MailerInterface $mailer;
2624
private LockFactory $lockFactory;
27-
private EntityManagerInterface $entityManager;
28-
private SubscriberProvider $subscriberProvider;
2925
private MessageProcessingPreparator $messagePreparator;
26+
private CampaignProcessor $campaignProcessor;
3027

3128
public function __construct(
3229
MessageRepository $messageRepository,
33-
MailerInterface $mailer,
3430
LockFactory $lockFactory,
35-
EntityManagerInterface $entityManager,
36-
SubscriberProvider $subscriberProvider,
37-
MessageProcessingPreparator $messagePreparator
31+
MessageProcessingPreparator $messagePreparator,
32+
CampaignProcessor $campaignProcessor,
3833
) {
3934
parent::__construct();
4035
$this->messageRepository = $messageRepository;
41-
$this->mailer = $mailer;
4236
$this->lockFactory = $lockFactory;
43-
$this->entityManager = $entityManager;
44-
$this->subscriberProvider = $subscriberProvider;
4537
$this->messagePreparator = $messagePreparator;
38+
$this->campaignProcessor = $campaignProcessor;
4639
}
4740

4841
/**
@@ -64,45 +57,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6457
$campaigns = $this->messageRepository->findBy(['status' => 'submitted']);
6558

6659
foreach ($campaigns as $campaign) {
67-
$this->processCampaign($campaign, $output);
60+
$this->campaignProcessor->process($campaign, $output);
6861
}
62+
} catch (Throwable $throwable) {
63+
$output->writeln($throwable->getMessage());
64+
65+
return Command::FAILURE;
6966
} finally {
7067
$lock->release();
7168
}
7269

7370
return Command::SUCCESS;
7471
}
75-
76-
private function processCampaign(Message $campaign, OutputInterface $output): void
77-
{
78-
$subscribers = $this->subscriberProvider->getSubscribersForMessage($campaign);
79-
// phpcs:ignore Generic.Commenting.Todo
80-
// @todo check $ISPrestrictions logic
81-
foreach ($subscribers as $subscriber) {
82-
if (!filter_var($subscriber->getEmail(), FILTER_VALIDATE_EMAIL)) {
83-
continue;
84-
}
85-
$this->messagePreparator->processMessageLinks($campaign, $subscriber->getId());
86-
$email = (new Email())
87-
88-
->to($subscriber->getEmail())
89-
->subject($campaign->getContent()->getSubject())
90-
->text($campaign->getContent()->getTextMessage())
91-
->html($campaign->getContent()->getText());
92-
93-
try {
94-
$this->mailer->send($email);
95-
96-
// phpcs:ignore Generic.Commenting.Todo
97-
// @todo log somewhere that this subscriber got email
98-
} catch (Throwable $e) {
99-
$output->writeln('Failed to send to: ' . $subscriber->getEmail());
100-
}
101-
102-
usleep(100000);
103-
}
104-
105-
$campaign->getMetadata()->setStatus('sent');
106-
$this->entityManager->flush();
107-
}
10872
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Messaging\Service;
6+
7+
use Doctrine\ORM\EntityManagerInterface;
8+
use PhpList\Core\Domain\Messaging\Model\Message;
9+
use PhpList\Core\Domain\Subscription\Service\Provider\SubscriberProvider;
10+
use Psr\Log\LoggerInterface;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
use Symfony\Component\Mailer\MailerInterface;
13+
use Symfony\Component\Mime\Email;
14+
use Throwable;
15+
16+
class CampaignProcessor
17+
{
18+
private MailerInterface $mailer;
19+
private EntityManagerInterface $entityManager;
20+
private SubscriberProvider $subscriberProvider;
21+
private MessageProcessingPreparator $messagePreparator;
22+
private LoggerInterface $logger;
23+
24+
public function __construct(
25+
MailerInterface $mailer,
26+
EntityManagerInterface $entityManager,
27+
SubscriberProvider $subscriberProvider,
28+
MessageProcessingPreparator $messagePreparator,
29+
LoggerInterface $logger,
30+
) {
31+
$this->mailer = $mailer;
32+
$this->entityManager = $entityManager;
33+
$this->subscriberProvider = $subscriberProvider;
34+
$this->messagePreparator = $messagePreparator;
35+
$this->logger = $logger;
36+
}
37+
38+
public function process(Message $campaign, ?OutputInterface $output = null): void
39+
{
40+
$subscribers = $this->subscriberProvider->getSubscribersForMessage($campaign);
41+
// phpcs:ignore Generic.Commenting.Todo
42+
// @todo check $ISPrestrictions logic
43+
foreach ($subscribers as $subscriber) {
44+
if (!filter_var($subscriber->getEmail(), FILTER_VALIDATE_EMAIL)) {
45+
continue;
46+
}
47+
$this->messagePreparator->processMessageLinks($campaign, $subscriber->getId());
48+
$email = (new Email())
49+
50+
->to($subscriber->getEmail())
51+
->subject($campaign->getContent()->getSubject())
52+
->text($campaign->getContent()->getTextMessage())
53+
->html($campaign->getContent()->getText());
54+
55+
try {
56+
$this->mailer->send($email);
57+
58+
// phpcs:ignore Generic.Commenting.Todo
59+
// @todo log somewhere that this subscriber got email
60+
} catch (Throwable $e) {
61+
$this->logger->error($e->getMessage(), [
62+
'subscriber_id' => $subscriber->getId(),
63+
'campaign_id' => $campaign->getId(),
64+
]);
65+
$output?->writeln('Failed to send to: ' . $subscriber->getEmail());
66+
}
67+
68+
usleep(100000);
69+
}
70+
71+
$campaign->getMetadata()->setStatus('sent');
72+
$this->entityManager->flush();
73+
}
74+
}

src/Domain/Subscription/Service/SubscriberCsvExporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function __construct(
2929
SubscriberAttributeManager $attributeManager,
3030
SubscriberRepository $subscriberRepository,
3131
SubscriberAttributeDefinitionRepository $definitionRepository,
32-
LoggerInterface $logger
32+
LoggerInterface $logger,
3333
) {
3434
$this->attributeManager = $attributeManager;
3535
$this->subscriberRepository = $subscriberRepository;

0 commit comments

Comments
 (0)