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 ;
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 $defaults ;
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
* @ param array $context The context
* @ param array $defaults The default values
*/
public function __construct ( RouteCollection $routes , array $context = array (), array $defaults = array ())
2010-02-17 13:53:31 +00:00
{
2010-05-06 12:25:53 +01:00
$this -> routes = $routes ;
$this -> context = $context ;
$this -> defaults = $defaults ;
$this -> cache = array ();
2010-02-17 13:53:31 +00:00
}
2011-01-24 15:59:32 +00:00
/**
* Sets the request context .
*
* @ param array $context The context
*/
public function setContext ( array $context = array ())
{
$this -> context = $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
{
2010-05-06 12:25:53 +01:00
$defaults = array_merge ( $this -> defaults , $defaults );
$tparams = array_merge ( $defaults , $parameters );
// 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
2010-05-07 15:09:11 +01:00
if ( $extra = array_diff_key ( $parameters , $variables , $defaults )) {
2010-05-06 12:25:53 +01:00
$url .= '?' . http_build_query ( $extra );
}
2010-02-17 13:53:31 +00:00
2010-05-06 12:25:53 +01:00
$url = ( isset ( $this -> context [ 'base_url' ]) ? $this -> context [ 'base_url' ] : '' ) . $url ;
2010-02-17 13:53:31 +00:00
2010-05-07 15:09:11 +01:00
if ( $absolute && isset ( $this -> context [ 'host' ])) {
2011-02-03 15:21:41 +00:00
$isSecure = ( isset ( $this -> context [ 'is_secure' ]) && $this -> context [ 'is_secure' ]);
$port = isset ( $this -> context [ 'port' ]) ? $this -> context [ 'port' ] : 80 ;
$urlBeginning = 'http' . ( $isSecure ? 's' : '' ) . '://' . $this -> context [ 'host' ];
if (( $isSecure && $port != 443 ) || ( ! $isSecure && $port != 80 )) {
$urlBeginning .= ':' . $port ;
}
$url = $urlBeginning . $url ;
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
}