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-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 >
2010-02-17 13:53:31 +00:00
*/
class UrlGenerator implements UrlGeneratorInterface
{
2010-05-06 12:25:53 +01:00
protected $context ;
2011-03-23 18:24:18 +00:00
private $routes ;
private $cache ;
2010-05-06 12:25:53 +01:00
/**
* Constructor .
*
* @ param RouteCollection $routes A RouteCollection instance
2011-04-20 12:54:39 +01:00
* @ param RequestContext $context The context
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-20 12:54:39 +01:00
* @ param RequestContext $context The context
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
* @ param array $parameters An array of parameters
* @ param Boolean $absolute Whether to generate an absolute URL
*
* @ return string The generated URL
*
* @ throws \InvalidArgumentException When route doesn ' t exist
*/
2011-03-26 08:54:44 +00:00
public function generate ( $name , array $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 )) {
2010-05-06 12:25:53 +01:00
throw new \InvalidArgumentException ( sprintf ( 'Route "%s" does not exist.' , $name ));
}
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
/**
* @ throws \InvalidArgumentException When route has some missing mandatory parameters
*/
protected function doGenerate ( $variables , $defaults , $requirements , $tokens , $parameters , $name , $absolute )
2010-02-17 13:53:31 +00:00
{
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 )) {
2010-05-06 12:25:53 +01:00
throw new \InvalidArgumentException ( sprintf ( 'The "%s" route has some missing mandatory parameters (%s).' , $name , implode ( ', ' , $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 ]) {
2010-05-07 15:09:11 +01:00
if ( false === $optional || ! isset ( $defaults [ $token [ 3 ]]) || ( isset ( $parameters [ $token [ 3 ]]) && $parameters [ $token [ 3 ]] != $defaults [ $token [ 3 ]])) {
2010-05-06 12:25:53 +01:00
// check requirement
2010-05-07 15:09:11 +01:00
if ( isset ( $requirements [ $token [ 3 ]]) && ! preg_match ( '#^' . $requirements [ $token [ 3 ]] . '$#' , $tparams [ $token [ 3 ]])) {
2010-05-06 12:25:53 +01:00
throw new \InvalidArgumentException ( sprintf ( 'Parameter "%s" for route "%s" must match "%s" ("%s" given).' , $token [ 3 ], $name , $requirements [ $token [ 3 ]], $tparams [ $token [ 3 ]]));
}
2011-04-18 14:35:05 +01:00
if ( isset ( $tparams [ $token [ 3 ]])) {
// %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it)
$url = $token [ 1 ] . str_replace ( '%2F' , '/' , urlencode ( $tparams [ $token [ 3 ]])) . $url ;
}
2010-05-06 12:25:53 +01:00
$optional = false ;
}
2010-05-07 15:09:11 +01:00
} elseif ( 'text' === $token [ 0 ]) {
2010-05-06 12:25:53 +01:00
$url = $token [ 1 ] . $token [ 2 ] . $url ;
$optional = false ;
2010-05-07 15:09:11 +01:00
} else {
2010-05-06 12:25:53 +01:00
// handle custom tokens
2010-05-07 15:09:11 +01:00
if ( $segment = call_user_func_array ( array ( $this , 'generateFor' . ucfirst ( array_shift ( $token ))), array_merge ( array ( $optional , $tparams ), $token ))) {
2010-05-06 12:25:53 +01:00
$url = $segment . $url ;
$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-04-21 08:52:35 +01:00
if ( $extra = array_diff_key ( $originParameters , $variables , $defaults )) {
2010-05-06 12:25:53 +01:00
$url .= '?' . http_build_query ( $extra );
}
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
}