function AttributeRouteDiscovery::createRouteCollection

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Routing/AttributeRouteDiscovery.php \Drupal\Core\Routing\AttributeRouteDiscovery::createRouteCollection()

Creates a route collection from a class's attributed methods.

Parameters

class-string $className: The class to generate a route collection for.

Return value

\Symfony\Component\Routing\RouteCollection The route collection.

File

core/lib/Drupal/Core/Routing/AttributeRouteDiscovery.php, line 68

Class

AttributeRouteDiscovery
Discovers routes using Symfony's Route attribute.

Namespace

Drupal\Core\Routing

Code

private function createRouteCollection(string $className) : RouteCollection {
  $collection = new RouteCollection();
  if (!class_exists($className)) {
    // In Symfony code this triggers an exception. It is removed here because
    // Drupal already has traits, interfaces and other things in this folder.
    // Alternatively, we could remove this if clause and then check what the
    // resulting reflection object is.
    return $collection;
  }
  $class = new \ReflectionClass($className);
  if ($class->isAbstract()) {
    return $collection;
  }
  $globals = $this->getGlobals($class);
  $fqcnAlias = FALSE;
  if (!$class->hasMethod('__invoke')) {
    foreach ($this->getAttributes($class) as $attribute) {
      if ($attribute->aliases) {
        throw new InvalidArgumentException(\sprintf('Route aliases cannot be used on non-invokable class "%s".', $class->getName()));
      }
    }
  }
  foreach ($class->getMethods() as $method) {
    $routeNamesBefore = array_keys($collection->all());
    foreach ($this->getAttributes($method) as $attribute) {
      $this->addRoute($collection, $attribute, $globals, $class, $method);
      if ($method->name === '__invoke') {
        $fqcnAlias = TRUE;
      }
    }
    if ($collection->count() - \count($routeNamesBefore) === 1) {
      $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore));
      if ($newRouteName !== $aliasName = \sprintf('%s::%s', $class->name, $method->name)) {
        $collection->addAlias($aliasName, $newRouteName);
      }
    }
  }
  // See https://symfony.com/doc/current/controller/service.html#invokable-controllers.
  if ($collection->count() && $class->hasMethod('__invoke') === 0) {
    $globals = $this->resetGlobals();
    foreach ($this->getAttributes($class) as $attribute) {
      $this->addRoute($collection, $attribute, $globals, $class, $class->getMethod('__invoke'));
      $fqcnAlias = TRUE;
    }
  }
  if ($fqcnAlias && $collection->count() === 1) {
    $invokeRouteName = key($collection->all());
    if ($invokeRouteName !== $class->name) {
      $collection->addAlias($class->name, $invokeRouteName);
    }
    $aliasName = \sprintf('%s::__invoke', $class->name);
    if ($aliasName !== $invokeRouteName) {
      $collection->addAlias($aliasName, $invokeRouteName);
    }
  }
  return $collection;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.