2018-02-01 20:01:12 +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\Routing\Loader ;
use Symfony\Component\Config\Loader\Loader ;
use Symfony\Component\Config\Resource\FileResource ;
use Symfony\Component\Routing\RouteCollection ;
/**
* A route loader that calls a method on an object to load the routes .
*
* @ author Ryan Weaver < ryan @ knpuniversity . com >
*/
2022-03-10 11:54:29 +00:00
abstract class ObjectLoader extends Loader
2018-02-01 20:01:12 +00:00
{
/**
* Returns the object that the method will be called on to load routes .
*
* For example , if your application uses a service container ,
* the $id may be a service id .
*
* @ return object
*/
2022-03-10 11:54:29 +00:00
abstract protected function getObject ( string $id );
2018-02-01 20:01:12 +00:00
/**
2022-03-10 11:54:29 +00:00
* Calls the object method that will load the routes .
2018-02-01 20:01:12 +00:00
*
2022-03-10 11:54:29 +00:00
* @ param string $resource object_id :: method
2018-02-01 20:01:12 +00:00
* @ param string | null $type The resource type
*
* @ return RouteCollection
*/
2022-03-10 11:54:29 +00:00
public function load ( $resource , string $type = null )
2018-02-01 20:01:12 +00:00
{
2022-03-10 11:54:29 +00:00
if ( ! preg_match ( '/^[^\:]+(?:::(?:[^\:]+))?$/' , $resource )) {
throw new \InvalidArgumentException ( sprintf ( 'Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.' , $resource , \is_string ( $type ) ? '"' . $type . '"' : 'object' ));
2018-10-14 19:50:32 +00:00
}
$parts = explode ( '::' , $resource );
2019-06-11 11:29:32 +00:00
$method = $parts [ 1 ] ? ? '__invoke' ;
2018-02-01 20:01:12 +00:00
2022-03-10 11:54:29 +00:00
$loaderObject = $this -> getObject ( $parts [ 0 ]);
2018-02-01 20:01:12 +00:00
2018-10-14 19:50:32 +00:00
if ( ! \is_object ( $loaderObject )) {
2022-03-10 11:54:29 +00:00
throw new \TypeError ( sprintf ( '"%s:getObject()" must return an object: "%s" returned.' , static :: class , get_debug_type ( $loaderObject )));
2018-02-01 20:01:12 +00:00
}
2019-06-11 11:29:32 +00:00
if ( ! \is_callable ([ $loaderObject , $method ])) {
2022-03-10 11:54:29 +00:00
throw new \BadMethodCallException ( sprintf ( 'Method "%s" not found on "%s" when importing routing resource "%s".' , $method , get_debug_type ( $loaderObject ), $resource ));
2018-02-01 20:01:12 +00:00
}
2022-03-10 11:54:29 +00:00
$routeCollection = $loaderObject -> $method ( $this , $this -> env );
2018-02-01 20:01:12 +00:00
if ( ! $routeCollection instanceof RouteCollection ) {
2022-03-10 11:54:29 +00:00
$type = get_debug_type ( $routeCollection );
2018-02-01 20:01:12 +00:00
2022-03-10 11:54:29 +00:00
throw new \LogicException ( sprintf ( 'The "%s::%s()" method must return a RouteCollection: "%s" returned.' , get_debug_type ( $loaderObject ), $method , $type ));
2018-02-01 20:01:12 +00:00
}
2022-03-10 11:54:29 +00:00
// make the object file tracked so that if it changes, the cache rebuilds
2018-02-01 20:01:12 +00:00
$this -> addClassResource ( new \ReflectionClass ( $loaderObject ), $routeCollection );
return $routeCollection ;
}
private function addClassResource ( \ReflectionClass $class , RouteCollection $collection )
{
do {
if ( is_file ( $class -> getFileName ())) {
$collection -> addResource ( new FileResource ( $class -> getFileName ()));
}
} while ( $class = $class -> getParentClass ());
}
}