2010-02-17 13:53:31 +00:00
< ? php
/*
2011-01-15 13:29:43 +00:00
* This file is part of the Symfony package .
2010-02-17 13:53:31 +00:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-02-17 13:53:31 +00:00
*
2011-01-15 13:29:43 +00:00
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
2010-02-17 13:53:31 +00:00
*/
2011-01-15 13:29:43 +00:00
namespace Symfony\Component\Routing\Generator ;
use Symfony\Component\Routing\Route ;
use Symfony\Component\Routing\RouteCollection ;
2011-04-20 12:54:39 +01:00
use Symfony\Component\Routing\RequestContext ;
2011-05-13 16:46:31 +01:00
use Symfony\Component\Routing\Exception\InvalidParameterException ;
2011-05-17 15:51:56 +01:00
use Symfony\Component\Routing\Exception\RouteNotFoundException ;
2011-05-13 16:46:31 +01:00
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException ;
2011-01-15 13:29:43 +00:00
2010-02-17 13:53:31 +00:00
/**
* UrlGenerator generates URL based on a set of routes .
*
2011-03-06 11:40:06 +00:00
* @ author Fabien Potencier < fabien @ symfony . com >
2011-06-14 14:35:32 +01:00
*
* @ api
2010-02-17 13:53:31 +00:00
*/
class UrlGenerator implements UrlGeneratorInterface
{
2010-05-06 12:25:53 +01:00
protected $context ;
2011-07-07 09:17:17 +01:00
protected $decodedChars = array (
2011-07-07 10:11:30 +01:00
// %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitely allowed it)
2011-07-07 09:17:17 +01:00
'%2F' => '/' ,
2011-07-07 08:38:15 +01:00
);
2011-03-23 18:24:18 +00:00
2011-07-26 06:57:40 +01:00
protected $routes ;
protected $cache ;
2010-05-06 12:25:53 +01:00
/**
* Constructor .
*
2011-04-23 16:05:44 +01:00
* @ param RouteCollection $routes A RouteCollection instance
* @ param RequestContext $context The context
2011-06-14 14:35:32 +01:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2011-04-20 21:49:56 +01:00
public function __construct ( RouteCollection $routes , RequestContext $context )
2010-02-17 13:53:31 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> routes = $routes ;
$this -> context = $context ;
$this -> cache = array ();
2010-02-17 13:53:31 +00:00
}
2011-01-24 15:59:32 +00:00
/**
* Sets the request context .
*
2011-04-23 16:05:44 +01:00
* @ param RequestContext $context The context
2011-06-14 14:35:32 +01:00
*
* @ api
2011-01-24 15:59:32 +00:00
*/
2011-04-20 12:54:39 +01:00
public function setContext ( RequestContext $context )
2011-01-24 15:59:32 +00:00
{
$this -> context = $context ;
}
2011-04-21 20:20:27 +01:00
/**
* Gets the request context .
*
* @ return RequestContext The context
*/
public function getContext ()
{
return $this -> context ;
}
2010-05-06 12:25:53 +01:00
/**
* Generates a URL from the given parameters .
*
* @ param string $name The name of the route
2011-07-26 06:57:40 +01:00
* @ param mixed $parameters An array of parameters
2010-05-06 12:25:53 +01:00
* @ param Boolean $absolute Whether to generate an absolute URL
*
* @ return string The generated URL
*
2011-05-17 15:51:56 +01:00
* @ throws Symfony\Component\Routing\Exception\RouteNotFoundException When route doesn ' t exist
2011-06-14 14:35:32 +01:00
*
* @ api
2010-05-06 12:25:53 +01:00
*/
2011-07-26 06:57:40 +01:00
public function generate ( $name , $parameters = array (), $absolute = false )
2010-02-17 13:53:31 +00:00
{
2010-11-23 08:42:19 +00:00
if ( null === $route = $this -> routes -> get ( $name )) {
2011-05-17 15:51:56 +01:00
throw new RouteNotFoundException ( sprintf ( 'Route "%s" does not exist.' , $name ));
2010-05-06 12:25:53 +01:00
}
2010-02-17 13:53:31 +00:00
2010-05-07 15:09:11 +01:00
if ( ! isset ( $this -> cache [ $name ])) {
2010-05-06 12:25:53 +01:00
$this -> cache [ $name ] = $route -> compile ();
}
2010-02-17 13:53:31 +00:00
2010-05-06 12:25:53 +01:00
return $this -> doGenerate ( $this -> cache [ $name ] -> getVariables (), $route -> getDefaults (), $route -> getRequirements (), $this -> cache [ $name ] -> getTokens (), $parameters , $name , $absolute );
2010-02-17 13:53:31 +00:00
}
2010-05-06 12:25:53 +01:00
/**
2011-05-13 16:46:31 +01:00
* @ 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
2010-05-06 12:25:53 +01:00
*/
protected function doGenerate ( $variables , $defaults , $requirements , $tokens , $parameters , $name , $absolute )
2010-02-17 13:53:31 +00:00
{
2011-04-25 11:03:41 +01:00
$variables = array_flip ( $variables );
2011-04-21 08:52:35 +01:00
$originParameters = $parameters ;
2011-04-20 22:01:05 +01:00
$parameters = array_replace ( $this -> context -> getParameters (), $parameters );
$tparams = array_replace ( $defaults , $parameters );
2010-05-06 12:25:53 +01:00
// all params must be given
2010-05-07 15:09:11 +01:00
if ( $diff = array_diff_key ( $variables , $tparams )) {
2011-05-26 11:54:21 +01:00
throw new MissingMandatoryParametersException ( sprintf ( 'The "%s" route has some missing mandatory parameters ("%s").' , $name , implode ( '", "' , array_keys ( $diff ))));
2010-02-17 13:53:31 +00:00
}
2010-05-06 12:25:53 +01:00
$url = '' ;
$optional = true ;
2010-05-07 15:09:11 +01:00
foreach ( $tokens as $token ) {
2010-05-08 14:32:30 +01:00
if ( 'variable' === $token [ 0 ]) {
2011-07-19 18:18:29 +01:00
if ( false === $optional || ! array_key_exists ( $token [ 3 ], $defaults ) || ( isset ( $parameters [ $token [ 3 ]]) && ( string ) $parameters [ $token [ 3 ]] != ( string ) $defaults [ $token [ 3 ]])) {
2011-05-03 13:48:08 +01:00
if ( ! $isEmpty = in_array ( $tparams [ $token [ 3 ]], array ( null , '' , false ), true )) {
// check requirement
if ( $tparams [ $token [ 3 ]] && ! preg_match ( '#^' . $token [ 2 ] . '$#' , $tparams [ $token [ 3 ]])) {
2011-05-13 15:57:17 +01:00
throw new InvalidParameterException ( sprintf ( 'Parameter "%s" for route "%s" must match "%s" ("%s" given).' , $token [ 3 ], $name , $token [ 2 ], $tparams [ $token [ 3 ]]));
2011-05-03 13:48:08 +01:00
}
2010-05-06 12:25:53 +01:00
}
2011-05-03 13:48:08 +01:00
if ( ! $isEmpty || ! $optional ) {
2011-07-07 09:17:17 +01:00
$url = $token [ 1 ] . strtr ( rawurlencode ( $tparams [ $token [ 3 ]]), $this -> decodedChars ) . $url ;
2011-04-18 14:35:05 +01:00
}
2010-05-06 12:25:53 +01:00
$optional = false ;
}
2010-05-07 15:09:11 +01:00
} elseif ( 'text' === $token [ 0 ]) {
2011-04-25 11:03:41 +01:00
$url = $token [ 1 ] . $url ;
2010-05-06 12:25:53 +01:00
$optional = false ;
}
2010-02-17 13:53:31 +00:00
}
2010-05-07 15:09:11 +01:00
if ( ! $url ) {
2010-05-06 12:25:53 +01:00
$url = '/' ;
}
2010-02-17 13:53:31 +00:00
2010-05-06 12:25:53 +01:00
// add a query string if needed
2011-07-22 17:51:08 +01:00
$extra = array_diff_key ( $originParameters , $variables , $defaults );
if ( $extra && $query = http_build_query ( $extra )) {
$url .= '?' . $query ;
2010-05-06 12:25:53 +01:00
}
2010-02-17 13:53:31 +00:00
2011-04-20 12:54:39 +01:00
$url = $this -> context -> getBaseUrl () . $url ;
2010-02-17 13:53:31 +00:00
2011-04-20 12:54:39 +01:00
if ( $this -> context -> getHost ()) {
$scheme = $this -> context -> getScheme ();
2011-04-19 23:25:45 +01:00
if ( isset ( $requirements [ '_scheme' ]) && ( $req = strtolower ( $requirements [ '_scheme' ])) && $scheme != $req ) {
$absolute = true ;
$scheme = $req ;
}
if ( $absolute ) {
$port = '' ;
2011-04-20 12:54:39 +01:00
if ( 'http' === $scheme && 80 != $this -> context -> getHttpPort ()) {
$port = ':' . $this -> context -> getHttpPort ();
} elseif ( 'https' === $scheme && 443 != $this -> context -> getHttpsPort ()) {
$port = ':' . $this -> context -> getHttpsPort ();
2011-04-19 23:25:45 +01:00
}
2011-04-20 12:54:39 +01:00
$url = $scheme . '://' . $this -> context -> getHost () . $port . $url ;
2011-02-03 15:21:41 +00:00
}
2010-05-06 12:25:53 +01:00
}
2010-02-17 13:53:31 +00:00
2010-05-06 12:25:53 +01:00
return $url ;
}
2010-02-17 13:53:31 +00:00
}