summaryrefslogtreecommitdiffstats
path: root/3rdparty/symfony/routing/Symfony/Component/Routing/Loader
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/symfony/routing/Symfony/Component/Routing/Loader')
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php213
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php77
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php125
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php54
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php64
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php224
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php142
-rw-r--r--3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd38
8 files changed, 937 insertions, 0 deletions
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php
new file mode 100644
index 00000000000..5f292d4589e
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php
@@ -0,0 +1,213 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Doctrine\Common\Annotations\Reader;
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\Config\Loader\LoaderResolver;
+
+/**
+ * AnnotationClassLoader loads routing information from a PHP class and its methods.
+ *
+ * You need to define an implementation for the getRouteDefaults() method. Most of the
+ * time, this method should define some PHP callable to be called for the route
+ * (a controller in MVC speak).
+ *
+ * The @Route annotation can be set on the class (for global parameters),
+ * and on each method.
+ *
+ * The @Route annotation main value is the route pattern. The annotation also
+ * recognizes three parameters: requirements, options, and name. The name parameter
+ * is mandatory. Here is an example of how you should be able to use it:
+ *
+ * /**
+ * * @Route("/Blog")
+ * * /
+ * class Blog
+ * {
+ * /**
+ * * @Route("/", name="blog_index")
+ * * /
+ * public function index()
+ * {
+ * }
+ *
+ * /**
+ * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"})
+ * * /
+ * public function show()
+ * {
+ * }
+ * }
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class AnnotationClassLoader implements LoaderInterface
+{
+ protected $reader;
+ protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route';
+ protected $defaultRouteIndex;
+
+ /**
+ * Constructor.
+ *
+ * @param Reader $reader
+ */
+ public function __construct(Reader $reader)
+ {
+ $this->reader = $reader;
+ }
+
+ /**
+ * Sets the annotation class to read route properties from.
+ *
+ * @param string $class A fully-qualified class name
+ */
+ public function setRouteAnnotationClass($class)
+ {
+ $this->routeAnnotationClass = $class;
+ }
+
+ /**
+ * Loads from annotations from a class.
+ *
+ * @param string $class A class name
+ * @param string $type The resource type
+ *
+ * @return RouteCollection A RouteCollection instance
+ *
+ * @throws \InvalidArgumentException When route can't be parsed
+ */
+ public function load($class, $type = null)
+ {
+ if (!class_exists($class)) {
+ throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+ }
+
+ $globals = array(
+ 'pattern' => '',
+ 'requirements' => array(),
+ 'options' => array(),
+ 'defaults' => array(),
+ );
+
+ $class = new \ReflectionClass($class);
+ if ($class->isAbstract()) {
+ throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class));
+ }
+
+ if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
+ if (null !== $annot->getPattern()) {
+ $globals['pattern'] = $annot->getPattern();
+ }
+
+ if (null !== $annot->getRequirements()) {
+ $globals['requirements'] = $annot->getRequirements();
+ }
+
+ if (null !== $annot->getOptions()) {
+ $globals['options'] = $annot->getOptions();
+ }
+
+ if (null !== $annot->getDefaults()) {
+ $globals['defaults'] = $annot->getDefaults();
+ }
+ }
+
+ $collection = new RouteCollection();
+ $collection->addResource(new FileResource($class->getFileName()));
+
+ foreach ($class->getMethods() as $method) {
+ $this->defaultRouteIndex = 0;
+ foreach ($this->reader->getMethodAnnotations($method) as $annot) {
+ if ($annot instanceof $this->routeAnnotationClass) {
+ $this->addRoute($collection, $annot, $globals, $class, $method);
+ }
+ }
+ }
+
+ return $collection;
+ }
+
+ protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method)
+ {
+ $name = $annot->getName();
+ if (null === $name) {
+ $name = $this->getDefaultRouteName($class, $method);
+ }
+
+ $defaults = array_merge($globals['defaults'], $annot->getDefaults());
+ $requirements = array_merge($globals['requirements'], $annot->getRequirements());
+ $options = array_merge($globals['options'], $annot->getOptions());
+
+ $route = new Route($globals['pattern'].$annot->getPattern(), $defaults, $requirements, $options);
+
+ $this->configureRoute($route, $class, $method, $annot);
+
+ $collection->add($name, $route);
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ */
+ public function supports($resource, $type = null)
+ {
+ return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type);
+ }
+
+ /**
+ * Sets the loader resolver.
+ *
+ * @param LoaderResolver $resolver A LoaderResolver instance
+ */
+ public function setResolver(LoaderResolver $resolver)
+ {
+ }
+
+ /**
+ * Gets the loader resolver.
+ *
+ * @return LoaderResolver A LoaderResolver instance
+ */
+ public function getResolver()
+ {
+ }
+
+ /**
+ * Gets the default route name for a class method.
+ *
+ * @param \ReflectionClass $class
+ * @param \ReflectionMethod $method
+ *
+ * @return string
+ */
+ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
+ {
+ $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name);
+ if ($this->defaultRouteIndex > 0) {
+ $name .= '_'.$this->defaultRouteIndex;
+ }
+ $this->defaultRouteIndex++;
+
+ return $name;
+ }
+
+ abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot);
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php
new file mode 100644
index 00000000000..8097cd67f96
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php
@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Config\Resource\DirectoryResource;
+
+/**
+ * AnnotationDirectoryLoader loads routing information from annotations set
+ * on PHP classes and methods.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class AnnotationDirectoryLoader extends AnnotationFileLoader
+{
+ /**
+ * Loads from annotations from a directory.
+ *
+ * @param string $path A directory path
+ * @param string $type The resource type
+ *
+ * @return RouteCollection A RouteCollection instance
+ *
+ * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed
+ */
+ public function load($path, $type = null)
+ {
+ $dir = $this->locator->locate($path);
+
+ $collection = new RouteCollection();
+ $collection->addResource(new DirectoryResource($dir, '/\.php$/'));
+ foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
+ if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) {
+ continue;
+ }
+
+ if ($class = $this->findClass($file)) {
+ $refl = new \ReflectionClass($class);
+ if ($refl->isAbstract()) {
+ continue;
+ }
+
+ $collection->addCollection($this->loader->load($class, $type));
+ }
+ }
+
+ return $collection;
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ */
+ public function supports($resource, $type = null)
+ {
+ try {
+ $path = $this->locator->locate($resource);
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type);
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
new file mode 100644
index 00000000000..49e1cb2f775
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
@@ -0,0 +1,125 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Loader\FileLoader;
+use Symfony\Component\Config\FileLocator;
+
+/**
+ * AnnotationFileLoader loads routing information from annotations set
+ * on a PHP class and its methods.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class AnnotationFileLoader extends FileLoader
+{
+ protected $loader;
+
+ /**
+ * Constructor.
+ *
+ * @param FileLocator $locator A FileLocator instance
+ * @param AnnotationClassLoader $loader An AnnotationClassLoader instance
+ * @param string|array $paths A path or an array of paths where to look for resources
+ */
+ public function __construct(FileLocator $locator, AnnotationClassLoader $loader, $paths = array())
+ {
+ if (!function_exists('token_get_all')) {
+ throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.');
+ }
+
+ parent::__construct($locator, $paths);
+
+ $this->loader = $loader;
+ }
+
+ /**
+ * Loads from annotations from a file.
+ *
+ * @param string $file A PHP file path
+ * @param string $type The resource type
+ *
+ * @return RouteCollection A RouteCollection instance
+ *
+ * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
+ */
+ public function load($file, $type = null)
+ {
+ $path = $this->locator->locate($file);
+
+ $collection = new RouteCollection();
+ if ($class = $this->findClass($path)) {
+ $collection->addResource(new FileResource($path));
+ $collection->addCollection($this->loader->load($class, $type));
+ }
+
+ return $collection;
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ */
+ public function supports($resource, $type = null)
+ {
+ return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type);
+ }
+
+ /**
+ * Returns the full class name for the first class in the file.
+ *
+ * @param string $file A PHP file path
+ *
+ * @return string|false Full class name if found, false otherwise
+ */
+ protected function findClass($file)
+ {
+ $class = false;
+ $namespace = false;
+ $tokens = token_get_all(file_get_contents($file));
+ for ($i = 0, $count = count($tokens); $i < $count; $i++) {
+ $token = $tokens[$i];
+
+ if (!is_array($token)) {
+ continue;
+ }
+
+ if (true === $class && T_STRING === $token[0]) {
+ return $namespace.'\\'.$token[1];
+ }
+
+ if (true === $namespace && T_STRING === $token[0]) {
+ $namespace = '';
+ do {
+ $namespace .= $token[1];
+ $token = $tokens[++$i];
+ } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
+ }
+
+ if (T_CLASS === $token[0]) {
+ $class = true;
+ }
+
+ if (T_NAMESPACE === $token[0]) {
+ $namespace = true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php
new file mode 100644
index 00000000000..ca49c8fa35a
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Config\Loader\Loader;
+
+/**
+ * ClosureLoader loads routes from a PHP closure.
+ *
+ * The Closure must return a RouteCollection instance.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class ClosureLoader extends Loader
+{
+ /**
+ * Loads a Closure.
+ *
+ * @param \Closure $closure A Closure
+ * @param string $type The resource type
+ *
+ * @api
+ */
+ public function load($closure, $type = null)
+ {
+ return call_user_func($closure);
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ *
+ * @api
+ */
+ public function supports($resource, $type = null)
+ {
+ return $resource instanceof \Closure && (!$type || 'closure' === $type);
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php
new file mode 100644
index 00000000000..ffd31f94442
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Loader\FileLoader;
+
+/**
+ * PhpFileLoader loads routes from a PHP file.
+ *
+ * The file must return a RouteCollection instance.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class PhpFileLoader extends FileLoader
+{
+ /**
+ * Loads a PHP file.
+ *
+ * @param mixed $file A PHP file path
+ * @param string $type The resource type
+ *
+ * @api
+ */
+ public function load($file, $type = null)
+ {
+ // the loader variable is exposed to the included file below
+ $loader = $this;
+
+ $path = $this->locator->locate($file);
+ $this->setCurrentDir(dirname($path));
+
+ $collection = include $path;
+ $collection->addResource(new FileResource($path));
+
+ return $collection;
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ *
+ * @api
+ */
+ public function supports($resource, $type = null)
+ {
+ return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type);
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php
new file mode 100644
index 00000000000..5dad9db3fae
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php
@@ -0,0 +1,224 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Loader\FileLoader;
+
+/**
+ * XmlFileLoader loads XML routing files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class XmlFileLoader extends FileLoader
+{
+ /**
+ * Loads an XML file.
+ *
+ * @param string $file An XML file path
+ * @param string $type The resource type
+ *
+ * @return RouteCollection A RouteCollection instance
+ *
+ * @throws \InvalidArgumentException When a tag can't be parsed
+ *
+ * @api
+ */
+ public function load($file, $type = null)
+ {
+ $path = $this->locator->locate($file);
+
+ $xml = $this->loadFile($path);
+
+ $collection = new RouteCollection();
+ $collection->addResource(new FileResource($path));
+
+ // process routes and imports
+ foreach ($xml->documentElement->childNodes as $node) {
+ if (!$node instanceof \DOMElement) {
+ continue;
+ }
+
+ $this->parseNode($collection, $node, $path, $file);
+ }
+
+ return $collection;
+ }
+
+ /**
+ * Parses a node from a loaded XML file.
+ *
+ * @param RouteCollection $collection the collection to associate with the node
+ * @param DOMElement $node the node to parse
+ * @param string $path the path of the XML file being processed
+ * @param string $file
+ */
+ protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file)
+ {
+ switch ($node->tagName) {
+ case 'route':
+ $this->parseRoute($collection, $node, $path);
+ break;
+ case 'import':
+ $resource = (string) $node->getAttribute('resource');
+ $type = (string) $node->getAttribute('type');
+ $prefix = (string) $node->getAttribute('prefix');
+ $this->setCurrentDir(dirname($path));
+ $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix);
+ break;
+ default:
+ throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName));
+ }
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ *
+ * @api
+ */
+ public function supports($resource, $type = null)
+ {
+ return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type);
+ }
+
+ /**
+ * Parses a route and adds it to the RouteCollection.
+ *
+ * @param RouteCollection $collection A RouteCollection instance
+ * @param \DOMElement $definition Route definition
+ * @param string $file An XML file path
+ *
+ * @throws \InvalidArgumentException When the definition cannot be parsed
+ */
+ protected function parseRoute(RouteCollection $collection, \DOMElement $definition, $file)
+ {
+ $defaults = array();
+ $requirements = array();
+ $options = array();
+
+ foreach ($definition->childNodes as $node) {
+ if (!$node instanceof \DOMElement) {
+ continue;
+ }
+
+ switch ($node->tagName) {
+ case 'default':
+ $defaults[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue);
+ break;
+ case 'option':
+ $options[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue);
+ break;
+ case 'requirement':
+ $requirements[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue);
+ break;
+ default:
+ throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName));
+ }
+ }
+
+ $route = new Route((string) $definition->getAttribute('pattern'), $defaults, $requirements, $options);
+
+ $collection->add((string) $definition->getAttribute('id'), $route);
+ }
+
+ /**
+ * Loads an XML file.
+ *
+ * @param string $file An XML file path
+ *
+ * @return \DOMDocument
+ *
+ * @throws \InvalidArgumentException When loading of XML file returns error
+ */
+ protected function loadFile($file)
+ {
+ $internalErrors = libxml_use_internal_errors(true);
+ $disableEntities = libxml_disable_entity_loader(true);
+ libxml_clear_errors();
+
+ $dom = new \DOMDocument();
+ $dom->validateOnParse = true;
+ if (!$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
+ libxml_disable_entity_loader($disableEntities);
+
+ throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($internalErrors)));
+ }
+ $dom->normalizeDocument();
+
+ libxml_use_internal_errors($internalErrors);
+ libxml_disable_entity_loader($disableEntities);
+
+ foreach ($dom->childNodes as $child) {
+ if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
+ throw new \InvalidArgumentException('Document types are not allowed.');
+ }
+ }
+
+ $this->validate($dom);
+
+ return $dom;
+ }
+
+ /**
+ * Validates a loaded XML file.
+ *
+ * @param \DOMDocument $dom A loaded XML file
+ *
+ * @throws \InvalidArgumentException When XML doesn't validate its XSD schema
+ */
+ protected function validate(\DOMDocument $dom)
+ {
+ $location = __DIR__.'/schema/routing/routing-1.0.xsd';
+
+ $current = libxml_use_internal_errors(true);
+ libxml_clear_errors();
+
+ if (!$dom->schemaValidate($location)) {
+ throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($current)));
+ }
+ libxml_use_internal_errors($current);
+ }
+
+ /**
+ * Retrieves libxml errors and clears them.
+ *
+ * @return array An array of libxml error strings
+ */
+ private function getXmlErrors($internalErrors)
+ {
+ $errors = array();
+ foreach (libxml_get_errors() as $error) {
+ $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
+ LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
+ $error->code,
+ trim($error->message),
+ $error->file ? $error->file : 'n/a',
+ $error->line,
+ $error->column
+ );
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return $errors;
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php
new file mode 100644
index 00000000000..ee723834355
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Routing\Loader;
+
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Yaml\Yaml;
+use Symfony\Component\Config\Loader\FileLoader;
+
+/**
+ * YamlFileLoader loads Yaml routing files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @api
+ */
+class YamlFileLoader extends FileLoader
+{
+ private static $availableKeys = array(
+ 'type', 'resource', 'prefix', 'pattern', 'options', 'defaults', 'requirements'
+ );
+
+ /**
+ * Loads a Yaml file.
+ *
+ * @param string $file A Yaml file path
+ * @param string $type The resource type
+ *
+ * @return RouteCollection A RouteCollection instance
+ *
+ * @throws \InvalidArgumentException When route can't be parsed
+ *
+ * @api
+ */
+ public function load($file, $type = null)
+ {
+ $path = $this->locator->locate($file);
+
+ $config = Yaml::parse($path);
+
+ $collection = new RouteCollection();
+ $collection->addResource(new FileResource($path));
+
+ // empty file
+ if (null === $config) {
+ $config = array();
+ }
+
+ // not an array
+ if (!is_array($config)) {
+ throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $file));
+ }
+
+ foreach ($config as $name => $config) {
+ $config = $this->normalizeRouteConfig($config);
+
+ if (isset($config['resource'])) {
+ $type = isset($config['type']) ? $config['type'] : null;
+ $prefix = isset($config['prefix']) ? $config['prefix'] : null;
+ $this->setCurrentDir(dirname($path));
+ $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix);
+ } else {
+ $this->parseRoute($collection, $name, $config, $path);
+ }
+ }
+
+ return $collection;
+ }
+
+ /**
+ * Returns true if this class supports the given resource.
+ *
+ * @param mixed $resource A resource
+ * @param string $type The resource type
+ *
+ * @return Boolean True if this class supports the given resource, false otherwise
+ *
+ * @api
+ */
+ public function supports($resource, $type = null)
+ {
+ return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type);
+ }
+
+ /**
+ * Parses a route and adds it to the RouteCollection.
+ *
+ * @param RouteCollection $collection A RouteCollection instance
+ * @param string $name Route name
+ * @param array $config Route definition
+ * @param string $file A Yaml file path
+ *
+ * @throws \InvalidArgumentException When config pattern is not defined for the given route
+ */
+ protected function parseRoute(RouteCollection $collection, $name, $config, $file)
+ {
+ $defaults = isset($config['defaults']) ? $config['defaults'] : array();
+ $requirements = isset($config['requirements']) ? $config['requirements'] : array();
+ $options = isset($config['options']) ? $config['options'] : array();
+
+ if (!isset($config['pattern'])) {
+ throw new \InvalidArgumentException(sprintf('You must define a "pattern" for the "%s" route.', $name));
+ }
+
+ $route = new Route($config['pattern'], $defaults, $requirements, $options);
+
+ $collection->add($name, $route);
+ }
+
+ /**
+ * Normalize route configuration.
+ *
+ * @param array $config A resource config
+ *
+ * @return array
+ *
+ * @throws InvalidArgumentException if one of the provided config keys is not supported
+ */
+ private function normalizeRouteConfig(array $config)
+ {
+ foreach ($config as $key => $value) {
+ if (!in_array($key, self::$availableKeys)) {
+ throw new \InvalidArgumentException(sprintf(
+ 'Yaml routing loader does not support given key: "%s". Expected one of the (%s).',
+ $key, implode(', ', self::$availableKeys)
+ ));
+ }
+ }
+
+ return $config;
+ }
+}
diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd
new file mode 100644
index 00000000000..a9554e64df3
--- /dev/null
+++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<xsd:schema xmlns="http://symfony.com/schema/routing"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://symfony.com/schema/routing"
+ elementFormDefault="qualified">
+
+ <xsd:element name="routes" type="routes" />
+
+ <xsd:complexType name="routes">
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element name="import" type="import" />
+ <xsd:element name="route" type="route" />
+ </xsd:choice>
+ </xsd:complexType>
+
+ <xsd:complexType name="route">
+ <xsd:sequence>
+ <xsd:element name="default" type="element" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="requirement" type="element" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="option" type="element" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+
+ <xsd:attribute name="id" type="xsd:string" />
+ <xsd:attribute name="pattern" type="xsd:string" />
+ </xsd:complexType>
+
+ <xsd:complexType name="import">
+ <xsd:attribute name="resource" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="prefix" type="xsd:string" />
+ <xsd:attribute name="class" type="xsd:string" />
+ </xsd:complexType>
+
+ <xsd:complexType name="element" mixed="true">
+ <xsd:attribute name="key" type="xsd:string" />
+ </xsd:complexType>
+</xsd:schema>