8000 [Routing] data type support for defaults · symfony/symfony@120b35c · GitHub
[go: up one dir, main page]

Skip to content

Commit 120b35c

Browse files
committed
[Routing] data type support for defaults
As pointed out in symfony/symfony-docs#4017, the XmlFileLoader was not capable of defining array default values. Additionally, this commit adds support for handling associative arrays, boolean, integer, float and string data types.
1 parent 9af416d commit 120b35c

15 files changed

+565
-3
lines changed

src/Symfony/Component/Routing/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.2.0
5+
-----
6+
7+
* Added support for `boolean`, `integer`, `float`, `string`, `list` and `map` defaults.
8+
49
2.8.0
510
-----
611

src/Symfony/Component/Routing/Loader/XmlFileLoader.php

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,16 @@ private function parseConfigs(\DOMElement $node, $path)
202202
$condition = null;
203203

204204
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
205+
if ($node !== $n->parentNode) {
206+
continue;
207+
}
208+
205209
switch ($n->localName) {
206210
case 'default':
207211
if ($this->isElementValueNull($n)) {
208212
$defaults[$n->getAttribute('key')] = null;
209213
} else {
210-
$defaults[$n->getAttribute('key')] = trim($n->textContent);
214+
$defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path);
211215
}
212216

213217
break;
@@ -228,6 +232,103 @@ private function parseConfigs(\DOMElement $node, $path)
228232
return array($defaults, $requirements, $options, $condition);
229233
}
230234

235+
/**
236+
* Parses the "default" elements.
237+
*
238+
* @param \DOMElement $element The "default" element to parse
239+
* @param string $path Full path of the XML file being processed
240+
*
241+
* @return array|bool|float|int|string|null The parsed value of the "default" element
242+
*/
243+
private function parseDefaultsConfig(\DOMElement $element, $path)
244+
{
245+
if ($this->isElementValueNull($element)) {
246+
return;
247+
}
248+
249+
// Check for existing element nodes in the default element. There can
250+
// only be a single element inside a default element. So this element
251+
// (if one was found) can safely be returned.
252+
foreach ($element->childNodes as $child) {
253+
if (!$child instanceof \DOMElement) {
254+
continue;
255+
}
256+
257+
if (self::NAMESPACE_URI !== $child->namespaceURI) {
258+
continue;
259+
}
260+
261+
return $this->parseDefaultNode($child, $path);
262+
}
263+
264+
// If the default element doesn't contain a nested "boolean", "integer",
265+
// "float", "string", "list" or "map" element, the element contents will
266+
// be treated as the string value of the associated default option.
267+
return trim($element->textContent);
268+
}
269+
270+
/**
271+
* Recursively parses the value of a "default" element.
272+
*
273+
* @param \DOMElement $node The node value
274+
* @param string $path Full path of the XML file being processed
275+
*
276+
* @return array|bool|float|int|string The parsed value
277+
*
278+
* @throws \InvalidArgumentException when the XML is invalid
279+
*/
280+
private function parseDefaultNode(\DOMElement $node, $path)
281+
{
282+
if ($this->isElementValueNull($node)) {
283+
return;
284+
}
285+
286+
switch ($node->localName) {
287+
case 'boolean':
288+
return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue);
289+
case 'integer':
290+
return (int) trim($node->nodeValue);
291+
case 'float':
292+
return (float) trim($node->nodeValue);
293+
case 'string':
294+
return trim($node->nodeValue);
295+
case 'list':
296+
$list = array();
297+
298+
foreach ($node->childNodes as $element) {
299+
if (!$element instanceof \DOMElement) {
300+
continue;
301+
}
302+
303+
if (self::NAMESPACE_URI !== $element->namespaceURI) {
304+
continue;
305+
}
306+
307+
$list[] = $this->parseDefaultNode($element, $path);
308+
}
309+
310+
return $list;
311+
case 'map':
312+
$map = array();
313+
314+
foreach ($node->childNodes as $element) {
315+
if (!$element instanceof \DOMElement) {
316+
continue;
317+
}
318+
319+
if (self::NAMESPACE_URI !== $element->namespaceURI) {
320+
continue;
321+
}
322+
323+
$map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path);
324+
}
325+
326+
return $map;
327+
default:
328+
throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "boolean", "integer", "float", "string", "list" or "map".', $node->localName, $path));
329+
}
330+
}
331+
231332
private function isElementValueNull(\DOMElement $element)
232333
{
233334
$namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';

src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
<xsd:group name="configs">
2828
<xsd:choice>
29-
<xsd:element name="default" nillable="true" type="element" />
29+
<xsd:element name="default" nillable="true" type="default" />
3030
<xsd:element name="requirement" type="element" />
3131
<xsd:element name="option" type="element" />
3232
<xsd:element name="condition" type="xsd:string" />
@@ -54,11 +54,93 @@
5454
<xsd:attribute name="methods" type="xsd:string" />
5555
</xsd:complexType>
5656

57+
<xsd:complexType name="default" mixed="true">
58+
<xsd:choice minOccurs="0" maxOccurs="1">
59+
<xsd:element name="boolean" type="xsd:boolean" />
60+
<xsd:element name="integer" type="xsd:integer" />
61+
<xsd:element name="float" type="xsd:float" />
62+
<xsd:element name="string" type="xsd:string" />
63+
<xsd:element name="list" type="list" />
64+
<xsd:element name="map" type="map" />
65+
</xsd:choice>
66+
<xsd:attribute name="key" type="xsd:string" use="required" />
67+
</xsd:complexType>
68+
5769
<xsd:complexType name="element">
5870
<xsd:simpleContent>
5971
<xsd:extension base="xsd:string">
6072
<xsd:attribute name="key" type="xsd:string" use="required" />
6173
</xsd:extension>
6274
</xsd:simpleContent>
6375
</xsd:complexType>
76+
77+
<xsd:complexType name="list">
78+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
79+
<xsd:element name="boolean" nillable="true" type="xsd:boolean" />
80+
<xsd:element name="integer" nillable="true" type="xsd:integer" />
81+
<xsd:element name="float" nillable="true" type="xsd:float" />
82+
<xsd:element name="string" nillable="true" type="xsd:string" />
83+
<xsd:element name="list" nillable="true" type="list" />
84+
<xsd:element name="map" nillable="true" type="map" />
85+
</xsd:choice>
86+
</xsd:complexType>
87+
88+
<xsd:complexType name="map">
89+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
90+
<xsd:element name="boolean" nillable="true" type="map-boolean-entry" />
91+
<xsd:element name="integer" nillable="true" type="map-integer-entry" />
92+
<xsd:element name="float" nillable="true" type="map-float-entry" />
93+
<xsd:element name="string" nillable="true" type="map-string-entry" />
94+
<xsd:element name="list" nillable="true" type="map-list-entry" />
95+
<xsd:element name="map" nillable="true" type="map-map-entry" />
96+
</xsd:choice>
97+
</xsd:complexType>
98+
99+
<xsd:complexType name="map-boolean-entry">
100+
<xsd:simpleContent>
101+
<xsd:extension base="xsd:boolean">
102+
<xsd:attribute name="key" type="xsd:string" use="required" />
103+
</xsd:extension>
104+
</xsd:simpleContent>
105+
</xsd:complexType>
106+
107+
<xsd:complexType name="map-integer-entry">
108+
<xsd:simpleContent>
109+
<xsd:extension base="xsd:integer">
110+
<xsd:attribute name="key" type="xsd:string" use="required" />
111+
</xsd:extension>
112+
</xsd:simpleContent>
113+
</xsd:complexType>
114+
115+
<xsd:complexType name="map-float-entry">
116+
<xsd:simpleContent>
117+
<xsd:extension base="xsd:float">
118+
<xsd:attribute name="key" type="xsd:string" use="required" />
119+
</xsd:extension>
120+
</xsd:simpleContent>
121+
</xsd:complexType>
122+
123+
<xsd:complexType name="map-string-entry">
124+
<xsd:simpleContent>
125+
<xsd:extension base="xsd:string">
126+
<xsd:attribute name="key" type="xsd:string" use="required" />
127+
</xsd:extension>
128+
</xsd:simpleContent>
129+
</xsd:complexType>
130+
131+
<xsd:complexType name="map-list-entry">
132+
<xsd:complexContent>
133+
<xsd:extension base="list">
134+
<xsd:attribute name="key" type="xsd:string" use="required" />
135+
</xsd:extension>
136+
</xsd:complexContent>
137+
</xsd:complexType>
138+
139+
<xsd:complexType name="map-map-entry">
140+
<xsd:complexContent>
141+
<xsd:extension base="map">
142+
<xsd:attribute name="key" type="xsd:string" use="required" />
143+
</xsd:extension>
144+
</xsd:complexContent>
145+
</xsd:complexType>
64146
</xsd:schema>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<list>
13+
<boolean>true</boolean>
14+
<integer>1</integer>
15+
<float>3.5</float>
16+
<string>foo</string>
17+
</list>
18+
</default>
19+
</route>
20+
</routes>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<list>
13+
<list>
14+
<boolean>true</boolean>
15+
<integer>1</integer>
16+
<float>3.5</float>
17+
<string>foo</string>
18+
</list>
19+
</list>
20+
</default>
21+
</route>
22+
</routes>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<map>
13+
<list key="list">
14+
<boolean>true</boolean>
15+
<integer>1</integer>
16+
<float>3.5</float>
17+
<string>foo</string>
18+
</list>
19+
</map>
20+
</default>
21+
</route>
22+
</routes>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="list">
12+
<list>
13+
<boolean xsi:nil="true" />
14+
<integer xsi:nil="true" />
15+
<float xsi:nil="1" />
16+
<string xsi:nil="true" />
17+
<list xsi:nil="true" />
18+
<map xsi:nil="true" />
19+
</list>
20+
</default>
21+
</route>
22+
</routes>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<map>
13+
<boolean key="public">true</boolean>
14+
<integer key="page">1</integer>
15+
<float key="price">3.5</float>
16+
<string key="title">foo</string>
17+
</map>
18+
</default>
19+
</route>
20+
</routes>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<list>
13+
<map>
14+
<boolean key="public">true</boolean>
15+
<integer key="page">1</integer>
16+
<float key="price">3.5</float>
17+
<string key="title">foo</string>
18+
</map>
19+
</list>
20+
</default>
21+
</route>
22+
</routes>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<routes xmlns="http://symfony.com/schema/routing"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://symfony.com/schema/routing
5+
http://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="blog" path="/blog">
8+
<default key="_controller">
9+
<string>AcmeBlogBundle:Blog:index</string>
10+
</default>
11+
<default key="values">
12+
<map>
13+
<map key="map">
14+
<boolean key="public">true</boolean>
15+
<integer key="page">1</integer>
16+
<float key="price">3.5</float>
17+
<string key="title">foo</string>
18+
</map>
19+
</map>
20+
</default>
21+
</route>
22+
</routes>

0 commit comments

Comments
 (0)
0