Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18c520a

Browse files
committed
merged branch Tobion/loaders (PR #6172)
This PR was merged into the master branch. Commits ------- 237bbd0 fixed and refactored YamlFileLoader in the same sense as the XmlFileLoader 392d785 removed covers annotation from loader tests and unneeded use statements 45987eb added tests for the previous XmlFileLoader fixes b20d6a7 ensure id, pattern and resource are specified 8361b5a refactor the XMlFileLoader 83fc5ff fix namespace handling in xml loader; it could not handle prefixes 1a60a3c make resource and key attributes required in xsd 02e01b9 improve exception messages in xml loader 51fbffe remove unneeded cast 358e9c4 fix some phpdoc Discussion ---------- [Routing] improve loaders BC break: no Main points: - fixed Xml loader that could not handle namespace prefixes but is valid xml - fixed Yaml loader where some nonsesense configs were not validated correctly like an imported resource with a pattern key. Added tests for all. Some refactoring + a few tweaks like better exception messages and more consistency between Xml loader and yaml loader. See also commits. --------------------------------------------------------------------------- by Tobion at 2012-12-07T18:16:08Z @fabpot this is ready --------------------------------------------------------------------------- by Tobion at 2012-12-11T17:30:10Z @fabpot rebased. Please don't squash to one big commit where one does not see what changed why. --------------------------------------------------------------------------- by fabpot at 2012-12-11T17:32:40Z I only squash when most commits are CS fixes and feedback. --------------------------------------------------------------------------- by Tobion at 2012-12-11T17:37:49Z Well, you squashed #6022 so it's not possible to revert a specific deprecation.
2 parents 2578f1e + 237bbd0 commit 18c520a

18 files changed

+242
-189
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Routing\Loader;
1313

1414
use Symfony\Component\Config\Loader\Loader;
15+
use Symfony\Component\Routing\RouteCollection;
1516

1617
/**
1718
* ClosureLoader loads routes from a PHP closure.
@@ -30,6 +31,8 @@ class ClosureLoader extends Loader
3031
* @param \Closure $closure A Closure
3132
* @param string|null $type The resource type
3233
*
34+
* @return RouteCollection A RouteCollection instance
35+
*
3336
* @api
3437
*/
3538
public function load($closure, $type = null)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111

1212
namespace Symfony\Component\Routing\Loader;
1313

14-
use Symfony\Component\Config\Resource\FileResource;
1514
use Symfony\Component\Config\Loader\FileLoader;
15+
use Symfony\Component\Config\Resource\FileResource;
16+
use Symfony\Component\Routing\RouteCollection;
1617

1718
/**
1819
* PhpFileLoader loads routes from a PHP file.
@@ -31,6 +32,8 @@ class PhpFileLoader extends FileLoader
3132
* @param string $file A PHP file path
3233
* @param string|null $type The resource type
3334
*
35+
* @return RouteCollection A RouteCollection instance
36+
*
3437
* @api
3538
*/
3639
public function load($file, $type = null)

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

Lines changed: 102 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@
2020
* XmlFileLoader loads XML routing files.
2121
*
2222
* @author Fabien Potencier <[email protected]>
23+
* @author Tobias Schultze <http://tobion.de>
2324
*
2425
* @api
2526
*/
2627
class XmlFileLoader extends FileLoader
2728
{
29+
const NAMESPACE_URI = 'http://symfony.com/schema/routing';
30+
const SCHEME_PATH = '/schema/routing/routing-1.0.xsd';
31+
2832
/**
2933
* Loads an XML file.
3034
*
@@ -33,7 +37,8 @@ class XmlFileLoader extends FileLoader
3337
*
3438
* @return RouteCollection A RouteCollection instance
3539
*
36-
* @throws \InvalidArgumentException When a tag can't be parsed
40+
* @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be
41+
* parsed because it does not validate against the scheme.
3742
*
3843
* @api
3944
*/
@@ -61,65 +66,28 @@ public function load($file, $type = null)
6166
/**
6267
* Parses a node from a loaded XML file.
6368
*
64-
* @param RouteCollection $collection the collection to associate with the node
65-
* @param \DOMElement $node the node to parse
66-
* @param string $path the path of the XML file being processed
67-
* @param string $file
69+
* @param RouteCollection $collection Collection to associate with the node
70+
* @param \DOMElement $node Element to parse
71+
* @param string $path Full path of the XML file being processed
72+
* @param string $file Loaded file name
6873
*
69-
* @throws \InvalidArgumentException When a tag can't be parsed
74+
* @throws \InvalidArgumentException When the XML is invalid
7075
*/
7176
protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file)
7277
{
73-
switch ($node->tagName) {
78+
if (self::NAMESPACE_URI !== $node->namespaceURI) {
79+
return;
80+
}
81+
82+
switch ($node->localName) {
7483
case 'route':
7584
$this->parseRoute($collection, $node, $path);
7685
break;
7786
case 'import':
78-
$resource = $node->getAttribute('resource');
79-
$type = $node->getAttribute('type');
80-
$prefix = $node->getAttribute('prefix');
81-
$hostnamePattern = $node->hasAttribute('hostname-pattern') ? $node->getAttribute('hostname-pattern') : null;
82-
83-
$defaults = array();
84-
$requirements = array();
85-
$options = array();
86-
87-
foreach ($node->childNodes as $n) {
88-
if (!$n instanceof \DOMElement) {
89-
continue;
90-
}
91-
92-
switch ($n->tagName) {
93-
case 'default':
94-
$defaults[$n->getAttribute('key')] = trim($n->nodeValue);
95-
break;
96-
case 'requirement':
97-
$requirements[$n->getAttribute('key')] = trim($n->nodeValue);
98-
break;
99-
case 'option':
100-
$options[$n->getAttribute('key')] = trim($n->nodeValue);
101-
break;
102-
default:
103-
throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $n->tagName));
104-
}
105-
}
106-
107-
$this->setCurrentDir(dirname($path));
108-
109-
$subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
110-
/* @var $subCollection RouteCollection */
111-
$subCollection->addPrefix($prefix);
112-
if (null !== $hostnamePattern) {
113-
$subCollection->setHostnamePattern($hostnamePattern);
114-
}
115-
$subCollection->addDefaults($defaults);
116-
$subCollection->addRequirements($requirements);
117-
$subCollection->addOptions($options);
118-
119-
$collection->addCollection($subCollection);
87+
$this->parseImport($collection, $node, $path, $file);
12088
break;
12189
default:
122-
throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName));
90+
throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
12391
}
12492
}
12593

@@ -136,41 +104,59 @@ public function supports($resource, $type = null)
136104
/**
137105
* Parses a route and adds it to the RouteCollection.
138106
*
139-
* @param RouteCollection $collection A RouteCollection instance
140-
* @param \DOMElement $definition Route definition
141-
* @param string $file An XML file path
107+
* @param RouteCollection $collection RouteCollection instance
108+
* @param \DOMElement $node Element to parse that represents a Route
109+
* @param string $path Full path of the XML file being processed
142110
*
143-
* @throws \InvalidArgumentException When the definition cannot be parsed
111+
* @throws \InvalidArgumentException When the XML is invalid
144112
*/
145-
protected function parseRoute(RouteCollection $collection, \DOMElement $definition, $file)
113+
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
146114
{
147-
$defaults = array();
148-
$requirements = array();
149-
$options = array();
115+
if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('pattern')) {
116+
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "pattern" attribute.', $path));
117+
}
150118

151-
foreach ($definition->childNodes as $node) {
152-
if (!$node instanceof \DOMElement) {
153-
continue;
154-
}
119+
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
155120

156-
switch ($node->tagName) {
157-
case 'default':
158-
$defaults[$node->getAttribute('key')] = trim((string) $node->nodeValue);
159-
break;
160-
case 'option':
161-
$options[$node->getAttribute('key')] = trim((string) $node->nodeValue);
162-
break;
163-
case 'requirement':
164-
$requirements[$node->getAttribute('key')] = trim((string) $node->nodeValue);
165-
break;
166-
default:
167-
throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName));
168-
}
121+
$route = new Route($node->getAttribute('pattern'), $defaults, $requirements, $options, $node->getAttribute('hostname-pattern'));
122+
$collection->add($id, $route);
123+
}
124+
125+
/**
126+
* Parses an import and adds the routes in the resource to the RouteCollection.
127+
*
128+
* @param RouteCollection $collection RouteCollection instance
129+
* @param \DOMElement $node Element to parse that represents a Route
130+
* @param string $path Full path of the XML file being processed
131+
* @param string $file Loaded file name
132+
*
133+
* @throws \InvalidArgumentException When the XML is invalid
134+
*/
135+
protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file)
136+
{
137+
if ('' === $resource = $node->getAttribute('resource')) {
138+
throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path));
169139
}
170140

171-
$route = new Route($definition->getAttribute('pattern'), $defaults, $requirements, $options, $definition->getAttribute('hostname-pattern'));
141+
$type = $node->getAttribute('type');
142+
$prefix = $node->getAttribute('prefix');
143+
$hostnamePattern = $node->hasAttribute('hostname-pattern') ? $node->getAttribute('hostname-pattern') : null;
144+
145+
list($defaults, $requirements, $options) = $this->parseConfigs($node, $path);
172146

173-
$collection->add($definition->getAttribute('id'), $route);
147+
$this->setCurrentDir(dirname($path));
148+
149+
$subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
150+
/* @var $subCollection RouteCollection */
151+
$subCollection->addPrefix($prefix);
152+
if (null !== $hostnamePattern) {
153+
$subCollection->setHostnamePattern($hostnamePattern);
154+
}
155+
$subCollection->addDefaults($defaults);
156+
$subCollection->addRequirements($requirements);
157+
$subCollection->addOptions($options);
158+
159+
$collection->addCollection($subCollection);
174160
}
175161

176162
/**
@@ -180,7 +166,9 @@ protected function parseRoute(RouteCollection $collection, \DOMElement $definiti
180166
*
181167
* @return \DOMDocument
182168
*
183-
* @throws \InvalidArgumentException When loading of XML file returns error
169+
* @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
170+
* or when the XML structure is not as expected by the scheme -
171+
* see validate()
184172
*/
185173
protected function loadFile($file)
186174
{
@@ -220,12 +208,10 @@ protected function loadFile($file)
220208
*/
221209
protected function validate(\DOMDocument $dom)
222210
{
223-
$location = __DIR__.'/schema/routing/routing-1.0.xsd';
224-
225211
$current = libxml_use_internal_errors(true);
226212
libxml_clear_errors();
227213

228-
if (!$dom->schemaValidate($location)) {
214+
if (!$dom->schemaValidate(__DIR__ . static::SCHEME_PATH)) {
229215
throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($current)));
230216
}
231217
libxml_use_internal_errors($current);
@@ -255,4 +241,39 @@ private function getXmlErrors($internalErrors)
255241

256242
return $errors;
257243
}
244+
245+
/**
246+
* Parses the config elements (default, requirement, option).
247+
*
248+
* @param \DOMElement $node Element to parse that contains the configs
249+
* @param string $path Full path of the XML file being processed
250+
*
251+
* @return array An array with the defaults as first item, requirements as second and options as third.
252+
*
253+
* @throws \InvalidArgumentException When the XML is invalid
254+
*/
255+
private function parseConfigs(\DOMElement $node, $path)
256+
{
257+
$defaults = array();
258+
$requirements = array();
259+
$options = array();
260+
261+
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
262+
switch ($n->localName) {
263+
case 'default':
264+
$defaults[$n->getAttribute('key')] = trim($n->textContent);
265+
break;
266+
case 'requirement':
267+
$requirements[$n->getAttribute('key')] = trim($n->textContent);
268+
break;
269+
case 'option':
270+
$options[$n->getAttribute('key')] = trim($n->textContent);
271+
break;
272+
default:
273+
throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path));
274+
}
275+
}
276+
277+
return array($defaults, $requirements, $options);
278+
}
258279
}

0 commit comments

Comments
 (0)