drupalmoduleupgrader-8.x-1.5/src/Plugin/DMU/Routing/ContentRoute.php
src/Plugin/DMU/Routing/ContentRoute.php
<?php
namespace Drupal\drupalmoduleupgrader\Plugin\DMU\Routing;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\drupalmoduleupgrader\ConverterBase;
use Drupal\drupalmoduleupgrader\Routing\Drupal7\RouteWrapper as Drupal7Route;
use Drupal\drupalmoduleupgrader\Routing\Drupal8\RouteWrapper as Drupal8Route;
use Drupal\drupalmoduleupgrader\Routing\ParameterMap;
use Drupal\drupalmoduleupgrader\Routing\RouteConverterInterface;
use Drupal\drupalmoduleupgrader\TargetInterface;
use Drupal\drupalmoduleupgrader\Utility\StringTransformTrait;
use Pharborist\ControlStructures\ReturnStatementNode;
use Pharborist\Filter;
use Pharborist\Functions\ParameterNode;
use Pharborist\Objects\ClassMethodCallNode;
use Psr\Log\LoggerInterface;
use Symfony\Component\Routing\Route as CoreRoute;
/**
* @Converter(
* id = "default",
* description = @Translation("Converts a menu item to a _controller route."),
* dependencies = { "router.route_provider", "plugin.manager.drupalmoduleupgrader.rewriter" }
* )
*/
class ContentRoute extends ConverterBase implements RouteConverterInterface, ContainerFactoryPluginInterface {
use StringTransformTrait;
/**
* @var \Drupal\Core\Routing\RouteProviderInterface
*/
protected $routeProvider;
/**
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $rewriters;
/**
* Constructs a RouteConverterBase object.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, TranslationInterface $translator, LoggerInterface $log, RouteProviderInterface $route_provider, PluginManagerInterface $rewriters) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $translator, $log);
$this->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);
}
}
