Skip to content

Commit 3861db0

Browse files
committed
FooterContentIsResolvedForNestedPlaceholders
1 parent 56ab93f commit 3861db0

2 files changed

Lines changed: 93 additions & 4 deletions

File tree

src/Domain/Configuration/Service/MessagePlaceholderProcessor.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,8 @@ public function process(
6565
name: 'ORGANIZATION_NAME',
6666
resolver: fn(PlaceholderContext $ctx) => $this->config->getValue(ConfigOption::OrganisationName) ?? ''
6767
);
68-
69-
foreach ($this->placeholderResolvers as $placeholderResolver) {
70-
$resolver->register($placeholderResolver->name(), $placeholderResolver);
71-
}
68+
69+
$this->registerNestedResolvers($resolver);
7270

7371
foreach ($this->patternResolvers as $patternResolver) {
7472
$resolver->registerPattern($patternResolver->pattern(), $patternResolver);
@@ -136,4 +134,57 @@ private function registerAttributeResolvers(
136134
);
137135
}
138136
}
137+
138+
private function maskFooterPlaceholders(string $value, array &$placeholderMap): string
139+
{
140+
$placeholderMap = [];
141+
$index = 0;
142+
143+
return preg_replace_callback(
144+
'/\[FOOTER(?:%%[^\]]+)?\]/i',
145+
function (array $matches) use (&$placeholderMap, &$index): string {
146+
$token = sprintf('__PHPLIST_FOOTER_TOKEN_%d__', $index++);
147+
$placeholderMap[$token] = $matches[0];
148+
149+
return $token;
150+
},
151+
$value
152+
) ?? $value;
153+
}
154+
155+
/** @param array<string, string> $placeholderMap */
156+
private function restoreFooterPlaceholders(string $value, array $placeholderMap): string
157+
{
158+
if ($placeholderMap === []) {
159+
return $value;
160+
}
161+
162+
return strtr($value, $placeholderMap);
163+
}
164+
165+
private function registerNestedResolvers(PlaceholderResolver $resolver): void
166+
{
167+
foreach ($this->placeholderResolvers as $placeholderResolver) {
168+
if (strtoupper($placeholderResolver->name()) !== 'FOOTER') {
169+
$resolver->register($placeholderResolver->name(), $placeholderResolver);
170+
continue;
171+
}
172+
173+
$resolver->register(
174+
$placeholderResolver->name(),
175+
function (PlaceholderContext $ctx) use ($placeholderResolver, $resolver): string {
176+
$footer = (string) $placeholderResolver($ctx);
177+
if (!str_contains($footer, '[')) {
178+
return $footer;
179+
}
180+
181+
$placeholderMap = [];
182+
$maskedFooter = $this->maskFooterPlaceholders($footer, $placeholderMap);
183+
$resolvedFooter = $resolver->resolve($maskedFooter, $ctx);
184+
185+
return $this->restoreFooterPlaceholders($resolvedFooter, $placeholderMap);
186+
}
187+
);
188+
}
189+
}
139190
}

tests/Unit/Domain/Configuration/Service/MessagePlaceholderProcessorTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,42 @@ public function resolve(string $key, PlaceholderContext $ctx): ?string
190190

191191
$this->assertStringContainsString('A XVAL B ABC C SVAL', $out);
192192
}
193+
194+
public function testFooterContentIsResolvedForNestedPlaceholders(): void
195+
{
196+
$user = $this->makeUser('nest@example.com');
197+
$dto = new MessagePrecacheDto();
198+
199+
$footerResolver = new class implements PlaceholderValueResolverInterface {
200+
public function name(): string
201+
{
202+
return 'FOOTER';
203+
}
204+
205+
public function __invoke(PlaceholderContext $ctx): string
206+
{
207+
return 'Footer contact [EMAIL]';
208+
}
209+
};
210+
211+
$processor = new MessagePlaceholderProcessor(
212+
config: $this->config,
213+
attributesRepository: $this->attrRepo,
214+
attributeValueResolver: $this->attrResolver,
215+
placeholderResolvers: [$footerResolver],
216+
patternResolvers: [],
217+
supportingResolvers: [],
218+
alwaysAddUserTrack: false,
219+
keepForwardedAttributes: false
220+
);
221+
222+
$out = $processor->process(
223+
value: 'Body [FOOTER]',
224+
receiver: $user,
225+
format: OutputFormat::Text,
226+
messagePrecacheDto: $dto,
227+
);
228+
229+
$this->assertStringContainsString('Body Footer contact nest@example.com', $out);
230+
}
193231
}

0 commit comments

Comments
 (0)