Skip to content

Commit 218a00b

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 890cd39 commit 218a00b

File tree

10 files changed

+442
-7
lines changed

10 files changed

+442
-7
lines changed

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

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,13 @@ private function parseConfigs(\DOMElement $node, $path)
217217
$condition = null;
218218

219219
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
220+
if ($node !== $n->parentNode) {
221+
continue;
222+
}
223+
220224
switch ($n->localName) {
221225
case 'default':
222-
if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) {
223-
$defaults[$n->getAttribute('key')] = null;
224-
} else {
225-
$defaults[$n->getAttribute('key')] = trim($n->textContent);
226-
}
227-
226+
$defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path);
228227
break;
229228
case 'requirement':
230229
$requirements[$n->getAttribute('key')] = trim($n->textContent);
@@ -242,4 +241,83 @@ private function parseConfigs(\DOMElement $node, $path)
242241

243242
return array($defaults, $requirements, $options, $condition);
244243
}
244+
245+
/**
246+
* Parses the "default" elements.
247+
*
248+
* @param \DOMElement $element The "default" element to parse
249+
* @param string $path Full path of the XML file being processed
250+
*
251+
* @return array|bool|float|int|string|null The parsed value of the "default" element
252+
*/
253+
private function parseDefaultsConfig(\DOMElement $element, $path)
254+
{
255+
if ($element->hasAttribute('xsi:nil') && 'true' == $element->getAttribute('xsi:nil')) {
256+
return;
257+
}
258+
259+
// Check for existing element nodes in the default element. There can
260+
// only be a single element inside a default element. So this element
261+
// (if one was found) can savely be returned.
262+
foreach ($element->childNodes as $child) {
263+
if ($child instanceof \DOMElement) {
264+
return $this->parseDefaultNode($child, $path);
265+
}
266+
}
267+
268+
// If the default element doesn't contain a nested "boolean", "integer",
269+
// "float", "string", "list" or "map" element, the element contents will
270+
// be treated as the string value of the associated default option.
271+
return trim($element->textContent);
272+
}
273+
274+
/**
275+
* Recursively parses the value of a "default" element.
276+
*
277+
* @param \DOMElement $node The node value
278+
* @param string $path Full path of the XML file being processed
279+
*
280+
* @return array|bool|float|int|string The parsed value
281+
*
282+
* @throws \InvalidArgumentException when the XML is invalid
283+
*/
284+
private function parseDefaultNode(\DOMElement $node, $path)
285+
{
286+
switch ($node->nodeName) {
287+
case 'boolean':
288+
return 'true' === 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+
$list[] = $this->parseDefaultNode($element, $path);
304+
}
305+
306+
return $list;
307+
case 'map':
308+
$map = array();
309+
310+
foreach ($node->childNodes as $element) {
311+
if (!$element instanceof \DOMElement) {
312+
continue;
313+
}
314+
315+
$map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path);
316+
}
317+
318+
return $map;
319+
default:
320+
throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "boolean", "integer", "float", "string", "list" or "map".', $node->localName, $path));
321+
}
322+
}
245323
}

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="condition" />
@@ -55,6 +55,18 @@
5555
<xsd:attribute name="methods" type="xsd:string" />
5656
</xsd:complexType>
5757

58+
<xsd:complexType name="default" mixed="true">
59+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
60+
<xsd:element name="boolean" type="xsd:boolean" />
61+
<xsd:element name="integer" type="xsd:integer" />
62+
<xsd:element name="float" type="xsd:float" />
63+
<xsd:element name="string" type="xsd:string" />
64+
<xsd:element name="list" type="list" />
65+
<xsd:element name="map" type="map" />
66+
</xsd:choice>
67+
<xsd:attribute name="key" type="xsd:string" use="required" />
68+
</xsd:complexType>
69+
5870
<xsd:complexType name="element">
5971
<xsd:simpleContent>
6072
<xsd:extension base="xsd:string">
@@ -67,4 +79,74 @@
6779
<xsd:restriction base="xsd:string">
6880
</xsd:restriction>
6981
</xsd:simpleType>
82+
83+
<xsd:complexType name="list">
84+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
85+
<xsd:element name="boolean" type="xsd:boolean" />
86+
<xsd:element name="integer" type="xsd:integer" />
87+
<xsd:element name="float" type="xsd:float" />
88+
<xsd:element name="string" type="xsd:string" />
89+
<xsd:element name="list" type="list" />
90+
<xsd:element name="map" type="map" />
91+
</xsd:choice>
92+
</xsd:complexType>
93+
94+
<xsd:complexType name="map">
95+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
96+
<xsd:element name="boolean" type="map-boolean-entry" />
97+
<xsd:element name="integer" type="map-integer-entry" />
98+
<xsd:element name="float" type="map-float-entry" />
99+
<xsd:element name="string" type="map-string-entry" />
100+
<xsd:element name="list" type="map-list-entry" />
101+
<xsd:element name="map" type="map-map-entry" />
102+
</xsd:choice>
103+
</xsd:complexType>
104+
105+
<xsd:complexType name="map-boolean-entry">
106+
<xsd:simpleContent>
107+
<xsd:extension base="xsd:boolean">
108+
<xsd:attribute name="key" type="xsd:string" use="required" />
109+
</xsd:extension>
110+
</xsd:simpleContent>
111+
</xsd:complexType>
112+
113+
<xsd:complexType name="map-integer-entry">
114+
<xsd:simpleContent>
115+
<xsd:extension base="xsd:integer">
116+
<xsd:attribute name="key" type="xsd:string" use="required" />
117+
</xsd:extension>
118+
</xsd:simpleContent>
119+
</xsd:complexType>
120+
121+
<xsd:complexType name="map-float-entry">
122+
<xsd:simpleContent>
123+
<xsd:extension base="xsd:float">
124+
<xsd:attribute name="key" type="xsd:string" use="required" />
125+
</xsd:extension>
126+
</xsd:simpleContent>
127+
</xsd:complexType>
128+
129+
<xsd:complexType name="map-string-entry">
130+
<xsd:simpleContent>
131+
<xsd:extension base="xsd:string">
132+
<xsd:attribute name="key" type="xsd:string" use="required" />
133+
</xsd:extension>
134+
</xsd:simpleContent>
135+
</xsd:complexType>
136+
137+
<xsd:complexType name="map-list-entry">
138+
<xsd:complexContent>
139+
<xsd:extension base="list">
140+
<xsd:attribute name="key" type="xsd:string" use="required" />
141+
</xsd:extension>
142+
</xsd:complexContent>
143+
</xsd:complexType>
144+
145+
<xsd:complexType name="map-map-entry">
146+
<xsd:complexContent>
147+
<xsd:extension base="map">
148+
<xsd:attribute name="key" type="xsd:string" use="required" />
149+
</xsd:extension>
150+
</xsd:complexContent>
151+
</xsd:complexType>
70152
</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: 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>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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="public">
12+
<boolean>true</boolean>
13+
</default>
14+
<default key="page">
15+
<integer>1</integer>
16+
</default>
17+
<default key="price">
18+
<float>3.5</float>
19+
</default>
20+
<default key="archived">
21+
<boolean>false</boolean>
22+
</default>
23+
</route>
24+
</routes>

0 commit comments

Comments
 (0)