Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\Routing\Loader; Chris@0: Chris@0: use Symfony\Component\Config\Loader\Loader; Chris@0: use Symfony\Component\Config\Resource\FileResource; Chris@0: use Symfony\Component\Routing\RouteCollection; Chris@0: Chris@0: /** Chris@0: * A route loader that calls a method on an object to load the routes. Chris@0: * Chris@0: * @author Ryan Weaver Chris@0: */ Chris@0: abstract class ObjectRouteLoader extends Loader Chris@0: { Chris@0: /** Chris@0: * Returns the object that the method will be called on to load routes. Chris@0: * Chris@0: * For example, if your application uses a service container, Chris@0: * the $id may be a service id. Chris@0: * Chris@0: * @param string $id Chris@0: * Chris@0: * @return object Chris@0: */ Chris@0: abstract protected function getServiceObject($id); Chris@0: Chris@0: /** Chris@0: * Calls the service that will load the routes. Chris@0: * Chris@0: * @param mixed $resource Some value that will resolve to a callable Chris@0: * @param string|null $type The resource type Chris@0: * Chris@0: * @return RouteCollection Chris@0: */ Chris@0: public function load($resource, $type = null) Chris@0: { Chris@0: $parts = explode(':', $resource); Chris@17: if (2 != \count($parts)) { Chris@0: throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource)); Chris@0: } Chris@0: Chris@0: $serviceString = $parts[0]; Chris@0: $method = $parts[1]; Chris@0: Chris@0: $loaderObject = $this->getServiceObject($serviceString); Chris@0: Chris@17: if (!\is_object($loaderObject)) { Chris@17: throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject))); Chris@0: } Chris@0: Chris@0: if (!method_exists($loaderObject, $method)) { Chris@17: throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource)); Chris@0: } Chris@0: Chris@17: $routeCollection = \call_user_func([$loaderObject, $method], $this); Chris@0: Chris@0: if (!$routeCollection instanceof RouteCollection) { Chris@17: $type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection); Chris@0: Chris@17: throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', \get_class($loaderObject), $method, $type)); Chris@0: } Chris@0: Chris@0: // make the service file tracked so that if it changes, the cache rebuilds Chris@0: $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); Chris@0: Chris@0: return $routeCollection; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function supports($resource, $type = null) Chris@0: { Chris@0: return 'service' === $type; Chris@0: } Chris@0: Chris@0: private function addClassResource(\ReflectionClass $class, RouteCollection $collection) Chris@0: { Chris@0: do { Chris@0: if (is_file($class->getFileName())) { Chris@0: $collection->addResource(new FileResource($class->getFileName())); Chris@0: } Chris@0: } while ($class = $class->getParentClass()); Chris@0: } Chris@0: }