routeProvider = $route_provider; $this->rewriters = $rewriters; } /** * Conform with ConverterInterface, which we implement through ConverterBase. * Because route conversion is so complex, the Routing plugin never calls * this method. It relies instead on the other methods defined in * RouteConverterInterface. */ final public function convert(TargetInterface $target) {} /** * {@inheritdoc} */ public function getName(TargetInterface $target, Drupal7Route $route) { $name = $target->id() . '.' . $this->unPrefix($route['page callback'], $target->id()); $arguments = array_filter($route['page arguments'], 'is_string'); if ($arguments) { $name .= '_' . implode('_', $arguments); } return $name; } /** * {@inheritdoc} */ public function buildPath(TargetInterface $target, Drupal7Route $route) { // The parameter map modifies the path in-place, so we'll clone it in order // to keep this method non-destructive. $path = clone $route->getPath(); $this->buildParameterMap($target, $route)->applyPath($path); return $path; } /** * Builds a parameter map from the aggregated arguments of the title, * access, and page callbacks. * * @return \Drupal\drupalmoduleupgrader\Routing\ParameterMap */ protected function buildParameterMap(TargetInterface $target, Drupal7Route $route) { $map = new ParameterMap(clone $route->getPath(), []); $indexer = $target->getIndexer('function'); if ($indexer->has($route['title callback'])) { $map->merge(new ParameterMap( $route->getPath(), $indexer->get($route['title callback'])->getParameters()->toArray(), $route['title arguments'] )); } if ($indexer->has($route['access callback'])) { $map->merge(new ParameterMap( $route->getPath(), $indexer->get($route['access callback'])->getParameters()->toArray(), $route['access arguments'] )); } if ($indexer->has($route['page callback'])) { $map->merge(new ParameterMap( $route->getPath(), $indexer->get($route['page callback'])->getParameters()->toArray(), $route['page arguments'] )); } return $map; } /** * {@inheritdoc} */ public function buildRouteDefinition(TargetInterface $target, Drupal7Route $route) { $indexer = $target->getIndexer('function'); $definition = new CoreRoute(''); $this->buildParameterMap($target, $route)->applyRoute($definition); $controller = $this->getController($target, $route)->getName()->getAbsolutePath(); if ($route->containsKey('title')) { $definition->setDefault('_title', $route['title']); } elseif ($indexer->has($route['title callback'])) { $definition->setDefault('_title_callback', $controller . '::' . $route['title callback']); } if ($route->isAbsoluteAccess()) { $definition->setRequirement('_access', $route['access callback'] ? 'true' : 'false'); } elseif ($route->isPermissionBased()) { $definition->setRequirement('_permission', $route['access arguments'][0]); } elseif ($indexer->has($route['access callback'])) { $definition->setRequirement('_custom_access', $controller . '::' . $route['access callback']); } if ($indexer->has($route['page callback'])) { $definition->setDefault('_controller', $controller . '::' . $route['page callback']); } return new Drupal8Route($this->getName($target, $route), $definition, $this->routeProvider); } /** * {@inheritdoc} */ public function buildRoute(TargetInterface $target, Drupal7Route $route) { $definition = $this->buildRouteDefinition($target, $route); $map = $this->buildParameterMap($target, $route); $map->applyRoute($definition->unwrap()); $indexer = $target->getIndexer('function'); foreach ($map->toArray() as $function_name => $parameters) { if ($parameters && $indexer->has($function_name)) { /** @var \Pharborist\Functions\FunctionDeclarationNode $function */ $function = $indexer->get($function_name); foreach ($parameters as $parameter_name => $info) { $parameter = $function->getParameterByName($parameter_name)->setName($info['name'], TRUE); if (isset($info['type'])) { $plugin_id = '_rewriter:' . $info['type']; if ($this->rewriters->hasDefinition($plugin_id)) { $this->rewriters->createInstance($plugin_id)->rewrite($parameter); } } } } } $class_indexer = $target->getIndexer('class'); if ($class_indexer->has('DefaultController')) { $controller = $class_indexer->get('DefaultController'); } else { $controller = $this->getController($target, $route); $class_indexer->addFile($this->writeClass($target, $controller)); } if ($indexer->has($route['title callback'])) { if (! $controller->hasMethod($route['title callback'])) { $indexer->get($route['title callback'])->cloneAsMethodOf($controller); } } if ($indexer->has($route['access callback'])) { $func = $indexer->get($route['access callback']); $returns = $func->find(Filter::isInstanceOf('\Pharborist\ReturnStatementNode')); foreach ($returns as $ret) { $call = ClassMethodCallNode::create('\Drupal\Core\Access\AccessResult', 'allowedIf')->appendArgument($ret->getExpression()); $ret->replaceWith(ReturnStatementNode::create($call)); } // The access callback always receives an $account parameter. if ($func->hasParameter('account')) { $func->getParameter('account')->setTypeHint('Drupal\Core\Session\AccountInterface'); } else { $account = ParameterNode::create('account')->setTypeHint('Drupal\Core\Session\AccountInterface'); $func->appendParameter($account); } if (! $controller->hasMethod($route['access callback'])) { $func->cloneAsMethodOf($controller); } } if ($indexer->has($route['page callback'])) { if (! $controller->hasMethod($route['page callback'])) { $indexer->get($route['page callback'])->cloneAsMethodOf($controller); } } $this->writeClass($target, $controller); } protected function getController(TargetInterface $target, Drupal7Route $route) { $render = [ '#theme' => 'dmu_controller', '#module' => $target->id(), ]; return $this->parse($render); } }