Browse Source
			
			
			Include copy of Symfony routing component, and don't use composer
			
			
				remotes/origin/stable5
			
			
		
		Include copy of Symfony routing component, and don't use composer
	
		
	
			
			
				remotes/origin/stable5
			
			
		
							committed by
							
								
								Robin Appelman
							
						
					
				
				 44 changed files with 4037 additions and 22 deletions
			
			
		- 
					4.gitignore
 - 
					BIN3rdparty/bin/composer
 - 
					1033rdparty/symfony/routing/Symfony/Component/Routing/Annotation/Route.php
 - 
					1343rdparty/symfony/routing/Symfony/Component/Routing/CompiledRoute.php
 - 
					233rdparty/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php
 - 
					233rdparty/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php
 - 
					383rdparty/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php
 - 
					243rdparty/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php
 - 
					253rdparty/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php
 - 
					233rdparty/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php
 - 
					393rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php
 - 
					453rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php
 - 
					1503rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php
 - 
					1763rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGenerator.php
 - 
					373rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php
 - 
					193rdparty/symfony/routing/Symfony/Component/Routing/LICENSE
 - 
					2133rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php
 - 
					773rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php
 - 
					1253rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php
 - 
					543rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php
 - 
					643rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php
 - 
					2243rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php
 - 
					1423rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php
 - 
					383rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd
 - 
					763rdparty/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php
 - 
					1553rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
 - 
					443rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php
 - 
					413rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php
 - 
					2933rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php
 - 
					533rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php
 - 
					353rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php
 - 
					1513rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php
 - 
					383rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php
 - 
					323rdparty/symfony/routing/Symfony/Component/Routing/README.md
 - 
					2503rdparty/symfony/routing/Symfony/Component/Routing/RequestContext.php
 - 
					273rdparty/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php
 - 
					3123rdparty/symfony/routing/Symfony/Component/Routing/Route.php
 - 
					2593rdparty/symfony/routing/Symfony/Component/Routing/RouteCollection.php
 - 
					1283rdparty/symfony/routing/Symfony/Component/Routing/RouteCompiler.php
 - 
					293rdparty/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php
 - 
					2633rdparty/symfony/routing/Symfony/Component/Routing/Router.php
 - 
					263rdparty/symfony/routing/Symfony/Component/Routing/RouterInterface.php
 - 
					293rdparty/symfony/routing/Symfony/Component/Routing/composer.json
 - 
					18composer.json
 
@ -0,0 +1,103 @@ | 
				
			|||
<?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\Annotation; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Annotation class for @Route(). | 
				
			|||
 * | 
				
			|||
 * @Annotation | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class Route | 
				
			|||
{ | 
				
			|||
    private $pattern; | 
				
			|||
    private $name; | 
				
			|||
    private $requirements; | 
				
			|||
    private $options; | 
				
			|||
    private $defaults; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param array $data An array of key/value parameters. | 
				
			|||
     */ | 
				
			|||
    public function __construct(array $data) | 
				
			|||
    { | 
				
			|||
        $this->requirements = array(); | 
				
			|||
        $this->options = array(); | 
				
			|||
        $this->defaults = array(); | 
				
			|||
 | 
				
			|||
        if (isset($data['value'])) { | 
				
			|||
            $data['pattern'] = $data['value']; | 
				
			|||
            unset($data['value']); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        foreach ($data as $key => $value) { | 
				
			|||
            $method = 'set'.$key; | 
				
			|||
            if (!method_exists($this, $method)) { | 
				
			|||
                throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this))); | 
				
			|||
            } | 
				
			|||
            $this->$method($value); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function setPattern($pattern) | 
				
			|||
    { | 
				
			|||
        $this->pattern = $pattern; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getPattern() | 
				
			|||
    { | 
				
			|||
        return $this->pattern; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function setName($name) | 
				
			|||
    { | 
				
			|||
        $this->name = $name; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getName() | 
				
			|||
    { | 
				
			|||
        return $this->name; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function setRequirements($requirements) | 
				
			|||
    { | 
				
			|||
        $this->requirements = $requirements; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getRequirements() | 
				
			|||
    { | 
				
			|||
        return $this->requirements; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function setOptions($options) | 
				
			|||
    { | 
				
			|||
        $this->options = $options; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getOptions() | 
				
			|||
    { | 
				
			|||
        return $this->options; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function setDefaults($defaults) | 
				
			|||
    { | 
				
			|||
        $this->defaults = $defaults; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getDefaults() | 
				
			|||
    { | 
				
			|||
        return $this->defaults; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,134 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * CompiledRoutes are returned by the RouteCompiler class. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class CompiledRoute | 
				
			|||
{ | 
				
			|||
    private $route; | 
				
			|||
    private $variables; | 
				
			|||
    private $tokens; | 
				
			|||
    private $staticPrefix; | 
				
			|||
    private $regex; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param Route  $route        A original Route instance | 
				
			|||
     * @param string $staticPrefix The static prefix of the compiled route | 
				
			|||
     * @param string $regex        The regular expression to use to match this route | 
				
			|||
     * @param array  $tokens       An array of tokens to use to generate URL for this route | 
				
			|||
     * @param array  $variables    An array of variables | 
				
			|||
     */ | 
				
			|||
    public function __construct(Route $route, $staticPrefix, $regex, array $tokens, array $variables) | 
				
			|||
    { | 
				
			|||
        $this->route = $route; | 
				
			|||
        $this->staticPrefix = $staticPrefix; | 
				
			|||
        $this->regex = $regex; | 
				
			|||
        $this->tokens = $tokens; | 
				
			|||
        $this->variables = $variables; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the Route instance. | 
				
			|||
     * | 
				
			|||
     * @return Route A Route instance | 
				
			|||
     */ | 
				
			|||
    public function getRoute() | 
				
			|||
    { | 
				
			|||
        return $this->route; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the static prefix. | 
				
			|||
     * | 
				
			|||
     * @return string The static prefix | 
				
			|||
     */ | 
				
			|||
    public function getStaticPrefix() | 
				
			|||
    { | 
				
			|||
        return $this->staticPrefix; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the regex. | 
				
			|||
     * | 
				
			|||
     * @return string The regex | 
				
			|||
     */ | 
				
			|||
    public function getRegex() | 
				
			|||
    { | 
				
			|||
        return $this->regex; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the tokens. | 
				
			|||
     * | 
				
			|||
     * @return array The tokens | 
				
			|||
     */ | 
				
			|||
    public function getTokens() | 
				
			|||
    { | 
				
			|||
        return $this->tokens; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the variables. | 
				
			|||
     * | 
				
			|||
     * @return array The variables | 
				
			|||
     */ | 
				
			|||
    public function getVariables() | 
				
			|||
    { | 
				
			|||
        return $this->variables; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the pattern. | 
				
			|||
     * | 
				
			|||
     * @return string The pattern | 
				
			|||
     */ | 
				
			|||
    public function getPattern() | 
				
			|||
    { | 
				
			|||
        return $this->route->getPattern(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the options. | 
				
			|||
     * | 
				
			|||
     * @return array The options | 
				
			|||
     */ | 
				
			|||
    public function getOptions() | 
				
			|||
    { | 
				
			|||
        return $this->route->getOptions(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the defaults. | 
				
			|||
     * | 
				
			|||
     * @return array The defaults | 
				
			|||
     */ | 
				
			|||
    public function getDefaults() | 
				
			|||
    { | 
				
			|||
        return $this->route->getDefaults(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the requirements. | 
				
			|||
     * | 
				
			|||
     * @return array The requirements | 
				
			|||
     */ | 
				
			|||
    public function getRequirements() | 
				
			|||
    { | 
				
			|||
        return $this->route->getRequirements(); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,23 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * ExceptionInterface | 
				
			|||
 * | 
				
			|||
 * @author Alexandre Salomé <alexandre.salome@gmail.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface ExceptionInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,23 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Exception thrown when a parameter is not valid | 
				
			|||
 * | 
				
			|||
 * @author Alexandre Salomé <alexandre.salome@gmail.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * The resource was found but the request method is not allowed. | 
				
			|||
 * | 
				
			|||
 * This exception should trigger an HTTP 405 response in your application code. | 
				
			|||
 * | 
				
			|||
 * @author Kris Wallsmith <kris@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface | 
				
			|||
{ | 
				
			|||
    protected $allowedMethods; | 
				
			|||
 | 
				
			|||
    public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) | 
				
			|||
    { | 
				
			|||
        $this->allowedMethods = array_map('strtoupper', $allowedMethods); | 
				
			|||
 | 
				
			|||
        parent::__construct($message, $code, $previous); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getAllowedMethods() | 
				
			|||
    { | 
				
			|||
        return $this->allowedMethods; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,24 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Exception thrown when a route cannot be generated because of missing | 
				
			|||
 * mandatory parameters. | 
				
			|||
 * | 
				
			|||
 * @author Alexandre Salomé <alexandre.salome@gmail.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,25 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * The resource was not found. | 
				
			|||
 * | 
				
			|||
 * This exception should trigger an HTTP 404 response in your application code. | 
				
			|||
 * | 
				
			|||
 * @author Kris Wallsmith <kris@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,23 @@ | 
				
			|||
<?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\Exception; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Exception thrown when a route does not exists | 
				
			|||
 * | 
				
			|||
 * @author Alexandre Salomé <alexandre.salome@gmail.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,39 @@ | 
				
			|||
<?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\Generator\Dumper; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * GeneratorDumper is the base class for all built-in generator dumpers. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
abstract class GeneratorDumper implements GeneratorDumperInterface | 
				
			|||
{ | 
				
			|||
    private $routes; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $routes The RouteCollection to dump | 
				
			|||
     */ | 
				
			|||
    public function __construct(RouteCollection $routes) | 
				
			|||
    { | 
				
			|||
        $this->routes = $routes; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getRoutes() | 
				
			|||
    { | 
				
			|||
        return $this->routes; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,45 @@ | 
				
			|||
<?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\Generator\Dumper; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * GeneratorDumperInterface is the interface that all generator dumper classes must implement. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface GeneratorDumperInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Dumps a set of routes to a PHP class. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * class:      The class name | 
				
			|||
     *  * base_class: The base class name | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @return string A PHP class representing the generator class | 
				
			|||
     */ | 
				
			|||
    public function dump(array $options = array()); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the routes to dump. | 
				
			|||
     * | 
				
			|||
     * @return RouteCollection A RouteCollection instance | 
				
			|||
     */ | 
				
			|||
    public function getRoutes(); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,150 @@ | 
				
			|||
<?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\Generator\Dumper; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Route; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class PhpGeneratorDumper extends GeneratorDumper | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Dumps a set of routes to a PHP class. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * class:      The class name | 
				
			|||
     *  * base_class: The base class name | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @return string A PHP class representing the generator class | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function dump(array $options = array()) | 
				
			|||
    { | 
				
			|||
        $options = array_merge(array( | 
				
			|||
            'class'      => 'ProjectUrlGenerator', | 
				
			|||
            'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | 
				
			|||
        ), $options); | 
				
			|||
 | 
				
			|||
        return | 
				
			|||
            $this->startClass($options['class'], $options['base_class']). | 
				
			|||
            $this->addConstructor(). | 
				
			|||
            $this->addGenerator(). | 
				
			|||
            $this->endClass() | 
				
			|||
        ; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function addGenerator() | 
				
			|||
    { | 
				
			|||
        $methods = array(); | 
				
			|||
        foreach ($this->getRoutes()->all() as $name => $route) { | 
				
			|||
            $compiledRoute = $route->compile(); | 
				
			|||
 | 
				
			|||
            $variables = str_replace("\n", '', var_export($compiledRoute->getVariables(), true)); | 
				
			|||
            $defaults = str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)); | 
				
			|||
            $requirements = str_replace("\n", '', var_export($compiledRoute->getRequirements(), true)); | 
				
			|||
            $tokens = str_replace("\n", '', var_export($compiledRoute->getTokens(), true)); | 
				
			|||
 | 
				
			|||
            $escapedName = str_replace('.', '__', $name); | 
				
			|||
 | 
				
			|||
            $methods[] = <<<EOF | 
				
			|||
    private function get{$escapedName}RouteInfo() | 
				
			|||
    { | 
				
			|||
        return array($variables, $defaults, $requirements, $tokens); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
EOF | 
				
			|||
            ; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $methods = implode("\n", $methods); | 
				
			|||
 | 
				
			|||
        return <<<EOF | 
				
			|||
 | 
				
			|||
    public function generate(\$name, \$parameters = array(), \$absolute = false) | 
				
			|||
    { | 
				
			|||
        if (!isset(self::\$declaredRouteNames[\$name])) { | 
				
			|||
            throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', \$name)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        \$escapedName = str_replace('.', '__', \$name); | 
				
			|||
 | 
				
			|||
        list(\$variables, \$defaults, \$requirements, \$tokens) = \$this->{'get'.\$escapedName.'RouteInfo'}(); | 
				
			|||
 | 
				
			|||
        return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$absolute); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
$methods | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function startClass($class, $baseClass) | 
				
			|||
    { | 
				
			|||
        $routes = array(); | 
				
			|||
        foreach ($this->getRoutes()->all() as $name => $route) { | 
				
			|||
            $routes[] = "       '$name' => true,"; | 
				
			|||
        } | 
				
			|||
        $routes  = implode("\n", $routes); | 
				
			|||
 | 
				
			|||
        return <<<EOF | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RequestContext; | 
				
			|||
use Symfony\Component\Routing\Exception\RouteNotFoundException; | 
				
			|||
 | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * $class | 
				
			|||
 * | 
				
			|||
 * This class has been auto-generated | 
				
			|||
 * by the Symfony Routing Component. | 
				
			|||
 */ | 
				
			|||
class $class extends $baseClass | 
				
			|||
{ | 
				
			|||
    static private \$declaredRouteNames = array( | 
				
			|||
$routes | 
				
			|||
    ); | 
				
			|||
 | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function addConstructor() | 
				
			|||
    { | 
				
			|||
        return <<<EOF | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     */ | 
				
			|||
    public function __construct(RequestContext \$context) | 
				
			|||
    { | 
				
			|||
        \$this->context = \$context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function endClass() | 
				
			|||
    { | 
				
			|||
        return <<<EOF | 
				
			|||
} | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,176 @@ | 
				
			|||
<?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\Generator; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Route; | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
use Symfony\Component\Routing\RequestContext; | 
				
			|||
use Symfony\Component\Routing\Exception\InvalidParameterException; | 
				
			|||
use Symfony\Component\Routing\Exception\RouteNotFoundException; | 
				
			|||
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * UrlGenerator generates URL based on a set of routes. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class UrlGenerator implements UrlGeneratorInterface | 
				
			|||
{ | 
				
			|||
    protected $context; | 
				
			|||
    protected $decodedChars = array( | 
				
			|||
        // %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it)
 | 
				
			|||
        '%2F' => '/', | 
				
			|||
    ); | 
				
			|||
 | 
				
			|||
    protected $routes; | 
				
			|||
    protected $cache; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $routes  A RouteCollection instance | 
				
			|||
     * @param RequestContext  $context The context | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function __construct(RouteCollection $routes, RequestContext $context) | 
				
			|||
    { | 
				
			|||
        $this->routes = $routes; | 
				
			|||
        $this->context = $context; | 
				
			|||
        $this->cache = array(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the request context. | 
				
			|||
     * | 
				
			|||
     * @param RequestContext $context The context | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setContext(RequestContext $context) | 
				
			|||
    { | 
				
			|||
        $this->context = $context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the request context. | 
				
			|||
     * | 
				
			|||
     * @return RequestContext The context | 
				
			|||
     */ | 
				
			|||
    public function getContext() | 
				
			|||
    { | 
				
			|||
        return $this->context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Generates a URL from the given parameters. | 
				
			|||
     * | 
				
			|||
     * @param string  $name       The name of the route | 
				
			|||
     * @param mixed   $parameters An array of parameters | 
				
			|||
     * @param Boolean $absolute   Whether to generate an absolute URL | 
				
			|||
     * | 
				
			|||
     * @return string The generated URL | 
				
			|||
     * | 
				
			|||
     * @throws Symfony\Component\Routing\Exception\RouteNotFoundException When route doesn't exist | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function generate($name, $parameters = array(), $absolute = false) | 
				
			|||
    { | 
				
			|||
        if (null === $route = $this->routes->get($name)) { | 
				
			|||
            throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (!isset($this->cache[$name])) { | 
				
			|||
            $this->cache[$name] = $route->compile(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->doGenerate($this->cache[$name]->getVariables(), $route->getDefaults(), $route->getRequirements(), $this->cache[$name]->getTokens(), $parameters, $name, $absolute); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @throws Symfony\Component\Routing\Exception\MissingMandatoryParametersException When route has some missing mandatory parameters | 
				
			|||
     * @throws Symfony\Component\Routing\Exception\InvalidParameterException When a parameter value is not correct | 
				
			|||
     */ | 
				
			|||
    protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute) | 
				
			|||
    { | 
				
			|||
        $variables = array_flip($variables); | 
				
			|||
 | 
				
			|||
        $originParameters = $parameters; | 
				
			|||
        $parameters = array_replace($this->context->getParameters(), $parameters); | 
				
			|||
        $tparams = array_replace($defaults, $parameters); | 
				
			|||
 | 
				
			|||
        // all params must be given
 | 
				
			|||
        if ($diff = array_diff_key($variables, $tparams)) { | 
				
			|||
            throw new MissingMandatoryParametersException(sprintf('The "%s" route has some missing mandatory parameters ("%s").', $name, implode('", "', array_keys($diff)))); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $url = ''; | 
				
			|||
        $optional = true; | 
				
			|||
        foreach ($tokens as $token) { | 
				
			|||
            if ('variable' === $token[0]) { | 
				
			|||
                if (false === $optional || !array_key_exists($token[3], $defaults) || (isset($parameters[$token[3]]) && (string) $parameters[$token[3]] != (string) $defaults[$token[3]])) { | 
				
			|||
                    if (!$isEmpty = in_array($tparams[$token[3]], array(null, '', false), true)) { | 
				
			|||
                        // check requirement
 | 
				
			|||
                        if ($tparams[$token[3]] && !preg_match('#^'.$token[2].'$#', $tparams[$token[3]])) { | 
				
			|||
                            throw new InvalidParameterException(sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $tparams[$token[3]])); | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
 | 
				
			|||
                    if (!$isEmpty || !$optional) { | 
				
			|||
                        $url = $token[1].strtr(rawurlencode($tparams[$token[3]]), $this->decodedChars).$url; | 
				
			|||
                    } | 
				
			|||
 | 
				
			|||
                    $optional = false; | 
				
			|||
                } | 
				
			|||
            } elseif ('text' === $token[0]) { | 
				
			|||
                $url = $token[1].$url; | 
				
			|||
                $optional = false; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (!$url) { | 
				
			|||
            $url = '/'; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // add a query string if needed
 | 
				
			|||
        $extra = array_diff_key($originParameters, $variables, $defaults); | 
				
			|||
        if ($extra && $query = http_build_query($extra, '', '&')) { | 
				
			|||
            $url .= '?'.$query; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $url = $this->context->getBaseUrl().$url; | 
				
			|||
 | 
				
			|||
        if ($this->context->getHost()) { | 
				
			|||
            $scheme = $this->context->getScheme(); | 
				
			|||
            if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme != $req) { | 
				
			|||
                $absolute = true; | 
				
			|||
                $scheme = $req; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if ($absolute) { | 
				
			|||
                $port = ''; | 
				
			|||
                if ('http' === $scheme && 80 != $this->context->getHttpPort()) { | 
				
			|||
                    $port = ':'.$this->context->getHttpPort(); | 
				
			|||
                } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { | 
				
			|||
                    $port = ':'.$this->context->getHttpsPort(); | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                $url = $scheme.'://'.$this->context->getHost().$port.$url; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $url; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,37 @@ | 
				
			|||
<?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\Generator; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RequestContextAwareInterface; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * UrlGeneratorInterface is the interface that all URL generator classes must implements. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface UrlGeneratorInterface extends RequestContextAwareInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Generates a URL from the given parameters. | 
				
			|||
     * | 
				
			|||
     * @param string  $name       The name of the route | 
				
			|||
     * @param mixed   $parameters An array of parameters | 
				
			|||
     * @param Boolean $absolute   Whether to generate an absolute URL | 
				
			|||
     * | 
				
			|||
     * @return string The generated URL | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function generate($name, $parameters = array(), $absolute = false); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,19 @@ | 
				
			|||
Copyright (c) 2004-2012 Fabien Potencier | 
				
			|||
 | 
				
			|||
Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			|||
of this software and associated documentation files (the "Software"), to deal | 
				
			|||
in the Software without restriction, including without limitation the rights | 
				
			|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
				
			|||
copies of the Software, and to permit persons to whom the Software is furnished | 
				
			|||
to do so, subject to the following conditions: | 
				
			|||
 | 
				
			|||
The above copyright notice and this permission notice shall be included in all | 
				
			|||
copies or substantial portions of the Software. | 
				
			|||
 | 
				
			|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
				
			|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
				
			|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
				
			|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
				
			|||
THE SOFTWARE. | 
				
			|||
@ -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); | 
				
			|||
} | 
				
			|||
@ -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); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -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> | 
				
			|||
@ -0,0 +1,76 @@ | 
				
			|||
<?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\Matcher; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Exception\MethodNotAllowedException; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper). | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class ApacheUrlMatcher extends UrlMatcher | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Tries to match a URL based on Apache mod_rewrite matching. | 
				
			|||
     * | 
				
			|||
     * Returns false if no route matches the URL. | 
				
			|||
     * | 
				
			|||
     * @param string $pathinfo The pathinfo to be parsed | 
				
			|||
     * | 
				
			|||
     * @return array An array of parameters | 
				
			|||
     * | 
				
			|||
     * @throws MethodNotAllowedException If the current method is not allowed | 
				
			|||
     */ | 
				
			|||
    public function match($pathinfo) | 
				
			|||
    { | 
				
			|||
        $parameters = array(); | 
				
			|||
        $defaults = array(); | 
				
			|||
        $allow = array(); | 
				
			|||
        $match = false; | 
				
			|||
 | 
				
			|||
        foreach ($_SERVER as $key => $value) { | 
				
			|||
            $name = $key; | 
				
			|||
 | 
				
			|||
            if (0 === strpos($name, 'REDIRECT_')) { | 
				
			|||
                $name = substr($name, 9); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if (0 === strpos($name, '_ROUTING_DEFAULTS_')) { | 
				
			|||
                $name = substr($name, 18); | 
				
			|||
                $defaults[$name] = $value; | 
				
			|||
            } elseif (0 === strpos($name, '_ROUTING_')) { | 
				
			|||
                $name = substr($name, 9); | 
				
			|||
                if ('_route' == $name) { | 
				
			|||
                    $match = true; | 
				
			|||
                    $parameters[$name] = $value; | 
				
			|||
                } elseif (0 === strpos($name, '_allow_')) { | 
				
			|||
                    $allow[] = substr($name, 7); | 
				
			|||
                } else { | 
				
			|||
                    $parameters[$name] = $value; | 
				
			|||
                } | 
				
			|||
            } else { | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            unset($_SERVER[$key]); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($match) { | 
				
			|||
            return $this->mergeDefaults($parameters, $defaults); | 
				
			|||
        } elseif (0 < count($allow)) { | 
				
			|||
            throw new MethodNotAllowedException($allow); | 
				
			|||
        } else { | 
				
			|||
            return parent::match($pathinfo); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,155 @@ | 
				
			|||
<?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\Matcher\Dumper; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Dumps a set of Apache mod_rewrite rules. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * @author Kris Wallsmith <kris@symfony.com> | 
				
			|||
 */ | 
				
			|||
class ApacheMatcherDumper extends MatcherDumper | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Dumps a set of Apache mod_rewrite rules. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * script_name: The script name (app.php by default) | 
				
			|||
     *  * base_uri:    The base URI ("" by default) | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @return string A string to be used as Apache rewrite rules | 
				
			|||
     * | 
				
			|||
     * @throws \LogicException When the route regex is invalid | 
				
			|||
     */ | 
				
			|||
    public function dump(array $options = array()) | 
				
			|||
    { | 
				
			|||
        $options = array_merge(array( | 
				
			|||
            'script_name' => 'app.php', | 
				
			|||
            'base_uri'    => '', | 
				
			|||
        ), $options); | 
				
			|||
 | 
				
			|||
        $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); | 
				
			|||
 | 
				
			|||
        $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); | 
				
			|||
        $methodVars = array(); | 
				
			|||
 | 
				
			|||
        foreach ($this->getRoutes()->all() as $name => $route) { | 
				
			|||
            $compiledRoute = $route->compile(); | 
				
			|||
 | 
				
			|||
            // prepare the apache regex
 | 
				
			|||
            $regex = $compiledRoute->getRegex(); | 
				
			|||
            $delimiter = $regex[0]; | 
				
			|||
            $regexPatternEnd = strrpos($regex, $delimiter); | 
				
			|||
            if (strlen($regex) < 2 || 0 === $regexPatternEnd) { | 
				
			|||
                throw new \LogicException('The "%s" route regex "%s" is invalid', $name, $regex); | 
				
			|||
            } | 
				
			|||
            $regex = preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); | 
				
			|||
            $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); | 
				
			|||
 | 
				
			|||
            $hasTrailingSlash = '/$' == substr($regex, -2) && '^/$' != $regex; | 
				
			|||
 | 
				
			|||
            $variables = array('E=_ROUTING__route:'.$name); | 
				
			|||
            foreach ($compiledRoute->getVariables() as $i => $variable) { | 
				
			|||
                $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1); | 
				
			|||
            } | 
				
			|||
            foreach ($route->getDefaults() as $key => $value) { | 
				
			|||
                $variables[] = 'E=_ROUTING_DEFAULTS_'.$key.':'.strtr($value, array( | 
				
			|||
                    ':'  => '\\:', | 
				
			|||
                    '='  => '\\=', | 
				
			|||
                    '\\' => '\\\\', | 
				
			|||
                    ' '  => '\\ ', | 
				
			|||
                )); | 
				
			|||
            } | 
				
			|||
            $variables = implode(',', $variables); | 
				
			|||
 | 
				
			|||
            $rule = array("# $name"); | 
				
			|||
 | 
				
			|||
            // method mismatch
 | 
				
			|||
            if ($req = $route->getRequirement('_method')) { | 
				
			|||
                $methods = explode('|', strtoupper($req)); | 
				
			|||
                // GET and HEAD are equivalent
 | 
				
			|||
                if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { | 
				
			|||
                    $methods[] = 'HEAD'; | 
				
			|||
                } | 
				
			|||
                $allow = array(); | 
				
			|||
                foreach ($methods as $method) { | 
				
			|||
                    $methodVars[] = $method; | 
				
			|||
                    $allow[] = 'E=_ROUTING__allow_'.$method.':1'; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                $rule[] = "RewriteCond %{REQUEST_URI} $regex"; | 
				
			|||
                $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods)); | 
				
			|||
                $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow)); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // redirect with trailing slash appended
 | 
				
			|||
            if ($hasTrailingSlash) { | 
				
			|||
                $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$'; | 
				
			|||
                $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]'; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // the main rule
 | 
				
			|||
            $rule[] = "RewriteCond %{REQUEST_URI} $regex"; | 
				
			|||
            $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]"; | 
				
			|||
 | 
				
			|||
            $rules[] = implode("\n", $rule); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (0 < count($methodVars)) { | 
				
			|||
            $rule = array('# 405 Method Not Allowed'); | 
				
			|||
            $methodVars = array_values(array_unique($methodVars)); | 
				
			|||
            foreach ($methodVars as $i => $methodVar) { | 
				
			|||
                $rule[] = sprintf('RewriteCond %%{_ROUTING__allow_%s} !-z%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : ''); | 
				
			|||
            } | 
				
			|||
            $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']); | 
				
			|||
 | 
				
			|||
            $rules[] = implode("\n", $rule); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return implode("\n\n", $rules)."\n"; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Escapes a string. | 
				
			|||
     * | 
				
			|||
     * @param string $string The string to be escaped | 
				
			|||
     * @param string $char   The character to be escaped | 
				
			|||
     * @param string $with   The character to be used for escaping | 
				
			|||
     * | 
				
			|||
     * @return string The escaped string | 
				
			|||
     */ | 
				
			|||
    private static function escape($string, $char, $with) | 
				
			|||
    { | 
				
			|||
        $escaped = false; | 
				
			|||
        $output = ''; | 
				
			|||
        foreach (str_split($string) as $symbol) { | 
				
			|||
            if ($escaped) { | 
				
			|||
                $output .= $symbol; | 
				
			|||
                $escaped = false; | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
            if ($symbol === $char) { | 
				
			|||
                $output .= $with.$char; | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
            if ($symbol === $with) { | 
				
			|||
                $escaped = true; | 
				
			|||
            } | 
				
			|||
            $output .= $symbol; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $output; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,44 @@ | 
				
			|||
<?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\Matcher\Dumper; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * MatcherDumper is the abstract class for all built-in matcher dumpers. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
abstract class MatcherDumper implements MatcherDumperInterface | 
				
			|||
{ | 
				
			|||
    private $routes; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $routes The RouteCollection to dump | 
				
			|||
     */ | 
				
			|||
    public function __construct(RouteCollection $routes) | 
				
			|||
    { | 
				
			|||
        $this->routes = $routes; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the routes to dump. | 
				
			|||
     * | 
				
			|||
     * @return RouteCollection A RouteCollection instance | 
				
			|||
     */ | 
				
			|||
    public function getRoutes() | 
				
			|||
    { | 
				
			|||
        return $this->routes; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,41 @@ | 
				
			|||
<?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\Matcher\Dumper; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * MatcherDumperInterface is the interface that all matcher dumper classes must implement. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
interface MatcherDumperInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Dumps a set of routes to a PHP class. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * class:      The class name | 
				
			|||
     *  * base_class: The base class name | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @return string A PHP class representing the matcher class | 
				
			|||
     */ | 
				
			|||
    public function dump(array $options = array()); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the routes to match. | 
				
			|||
     * | 
				
			|||
     * @return RouteCollection A RouteCollection instance | 
				
			|||
     */ | 
				
			|||
    public function getRoutes(); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,293 @@ | 
				
			|||
<?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\Matcher\Dumper; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Route; | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class PhpMatcherDumper extends MatcherDumper | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Dumps a set of routes to a PHP class. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * class:      The class name | 
				
			|||
     *  * base_class: The base class name | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @return string A PHP class representing the matcher class | 
				
			|||
     */ | 
				
			|||
    public function dump(array $options = array()) | 
				
			|||
    { | 
				
			|||
        $options = array_merge(array( | 
				
			|||
            'class'      => 'ProjectUrlMatcher', | 
				
			|||
            'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | 
				
			|||
        ), $options); | 
				
			|||
 | 
				
			|||
        // trailing slash support is only enabled if we know how to redirect the user
 | 
				
			|||
        $interfaces = class_implements($options['base_class']); | 
				
			|||
        $supportsRedirections = isset($interfaces['Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface']); | 
				
			|||
 | 
				
			|||
        return | 
				
			|||
            $this->startClass($options['class'], $options['base_class']). | 
				
			|||
            $this->addConstructor(). | 
				
			|||
            $this->addMatcher($supportsRedirections). | 
				
			|||
            $this->endClass() | 
				
			|||
        ; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function addMatcher($supportsRedirections) | 
				
			|||
    { | 
				
			|||
        // we need to deep clone the routes as we will modify the structure to optimize the dump
 | 
				
			|||
        $code = implode("\n", $this->compileRoutes(clone $this->getRoutes(), $supportsRedirections)); | 
				
			|||
 | 
				
			|||
        return <<<EOF | 
				
			|||
 | 
				
			|||
    public function match(\$pathinfo) | 
				
			|||
    { | 
				
			|||
        \$allow = array(); | 
				
			|||
        \$pathinfo = urldecode(\$pathinfo); | 
				
			|||
 | 
				
			|||
$code | 
				
			|||
        throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function compileRoutes(RouteCollection $routes, $supportsRedirections, $parentPrefix = null) | 
				
			|||
    { | 
				
			|||
        $code = array(); | 
				
			|||
 | 
				
			|||
        $routeIterator = $routes->getIterator(); | 
				
			|||
        $keys = array_keys($routeIterator->getArrayCopy()); | 
				
			|||
        $keysCount = count($keys); | 
				
			|||
 | 
				
			|||
        $i = 0; | 
				
			|||
        foreach ($routeIterator as $name => $route) { | 
				
			|||
            $i++; | 
				
			|||
 | 
				
			|||
            if ($route instanceof RouteCollection) { | 
				
			|||
                $prefix = $route->getPrefix(); | 
				
			|||
                $optimizable = $prefix && count($route->all()) > 1 && false === strpos($route->getPrefix(), '{'); | 
				
			|||
                $indent = ''; | 
				
			|||
                if ($optimizable) { | 
				
			|||
                    for ($j = $i; $j < $keysCount; $j++) { | 
				
			|||
                        if ($keys[$j] === null) { | 
				
			|||
                            continue; | 
				
			|||
                        } | 
				
			|||
 | 
				
			|||
                        $testRoute = $routeIterator->offsetGet($keys[$j]); | 
				
			|||
                        $isCollection = ($testRoute instanceof RouteCollection); | 
				
			|||
 | 
				
			|||
                        $testPrefix = $isCollection ? $testRoute->getPrefix() : $testRoute->getPattern(); | 
				
			|||
 | 
				
			|||
                        if (0 === strpos($testPrefix, $prefix)) { | 
				
			|||
                            $routeIterator->offsetUnset($keys[$j]); | 
				
			|||
 | 
				
			|||
                            if ($isCollection) { | 
				
			|||
                                $route->addCollection($testRoute); | 
				
			|||
                            } else { | 
				
			|||
                                $route->add($keys[$j], $testRoute); | 
				
			|||
                            } | 
				
			|||
 | 
				
			|||
                            $i++; | 
				
			|||
                            $keys[$j] = null; | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
 | 
				
			|||
                    if ($prefix !== $parentPrefix) { | 
				
			|||
                        $code[] = sprintf("        if (0 === strpos(\$pathinfo, %s)) {", var_export($prefix, true)); | 
				
			|||
                        $indent = '    '; | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                foreach ($this->compileRoutes($route, $supportsRedirections, $prefix) as $line) { | 
				
			|||
                    foreach (explode("\n", $line) as $l) { | 
				
			|||
                        if ($l) { | 
				
			|||
                            $code[] = $indent.$l; | 
				
			|||
                        } else { | 
				
			|||
                            $code[] = $l; | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                if ($optimizable && $prefix !== $parentPrefix) { | 
				
			|||
                    $code[] = "        }\n"; | 
				
			|||
                } | 
				
			|||
            } else { | 
				
			|||
                foreach ($this->compileRoute($route, $name, $supportsRedirections, $parentPrefix) as $line) { | 
				
			|||
                    $code[] = $line; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $code; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) | 
				
			|||
    { | 
				
			|||
        $code = array(); | 
				
			|||
        $compiledRoute = $route->compile(); | 
				
			|||
        $conditions = array(); | 
				
			|||
        $hasTrailingSlash = false; | 
				
			|||
        $matches = false; | 
				
			|||
        if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) { | 
				
			|||
            if ($supportsRedirections && substr($m['url'], -1) === '/') { | 
				
			|||
                $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); | 
				
			|||
                $hasTrailingSlash = true; | 
				
			|||
            } else { | 
				
			|||
                $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); | 
				
			|||
            } | 
				
			|||
        } else { | 
				
			|||
            if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() != $parentPrefix) { | 
				
			|||
                $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $regex = $compiledRoute->getRegex(); | 
				
			|||
            if ($supportsRedirections && $pos = strpos($regex, '/$')) { | 
				
			|||
                $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); | 
				
			|||
                $hasTrailingSlash = true; | 
				
			|||
            } | 
				
			|||
            $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true)); | 
				
			|||
 | 
				
			|||
            $matches = true; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $conditions = implode(' && ', $conditions); | 
				
			|||
 | 
				
			|||
        $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); | 
				
			|||
 | 
				
			|||
        $code[] = <<<EOF | 
				
			|||
        // $name
 | 
				
			|||
        if ($conditions) { | 
				
			|||
EOF; | 
				
			|||
 | 
				
			|||
        if ($req = $route->getRequirement('_method')) { | 
				
			|||
            $methods = explode('|', strtoupper($req)); | 
				
			|||
            // GET and HEAD are equivalent
 | 
				
			|||
            if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { | 
				
			|||
                $methods[] = 'HEAD'; | 
				
			|||
            } | 
				
			|||
            if (1 === count($methods)) { | 
				
			|||
                $code[] = <<<EOF | 
				
			|||
            if (\$this->context->getMethod() != '$methods[0]') { | 
				
			|||
                \$allow[] = '$methods[0]'; | 
				
			|||
                goto $gotoname; | 
				
			|||
            } | 
				
			|||
EOF; | 
				
			|||
            } else { | 
				
			|||
                $methods = implode('\', \'', $methods); | 
				
			|||
                $code[] = <<<EOF | 
				
			|||
            if (!in_array(\$this->context->getMethod(), array('$methods'))) { | 
				
			|||
                \$allow = array_merge(\$allow, array('$methods')); | 
				
			|||
                goto $gotoname; | 
				
			|||
            } | 
				
			|||
EOF; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($hasTrailingSlash) { | 
				
			|||
            $code[] = sprintf(<<<EOF | 
				
			|||
            if (substr(\$pathinfo, -1) !== '/') { | 
				
			|||
                return \$this->redirect(\$pathinfo.'/', '%s'); | 
				
			|||
            } | 
				
			|||
EOF | 
				
			|||
            , $name); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($scheme = $route->getRequirement('_scheme')) { | 
				
			|||
            if (!$supportsRedirections) { | 
				
			|||
                throw new \LogicException('The "_scheme" requirement is only supported for route dumper that implements RedirectableUrlMatcherInterface.'); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $code[] = sprintf(<<<EOF | 
				
			|||
            if (\$this->context->getScheme() !== '$scheme') { | 
				
			|||
                return \$this->redirect(\$pathinfo, '%s', '$scheme'); | 
				
			|||
            } | 
				
			|||
EOF | 
				
			|||
            , $name); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // optimize parameters array
 | 
				
			|||
        if (true === $matches && $compiledRoute->getDefaults()) { | 
				
			|||
            $code[] = sprintf("            return array_merge(\$this->mergeDefaults(\$matches, %s), array('_route' => '%s'));" | 
				
			|||
                , str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)), $name); | 
				
			|||
        } elseif (true === $matches) { | 
				
			|||
            $code[] = sprintf("            \$matches['_route'] = '%s';", $name); | 
				
			|||
            $code[] = sprintf("            return \$matches;", $name); | 
				
			|||
        } elseif ($compiledRoute->getDefaults()) { | 
				
			|||
            $code[] = sprintf('            return %s;', str_replace("\n", '', var_export(array_merge($compiledRoute->getDefaults(), array('_route' => $name)), true))); | 
				
			|||
        } else { | 
				
			|||
            $code[] = sprintf("            return array('_route' => '%s');", $name); | 
				
			|||
        } | 
				
			|||
        $code[] = "        }"; | 
				
			|||
 | 
				
			|||
        if ($req) { | 
				
			|||
            $code[] = "        $gotoname:"; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $code[] = ''; | 
				
			|||
 | 
				
			|||
        return $code; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function startClass($class, $baseClass) | 
				
			|||
    { | 
				
			|||
        return <<<EOF | 
				
			|||
<?php | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Exception\MethodNotAllowedException; | 
				
			|||
use Symfony\Component\Routing\Exception\ResourceNotFoundException; | 
				
			|||
use Symfony\Component\Routing\RequestContext; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * $class | 
				
			|||
 * | 
				
			|||
 * This class has been auto-generated | 
				
			|||
 * by the Symfony Routing Component. | 
				
			|||
 */ | 
				
			|||
class $class extends $baseClass | 
				
			|||
{ | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function addConstructor() | 
				
			|||
    { | 
				
			|||
        return <<<EOF | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     */ | 
				
			|||
    public function __construct(RequestContext \$context) | 
				
			|||
    { | 
				
			|||
        \$this->context = \$context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function endClass() | 
				
			|||
    { | 
				
			|||
        return <<<EOF | 
				
			|||
} | 
				
			|||
 | 
				
			|||
EOF; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,53 @@ | 
				
			|||
<?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\Matcher; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Exception\ResourceNotFoundException; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface | 
				
			|||
{ | 
				
			|||
    private $trailingSlashTest = false; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @see UrlMatcher::match() | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function match($pathinfo) | 
				
			|||
    { | 
				
			|||
        try { | 
				
			|||
            $parameters = parent::match($pathinfo); | 
				
			|||
        } catch (ResourceNotFoundException $e) { | 
				
			|||
            if ('/' === substr($pathinfo, -1)) { | 
				
			|||
                throw $e; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // try with a / at the end
 | 
				
			|||
            $this->trailingSlashTest = true; | 
				
			|||
 | 
				
			|||
            return $this->match($pathinfo.'/'); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($this->trailingSlashTest) { | 
				
			|||
            $this->trailingSlashTest = false; | 
				
			|||
 | 
				
			|||
            return $this->redirect($pathinfo, null); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $parameters; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,35 @@ | 
				
			|||
<?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\Matcher; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * RedirectableUrlMatcherInterface knows how to redirect the user. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface RedirectableUrlMatcherInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Redirects the user to another URL. | 
				
			|||
     * | 
				
			|||
     * @param string $path   The path info to redirect to. | 
				
			|||
     * @param string $route  The route that matched | 
				
			|||
     * @param string $scheme The URL scheme (null to keep the current one) | 
				
			|||
     * | 
				
			|||
     * @return array An array of parameters | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function redirect($path, $route, $scheme = null); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,151 @@ | 
				
			|||
<?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\Matcher; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Exception\MethodNotAllowedException; | 
				
			|||
use Symfony\Component\Routing\Exception\ResourceNotFoundException; | 
				
			|||
use Symfony\Component\Routing\RouteCollection; | 
				
			|||
use Symfony\Component\Routing\RequestContext; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * UrlMatcher matches URL based on a set of routes. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class UrlMatcher implements UrlMatcherInterface | 
				
			|||
{ | 
				
			|||
    protected $context; | 
				
			|||
    protected $allow; | 
				
			|||
 | 
				
			|||
    private $routes; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $routes  A RouteCollection instance | 
				
			|||
     * @param RequestContext  $context The context | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function __construct(RouteCollection $routes, RequestContext $context) | 
				
			|||
    { | 
				
			|||
        $this->routes = $routes; | 
				
			|||
        $this->context = $context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the request context. | 
				
			|||
     * | 
				
			|||
     * @param RequestContext $context The context | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setContext(RequestContext $context) | 
				
			|||
    { | 
				
			|||
        $this->context = $context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the request context. | 
				
			|||
     * | 
				
			|||
     * @return RequestContext The context | 
				
			|||
     */ | 
				
			|||
    public function getContext() | 
				
			|||
    { | 
				
			|||
        return $this->context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Tries to match a URL with a set of routes. | 
				
			|||
     * | 
				
			|||
     * @param string $pathinfo The path info to be parsed | 
				
			|||
     * | 
				
			|||
     * @return array An array of parameters | 
				
			|||
     * | 
				
			|||
     * @throws ResourceNotFoundException If the resource could not be found | 
				
			|||
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function match($pathinfo) | 
				
			|||
    { | 
				
			|||
        $this->allow = array(); | 
				
			|||
 | 
				
			|||
        if ($ret = $this->matchCollection($pathinfo, $this->routes)) { | 
				
			|||
            return $ret; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        throw 0 < count($this->allow) | 
				
			|||
            ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) | 
				
			|||
            : new ResourceNotFoundException(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    protected function matchCollection($pathinfo, RouteCollection $routes) | 
				
			|||
    { | 
				
			|||
        $pathinfo = urldecode($pathinfo); | 
				
			|||
 | 
				
			|||
        foreach ($routes as $name => $route) { | 
				
			|||
            if ($route instanceof RouteCollection) { | 
				
			|||
                if (false === strpos($route->getPrefix(), '{') && $route->getPrefix() !== substr($pathinfo, 0, strlen($route->getPrefix()))) { | 
				
			|||
                    continue; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                if (!$ret = $this->matchCollection($pathinfo, $route)) { | 
				
			|||
                    continue; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                return $ret; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $compiledRoute = $route->compile(); | 
				
			|||
 | 
				
			|||
            // check the static prefix of the URL first. Only use the more expensive preg_match when it matches
 | 
				
			|||
            if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            // check HTTP method requirement
 | 
				
			|||
            if ($req = $route->getRequirement('_method')) { | 
				
			|||
                // HEAD and GET are equivalent as per RFC
 | 
				
			|||
                if ('HEAD' === $method = $this->context->getMethod()) { | 
				
			|||
                    $method = 'GET'; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                if (!in_array($method, $req = explode('|', strtoupper($req)))) { | 
				
			|||
                    $this->allow = array_merge($this->allow, $req); | 
				
			|||
 | 
				
			|||
                    continue; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name)); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    protected function mergeDefaults($params, $defaults) | 
				
			|||
    { | 
				
			|||
        $parameters = $defaults; | 
				
			|||
        foreach ($params as $key => $value) { | 
				
			|||
            if (!is_int($key)) { | 
				
			|||
                $parameters[$key] = rawurldecode($value); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $parameters; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<?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\Matcher; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\RequestContextAwareInterface; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * UrlMatcherInterface is the interface that all URL matcher classes must implement. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface UrlMatcherInterface extends RequestContextAwareInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Tries to match a URL with a set of routes. | 
				
			|||
     * | 
				
			|||
     * @param string $pathinfo The path info to be parsed | 
				
			|||
     * | 
				
			|||
     * @return array An array of parameters | 
				
			|||
     * | 
				
			|||
     * @throws ResourceNotFoundException If the resource could not be found | 
				
			|||
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function match($pathinfo); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,32 @@ | 
				
			|||
Routing Component | 
				
			|||
================= | 
				
			|||
 | 
				
			|||
Routing associates a request with the code that will convert it to a response. | 
				
			|||
 | 
				
			|||
The example below demonstrates how you can set up a fully working routing | 
				
			|||
system: | 
				
			|||
 | 
				
			|||
    use Symfony\Component\HttpFoundation\Request; | 
				
			|||
    use Symfony\Component\Routing\Matcher\UrlMatcher; | 
				
			|||
    use Symfony\Component\Routing\RequestContext; | 
				
			|||
    use Symfony\Component\Routing\RouteCollection; | 
				
			|||
    use Symfony\Component\Routing\Route; | 
				
			|||
 | 
				
			|||
    $routes = new RouteCollection(); | 
				
			|||
    $routes->add('hello', new Route('/hello', array('controller' => 'foo'))); | 
				
			|||
 | 
				
			|||
    $context = new RequestContext(); | 
				
			|||
 | 
				
			|||
    // this is optional and can be done without a Request instance | 
				
			|||
    $context->fromRequest(Request::createFromGlobals()); | 
				
			|||
 | 
				
			|||
    $matcher = new UrlMatcher($routes, $context); | 
				
			|||
 | 
				
			|||
    $parameters = $matcher->match('/hello'); | 
				
			|||
 | 
				
			|||
Resources | 
				
			|||
--------- | 
				
			|||
 | 
				
			|||
Unit tests: | 
				
			|||
 | 
				
			|||
https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/Routing | 
				
			|||
@ -0,0 +1,250 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * Holds information about the current request. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class RequestContext | 
				
			|||
{ | 
				
			|||
    private $baseUrl; | 
				
			|||
    private $method; | 
				
			|||
    private $host; | 
				
			|||
    private $scheme; | 
				
			|||
    private $httpPort; | 
				
			|||
    private $httpsPort; | 
				
			|||
    private $parameters; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param string  $baseUrl   The base URL | 
				
			|||
     * @param string  $method    The HTTP method | 
				
			|||
     * @param string  $host      The HTTP host name | 
				
			|||
     * @param string  $scheme    The HTTP scheme | 
				
			|||
     * @param integer $httpPort  The HTTP port | 
				
			|||
     * @param integer $httpsPort The HTTPS port | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443) | 
				
			|||
    { | 
				
			|||
        $this->baseUrl = $baseUrl; | 
				
			|||
        $this->method = strtoupper($method); | 
				
			|||
        $this->host = $host; | 
				
			|||
        $this->scheme = strtolower($scheme); | 
				
			|||
        $this->httpPort = $httpPort; | 
				
			|||
        $this->httpsPort = $httpsPort; | 
				
			|||
        $this->parameters = array(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the base URL. | 
				
			|||
     * | 
				
			|||
     * @return string The base URL | 
				
			|||
     */ | 
				
			|||
    public function getBaseUrl() | 
				
			|||
    { | 
				
			|||
        return $this->baseUrl; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the base URL. | 
				
			|||
     * | 
				
			|||
     * @param string $baseUrl The base URL | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setBaseUrl($baseUrl) | 
				
			|||
    { | 
				
			|||
        $this->baseUrl = $baseUrl; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the HTTP method. | 
				
			|||
     * | 
				
			|||
     * The method is always an uppercased string. | 
				
			|||
     * | 
				
			|||
     * @return string The HTTP method | 
				
			|||
     */ | 
				
			|||
    public function getMethod() | 
				
			|||
    { | 
				
			|||
        return $this->method; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the HTTP method. | 
				
			|||
     * | 
				
			|||
     * @param string $method The HTTP method | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setMethod($method) | 
				
			|||
    { | 
				
			|||
        $this->method = strtoupper($method); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the HTTP host. | 
				
			|||
     * | 
				
			|||
     * @return string The HTTP host | 
				
			|||
     */ | 
				
			|||
    public function getHost() | 
				
			|||
    { | 
				
			|||
        return $this->host; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the HTTP host. | 
				
			|||
     * | 
				
			|||
     * @param string $host The HTTP host | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setHost($host) | 
				
			|||
    { | 
				
			|||
        $this->host = $host; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the HTTP scheme. | 
				
			|||
     * | 
				
			|||
     * @return string The HTTP scheme | 
				
			|||
     */ | 
				
			|||
    public function getScheme() | 
				
			|||
    { | 
				
			|||
        return $this->scheme; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the HTTP scheme. | 
				
			|||
     * | 
				
			|||
     * @param string $scheme The HTTP scheme | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setScheme($scheme) | 
				
			|||
    { | 
				
			|||
        $this->scheme = strtolower($scheme); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the HTTP port. | 
				
			|||
     * | 
				
			|||
     * @return string The HTTP port | 
				
			|||
     */ | 
				
			|||
    public function getHttpPort() | 
				
			|||
    { | 
				
			|||
        return $this->httpPort; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the HTTP port. | 
				
			|||
     * | 
				
			|||
     * @param string $httpPort The HTTP port | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setHttpPort($httpPort) | 
				
			|||
    { | 
				
			|||
        $this->httpPort = $httpPort; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the HTTPS port. | 
				
			|||
     * | 
				
			|||
     * @return string The HTTPS port | 
				
			|||
     */ | 
				
			|||
    public function getHttpsPort() | 
				
			|||
    { | 
				
			|||
        return $this->httpsPort; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the HTTPS port. | 
				
			|||
     * | 
				
			|||
     * @param string $httpsPort The HTTPS port | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setHttpsPort($httpsPort) | 
				
			|||
    { | 
				
			|||
        $this->httpsPort = $httpsPort; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the parameters. | 
				
			|||
     * | 
				
			|||
     * @return array The parameters | 
				
			|||
     */ | 
				
			|||
    public function getParameters() | 
				
			|||
    { | 
				
			|||
        return $this->parameters; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the parameters. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param array $parameters The parameters | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     */ | 
				
			|||
    public function setParameters(array $parameters) | 
				
			|||
    { | 
				
			|||
        $this->parameters = $parameters; | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets a parameter value. | 
				
			|||
     * | 
				
			|||
     * @param string $name A parameter name | 
				
			|||
     * | 
				
			|||
     * @return mixed The parameter value | 
				
			|||
     */ | 
				
			|||
    public function getParameter($name) | 
				
			|||
    { | 
				
			|||
        return isset($this->parameters[$name]) ? $this->parameters[$name] : null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Checks if a parameter value is set for the given parameter. | 
				
			|||
     * | 
				
			|||
     * @param string $name A parameter name | 
				
			|||
     * | 
				
			|||
     * @return Boolean true if the parameter value is set, false otherwise | 
				
			|||
     */ | 
				
			|||
    public function hasParameter($name) | 
				
			|||
    { | 
				
			|||
        return array_key_exists($name, $this->parameters); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets a parameter value. | 
				
			|||
     * | 
				
			|||
     * @param string $name      A parameter name | 
				
			|||
     * @param mixed  $parameter The parameter value | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setParameter($name, $parameter) | 
				
			|||
    { | 
				
			|||
        $this->parameters[$name] = $parameter; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,27 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
interface RequestContextAwareInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Sets the request context. | 
				
			|||
     * | 
				
			|||
     * @param RequestContext $context The context | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setContext(RequestContext $context); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,312 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * A Route describes a route and its parameters. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class Route | 
				
			|||
{ | 
				
			|||
    private $pattern; | 
				
			|||
    private $defaults; | 
				
			|||
    private $requirements; | 
				
			|||
    private $options; | 
				
			|||
    private $compiled; | 
				
			|||
 | 
				
			|||
    private static $compilers = array(); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *  * compiler_class: A class name able to compile this route instance (RouteCompiler by default) | 
				
			|||
     * | 
				
			|||
     * @param string $pattern      The pattern to match | 
				
			|||
     * @param array  $defaults     An array of default parameter values | 
				
			|||
     * @param array  $requirements An array of requirements for parameters (regexes) | 
				
			|||
     * @param array  $options      An array of options | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array()) | 
				
			|||
    { | 
				
			|||
        $this->setPattern($pattern); | 
				
			|||
        $this->setDefaults($defaults); | 
				
			|||
        $this->setRequirements($requirements); | 
				
			|||
        $this->setOptions($options); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function __clone() | 
				
			|||
    { | 
				
			|||
        $this->compiled = null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the pattern. | 
				
			|||
     * | 
				
			|||
     * @return string The pattern | 
				
			|||
     */ | 
				
			|||
    public function getPattern() | 
				
			|||
    { | 
				
			|||
        return $this->pattern; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the pattern. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param string $pattern The pattern | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     */ | 
				
			|||
    public function setPattern($pattern) | 
				
			|||
    { | 
				
			|||
        $this->pattern = trim($pattern); | 
				
			|||
 | 
				
			|||
        // a route must start with a slash
 | 
				
			|||
        if (empty($this->pattern) || '/' !== $this->pattern[0]) { | 
				
			|||
            $this->pattern = '/'.$this->pattern; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the options. | 
				
			|||
     * | 
				
			|||
     * @return array The options | 
				
			|||
     */ | 
				
			|||
    public function getOptions() | 
				
			|||
    { | 
				
			|||
        return $this->options; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the options. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param array $options The options | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     */ | 
				
			|||
    public function setOptions(array $options) | 
				
			|||
    { | 
				
			|||
        $this->options = array_merge(array( | 
				
			|||
            'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', | 
				
			|||
        ), $options); | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets an option value. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param string $name  An option name | 
				
			|||
     * @param mixed  $value The option value | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setOption($name, $value) | 
				
			|||
    { | 
				
			|||
        $this->options[$name] = $value; | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Get an option value. | 
				
			|||
     * | 
				
			|||
     * @param string $name An option name | 
				
			|||
     * | 
				
			|||
     * @return mixed The option value | 
				
			|||
     */ | 
				
			|||
    public function getOption($name) | 
				
			|||
    { | 
				
			|||
        return isset($this->options[$name]) ? $this->options[$name] : null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the defaults. | 
				
			|||
     * | 
				
			|||
     * @return array The defaults | 
				
			|||
     */ | 
				
			|||
    public function getDefaults() | 
				
			|||
    { | 
				
			|||
        return $this->defaults; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the defaults. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param array $defaults The defaults | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     */ | 
				
			|||
    public function setDefaults(array $defaults) | 
				
			|||
    { | 
				
			|||
        $this->defaults = array(); | 
				
			|||
        foreach ($defaults as $name => $default) { | 
				
			|||
            $this->defaults[(string) $name] = $default; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets a default value. | 
				
			|||
     * | 
				
			|||
     * @param string $name A variable name | 
				
			|||
     * | 
				
			|||
     * @return mixed The default value | 
				
			|||
     */ | 
				
			|||
    public function getDefault($name) | 
				
			|||
    { | 
				
			|||
        return isset($this->defaults[$name]) ? $this->defaults[$name] : null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Checks if a default value is set for the given variable. | 
				
			|||
     * | 
				
			|||
     * @param string $name A variable name | 
				
			|||
     * | 
				
			|||
     * @return Boolean true if the default value is set, false otherwise | 
				
			|||
     */ | 
				
			|||
    public function hasDefault($name) | 
				
			|||
    { | 
				
			|||
        return array_key_exists($name, $this->defaults); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets a default value. | 
				
			|||
     * | 
				
			|||
     * @param string $name    A variable name | 
				
			|||
     * @param mixed  $default The default value | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setDefault($name, $default) | 
				
			|||
    { | 
				
			|||
        $this->defaults[(string) $name] = $default; | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the requirements. | 
				
			|||
     * | 
				
			|||
     * @return array The requirements | 
				
			|||
     */ | 
				
			|||
    public function getRequirements() | 
				
			|||
    { | 
				
			|||
        return $this->requirements; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the requirements. | 
				
			|||
     * | 
				
			|||
     * This method implements a fluent interface. | 
				
			|||
     * | 
				
			|||
     * @param array $requirements The requirements | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     */ | 
				
			|||
    public function setRequirements(array $requirements) | 
				
			|||
    { | 
				
			|||
        $this->requirements = array(); | 
				
			|||
        foreach ($requirements as $key => $regex) { | 
				
			|||
            $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the requirement for the given key. | 
				
			|||
     * | 
				
			|||
     * @param string $key The key | 
				
			|||
     * | 
				
			|||
     * @return string The regex | 
				
			|||
     */ | 
				
			|||
    public function getRequirement($key) | 
				
			|||
    { | 
				
			|||
        return isset($this->requirements[$key]) ? $this->requirements[$key] : null; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets a requirement for the given key. | 
				
			|||
     * | 
				
			|||
     * @param string $key   The key | 
				
			|||
     * @param string $regex The regex | 
				
			|||
     * | 
				
			|||
     * @return Route The current Route instance | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function setRequirement($key, $regex) | 
				
			|||
    { | 
				
			|||
        $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); | 
				
			|||
 | 
				
			|||
        return $this; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Compiles the route. | 
				
			|||
     * | 
				
			|||
     * @return CompiledRoute A CompiledRoute instance | 
				
			|||
     */ | 
				
			|||
    public function compile() | 
				
			|||
    { | 
				
			|||
        if (null !== $this->compiled) { | 
				
			|||
            return $this->compiled; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $class = $this->getOption('compiler_class'); | 
				
			|||
 | 
				
			|||
        if (!isset(self::$compilers[$class])) { | 
				
			|||
            self::$compilers[$class] = new $class; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->compiled = self::$compilers[$class]->compile($this); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    private function sanitizeRequirement($key, $regex) | 
				
			|||
    { | 
				
			|||
        if (is_array($regex)) { | 
				
			|||
            throw new \InvalidArgumentException(sprintf('Routing requirements must be a string, array given for "%s"', $key)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ('^' == $regex[0]) { | 
				
			|||
            $regex = substr($regex, 1); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ('$' == substr($regex, -1)) { | 
				
			|||
            $regex = substr($regex, 0, -1); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $regex; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,259 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Config\Resource\ResourceInterface; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * A RouteCollection represents a set of Route instances. | 
				
			|||
 * | 
				
			|||
 * When adding a route, it overrides existing routes with the | 
				
			|||
 * same name defined in the instance or its children and parents. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 * | 
				
			|||
 * @api | 
				
			|||
 */ | 
				
			|||
class RouteCollection implements \IteratorAggregate | 
				
			|||
{ | 
				
			|||
    private $routes; | 
				
			|||
    private $resources; | 
				
			|||
    private $prefix; | 
				
			|||
    private $parent; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function __construct() | 
				
			|||
    { | 
				
			|||
        $this->routes = array(); | 
				
			|||
        $this->resources = array(); | 
				
			|||
        $this->prefix = ''; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function __clone() | 
				
			|||
    { | 
				
			|||
        foreach ($this->routes as $name => $route) { | 
				
			|||
            $this->routes[$name] = clone $route; | 
				
			|||
            if ($route instanceof RouteCollection) { | 
				
			|||
                $this->routes[$name]->setParent($this); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the parent RouteCollection. | 
				
			|||
     * | 
				
			|||
     * @return RouteCollection The parent RouteCollection | 
				
			|||
     */ | 
				
			|||
    public function getParent() | 
				
			|||
    { | 
				
			|||
        return $this->parent; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the parent RouteCollection. | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $parent The parent RouteCollection | 
				
			|||
     */ | 
				
			|||
    public function setParent(RouteCollection $parent) | 
				
			|||
    { | 
				
			|||
        $this->parent = $parent; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the current RouteCollection as an Iterator. | 
				
			|||
     * | 
				
			|||
     * @return \ArrayIterator An \ArrayIterator interface | 
				
			|||
     */ | 
				
			|||
    public function getIterator() | 
				
			|||
    { | 
				
			|||
        return new \ArrayIterator($this->routes); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Adds a route. | 
				
			|||
     * | 
				
			|||
     * @param string $name  The route name | 
				
			|||
     * @param Route  $route A Route instance | 
				
			|||
     * | 
				
			|||
     * @throws \InvalidArgumentException When route name contains non valid characters | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function add($name, Route $route) | 
				
			|||
    { | 
				
			|||
        if (!preg_match('/^[a-z0-9A-Z_.]+$/', $name)) { | 
				
			|||
            throw new \InvalidArgumentException(sprintf('The provided route name "%s" contains non valid characters. A route name must only contain digits (0-9), letters (a-z and A-Z), underscores (_) and dots (.).', $name)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $parent = $this; | 
				
			|||
        while ($parent->getParent()) { | 
				
			|||
            $parent = $parent->getParent(); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($parent) { | 
				
			|||
            $parent->remove($name); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $this->routes[$name] = $route; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns the array of routes. | 
				
			|||
     * | 
				
			|||
     * @return array An array of routes | 
				
			|||
     */ | 
				
			|||
    public function all() | 
				
			|||
    { | 
				
			|||
        $routes = array(); | 
				
			|||
        foreach ($this->routes as $name => $route) { | 
				
			|||
            if ($route instanceof RouteCollection) { | 
				
			|||
                $routes = array_merge($routes, $route->all()); | 
				
			|||
            } else { | 
				
			|||
                $routes[$name] = $route; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $routes; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets a route by name. | 
				
			|||
     * | 
				
			|||
     * @param string $name The route name | 
				
			|||
     * | 
				
			|||
     * @return Route  $route A Route instance | 
				
			|||
     */ | 
				
			|||
    public function get($name) | 
				
			|||
    { | 
				
			|||
        // get the latest defined route
 | 
				
			|||
        foreach (array_reverse($this->routes) as $routes) { | 
				
			|||
            if (!$routes instanceof RouteCollection) { | 
				
			|||
                continue; | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            if (null !== $route = $routes->get($name)) { | 
				
			|||
                return $route; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (isset($this->routes[$name])) { | 
				
			|||
            return $this->routes[$name]; | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Removes a route by name. | 
				
			|||
     * | 
				
			|||
     * @param string $name The route name | 
				
			|||
     */ | 
				
			|||
    public function remove($name) | 
				
			|||
    { | 
				
			|||
        if (isset($this->routes[$name])) { | 
				
			|||
            unset($this->routes[$name]); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        foreach ($this->routes as $routes) { | 
				
			|||
            if ($routes instanceof RouteCollection) { | 
				
			|||
                $routes->remove($name); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Adds a route collection to the current set of routes (at the end of the current set). | 
				
			|||
     * | 
				
			|||
     * @param RouteCollection $collection A RouteCollection instance | 
				
			|||
     * @param string          $prefix     An optional prefix to add before each pattern of the route collection | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function addCollection(RouteCollection $collection, $prefix = '') | 
				
			|||
    { | 
				
			|||
        $collection->setParent($this); | 
				
			|||
        $collection->addPrefix($prefix); | 
				
			|||
 | 
				
			|||
        // remove all routes with the same name in all existing collections
 | 
				
			|||
        foreach (array_keys($collection->all()) as $name) { | 
				
			|||
            $this->remove($name); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $this->routes[] = $collection; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Adds a prefix to all routes in the current set. | 
				
			|||
     * | 
				
			|||
     * @param string $prefix An optional prefix to add before each pattern of the route collection | 
				
			|||
     * | 
				
			|||
     * @api | 
				
			|||
     */ | 
				
			|||
    public function addPrefix($prefix) | 
				
			|||
    { | 
				
			|||
        // a prefix must not end with a slash
 | 
				
			|||
        $prefix = rtrim($prefix, '/'); | 
				
			|||
 | 
				
			|||
        if (!$prefix) { | 
				
			|||
            return; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // a prefix must start with a slash
 | 
				
			|||
        if ('/' !== $prefix[0]) { | 
				
			|||
            $prefix = '/'.$prefix; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $this->prefix = $prefix.$this->prefix; | 
				
			|||
 | 
				
			|||
        foreach ($this->routes as $name => $route) { | 
				
			|||
            if ($route instanceof RouteCollection) { | 
				
			|||
                $route->addPrefix($prefix); | 
				
			|||
            } else { | 
				
			|||
                $route->setPattern($prefix.$route->getPattern()); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    public function getPrefix() | 
				
			|||
    { | 
				
			|||
        return $this->prefix; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Returns an array of resources loaded to build this collection. | 
				
			|||
     * | 
				
			|||
     * @return ResourceInterface[] An array of resources | 
				
			|||
     */ | 
				
			|||
    public function getResources() | 
				
			|||
    { | 
				
			|||
        $resources = $this->resources; | 
				
			|||
        foreach ($this as $routes) { | 
				
			|||
            if ($routes instanceof RouteCollection) { | 
				
			|||
                $resources = array_merge($resources, $routes->getResources()); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return array_unique($resources); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Adds a resource for this collection. | 
				
			|||
     * | 
				
			|||
     * @param ResourceInterface $resource A resource instance | 
				
			|||
     */ | 
				
			|||
    public function addResource(ResourceInterface $resource) | 
				
			|||
    { | 
				
			|||
        $this->resources[] = $resource; | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,128 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * RouteCompiler compiles Route instances to CompiledRoute instances. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class RouteCompiler implements RouteCompilerInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Compiles the current route instance. | 
				
			|||
     * | 
				
			|||
     * @param Route $route A Route instance | 
				
			|||
     * | 
				
			|||
     * @return CompiledRoute A CompiledRoute instance | 
				
			|||
     */ | 
				
			|||
    public function compile(Route $route) | 
				
			|||
    { | 
				
			|||
        $pattern = $route->getPattern(); | 
				
			|||
        $len = strlen($pattern); | 
				
			|||
        $tokens = array(); | 
				
			|||
        $variables = array(); | 
				
			|||
        $pos = 0; | 
				
			|||
        preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); | 
				
			|||
        foreach ($matches as $match) { | 
				
			|||
            if ($text = substr($pattern, $pos, $match[0][1] - $pos)) { | 
				
			|||
                $tokens[] = array('text', $text); | 
				
			|||
            } | 
				
			|||
            $seps = array($pattern[$pos]); | 
				
			|||
            $pos = $match[0][1] + strlen($match[0][0]); | 
				
			|||
            $var = $match[1][0]; | 
				
			|||
 | 
				
			|||
            if ($req = $route->getRequirement($var)) { | 
				
			|||
                $regexp = $req; | 
				
			|||
            } else { | 
				
			|||
                if ($pos !== $len) { | 
				
			|||
                    $seps[] = $pattern[$pos]; | 
				
			|||
                } | 
				
			|||
                $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#')); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $tokens[] = array('variable', $match[0][0][0], $regexp, $var); | 
				
			|||
 | 
				
			|||
            if (in_array($var, $variables)) { | 
				
			|||
                throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $route->getPattern(), $var)); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $variables[] = $var; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($pos < $len) { | 
				
			|||
            $tokens[] = array('text', substr($pattern, $pos)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // find the first optional token
 | 
				
			|||
        $firstOptional = INF; | 
				
			|||
        for ($i = count($tokens) - 1; $i >= 0; $i--) { | 
				
			|||
            $token = $tokens[$i]; | 
				
			|||
            if ('variable' === $token[0] && $route->hasDefault($token[3])) { | 
				
			|||
                $firstOptional = $i; | 
				
			|||
            } else { | 
				
			|||
                break; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        // compute the matching regexp
 | 
				
			|||
        $regexp = ''; | 
				
			|||
        for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { | 
				
			|||
            $regexp .= $this->computeRegexp($tokens, $i, $firstOptional); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return new CompiledRoute( | 
				
			|||
            $route, | 
				
			|||
            'text' === $tokens[0][0] ? $tokens[0][1] : '', | 
				
			|||
            sprintf("#^%s$#s", $regexp), | 
				
			|||
            array_reverse($tokens), | 
				
			|||
            $variables | 
				
			|||
        ); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Computes the regexp used to match the token. | 
				
			|||
     * | 
				
			|||
     * @param array   $tokens        The route tokens | 
				
			|||
     * @param integer $index         The index of the current token | 
				
			|||
     * @param integer $firstOptional The index of the first optional token | 
				
			|||
     * | 
				
			|||
     * @return string The regexp | 
				
			|||
     */ | 
				
			|||
    private function computeRegexp(array $tokens, $index, $firstOptional) | 
				
			|||
    { | 
				
			|||
        $token = $tokens[$index]; | 
				
			|||
        if ('text' === $token[0]) { | 
				
			|||
            // Text tokens
 | 
				
			|||
            return preg_quote($token[1], '#'); | 
				
			|||
        } else { | 
				
			|||
            // Variable tokens
 | 
				
			|||
            if (0 === $index && 0 === $firstOptional && 1 == count($tokens)) { | 
				
			|||
                // When the only token is an optional variable token, the separator is required
 | 
				
			|||
                return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], '#'), $token[3], $token[2]); | 
				
			|||
            } else { | 
				
			|||
                $nbTokens = count($tokens); | 
				
			|||
                $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], '#'), $token[3], $token[2]); | 
				
			|||
                if ($index >= $firstOptional) { | 
				
			|||
                    // Enclose each optional tokens in a subpattern to make it optional
 | 
				
			|||
                    $regexp = "(?:$regexp"; | 
				
			|||
                    if ($nbTokens - 1 == $index) { | 
				
			|||
                        // Close the optional subpatterns
 | 
				
			|||
                        $regexp .= str_repeat(")?", $nbTokens - $firstOptional); | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                return $regexp; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,29 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * RouteCompilerInterface is the interface that all RouteCompiler classes must implements. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
interface RouteCompilerInterface | 
				
			|||
{ | 
				
			|||
    /** | 
				
			|||
     * Compiles the current route instance. | 
				
			|||
     * | 
				
			|||
     * @param Route $route A Route instance | 
				
			|||
     * | 
				
			|||
     * @return CompiledRoute A CompiledRoute instance | 
				
			|||
     */ | 
				
			|||
    public function compile(Route $route); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,263 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Config\Loader\LoaderInterface; | 
				
			|||
use Symfony\Component\Config\ConfigCache; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * The Router class is an example of the integration of all pieces of the | 
				
			|||
 * routing system for easier use. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
class Router implements RouterInterface | 
				
			|||
{ | 
				
			|||
    protected $matcher; | 
				
			|||
    protected $generator; | 
				
			|||
    protected $defaults; | 
				
			|||
    protected $context; | 
				
			|||
    protected $loader; | 
				
			|||
    protected $collection; | 
				
			|||
    protected $resource; | 
				
			|||
    protected $options; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Constructor. | 
				
			|||
     * | 
				
			|||
     * @param LoaderInterface $loader   A LoaderInterface instance | 
				
			|||
     * @param mixed           $resource The main resource to load | 
				
			|||
     * @param array           $options  An array of options | 
				
			|||
     * @param RequestContext  $context  The context | 
				
			|||
     * @param array           $defaults The default values | 
				
			|||
     */ | 
				
			|||
    public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, array $defaults = array()) | 
				
			|||
    { | 
				
			|||
        $this->loader = $loader; | 
				
			|||
        $this->resource = $resource; | 
				
			|||
        $this->context = null === $context ? new RequestContext() : $context; | 
				
			|||
        $this->defaults = $defaults; | 
				
			|||
        $this->setOptions($options); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets options. | 
				
			|||
     * | 
				
			|||
     * Available options: | 
				
			|||
     * | 
				
			|||
     *   * cache_dir:     The cache directory (or null to disable caching) | 
				
			|||
     *   * debug:         Whether to enable debugging or not (false by default) | 
				
			|||
     *   * resource_type: Type hint for the main resource (optional) | 
				
			|||
     * | 
				
			|||
     * @param array $options An array of options | 
				
			|||
     * | 
				
			|||
     * @throws \InvalidArgumentException When unsupported option is provided | 
				
			|||
     */ | 
				
			|||
    public function setOptions(array $options) | 
				
			|||
    { | 
				
			|||
        $this->options = array( | 
				
			|||
            'cache_dir'              => null, | 
				
			|||
            'debug'                  => false, | 
				
			|||
            'generator_class'        => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | 
				
			|||
            'generator_base_class'   => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | 
				
			|||
            'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', | 
				
			|||
            'generator_cache_class'  => 'ProjectUrlGenerator', | 
				
			|||
            'matcher_class'          => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | 
				
			|||
            'matcher_base_class'     => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | 
				
			|||
            'matcher_dumper_class'   => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', | 
				
			|||
            'matcher_cache_class'    => 'ProjectUrlMatcher', | 
				
			|||
            'resource_type'          => null, | 
				
			|||
        ); | 
				
			|||
 | 
				
			|||
        // check option names and live merge, if errors are encountered Exception will be thrown
 | 
				
			|||
        $invalid = array(); | 
				
			|||
        $isInvalid = false; | 
				
			|||
        foreach ($options as $key => $value) { | 
				
			|||
            if (array_key_exists($key, $this->options)) { | 
				
			|||
                $this->options[$key] = $value; | 
				
			|||
            } else { | 
				
			|||
                $isInvalid = true; | 
				
			|||
                $invalid[] = $key; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if ($isInvalid) { | 
				
			|||
            throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('\', \'', $invalid))); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets an option. | 
				
			|||
     * | 
				
			|||
     * @param string $key   The key | 
				
			|||
     * @param mixed  $value The value | 
				
			|||
     * | 
				
			|||
     * @throws \InvalidArgumentException | 
				
			|||
     */ | 
				
			|||
    public function setOption($key, $value) | 
				
			|||
    { | 
				
			|||
        if (!array_key_exists($key, $this->options)) { | 
				
			|||
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $this->options[$key] = $value; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets an option value. | 
				
			|||
     * | 
				
			|||
     * @param string $key The key | 
				
			|||
     * | 
				
			|||
     * @return mixed The value | 
				
			|||
     * | 
				
			|||
     * @throws \InvalidArgumentException | 
				
			|||
     */ | 
				
			|||
    public function getOption($key) | 
				
			|||
    { | 
				
			|||
        if (!array_key_exists($key, $this->options)) { | 
				
			|||
            throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->options[$key]; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the RouteCollection instance associated with this Router. | 
				
			|||
     * | 
				
			|||
     * @return RouteCollection A RouteCollection instance | 
				
			|||
     */ | 
				
			|||
    public function getRouteCollection() | 
				
			|||
    { | 
				
			|||
        if (null === $this->collection) { | 
				
			|||
            $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        return $this->collection; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Sets the request context. | 
				
			|||
     * | 
				
			|||
     * @param RequestContext $context The context | 
				
			|||
     */ | 
				
			|||
    public function setContext(RequestContext $context) | 
				
			|||
    { | 
				
			|||
        $this->context = $context; | 
				
			|||
 | 
				
			|||
        $this->getMatcher()->setContext($context); | 
				
			|||
        $this->getGenerator()->setContext($context); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the request context. | 
				
			|||
     * | 
				
			|||
     * @return RequestContext The context | 
				
			|||
     */ | 
				
			|||
    public function getContext() | 
				
			|||
    { | 
				
			|||
        return $this->context; | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Generates a URL from the given parameters. | 
				
			|||
     * | 
				
			|||
     * @param string  $name       The name of the route | 
				
			|||
     * @param mixed   $parameters An array of parameters | 
				
			|||
     * @param Boolean $absolute   Whether to generate an absolute URL | 
				
			|||
     * | 
				
			|||
     * @return string The generated URL | 
				
			|||
     */ | 
				
			|||
    public function generate($name, $parameters = array(), $absolute = false) | 
				
			|||
    { | 
				
			|||
        return $this->getGenerator()->generate($name, $parameters, $absolute); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Tries to match a URL with a set of routes. | 
				
			|||
     * | 
				
			|||
     * Returns false if no route matches the URL. | 
				
			|||
     * | 
				
			|||
     * @param string $url URL to be parsed | 
				
			|||
     * | 
				
			|||
     * @return array|false An array of parameters or false if no route matches | 
				
			|||
     */ | 
				
			|||
    public function match($url) | 
				
			|||
    { | 
				
			|||
        return $this->getMatcher()->match($url); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the UrlMatcher instance associated with this Router. | 
				
			|||
     * | 
				
			|||
     * @return UrlMatcherInterface A UrlMatcherInterface instance | 
				
			|||
     */ | 
				
			|||
    public function getMatcher() | 
				
			|||
    { | 
				
			|||
        if (null !== $this->matcher) { | 
				
			|||
            return $this->matcher; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { | 
				
			|||
            return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context, $this->defaults); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $class = $this->options['matcher_cache_class']; | 
				
			|||
        $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); | 
				
			|||
        if (!$cache->isFresh($class)) { | 
				
			|||
            $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection()); | 
				
			|||
 | 
				
			|||
            $options = array( | 
				
			|||
                'class'      => $class, | 
				
			|||
                'base_class' => $this->options['matcher_base_class'], | 
				
			|||
            ); | 
				
			|||
 | 
				
			|||
            $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        require_once $cache; | 
				
			|||
 | 
				
			|||
        return $this->matcher = new $class($this->context, $this->defaults); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * Gets the UrlGenerator instance associated with this Router. | 
				
			|||
     * | 
				
			|||
     * @return UrlGeneratorInterface A UrlGeneratorInterface instance | 
				
			|||
     */ | 
				
			|||
    public function getGenerator() | 
				
			|||
    { | 
				
			|||
        if (null !== $this->generator) { | 
				
			|||
            return $this->generator; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { | 
				
			|||
            return $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->defaults); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        $class = $this->options['generator_cache_class']; | 
				
			|||
        $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); | 
				
			|||
        if (!$cache->isFresh($class)) { | 
				
			|||
            $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection()); | 
				
			|||
 | 
				
			|||
            $options = array( | 
				
			|||
                'class'      => $class, | 
				
			|||
                'base_class' => $this->options['generator_base_class'], | 
				
			|||
            ); | 
				
			|||
 | 
				
			|||
            $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        require_once $cache; | 
				
			|||
 | 
				
			|||
        return $this->generator = new $class($this->context, $this->defaults); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,26 @@ | 
				
			|||
<?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; | 
				
			|||
 | 
				
			|||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 
				
			|||
use Symfony\Component\Routing\Matcher\UrlMatcherInterface; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * RouterInterface is the interface that all Router classes must implements. | 
				
			|||
 * | 
				
			|||
 * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. | 
				
			|||
 * | 
				
			|||
 * @author Fabien Potencier <fabien@symfony.com> | 
				
			|||
 */ | 
				
			|||
interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface | 
				
			|||
{ | 
				
			|||
} | 
				
			|||
@ -0,0 +1,29 @@ | 
				
			|||
{ | 
				
			|||
    "name": "symfony/routing", | 
				
			|||
    "type": "library", | 
				
			|||
    "description": "Symfony Routing Component", | 
				
			|||
    "keywords": [], | 
				
			|||
    "homepage": "http://symfony.com", | 
				
			|||
    "license": "MIT", | 
				
			|||
    "authors": [ | 
				
			|||
        { | 
				
			|||
            "name": "Fabien Potencier", | 
				
			|||
            "email": "fabien@symfony.com" | 
				
			|||
        }, | 
				
			|||
        { | 
				
			|||
            "name": "Symfony Community", | 
				
			|||
            "homepage": "http://symfony.com/contributors" | 
				
			|||
        } | 
				
			|||
    ], | 
				
			|||
    "require": { | 
				
			|||
        "php": ">=5.3.2" | 
				
			|||
    }, | 
				
			|||
    "suggest": { | 
				
			|||
        "symfony/config": "self.version", | 
				
			|||
        "symfony/yaml": "self.version" | 
				
			|||
    }, | 
				
			|||
    "autoload": { | 
				
			|||
        "psr-0": { "Symfony\\Component\\Routing": "" } | 
				
			|||
    }, | 
				
			|||
    "target-dir": "Symfony/Component/Routing" | 
				
			|||
} | 
				
			|||
@ -1,18 +0,0 @@ | 
				
			|||
{ | 
				
			|||
	"description": "ownCloud gives you universal access to your files/contacts/calendar through a web interface or WebDAV.", | 
				
			|||
	"homepage": "http://owncloud.org", | 
				
			|||
	"license": "AGPL-3.0+", | 
				
			|||
	"support": { | 
				
			|||
		"email": "owncloud@kde.org", | 
				
			|||
		"irc": "irc://irc.freenode.org/owncloud", | 
				
			|||
		"forum": "http://forum.owncloud.org/", | 
				
			|||
		"issues": "https://github.com/owncloud/core/issues" | 
				
			|||
	}, | 
				
			|||
	"require": { | 
				
			|||
		"php": ">=5.3.2", | 
				
			|||
		"symfony/routing": "2.0.*" | 
				
			|||
	}, | 
				
			|||
	"config": { | 
				
			|||
		"vendor-dir": "3rdparty" | 
				
			|||
	} | 
				
			|||
} | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue