Skip to content

Commit 69884a8

Browse files
committed
Refactor
1 parent 5fc8637 commit 69884a8

File tree

6 files changed

+126
-91
lines changed

6 files changed

+126
-91
lines changed

config/parameters.yml.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ parameters:
9191
env(MAX_MAILSIZE): '209715200'
9292
messaging.default_message_age: '%%env(DEFAULT_MESSAGEAGE)%%'
9393
env(DEFAULT_MESSAGEAGE): '691200'
94-
messaging.use_manual_text_part : '%%env(USE_MANUAL_TEXT_PART)%%'
94+
messaging.use_manual_text_part: '%%env(USE_MANUAL_TEXT_PART)%%'
9595
env(USE_MANUAL_TEXT_PART): 0
9696

9797
phplist.upload_images_dir: '%%env(PHPLIST_UPLOADIMAGES_DIR)%%'

src/Domain/Messaging/MessageHandler/CampaignProcessorMessageHandler.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use PhpList\Core\Domain\Messaging\Service\Handler\RequeueHandler;
2020
use PhpList\Core\Domain\Messaging\Service\Manager\MessageDataManager;
2121
use PhpList\Core\Domain\Messaging\Service\MaxProcessTimeLimiter;
22+
use PhpList\Core\Domain\Messaging\Service\MessageDataLoader;
2223
use PhpList\Core\Domain\Messaging\Service\MessagePrecacheService;
2324
use PhpList\Core\Domain\Messaging\Service\MessageProcessingPreparator;
2425
use PhpList\Core\Domain\Messaging\Service\RateLimitedCampaignMailer;
@@ -59,6 +60,7 @@ public function __construct(
5960
private readonly MessageDataManager $messageDataManager,
6061
private readonly MessagePrecacheService $precacheService,
6162
private readonly UserPersonalizer $userPersonalizer,
63+
private readonly MessageDataLoader $messageDataLoader,
6264
?int $maxMailSize = null,
6365
) {
6466
$this->maxMailSize = $maxMailSize ?? 0;
@@ -76,8 +78,29 @@ public function __invoke(CampaignProcessorMessage|SyncCampaignProcessorMessage $
7678
return;
7779
}
7880

79-
$messagePrecacheDto = $this->precacheService->getOrCacheBaseMessageContent($campaign);
80-
if (!$messagePrecacheDto) {
81+
$loadedMessageData = ($this->messageDataLoader)($campaign);
82+
// if (!empty($loadedMessageData['resetstats'])) {
83+
// resetMessageStatistics($loadedMessageData['id']);
84+
// setMessageData($loadedMessageData['id'], 'resetstats', 0);
85+
// }
86+
// $stopSending = false;
87+
// if (!empty($loadedMessageData['finishsending'])) {
88+
// $finishSendingBefore = mktime(
89+
// $loadedMessageData['finishsending']['hour'],
90+
// $loadedMessageData['finishsending']['minute'],
91+
// 0,
92+
// $loadedMessageData['finishsending']['month'],
93+
// $loadedMessageData['finishsending']['day'],
94+
// $loadedMessageData['finishsending']['year'],
95+
// );
96+
// $secondsTogo = $finishSendingBefore - time();
97+
// $stopSending = $secondsTogo < 0;
98+
// }
99+
// $userSelection = $loadedMessageData['userselection'];
100+
101+
$cacheKey = sprintf('messaging.message.base.%d', $campaign->getId());
102+
$messagePrecached = $this->precacheService->precacheMessage($campaign, $loadedMessageData);
103+
if (!$messagePrecached) {
81104
$this->updateMessageStatus($campaign, MessageStatus::Suspended);
82105

83106
return;
@@ -112,6 +135,7 @@ public function __invoke(CampaignProcessorMessage|SyncCampaignProcessorMessage $
112135
continue;
113136
}
114137

138+
$messagePrecacheDto = $this->cache->get($cacheKey);
115139
$this->handleEmailSending($campaign, $subscriber, $userMessage, $messagePrecacheDto);
116140
}
117141

src/Domain/Messaging/Repository/MessageRepository.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpList\Core\Domain\Messaging\Repository;
66

77
use DateTimeImmutable;
8+
use Doctrine\ORM\AbstractQuery;
89
use PhpList\Core\Domain\Common\Model\Filter\FilterRequestInterface;
910
use PhpList\Core\Domain\Common\Repository\AbstractRepository;
1011
use PhpList\Core\Domain\Common\Repository\Interfaces\PaginatableRepositoryInterface;
@@ -97,4 +98,21 @@ public function findByIdAndStatus(int $id, Message\MessageStatus $status)
9798
->getQuery()
9899
->getOneOrNullResult();
99100
}
101+
102+
public function getNonEmptyFields(int $id): array
103+
{
104+
$message = $this->createQueryBuilder('m')
105+
->where('m.id = :id')
106+
->setParameter('id', $id)
107+
->getQuery()
108+
->getOneOrNullResult(AbstractQuery::HYDRATE_ARRAY) ?? [];
109+
110+
foreach ($message as $key => $value) {
111+
if ($value === null || $value === '') {
112+
unset($message[$key]);
113+
}
114+
}
115+
116+
return $message;
117+
}
100118
}

src/Domain/Messaging/Service/Manager/TemplateImageManager.php

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
use Doctrine\ORM\EntityManagerInterface;
88
use DOMDocument;
9+
use PhpList\Core\Domain\Configuration\Model\ConfigOption;
10+
use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
911
use PhpList\Core\Domain\Messaging\Model\Template;
1012
use PhpList\Core\Domain\Messaging\Model\TemplateImage;
1113
use PhpList\Core\Domain\Messaging\Repository\TemplateImageRepository;
@@ -24,15 +26,11 @@ class TemplateImageManager
2426
'swf' => 'application/x-shockwave-flash',
2527
];
2628

27-
private TemplateImageRepository $templateImageRepository;
28-
private EntityManagerInterface $entityManager;
29-
3029
public function __construct(
31-
TemplateImageRepository $templateImageRepository,
32-
EntityManagerInterface $entityManager
30+
private readonly TemplateImageRepository $templateImageRepository,
31+
private readonly EntityManagerInterface $entityManager,
32+
private readonly ConfigProvider $configProvider,
3333
) {
34-
$this->templateImageRepository = $templateImageRepository;
35-
$this->entityManager = $entityManager;
3634
}
3735

3836
/** @return TemplateImage[] */
@@ -99,4 +97,67 @@ public function delete(TemplateImage $templateImage): void
9997
{
10098
$this->templateImageRepository->remove($templateImage);
10199
}
100+
101+
public function createCachedLogoImage(int $size): void
102+
{
103+
$logoImageId = $this->configProvider->getValue(ConfigOption::OrganisationLogo);
104+
if (empty($logoImageId)) {
105+
return;
106+
}
107+
108+
$orgLogoImage = $this->templateImageRepository->findByFilename("ORGANISATIONLOGO$size.png");
109+
if (!empty($orgLogoImage->getData())) {
110+
return;
111+
}
112+
113+
$logoImage = $this->templateImageRepository->findById((int) $logoImageId);
114+
$imageContent = base64_decode($logoImage->getData());
115+
if (empty($imageContent)) {
116+
//# fall back to a single pixel, so that there are no broken images
117+
$imageContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAABGdBTUEAALGPC/xhBQAAAAZQTFRF////AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH0gQCEx05cqKA8gAAAApJREFUeJxjYAAAAAIAAUivpHEAAAAASUVORK5CYII=');
118+
}
119+
120+
$imgSize = getimagesizefromstring($imageContent);
121+
$sizeW = $imgSize[0];
122+
$sizeH = $imgSize[1];
123+
if ($sizeH > $sizeW) {
124+
$sizeFactor = (float) ($size / $sizeH);
125+
} else {
126+
$sizeFactor = (float) ($size / $sizeW);
127+
}
128+
$newWidth = (int) ($sizeW * $sizeFactor);
129+
$newHeight = (int) ($sizeH * $sizeFactor);
130+
131+
if ($sizeFactor < 1) {
132+
$original = imagecreatefromstring($imageContent);
133+
//# creates a black image (why would you want that....)
134+
$resized = imagecreatetruecolor($newWidth, $newHeight);
135+
imagesavealpha($resized, true);
136+
//# white. All the methods to make it transparent didn't work for me @@TODO really make transparent
137+
$transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127);
138+
imagefill($resized, 0, 0, $transparent);
139+
140+
if (imagecopyresized($resized, $original, 0, 0, 0, 0, $newWidth, $newHeight, $sizeW, $sizeH)) {
141+
$this->entityManager->remove($orgLogoImage);
142+
143+
//# rather convoluted way to get the image contents
144+
$buffer = ob_get_contents();
145+
ob_end_clean();
146+
ob_start();
147+
imagepng($resized);
148+
$imageContent = ob_get_contents();
149+
ob_end_clean();
150+
echo $buffer;
151+
}
152+
}
153+
// else copy original
154+
$templateImage = (new TemplateImage())
155+
->setFilename("ORGANISATIONLOGO$size.png")
156+
->setMimetype($imgSize['mime'])
157+
->setData(base64_encode($imageContent))
158+
->setWidth($newWidth)
159+
->setHeight($newHeight);
160+
161+
$this->entityManager->persist($templateImage);
162+
}
102163
}

src/Domain/Messaging/Service/MessageDataLoader.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
99
use PhpList\Core\Domain\Messaging\Model\Message;
1010
use PhpList\Core\Domain\Messaging\Repository\MessageDataRepository;
11+
use PhpList\Core\Domain\Messaging\Repository\MessageRepository;
1112

1213
class MessageDataLoader
1314
{
1415
public function __construct(
1516
private readonly ConfigProvider $configProvider,
1617
private readonly MessageDataRepository $messageDataRepository,
18+
private readonly MessageRepository $messageRepository,
1719
private readonly int $defaultMessageAge,
1820
) {
1921
}
@@ -84,11 +86,8 @@ public function __invoke(Message $message): array
8486
'excludelist' => [],
8587
'sentastest' => 0,
8688
];
87-
// todo: set correct values from entity
88-
$nonEmptyFields = array_filter(
89-
get_object_vars($message),
90-
fn($v) => $v !== null && $v !== '',
91-
);
89+
90+
$nonEmptyFields = $this->messageRepository->getNonEmptyFields($message->getId());
9291
foreach ($nonEmptyFields as $key => $val) {
9392
$messageData[$key] = $val;
9493
}
@@ -110,7 +109,7 @@ public function __invoke(Message $message): array
110109
}
111110
}
112111

113-
foreach (array('embargo', 'repeatuntil', 'requeueuntil') as $dateField) {
112+
foreach (['embargo', 'repeatuntil', 'requeueuntil'] as $dateField) {
114113
if (!is_array($messageData[$dateField])) {
115114
$messageData[$dateField] = [
116115
'year' => date('Y'),

src/Domain/Messaging/Service/MessagePrecacheService.php

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

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

7-
use Doctrine\ORM\EntityManagerInterface;
87
use PhpList\Core\Domain\Common\HtmlToText;
98
use PhpList\Core\Domain\Common\RemotePageFetcher;
109
use PhpList\Core\Domain\Common\TextParser;
@@ -15,26 +14,23 @@
1514
use PhpList\Core\Domain\Identity\Repository\AdministratorRepository;
1615
use PhpList\Core\Domain\Messaging\Model\Dto\MessagePrecacheDto;
1716
use PhpList\Core\Domain\Messaging\Model\Message;
18-
use PhpList\Core\Domain\Messaging\Model\TemplateImage;
19-
use PhpList\Core\Domain\Messaging\Repository\TemplateImageRepository;
2017
use PhpList\Core\Domain\Messaging\Repository\TemplateRepository;
18+
use PhpList\Core\Domain\Messaging\Service\Manager\TemplateImageManager;
2119
use Psr\SimpleCache\CacheInterface;
2220

2321
class MessagePrecacheService
2422
{
2523
public function __construct(
2624
private readonly CacheInterface $cache,
27-
private readonly MessageDataLoader $messageDataLoader,
2825
private readonly ConfigProvider $configProvider,
2926
private readonly HtmlToText $htmlToText,
3027
private readonly TextParser $textParser,
3128
private readonly TemplateRepository $templateRepository,
32-
private readonly TemplateImageRepository $templateImageRepository,
3329
private readonly RemotePageFetcher $remotePageFetcher,
3430
private readonly EventLogManager $eventLogManager,
3531
private readonly AdminAttributeDefinitionRepository $adminAttributeDefRepository,
3632
private readonly AdministratorRepository $adminRepository,
37-
private readonly EntityManagerInterface $entityManager,
33+
private readonly TemplateImageManager $templateImageManager,
3834
private readonly bool $useManualTextPart,
3935
private readonly string $uploadImageDir,
4036
private readonly string $publicSchema,
@@ -45,7 +41,7 @@ public function __construct(
4541
* Retrieve the base (unpersonalized) message content for a campaign from cache,
4642
* or cache it on first access. Handle [URL:] token fetch and basic placeholder replacements.
4743
*/
48-
public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardContent = false): ?MessagePrecacheDto
44+
public function precacheMessage(Message $campaign, $loadedMessageData, ?bool $forwardContent = false): bool
4945
{
5046
$cacheKey = sprintf('messaging.message.base.%d', $campaign->getId());
5147

@@ -55,7 +51,6 @@ public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardCo
5551
}
5652
$domain = $this->configProvider->getValue(ConfigOption::Domain);
5753

58-
$loadedMessageData = ($this->messageDataLoader)($campaign);
5954
$messagePrecacheDto = new MessagePrecacheDto();
6055

6156
// parse the reply-to field into its components - email and name
@@ -136,7 +131,7 @@ public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardCo
136131
entry: 'Error fetching URL: '.$loadedMessageData['sendurl'].' cannot proceed',
137132
);
138133

139-
return null;
134+
return false;
140135
}
141136
}
142137
}
@@ -192,7 +187,7 @@ public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardCo
192187

193188
$this->cache->set($cacheKey, $messagePrecacheDto);
194189

195-
return $messagePrecacheDto;
190+
return true;
196191
}
197192

198193
private function buildBasicReplacements(Message $campaign, string $subject): array
@@ -214,6 +209,7 @@ private function parseFromField(string $fromField): array
214209
}
215210
$name = trim(str_replace([$email, '"'], ['', ''], $fromField));
216211
$name = trim(str_replace(['<', '>'], '', $name));
212+
217213
return [$name, $email];
218214
}
219215

@@ -222,6 +218,7 @@ private function applyReplacements(?string $input, array $replacements): ?string
222218
if ($input === null) {
223219
return null;
224220
}
221+
225222
return str_ireplace(array_keys($replacements), array_values($replacements), $input);
226223
}
227224

@@ -232,74 +229,10 @@ private function parseLogoPlaceholders($content)
232229
foreach ($logoInstances[0] as $index => $logoInstance) {
233230
$size = sprintf('%d', $logoInstances[1][$index]);
234231
$logoSize = !empty($size) ? $size : '500';
235-
$this->createCachedLogoImage((int)$logoSize);
232+
$this->templateImageManager->createCachedLogoImage((int)$logoSize);
236233
$content = str_replace($logoInstance, 'ORGANISATIONLOGO'.$logoSize.'.png', $content);
237234
}
238235

239236
return $content;
240237
}
241-
242-
private function createCachedLogoImage(int $size): void
243-
{
244-
$logoImageId = $this->configProvider->getValue(ConfigOption::OrganisationLogo);
245-
if (empty($logoImageId)) {
246-
return;
247-
}
248-
249-
$orgLogoImage = $this->templateImageRepository->findByFilename("ORGANISATIONLOGO$size.png");
250-
if (!empty($orgLogoImage->getData())) {
251-
return;
252-
}
253-
254-
$logoImage = $this->templateImageRepository->findById((int) $logoImageId);
255-
$imageContent = base64_decode($logoImage->getData());
256-
if (empty($imageContent)) {
257-
//# fall back to a single pixel, so that there are no broken images
258-
$imageContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAABGdBTUEAALGPC/xhBQAAAAZQTFRF////AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH0gQCEx05cqKA8gAAAApJREFUeJxjYAAAAAIAAUivpHEAAAAASUVORK5CYII=');
259-
}
260-
261-
$imgSize = getimagesizefromstring($imageContent);
262-
$sizeW = $imgSize[0];
263-
$sizeH = $imgSize[1];
264-
if ($sizeH > $sizeW) {
265-
$sizeFactor = (float) ($size / $sizeH);
266-
} else {
267-
$sizeFactor = (float) ($size / $sizeW);
268-
}
269-
$newWidth = (int) ($sizeW * $sizeFactor);
270-
$newHeight = (int) ($sizeH * $sizeFactor);
271-
272-
if ($sizeFactor < 1) {
273-
$original = imagecreatefromstring($imageContent);
274-
//# creates a black image (why would you want that....)
275-
$resized = imagecreatetruecolor($newWidth, $newHeight);
276-
imagesavealpha($resized, true);
277-
//# white. All the methods to make it transparent didn't work for me @@TODO really make transparent
278-
$transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127);
279-
imagefill($resized, 0, 0, $transparent);
280-
281-
if (imagecopyresized($resized, $original, 0, 0, 0, 0, $newWidth, $newHeight, $sizeW, $sizeH)) {
282-
$this->entityManager->remove($orgLogoImage);
283-
284-
//# rather convoluted way to get the image contents
285-
$buffer = ob_get_contents();
286-
ob_end_clean();
287-
ob_start();
288-
imagepng($resized);
289-
$imageContent = ob_get_contents();
290-
ob_end_clean();
291-
echo $buffer;
292-
}
293-
}
294-
// else copy original
295-
$templateImage = (new TemplateImage())
296-
->setFilename("ORGANISATIONLOGO$size.png")
297-
->setMimetype($imgSize['mime'])
298-
->setData(base64_encode($imageContent))
299-
->setWidth($newWidth)
300-
->setHeight($newHeight);
301-
302-
$this->entityManager->persist($templateImage);
303-
304-
}
305238
}

0 commit comments

Comments
 (0)