Skip to content

Commit 6f96acb

Browse files
authored
Merge pull request #1276 from wouterj/sanitizer-config
Fix sanitizer config
2 parents da0b098 + 548670c commit 6f96acb

File tree

7 files changed

+155
-19
lines changed

7 files changed

+155
-19
lines changed

packages/guides-cli/resources/schema/guides.xsd

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,27 @@
9393

9494
<xsd:complexType name="sanitizer">
9595
<xsd:choice minOccurs="0" maxOccurs="unbounded">
96-
<xsd:element name="allow-element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
96+
<xsd:element name="allow-element" type="element-option" minOccurs="0" maxOccurs="unbounded" />
9797
<xsd:element name="block-element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
9898
<xsd:element name="drop-element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
99-
<xsd:element name="allow-attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
100-
<xsd:element name="drop-attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
99+
<xsd:element name="allow-attribute" type="attribute-option" minOccurs="0" maxOccurs="unbounded" />
100+
<xsd:element name="drop-attribute" type="attribute-option" minOccurs="0" maxOccurs="unbounded" />
101101
</xsd:choice>
102102

103103
<xsd:attribute name="name" type="xsd:string" use="required" />
104104
</xsd:complexType>
105+
106+
<xsd:complexType name="element-option">
107+
<xsd:sequence>
108+
<xsd:element name="attribute" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
109+
</xsd:sequence>
110+
<xsd:attribute name="name" type="xsd:string" use="required" />
111+
</xsd:complexType>
112+
113+
<xsd:complexType name="attribute-option">
114+
<xsd:sequence>
115+
<xsd:element name="element" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
116+
</xsd:sequence>
117+
<xsd:attribute name="name" type="xsd:string" use="required" />
118+
</xsd:complexType>
105119
</xsd:schema>

packages/guides-restructured-text/resources/config/guides-restructured-text.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,16 @@
149149

150150
->load(
151151
'phpDocumentor\\Guides\RestructuredText\\Parser\\Productions\\InlineRules\\',
152-
'%vendor_dir%/phpdocumentor/guides-restructured-text/src/RestructuredText/Parser/Productions/InlineRules',
152+
'../../src/RestructuredText/Parser/Productions/InlineRules',
153153
)
154154
->load(
155155
'phpDocumentor\\Guides\RestructuredText\\NodeRenderers\\Html\\',
156-
'%vendor_dir%/phpdocumentor/guides-restructured-text/src/RestructuredText/NodeRenderers/Html',
156+
'../../src/RestructuredText/NodeRenderers/Html',
157157
)
158158
->tag('phpdoc.guides.noderenderer.html')
159159
->load(
160160
'phpDocumentor\\Guides\RestructuredText\\NodeRenderers\\LaTeX\\',
161-
'%vendor_dir%/phpdocumentor/guides-restructured-text/src/RestructuredText/NodeRenderers/LaTeX',
161+
'../../src/RestructuredText/NodeRenderers/LaTeX',
162162
)
163163
->tag('phpdoc.guides.noderenderer.tex')
164164

packages/guides-theme-rst/resources/config/guides-theme-rst.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/*
1717
->load(
1818
'phpDocumentor\\Guides\RstTheme\\NodeRenderers\\Rst\\',
19-
'%vendor_dir%/phpdocumentor/guides-rst-theme/src/RstTheme/NodeRenderers/Rst',
19+
'../../src/RstTheme/NodeRenderers/Rst',
2020
)
2121
->tag('phpdoc.guides.noderenderer.rst')
2222
*/

packages/guides/resources/config/guides.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,16 @@
9292

9393
->load(
9494
'phpDocumentor\\Guides\\Compiler\\NodeTransformers\\',
95-
'%vendor_dir%/phpdocumentor/guides/src/Compiler/NodeTransformers/*Transformer.php',
95+
'../../src/Compiler/NodeTransformers/*Transformer.php',
9696
)
9797
->load(
9898
'phpDocumentor\\Guides\\Compiler\\NodeTransformers\\MenuNodeTransformers\\',
99-
'%vendor_dir%/phpdocumentor/guides/src/Compiler/NodeTransformers/MenuNodeTransformers/*Transformer.php',
99+
'../../src/Compiler/NodeTransformers/MenuNodeTransformers/*Transformer.php',
100100
)
101101

102102
->load(
103103
'phpDocumentor\\Guides\\Compiler\\Passes\\',
104-
'%vendor_dir%/phpdocumentor/guides/src/Compiler/Passes/*Pass.php',
104+
'../../src/Compiler/Passes/*Pass.php',
105105
)
106106

107107
->set(InternalMenuEntryNodeTransformer::class)

packages/guides/src/DependencyInjection/GuidesExtension.php

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,55 @@ static function ($value) {
183183
->scalarNode('sanitizer_name')->end()
184184
->arrayNode('sanitizers')
185185
->defaultValue([])
186+
->useAttributeAsKey('name')
186187
->arrayPrototype()
187188
->fixXmlConfig('allow_element')
188189
->fixXmlConfig('drop_element')
189190
->fixXmlConfig('block_element')
190191
->fixXmlConfig('allow_attribute')
191192
->fixXmlConfig('drop_attribute')
192193
->children()
193-
->scalarNode('name')->isRequired()->end()
194194
->booleanNode('allow_safe_elements')->defaultValue(true)->end()
195195
->booleanNode('allow_static_elements')->defaultValue(true)->end()
196-
->arrayNode('allow_elements')->scalarPrototype()->end()->end()
197-
->arrayNode('block_elements')->scalarPrototype()->end()->end()
198-
->arrayNode('drop_elements')->scalarPrototype()->end()->end()
199-
->arrayNode('allow_attributes')->scalarPrototype()->end()->end()
200-
->arrayNode('drop_attributes')->scalarPrototype()->end()->end()
196+
->arrayNode('allow_elements')
197+
->normalizeKeys(false)
198+
->useAttributeAsKey('name')
199+
->variablePrototype()
200+
->beforeNormalization()
201+
->ifArray()->then(static fn ($n) => $n['attribute'] ?? $n)
202+
->end()
203+
->validate()
204+
->ifTrue(static fn ($n): bool => !is_string($n) && !is_array($n))
205+
->thenInvalid('The value must be either a string or an array of strings.')
206+
->end()
207+
->end()
208+
->end()
209+
->arrayNode('block_elements')
210+
->beforeNormalization()->castToArray()->end()
211+
->scalarPrototype()->end()
212+
->end()
213+
->arrayNode('drop_elements')
214+
->beforeNormalization()->castToArray()->end()
215+
->scalarPrototype()->end()
216+
->end()
217+
->arrayNode('allow_attributes')
218+
->normalizeKeys(false)
219+
->useAttributeAsKey('name')
220+
->variablePrototype()
221+
->beforeNormalization()
222+
->ifArray()->then(static fn ($n) => $n['element'] ?? $n)
223+
->end()
224+
->end()
225+
->end()
226+
->arrayNode('drop_attributes')
227+
->normalizeKeys(false)
228+
->useAttributeAsKey('name')
229+
->variablePrototype()
230+
->beforeNormalization()
231+
->ifArray()->then(static fn ($n) => $n['element'] ?? $n)
232+
->end()
233+
->end()
234+
->end()
201235
->end()
202236
->end()
203237
->end()
@@ -413,8 +447,8 @@ private function configureSanitizers(array $rawNodeConfig, ContainerBuilder $con
413447
return;
414448
}
415449

416-
foreach ($rawNodeConfig['sanitizers'] as $sanitizerConfig) {
417-
$def = $container->register('phpdoc.guides.raw_node.sanitizer.' . $sanitizerConfig['name'], HtmlSanitizerConfig::class);
450+
foreach ($rawNodeConfig['sanitizers'] as $sanitizerName => $sanitizerConfig) {
451+
$def = $container->register('phpdoc.guides.raw_node.sanitizer.' . $sanitizerName, HtmlSanitizerConfig::class);
418452

419453
// Base
420454
if ($sanitizerConfig['allow_safe_elements']) {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of phpDocumentor.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*
11+
* @link https://phpdoc.org
12+
*/
13+
14+
namespace phpDocumentor\Guides\DependencyInjection;
15+
16+
use PHPUnit\Framework\Attributes\DataProvider;
17+
use PHPUnit\Framework\TestCase;
18+
use Symfony\Component\DependencyInjection\ContainerBuilder;
19+
20+
use function array_filter;
21+
use function array_values;
22+
23+
class GuidesExtensionTest extends TestCase
24+
{
25+
/**
26+
* @param array<array<mixed>> $configs
27+
* @param callable(ContainerBuilder):void $assertions
28+
*/
29+
#[DataProvider('provideConfigs')]
30+
public function testLoad(array $configs, callable $assertions): void
31+
{
32+
$container = new ContainerBuilder();
33+
34+
$extension = new GuidesExtension();
35+
$extension->load($configs, $container);
36+
37+
$assertions($container);
38+
}
39+
40+
/** @return iterable<string, array{array<mixed>, callable(ContainerBuilder):void}> */
41+
public static function provideConfigs(): iterable
42+
{
43+
$sanitizerAssertions = static function (ContainerBuilder $container): void {
44+
self::assertTrue($container->hasDefinition('phpdoc.guides.raw_node.sanitizer.default'));
45+
46+
$definition = $container->getDefinition('phpdoc.guides.raw_node.sanitizer.default');
47+
$allowElementMethodCalls = array_values(array_filter($definition->getMethodCalls(), static fn (array $call) => $call[0] === 'allowElement'));
48+
self::assertCount(1, $allowElementMethodCalls);
49+
self::assertSame(['object', ['type', 'data', 'alt']], $allowElementMethodCalls[0][1]);
50+
};
51+
52+
yield 'sanitizer' => [
53+
[
54+
[
55+
'raw_node' => [
56+
'sanitizers' => [
57+
'default' => [
58+
'allow_elements' => [
59+
'object' => ['type', 'data', 'alt'],
60+
],
61+
],
62+
],
63+
],
64+
],
65+
],
66+
$sanitizerAssertions,
67+
];
68+
69+
yield 'sanitizer XML' => [
70+
[
71+
[
72+
'raw_node' => [
73+
'sanitizer' => [
74+
'name' => 'default',
75+
'allow_element' => [
76+
[
77+
'name' => 'object',
78+
'attribute' => ['type', 'data', 'alt'],
79+
],
80+
],
81+
],
82+
],
83+
],
84+
],
85+
$sanitizerAssertions,
86+
];
87+
}
88+
}

tests/Integration/tests/directives/directive-raw-custom-sanitizer/input/guides.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<project title="Project Title" version="6.4"/>
88
<raw-node sanitizer-name="custom" >
99
<sanitizer name="custom">
10-
<allow-element>p</allow-element>
10+
<allow-element name="p"/>
1111
<block-element>div</block-element>
1212
<drop-element>h2</drop-element>
1313
</sanitizer>

0 commit comments

Comments
 (0)