2016-12-30 13:37:02 +01:00
< ? php
/*
* This file is part of the NelmioApiDocBundle package .
*
* ( c ) Nelmio
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Nelmio\ApiDocBundle\Util ;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser ;
use Symfony\Component\DependencyInjection\ContainerInterface ;
2019-07-09 11:59:30 +02:00
use Symfony\Component\HttpKernel\Kernel ;
2016-12-30 13:37:02 +01:00
/**
* @ internal
*/
2019-01-05 16:37:43 +01:00
class ControllerReflector
2016-12-30 13:37:02 +01:00
{
private $container ;
2017-12-22 17:42:18 +00:00
2016-12-30 13:37:02 +01:00
private $controllerNameParser ;
2017-01-23 19:46:38 +01:00
private $controllers = [];
2019-11-19 17:23:12 +01:00
public function __construct ( ContainerInterface $container )
2016-12-30 13:37:02 +01:00
{
$this -> container = $container ;
2019-11-19 17:23:12 +01:00
if ( 1 < \func_num_args () && func_get_arg ( 1 ) instanceof ControllerNameParser ) {
$this -> controllerNameParser = func_get_arg ( 1 );
}
2016-12-30 13:37:02 +01:00
}
/**
* Returns the ReflectionMethod for the given controller string .
*
* @ return \ReflectionMethod | null
*/
2020-08-11 16:46:05 +02:00
public function getReflectionMethod ( $controller )
2016-12-30 13:37:02 +01:00
{
2020-08-11 16:46:05 +02:00
if ( is_string ( $controller )) {
$controller = $this -> getClassAndMethod ( $controller );
if ( null === $controller ) {
return null ;
}
2016-12-30 13:37:02 +01:00
}
2020-08-11 16:46:05 +02:00
return $this -> geReflectionMethodByClassNameAndMethodName ( ... $controller );
}
2017-12-22 17:42:18 +00:00
2020-08-11 16:46:05 +02:00
/**
* @ return \ReflectionMethod | null
*/
public function geReflectionMethodByClassNameAndMethodName ( string $class , string $method )
{
2016-12-30 13:37:02 +01:00
try {
return new \ReflectionMethod ( $class , $method );
} catch ( \ReflectionException $e ) {
// In case we can't reflect the controller, we just
// ignore the route
}
2020-08-11 16:46:05 +02:00
return null ;
2016-12-30 13:37:02 +01:00
}
private function getClassAndMethod ( string $controller )
{
2017-01-23 19:46:38 +01:00
if ( isset ( $this -> controllers [ $controller ])) {
return $this -> controllers [ $controller ];
}
2019-11-19 17:23:12 +01:00
if ( $this -> controllerNameParser && false === strpos ( $controller , '::' ) && 2 === substr_count ( $controller , ':' )) {
$deprecatedNotation = $controller ;
try {
$controller = $this -> controllerNameParser -> parse ( $controller );
@ trigger_error ( sprintf ( 'Referencing controllers with %s is deprecated since Symfony 4.1, use "%s" instead.' , $deprecatedNotation , $controller ), E_USER_DEPRECATED );
} catch ( \InvalidArgumentException $e ) {
// unable to optimize unknown notation
}
2016-12-30 13:37:02 +01:00
}
if ( preg_match ( '#(.+)::([\w]+)#' , $controller , $matches )) {
$class = $matches [ 1 ];
$method = $matches [ 2 ];
2019-07-09 11:59:30 +02:00
// Since symfony 4.1 routes are defined like service_id::method_name
if ( Kernel :: VERSION_ID >= 40100 && ! class_exists ( $class )) {
if ( $this -> container -> has ( $class )) {
$class = get_class ( $this -> container -> get ( $class ));
if ( class_exists ( ClassUtils :: class )) {
$class = ClassUtils :: getRealClass ( $class );
}
}
}
2016-12-30 13:37:02 +01:00
} elseif ( class_exists ( $controller )) {
$class = $controller ;
$method = '__invoke' ;
} else {
2019-07-09 11:59:30 +02:00
// Has to be removed when dropping support of symfony < 4.1
2016-12-30 13:37:02 +01:00
if ( preg_match ( '#(.+):([\w]+)#' , $controller , $matches )) {
$controller = $matches [ 1 ];
$method = $matches [ 2 ];
}
if ( $this -> container -> has ( $controller )) {
$class = get_class ( $this -> container -> get ( $controller ));
if ( class_exists ( ClassUtils :: class )) {
$class = ClassUtils :: getRealClass ( $class );
}
if ( ! isset ( $method ) && method_exists ( $class , '__invoke' )) {
$method = '__invoke' ;
}
}
}
if ( ! isset ( $class ) || ! isset ( $method )) {
2017-01-23 19:46:38 +01:00
$this -> controllers [ $controller ] = null ;
2016-12-30 13:37:02 +01:00
return ;
}
2017-01-23 19:46:38 +01:00
return $this -> controllers [ $controller ] = [ $class , $method ];
2016-12-30 13:37:02 +01:00
}
}