2015-08-18 00:00:26 +00:00
< ? 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\HttpKernel\Controller ;
use Psr\Log\LoggerInterface ;
use Symfony\Component\HttpFoundation\Request ;
/**
* 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 .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
class ControllerResolver implements ControllerResolverInterface
{
private $logger ;
/**
* Constructor .
*
* @ param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct ( LoggerInterface $logger = null )
{
$this -> logger = $logger ;
}
/**
* { @ inheritdoc }
*
* This method looks for a '_controller' request attribute that represents
* the controller name ( a string like ClassName :: MethodName ) .
*/
public function getController ( Request $request )
{
if ( ! $controller = $request -> attributes -> get ( '_controller' )) {
if ( null !== $this -> logger ) {
$this -> logger -> warning ( 'Unable to look for the controller as the "_controller" parameter is missing.' );
}
return false ;
}
if ( is_array ( $controller )) {
return $controller ;
}
if ( is_object ( $controller )) {
if ( method_exists ( $controller , '__invoke' )) {
return $controller ;
}
throw new \InvalidArgumentException ( sprintf ( 'Controller "%s" for URI "%s" is not callable.' , get_class ( $controller ), $request -> getPathInfo ()));
}
if ( false === strpos ( $controller , ':' )) {
if ( method_exists ( $controller , '__invoke' )) {
return $this -> instantiateController ( $controller );
} elseif ( function_exists ( $controller )) {
return $controller ;
}
}
$callable = $this -> createController ( $controller );
if ( ! is_callable ( $callable )) {
throw new \InvalidArgumentException ( sprintf ( 'Controller "%s" for URI "%s" is not callable.' , $controller , $request -> getPathInfo ()));
}
return $callable ;
}
/**
* { @ inheritdoc }
*/
public function getArguments ( Request $request , $controller )
{
if ( is_array ( $controller )) {
$r = new \ReflectionMethod ( $controller [ 0 ], $controller [ 1 ]);
} elseif ( is_object ( $controller ) && ! $controller instanceof \Closure ) {
$r = new \ReflectionObject ( $controller );
$r = $r -> getMethod ( '__invoke' );
} else {
$r = new \ReflectionFunction ( $controller );
}
return $this -> doGetArguments ( $request , $controller , $r -> getParameters ());
}
protected function doGetArguments ( Request $request , $controller , array $parameters )
{
$attributes = $request -> attributes -> all ();
$arguments = array ();
foreach ( $parameters as $param ) {
if ( array_key_exists ( $param -> name , $attributes )) {
$arguments [] = $attributes [ $param -> name ];
} elseif ( $param -> getClass () && $param -> getClass () -> isInstance ( $request )) {
$arguments [] = $request ;
} elseif ( $param -> isDefaultValueAvailable ()) {
$arguments [] = $param -> getDefaultValue ();
} else {
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 ;
}
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 -> name ));
}
}
return $arguments ;
}
/**
* Returns a callable for the given controller .
*
* @ param string $controller A Controller string
*
2015-11-17 21:42:33 +00:00
* @ return callable A PHP callable
2015-08-18 00:00:26 +00:00
*
* @ throws \InvalidArgumentException
*/
protected function createController ( $controller )
{
if ( false === strpos ( $controller , '::' )) {
throw new \InvalidArgumentException ( sprintf ( 'Unable to find controller "%s".' , $controller ));
}
list ( $class , $method ) = explode ( '::' , $controller , 2 );
if ( ! class_exists ( $class )) {
throw new \InvalidArgumentException ( sprintf ( 'Class "%s" does not exist.' , $class ));
}
return array ( $this -> instantiateController ( $class ), $method );
}
/**
2015-10-08 18:40:12 +00:00
* Returns an instantiated controller .
2015-08-18 00:00:26 +00:00
*
* @ param string $class A class name
*
* @ return object
*/
protected function instantiateController ( $class )
{
return new $class ();
}
}