2010-08-09 14:21:59 +01:00
< ? php
/*
2011-01-15 13:29:43 +00:00
* This file is part of the Symfony package .
2010-08-09 14:21:59 +01:00
*
2011-03-06 11:40:06 +00:00
* ( c ) Fabien Potencier < fabien @ symfony . com >
2010-08-09 14:21:59 +01: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-08-09 14:21:59 +01:00
*/
2011-01-15 13:29:43 +00:00
namespace Symfony\Component\HttpKernel\Controller ;
use Symfony\Component\HttpKernel\Log\LoggerInterface ;
use Symfony\Component\HttpFoundation\Request ;
2010-08-09 14:21:59 +01:00
/**
* ControllerResolver .
*
* This implementation uses the '_controller' request attribute to determine
* the controller to execute and uses the request attributes to determine
* the controller method arguments .
*
2011-03-06 11:40:06 +00:00
* @ author Fabien Potencier < fabien @ symfony . com >
2011-07-20 09:14:31 +01:00
*
* @ api
2010-08-09 14:21:59 +01:00
*/
class ControllerResolver implements ControllerResolverInterface
{
2011-03-23 18:47:16 +00:00
private $logger ;
2010-08-09 14:21:59 +01:00
/**
* Constructor .
*
* @ param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct ( LoggerInterface $logger = null )
{
$this -> logger = $logger ;
}
/**
* Returns the Controller instance associated with a Request .
*
* This method looks for a '_controller' request attribute that represents
2011-01-23 11:10:45 +00:00
* the controller name ( a string like ClassName :: MethodName ) .
2010-08-09 14:21:59 +01:00
*
* @ param Request $request A Request instance
*
* @ return mixed | Boolean A PHP callable representing the Controller ,
* or false if this resolver is not able to determine the controller
*
* @ throws \InvalidArgumentException | \LogicException If the controller can ' t be found
2011-07-20 09:14:31 +01:00
*
* @ api
2010-08-09 14:21:59 +01:00
*/
public function getController ( Request $request )
{
if ( ! $controller = $request -> attributes -> get ( '_controller' )) {
if ( null !== $this -> logger ) {
2011-06-15 11:42:34 +01:00
$this -> logger -> warn ( 'Unable to look for the controller as the "_controller" parameter is missing' );
2010-08-09 14:21:59 +01:00
}
return false ;
}
2011-08-08 22:16:52 +01:00
if ( is_array ( $controller ) || ( is_object ( $controller ) && method_exists ( $controller , '__invoke' ))) {
2010-09-16 09:46:38 +01:00
return $controller ;
}
2011-08-08 22:16:52 +01:00
if ( false === strpos ( $controller , ':' ) && method_exists ( $controller , '__invoke' )) {
return new $controller ;
}
2010-08-09 14:21:59 +01:00
list ( $controller , $method ) = $this -> createController ( $controller );
if ( ! method_exists ( $controller , $method )) {
throw new \InvalidArgumentException ( sprintf ( 'Method "%s::%s" does not exist.' , get_class ( $controller ), $method ));
}
return array ( $controller , $method );
}
/**
* Returns the arguments to pass to the controller .
*
* @ param Request $request A Request instance
* @ param mixed $controller A PHP callable
*
* @ throws \RuntimeException When value for argument given is not provided
2011-07-20 09:14:31 +01:00
*
* @ api
2010-08-09 14:21:59 +01:00
*/
public function getArguments ( Request $request , $controller )
{
2010-09-16 09:46:38 +01:00
if ( is_array ( $controller )) {
2011-01-29 14:36:57 +00:00
$r = new \ReflectionMethod ( $controller [ 0 ], $controller [ 1 ]);
2011-04-16 15:26:13 +01:00
} elseif ( is_object ( $controller )) {
2011-11-22 13:52:21 +00:00
if ( $controller instanceof \Closure ) {
$r = new \ReflectionFunction ( $controller );
} else {
$r = new \ReflectionObject ( $controller );
$r = $r -> getMethod ( '__invoke' );
}
2010-09-16 09:46:38 +01:00
} else {
2011-01-29 14:36:57 +00:00
$r = new \ReflectionFunction ( $controller );
2010-09-16 09:46:38 +01:00
}
2010-08-09 14:21:59 +01:00
2011-08-08 22:20:53 +01:00
return $this -> doGetArguments ( $request , $controller , $r -> getParameters ());
}
protected function doGetArguments ( Request $request , $controller , array $parameters )
{
$attributes = $request -> attributes -> all ();
2010-08-09 14:21:59 +01:00
$arguments = array ();
2011-08-08 22:20:53 +01:00
foreach ( $parameters as $param ) {
2010-08-09 14:21:59 +01:00
if ( array_key_exists ( $param -> getName (), $attributes )) {
$arguments [] = $attributes [ $param -> getName ()];
2011-04-16 15:26:13 +01:00
} elseif ( $param -> getClass () && $param -> getClass () -> isInstance ( $request )) {
$arguments [] = $request ;
2010-08-09 14:21:59 +01:00
} elseif ( $param -> isDefaultValueAvailable ()) {
$arguments [] = $param -> getDefaultValue ();
} else {
2011-08-08 22:20:53 +01:00
if ( is_array ( $controller )) {
$repr = sprintf ( '%s::%s()' , get_class ( $controller [ 0 ]), $controller [ 1 ]);
} elseif ( is_object ( $controller )) {
$repr = get_class ( $controller );
} else {
$repr = $controller ;
}
2010-09-16 09:46:38 +01:00
throw new \RuntimeException ( sprintf ( 'Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).' , $repr , $param -> getName ()));
2010-08-09 14:21:59 +01:00
}
}
return $arguments ;
}
/**
* Returns a callable for the given controller .
*
* @ param string $controller A Controller string
*
* @ return mixed A PHP callable
*/
protected function createController ( $controller )
{
if ( false === strpos ( $controller , '::' )) {
throw new \InvalidArgumentException ( sprintf ( 'Unable to find controller "%s".' , $controller ));
}
list ( $class , $method ) = explode ( '::' , $controller );
if ( ! class_exists ( $class )) {
throw new \InvalidArgumentException ( sprintf ( 'Class "%s" does not exist.' , $class ));
}
return array ( new $class (), $method );
}
}