Skip to content

Commit 5fe45ab

Browse files
committed
Use MessagePrecacheDto
1 parent 3b9267f commit 5fe45ab

4 files changed

Lines changed: 115 additions & 121 deletions

File tree

config/parameters.yml.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,5 @@ parameters:
9696

9797
phplist.upload_images_dir: '%%env(PHPLIST_UPLOADIMAGES_DIR)%%'
9898
env(PHPLIST_UPLOADIMAGES_DIR): 'images'
99+
phplist.public_schema: '%%env(PUBLIC_SCHEMA)%%'
100+
env(PUBLIC_SCHEMA): 'http'

src/Domain/Identity/Repository/AdministratorRepository.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,18 @@ public function findOneByLoginCredentials(string $loginName, string $plainTextPa
5555
]
5656
);
5757
}
58+
59+
/** @return Administrator[] */
60+
public function getMessageRelatedAdmins(int $messageId): array
61+
{
62+
return $this->createQueryBuilder('a')
63+
->select('DISTINCT a')
64+
->join('a.ownedLists', 'ag')
65+
->join('ag.listMessages', 'lm')
66+
->join('lm.message', 'm')
67+
->where('m.id = :messageId')
68+
->setParameter('messageId', $messageId)
69+
->getQuery()
70+
->getResult();
71+
}
5872
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Messaging\Model\Dto;
6+
7+
class MessagePrecacheDto
8+
{
9+
public string $replyToEmail;
10+
public string $replyToName;
11+
public string $fromName;
12+
public string $fromEmail;
13+
public string $to;
14+
public string $subject;
15+
public string $content;
16+
public string $textContent = '';
17+
public string $footer;
18+
public string $textFooter;
19+
public string $htmlFooter;
20+
public bool $htmlFormatted;
21+
public string $sendFormat;
22+
public ?string $template = '';
23+
public ?string $templateText = '';
24+
public ?int $templateId = 0;
25+
public string $htmlCharset= 'UTF-8';
26+
public string $textCharset= 'UTF-8';
27+
public bool $userSpecificUrl;
28+
public string $googleTrack;
29+
public array $adminAttributes = [];
30+
}

src/Domain/Messaging/Service/MessagePrecacheService.php

Lines changed: 69 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PhpList\Core\Domain\Configuration\Service\Provider\ConfigProvider;
1414
use PhpList\Core\Domain\Identity\Repository\AdminAttributeDefinitionRepository;
1515
use PhpList\Core\Domain\Identity\Repository\AdministratorRepository;
16+
use PhpList\Core\Domain\Messaging\Model\Dto\MessagePrecacheDto;
1617
use PhpList\Core\Domain\Messaging\Model\Message;
1718
use PhpList\Core\Domain\Messaging\Model\TemplateImage;
1819
use PhpList\Core\Domain\Messaging\Repository\TemplateImageRepository;
@@ -36,110 +37,99 @@ public function __construct(
3637
private readonly EntityManagerInterface $entityManager,
3738
private readonly bool $useManualTextPart,
3839
private readonly string $uploadImageDir,
40+
private readonly string $publicSchema,
3941
) {
4042
}
4143

4244
/**
4345
* Retrieve the base (unpersonalized) message content for a campaign from cache,
44-
* or cache it on first access. Legacy-like behavior: handle [URL:] token fetch
45-
* and basic placeholder replacements.
46+
* or cache it on first access. Handle [URL:] token fetch and basic placeholder replacements.
4647
*/
47-
public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardContent = false): ?Message\MessageContent
48+
public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardContent = false): ?MessagePrecacheDto
4849
{
4950
$cacheKey = sprintf('messaging.message.base.%d', $campaign->getId());
5051

51-
$cached = $this->getFromCache($cacheKey);
52+
$cached = $this->cache->get($cacheKey);
5253
if ($cached !== null) {
5354
return $cached;
5455
}
5556
$domain = $this->configProvider->getValue(ConfigOption::Domain);
56-
$messageId = $campaign->getId();
5757

5858
$loadedMessageData = ($this->messageDataLoader)($campaign);
59+
$messagePrecacheDto = new MessagePrecacheDto();
5960

6061
// parse the reply-to field into its components - email and name
6162
if (preg_match('/([^ ]+@[^ ]+)/', $loadedMessageData['replyto'], $regs)) {
6263
// if there is an email in the from, rewrite it as "name <email>"
6364
$loadedMessageData['replyto'] = str_replace($regs[0], '', $loadedMessageData['replyto']);
64-
$cached[$messageId]['replytoemail'] = $regs[0];
65+
$replyToEmail = $regs[0];
6566
// if the email has < and > take them out here
66-
$cached[$messageId]['replytoemail'] = str_replace('<', '', $cached[$messageId]['replytoemail']);
67-
$cached[$messageId]['replytoemail'] = str_replace('>', '', $cached[$messageId]['replytoemail']);
67+
$replyToEmail = str_replace('<', '', $replyToEmail);
68+
$replyToEmail = str_replace('>', '', $replyToEmail);
69+
$messagePrecacheDto->replyToEmail = $replyToEmail;
6870
// make sure there are no quotes around the name
69-
$cached[$messageId]['replytoname'] = str_replace('"', '', ltrim(rtrim($loadedMessageData['replyto'])));
71+
$messagePrecacheDto->replyToName = str_replace('"', '', ltrim(rtrim($loadedMessageData['replyto'])));
7072
} elseif (strpos($loadedMessageData['replyto'], ' ')) {
7173
// if there is a space, we need to add the email
72-
$cached[$messageId]['replytoname'] = $loadedMessageData['replyto'];
73-
$cached[$messageId]['replytoemail'] = "listmaster@$domain";
74-
} else {
75-
if (!empty($loadedMessageData['replyto'])) {
76-
$cached[$messageId]['replytoemail'] = $loadedMessageData['replyto']."@$domain";
77-
78-
//# makes more sense not to add the domain to the word, but the help says it does
79-
//# so let's keep it for now
80-
$cached[$messageId]['replytoname'] = $loadedMessageData['replyto']."@$domain";
81-
}
74+
$messagePrecacheDto->replyToName = $loadedMessageData['replyto'];
75+
$messagePrecacheDto->replyToEmail = "listmaster@$domain";
76+
} elseif (!empty($loadedMessageData['replyto'])) {
77+
$messagePrecacheDto->replyToEmail = $loadedMessageData['replyto']."@$domain";
78+
//# makes more sense not to add the domain to the word, but the help says it does
79+
//# so let's keep it for now
80+
$messagePrecacheDto->replyToName = $loadedMessageData['replyto']."@$domain";
8281
}
8382

84-
$cached[$messageId]['fromname'] = $loadedMessageData['fromname'];
85-
$cached[$messageId]['fromemail'] = $loadedMessageData['fromemail'];
86-
$cached[$messageId]['to'] = $loadedMessageData['tofield'];
83+
$messagePrecacheDto->fromName = $loadedMessageData['fromname'];
84+
$messagePrecacheDto->fromEmail = $loadedMessageData['fromemail'];
85+
$messagePrecacheDto->to = $loadedMessageData['tofield'];
8786
//0013076: different content when forwarding 'to a friend'
88-
$cached[$messageId]['subject'] = $forwardContent ? stripslashes($loadedMessageData['forwardsubject']) : $loadedMessageData['subject'];
87+
$messagePrecacheDto->subject = $forwardContent ? stripslashes($loadedMessageData['forwardsubject']) : $loadedMessageData['subject'];
8988
//0013076: different content when forwarding 'to a friend'
90-
$cached[$messageId]['content'] = $forwardContent ? stripslashes($loadedMessageData['forwardmessage']) : $loadedMessageData['message'];
89+
$messagePrecacheDto->content = $forwardContent ? stripslashes($loadedMessageData['forwardmessage']) : $loadedMessageData['message'];
9190
if ($this->useManualTextPart && !$forwardContent) {
92-
$cached[$messageId]['textcontent'] = $loadedMessageData['textmessage'];
93-
} else {
94-
$cached[$messageId]['textcontent'] = '';
91+
$messagePrecacheDto->textContent = $loadedMessageData['textmessage'];
9592
}
9693
//0013076: different content when forwarding 'to a friend'
97-
$cached[$messageId]['footer'] = $forwardContent ? stripslashes($loadedMessageData['forwardfooter']) : $loadedMessageData['footer'];
94+
$messagePrecacheDto->footer = $forwardContent ? stripslashes($loadedMessageData['forwardfooter']) : $loadedMessageData['footer'];
9895

99-
if (strip_tags($cached[$messageId]['footer']) != $cached[$messageId]['footer']) {
100-
$cached[$messageId]['textfooter'] = ($this->htmlToText)($cached[$messageId]['footer']);
101-
$cached[$messageId]['htmlfooter'] = $cached[$messageId]['footer'];
96+
if (strip_tags($messagePrecacheDto->footer ) !== $messagePrecacheDto->footer) {
97+
$messagePrecacheDto->textFooter = ($this->htmlToText)($messagePrecacheDto->footer);
98+
$messagePrecacheDto->htmlFooter = $messagePrecacheDto->footer;
10299
} else {
103-
$cached[$messageId]['textfooter'] = $cached[$messageId]['footer'];
104-
$cached[$messageId]['htmlfooter'] = ($this->textParser)($cached[$messageId]['footer']);
100+
$messagePrecacheDto->textFooter = $messagePrecacheDto->footer;
101+
$messagePrecacheDto->htmlFooter = ($this->textParser)($messagePrecacheDto->footer);
105102
}
106103

107-
$cached[$messageId]['htmlformatted'] = strip_tags($cached[$messageId]['content']) != $cached[$messageId]['content'];
108-
$cached[$messageId]['sendformat'] = $loadedMessageData['sendformat'];
104+
$messagePrecacheDto->htmlFormatted = strip_tags($messagePrecacheDto->content) !== $messagePrecacheDto->content;
105+
$messagePrecacheDto->sendFormat = $loadedMessageData['sendformat'];
109106

110-
$cached[$messageId]['template'] = '';
111-
$cached[$messageId]['template_text'] = '';
112-
$cached[$messageId]['templateid'] = 0;
113107
if ($loadedMessageData['template']) {
114108
$template = $this->templateRepository->findOneById($loadedMessageData['template']);
115109
if ($template) {
116-
$cached[$messageId]['template'] = stripslashes($template->getContent());
117-
$cached[$messageId]['template_text'] = stripslashes($template->getText());
118-
$cached[$messageId]['templateid'] = $template->getId();
110+
$messagePrecacheDto->template = stripslashes($template->getContent());
111+
$messagePrecacheDto->templateText = stripslashes($template->getText());
112+
$messagePrecacheDto->templateId = $template->getId();
119113
}
120114
}
121115

122-
//# @@ put this here, so it can become editable per email sent out at a later stage
123-
$cached[$messageId]['html_charset'] = 'UTF-8'; //getConfig("html_charset");
124-
$cached[$messageId]['text_charset'] = 'UTF-8'; //getConfig("text_charset");
125-
126116
//# if we are sending a URL that contains user attributes, we cannot pre-parse the message here
127117
//# but that has quite some impact on speed. So check if that's the case and apply
128-
$cached[$messageId]['userspecific_url'] = preg_match('/\[.+\]/', $loadedMessageData['sendurl']);
118+
$messagePrecacheDto->userSpecificUrl = preg_match('/\[.+\]/', $loadedMessageData['sendurl']);
129119

130-
if (!$cached[$messageId]['userspecific_url']) {
120+
if (!$messagePrecacheDto->userSpecificUrl) {
131121
//# Fetch external content here, because URL does not contain placeholders
132-
if (preg_match("/\[URL:([^\s]+)\]/i", $cached[$messageId]['content'], $regs)) {
122+
if (preg_match("/\[URL:([^\s]+)\]/i", $messagePrecacheDto->content, $regs)) {
133123
$remoteContent = ($this->remotePageFetcher)($regs[1], []);
134124

135125
if ($remoteContent) {
136-
$cached[$messageId]['content'] = str_replace($regs[0], $remoteContent, $cached[$messageId]['content']);
137-
$cached[$messageId]['htmlformatted'] = strip_tags($remoteContent) != $remoteContent;
126+
$messagePrecacheDto->content = str_replace($regs[0], $remoteContent, $messagePrecacheDto->content);
127+
$messagePrecacheDto->htmlFormatted = strip_tags($remoteContent) !== $remoteContent;
138128

139129
//# 17086 - disregard any template settings when we have a valid remote URL
140-
$cached[$messageId]['template'] = null;
141-
$cached[$messageId]['template_text'] = null;
142-
$cached[$messageId]['templateid'] = null;
130+
$messagePrecacheDto->template = null;
131+
$messagePrecacheDto->templateText = null;
132+
$messagePrecacheDto->templateId = null;
143133
} else {
144134
$this->eventLogManager->log(
145135
page: 'unknown page',
@@ -151,76 +141,58 @@ public function getOrCacheBaseMessageContent(Message $campaign, ?bool $forwardCo
151141
}
152142
}
153143

154-
$cached[$messageId]['google_track'] = $loadedMessageData['google_track'];
144+
$messagePrecacheDto->googleTrack = $loadedMessageData['google_track'];
155145

156146
foreach (['subject', 'id', 'fromname', 'fromemail'] as $key) {
157147
$val = $loadedMessageData[$key];
158148
// Replace in content except for user-specific URL
159-
if (!$cached[$messageId]['userspecific_url']) {
160-
$cached[$messageId]['content'] = str_ireplace("[$key]", $val, $cached[$messageId]['content']);
149+
if (!$messagePrecacheDto->userSpecificUrl) {
150+
$messagePrecacheDto->content = str_ireplace("[$key]", $val, $messagePrecacheDto->content);
161151
}
162-
$cached[$messageId]['textcontent'] = str_ireplace("[$key]", $val, $cached[$messageId]['textcontent']);
163-
$cached[$messageId]['textfooter'] = str_ireplace("[$key]", $val, $cached[$messageId]['textfooter']);
164-
$cached[$messageId]['htmlfooter'] = str_ireplace("[$key]", $val, $cached[$messageId]['htmlfooter']);
152+
$messagePrecacheDto->textContent = str_ireplace("[$key]", $val, $messagePrecacheDto->textContent);
153+
$messagePrecacheDto->textFooter = str_ireplace("[$key]", $val, $messagePrecacheDto->textFooter);
154+
$messagePrecacheDto->htmlFooter = str_ireplace("[$key]", $val, $messagePrecacheDto->htmlFooter);
165155
}
166156

167-
$cached[$messageId]['adminattributes'] = [];
168157
$ownerAttrValues = $this->adminAttributeDefRepository->getForAdmin($campaign->getOwner());
169158
foreach ($ownerAttrValues as $attr) {
170-
$cached[$messageId]['adminattributes']['OWNER.'.$attr['name']] = $attr['value'];
159+
$messagePrecacheDto->adminAttributes['OWNER.'.$attr['name']] = $attr['value'];
171160
}
172161

173-
$relatedAdmins = $this->adminRepository->createQueryBuilder('a')
174-
->select('DISTINCT a')
175-
->join('a.ownedLists', 'ag')
176-
->join('ag.listMessages', 'lm')
177-
->join('lm.message', 'm')
178-
->where('m.id = :messageId')
179-
->setParameter('messageId', $messageId)
180-
->getQuery()
181-
->getResult();
182-
162+
$relatedAdmins = $this->adminRepository->getMessageRelatedAdmins($campaign->getId());
183163
if (count($relatedAdmins) === 1) {
184164
$listOwnerAttrValues = $this->adminAttributeDefRepository->getForAdmin($relatedAdmins[0]);
185165
} else {
186166
$listOwnerAttrValues = $this->adminAttributeDefRepository->getAllWIthEmptyValues();
187167
}
188168

189169
foreach ($listOwnerAttrValues as $attr) {
190-
$cached[$messageId]['adminattributes']['LISTOWNER.'.$attr['name']] = $attr['value'];
170+
$messagePrecacheDto->adminAttributes['LISTOWNER.'.$attr['name']] = $attr['value'];
191171
}
192172

193173
$baseurl = $this->configProvider->getValue(ConfigOption::Website);
194174
if ($this->uploadImageDir) {
195175
//# escape subdirectories, otherwise this renders empty
196176
$dir = str_replace('/', '\/', $this->uploadImageDir);
197-
$cached[$messageId]['content'] = preg_replace('/<img(.*)src="\/'.$dir.'(.*)>/iU',
198-
'<img\\1src="'.$GLOBALS['public_scheme'].'://'.$baseurl.'/'.$this->uploadImageDir.'\\2>',
199-
$cached[$messageId]['content']);
200-
}
201-
202-
foreach (['content', 'template', 'htmlfooter'] as $element) {
203-
$cached[$messageId][$element] = $this->parseLogoPlaceholders($cached[$messageId][$element]);
177+
$messagePrecacheDto->content = preg_replace(
178+
'/<img(.*)src="\/'.$dir.'(.*)>/iU',
179+
'<img\\1src="'.$this->publicSchema.'://'.$baseurl.'/'.$this->uploadImageDir.'\\2>',
180+
$messagePrecacheDto->content
181+
);
204182
}
205183

206-
$this->cache->set($cacheKey, $cached);
184+
$messagePrecacheDto->content = $this->parseLogoPlaceholders($messagePrecacheDto->content);
185+
$messagePrecacheDto->template = $this->parseLogoPlaceholders($messagePrecacheDto->template);
186+
$messagePrecacheDto->htmlFooter = $this->parseLogoPlaceholders($messagePrecacheDto->htmlFooter);
207187

208-
// Replace basic placeholders [subject],[id],[fromname],[fromemail]
209-
$replacements = $this->buildBasicReplacements($campaign, $subject);
210-
$html = $this->applyReplacements($html, $replacements);
211-
$text = $this->applyReplacements($text, $replacements);
212-
$footer = $this->applyReplacements($footer, $replacements);
188+
// $replacements = $this->buildBasicReplacements($campaign, $subject);
189+
// $html = $this->applyReplacements($html, $replacements);
190+
// $text = $this->applyReplacements($text, $replacements);
191+
// $footer = $this->applyReplacements($footer, $replacements);
213192

214-
$snapshot = [
215-
'subject' => $subject,
216-
'text' => $html,
217-
'textMessage' => $text,
218-
'footer' => $footer,
219-
];
220-
221-
$this->cache->set($cacheKey, $snapshot);
193+
$this->cache->set($cacheKey, $messagePrecacheDto);
222194

223-
return new Message\MessageContent($subject, $html, $text, $footer);
195+
return $messagePrecacheDto;
224196
}
225197

226198
private function buildBasicReplacements(Message $campaign, string $subject): array
@@ -253,45 +225,21 @@ private function applyReplacements(?string $input, array $replacements): ?string
253225
return str_ireplace(array_keys($replacements), array_values($replacements), $input);
254226
}
255227

256-
private function getFromCache(string $cacheKey): ?Message\MessageContent
257-
{
258-
$cached = $this->cache->get($cacheKey);
259-
if (is_array($cached)
260-
&& array_key_exists('subject', $cached)
261-
&& array_key_exists('text', $cached)
262-
&& array_key_exists('textMessage', $cached)
263-
&& array_key_exists('footer', $cached)
264-
) {
265-
return new Message\MessageContent(
266-
$cached['subject'],
267-
$cached['text'],
268-
$cached['textMessage'],
269-
$cached['footer']
270-
);
271-
}
272-
273-
return null;
274-
}
275-
276228
private function parseLogoPlaceholders($content)
277229
{
278230
//# replace Logo placeholders
279231
preg_match_all('/\[LOGO\:?(\d+)?\]/', $content, $logoInstances);
280232
foreach ($logoInstances[0] as $index => $logoInstance) {
281233
$size = sprintf('%d', $logoInstances[1][$index]);
282-
if (!empty($size)) {
283-
$logoSize = $size;
284-
} else {
285-
$logoSize = '500';
286-
}
287-
$this->createCachedLogoImage($logoSize);
234+
$logoSize = !empty($size) ? $size : '500';
235+
$this->createCachedLogoImage((int)$logoSize);
288236
$content = str_replace($logoInstance, 'ORGANISATIONLOGO'.$logoSize.'.png', $content);
289237
}
290238

291239
return $content;
292240
}
293241

294-
private function createCachedLogoImage($size): void
242+
private function createCachedLogoImage(int $size): void
295243
{
296244
$logoImageId = $this->configProvider->getValue(ConfigOption::OrganisationLogo);
297245
if (empty($logoImageId)) {

0 commit comments

Comments
 (0)