Skip to content

Commit 310fc13

Browse files
authored
Merge pull request #43 from sitegeist/feature/plaintextModeForDataTemplate
Feature: Add separate plaintext mode for DataTemplate
2 parents e106f44 + c3defea commit 310fc13

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

Classes/FusionObjects/DataTemplateImplementation.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,29 @@ public function getDateTimeFormat(): string
3333
return $this->fusionValue('dateTimeFormat') ?? \DateTimeInterface::W3C;
3434
}
3535

36+
/**
37+
* @return string "plaintext" or "html" are supported modes
38+
*/
39+
public function getMode(): string
40+
{
41+
return $this->fusionValue('mode') ?? 'html';
42+
}
43+
3644
public function evaluate()
3745
{
3846
$template = $this->getTemplate();
3947
$data = $this->getData();
48+
$mode = $this->getMode();
4049

4150
return preg_replace_callback(
4251
'/{([a-z0-9\\-\\.]+)}/ium',
43-
function (array $matches) use ($data) {
52+
function (array $matches) use ($data, $mode) {
4453
$value = Arrays::getValueByPath($data, $matches[1]);
45-
return htmlspecialchars(strip_tags($this->stringify($value)));
54+
return match ($mode) {
55+
'plaintext' => strip_tags($this->stringify($value)),
56+
'html' => htmlspecialchars(strip_tags($this->stringify($value))),
57+
default => htmlspecialchars(strip_tags($this->stringify($value)))
58+
};
4659
},
4760
$template
4861
);

NodeTypes/Action/Email/Email.Definition.fusion

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ prototype(Sitegeist.PaperTiger:Action.Email.Definition) < prototype(Neos.Fusion:
33
[email protected] = Sitegeist.PaperTiger:Action.DataTemplate
44
format = ${q(node).property('format')}
55
plaintext = ${q(node).property('plaintext')}
6-
[email protected] = Sitegeist.PaperTiger:Action.DataTemplate
6+
[email protected] = Sitegeist.PaperTiger:Action.DataTemplate {
7+
mode = 'plaintext'
8+
}
79
[email protected] = ${this.format != 'html'}
810
html = ${q(node).property('html')}
911
[email protected] = ${this.format != 'plaintext'}
10-
[email protected] = Sitegeist.PaperTiger:Action.DataTemplate
12+
[email protected] = Sitegeist.PaperTiger:Action.DataTemplate {
13+
mode = 'html'
14+
}
1115
recipientAddress = ${q(node).property('recipientAddress')}
1216
recipientName = ${q(node).property('recipientName')}
1317
senderAddress = ${q(node).property('senderAddress')}

Resources/Private/Fusion/Prototypes/DataTemplate.fusion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ prototype(Sitegeist.PaperTiger:Action.DataTemplate) < prototype(Neos.Fusion:Valu
22
@class = '\\Sitegeist\\PaperTiger\\FusionObjects\\DataTemplateImplementation'
33
template = ${value}
44
data = ${data}
5+
mode = 'html'
56

67
dateTimeFormat = 'Y-m-d H:i:s'
78
}

Tests/Unit/DataTemplateTest.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ class DataTemplateTest extends TestCase
1313

1414
public function setUp(): void
1515
{
16-
$this->dataTemplate = $this->createPartialMock(DataTemplateImplementation::class, ['getTemplate', 'getData', 'getDateTimeFormat']);
16+
$this->dataTemplate = $this->createPartialMock(DataTemplateImplementation::class, ['getTemplate', 'getData', 'getMode', 'getDateTimeFormat']);
1717
$this->dataTemplate->expects($this->any())->method('getDateTimeFormat')->willReturn(\DateTimeImmutable::W3C);
18+
$this->dataTemplate->expects($this->any())->method('getMode')->willReturn('html');
19+
1820
}
1921

2022
public function stringifyConvertsDataProvider(): \Generator
@@ -76,4 +78,33 @@ public function evaluateAccessesNestedData(mixed $data, string $template, string
7678
$this->dataTemplate->expects($this->once())->method('getData')->willReturn($data);
7779
$this->assertSame($expectedString, $this->dataTemplate->evaluate());
7880
}
81+
82+
public function modeControlsEntityEscapingDataProvider(): \Generator
83+
{
84+
yield 'string with ampersand' => ['foo & bar', 'foo &amp; bar', 'foo & bar'];
85+
yield 'string with script' => ['foo <script>evil</script> bar', 'foo evil bar', 'foo evil bar'];
86+
}
87+
88+
/**
89+
* @test
90+
* @dataProvider modeControlsEntityEscapingDataProvider
91+
*/
92+
public function modeControlsEntityEscaping(mixed $data, string $expectedHtmlString, string $expectedPlaintextString): void
93+
{
94+
95+
$htmlDataTemplate = $this->createPartialMock(DataTemplateImplementation::class, ['getTemplate', 'getData', 'getDateTimeFormat', 'getMode']);
96+
$htmlDataTemplate->expects($this->any())->method('getDateTimeFormat')->willReturn(\DateTimeImmutable::W3C);
97+
$htmlDataTemplate->expects($this->any())->method('getMode')->willReturn('html');
98+
$htmlDataTemplate->expects($this->any())->method('getTemplate')->willReturn('{data}');
99+
$htmlDataTemplate->expects($this->any())->method('getData')->willReturn(['data' => $data]);
100+
101+
$plainte = $this->createPartialMock(DataTemplateImplementation::class, ['getTemplate', 'getData', 'getDateTimeFormat', 'getMode']);
102+
$plainte->expects($this->any())->method('getDateTimeFormat')->willReturn(\DateTimeImmutable::W3C);
103+
$plainte->expects($this->any())->method('getMode')->willReturn('plaintext');
104+
$plainte->expects($this->any())->method('getTemplate')->willReturn('{data}');
105+
$plainte->expects($this->any())->method('getData')->willReturn(['data' => $data]);
106+
107+
$this->assertSame($expectedHtmlString, $htmlDataTemplate->evaluate());
108+
$this->assertSame($expectedPlaintextString, $plainte->evaluate());
109+
}
79110
}

0 commit comments

Comments
 (0)