Further modules included.
[yaffs-website] / web / modules / contrib / drupalmoduleupgrader / src / Plugin / DMU / Routing / ContentRoute.php
1 <?php
2
3 namespace Drupal\drupalmoduleupgrader\Plugin\DMU\Routing;
4
5 use Drupal\Component\Plugin\PluginManagerInterface;
6 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
7 use Drupal\Core\Routing\RouteProviderInterface;
8 use Drupal\Core\StringTranslation\TranslationInterface;
9 use Drupal\drupalmoduleupgrader\ConverterBase;
10 use Drupal\drupalmoduleupgrader\Routing\Drupal7\RouteWrapper as Drupal7Route;
11 use Drupal\drupalmoduleupgrader\Routing\Drupal8\RouteWrapper as Drupal8Route;
12 use Drupal\drupalmoduleupgrader\Routing\ParameterMap;
13 use Drupal\drupalmoduleupgrader\Routing\RouteConverterInterface;
14 use Drupal\drupalmoduleupgrader\TargetInterface;
15 use Drupal\drupalmoduleupgrader\Utility\StringTransformTrait;
16 use Pharborist\ControlStructures\ReturnStatementNode;
17 use Pharborist\Filter;
18 use Pharborist\Functions\ParameterNode;
19 use Pharborist\Objects\ClassMethodCallNode;
20 use Psr\Log\LoggerInterface;
21 use Symfony\Component\Routing\Route as CoreRoute;
22
23 /**
24  * @Converter(
25  *  id = "default",
26  *  description = @Translation("Converts a menu item to a _controller route."),
27  *  dependencies = { "router.route_provider", "plugin.manager.drupalmoduleupgrader.rewriter" }
28  * )
29  */
30 class ContentRoute extends ConverterBase implements RouteConverterInterface, ContainerFactoryPluginInterface {
31
32   use StringTransformTrait;
33
34   /**
35    * @var RouteProviderInterface
36    */
37   protected $routeProvider;
38
39   /**
40    * @var PluginManagerInterface
41    */
42   protected $rewriters;
43
44   /**
45    * Constructs a RouteConverterBase object.
46    */
47   public function __construct(array $configuration, $plugin_id, $plugin_definition, TranslationInterface $translator, LoggerInterface $log, RouteProviderInterface $route_provider, PluginManagerInterface $rewriters) {
48     parent::__construct($configuration, $plugin_id, $plugin_definition, $translator, $log);
49     $this->routeProvider = $route_provider;
50     $this->rewriters = $rewriters;
51   }
52
53   /**
54    * Conform with ConverterInterface, which we implement through ConverterBase.
55    * Because route conversion is so complex, the Routing plugin never calls
56    * this method. It relies instead on the other methods defined in
57    * RouteConverterInterface.
58    */
59   final public function convert(TargetInterface $target) {}
60
61   /**
62    * {@inheritdoc}
63    */
64   public function getName(TargetInterface $target, Drupal7Route $route) {
65     $name = $target->id() . '.' . $this->unPrefix($route['page callback'], $target->id());
66
67     $arguments = array_filter($route['page arguments'], 'is_string');
68     if ($arguments) {
69       $name .= '_' . implode('_', $arguments);
70     }
71
72     return $name;
73   }
74
75   /**
76    * {@inheritdoc}
77    */
78   public function buildPath(TargetInterface $target, Drupal7Route $route) {
79     // The parameter map modifies the path in-place, so we'll clone it in order
80     // to keep this method non-destructive.
81     $path = clone $route->getPath();
82     $this->buildParameterMap($target, $route)->applyPath($path);
83     return $path;
84   }
85
86   /**
87    * Builds a parameter map from the aggregated arguments of the title,
88    * access, and page callbacks.
89    *
90    * @return \Drupal\drupalmoduleupgrader\Routing\ParameterMap
91    */
92   protected function buildParameterMap(TargetInterface $target, Drupal7Route $route) {
93     $map = new ParameterMap(clone $route->getPath(), []);
94
95     $indexer = $target->getIndexer('function');
96
97     if ($indexer->has($route['title callback'])) {
98       $map->merge(new ParameterMap(
99         $route->getPath(),
100         $indexer->get($route['title callback'])->getParameters()->toArray(),
101         $route['title arguments']
102       ));
103     }
104
105     if ($indexer->has($route['access callback'])) {
106       $map->merge(new ParameterMap(
107         $route->getPath(),
108         $indexer->get($route['access callback'])->getParameters()->toArray(),
109         $route['access arguments']
110       ));
111     }
112
113     if ($indexer->has($route['page callback'])) {
114       $map->merge(new ParameterMap(
115         $route->getPath(),
116         $indexer->get($route['page callback'])->getParameters()->toArray(),
117         $route['page arguments']
118       ));
119     }
120
121     return $map;
122   }
123
124   /**
125    * {@inheritdoc}
126    */
127   public function buildRouteDefinition(TargetInterface $target, Drupal7Route $route) {
128     $indexer = $target->getIndexer('function');
129
130     $definition = new CoreRoute('');
131     $this->buildParameterMap($target, $route)->applyRoute($definition);
132
133     $controller = $this->getController($target, $route)->getName()->getAbsolutePath();
134
135     if ($route->containsKey('title')) {
136       $definition->setDefault('_title', $route['title']);
137     }
138     elseif ($indexer->has($route['title callback'])) {
139       $definition->setDefault('_title_callback', $controller . '::' . $route['title callback']);
140     }
141
142     if ($route->isAbsoluteAccess()) {
143       $definition->setRequirement('_access', $route['access callback'] ? 'true' : 'false');
144     }
145     elseif ($route->isPermissionBased()) {
146       $definition->setRequirement('_permission', $route['access arguments'][0]);
147     }
148     elseif ($indexer->has($route['access callback'])) {
149       $definition->setRequirement('_custom_access', $controller . '::' . $route['access callback']);
150     }
151
152     if ($indexer->has($route['page callback'])) {
153       $definition->setDefault('_controller', $controller . '::' . $route['page callback']);
154     }
155
156     return new Drupal8Route($this->getName($target, $route), $definition, $this->routeProvider);
157   }
158
159   /**
160    * {@inheritdoc}
161    */
162   public function buildRoute(TargetInterface $target, Drupal7Route $route) {
163     $definition = $this->buildRouteDefinition($target, $route);
164
165     $map = $this->buildParameterMap($target, $route);
166     $map->applyRoute($definition->unwrap());
167
168     $indexer = $target->getIndexer('function');
169
170     foreach ($map->toArray() as $function_name => $parameters) {
171       if ($parameters && $indexer->has($function_name)) {
172         /** @var \Pharborist\Functions\FunctionDeclarationNode $function */
173         $function = $indexer->get($function_name);
174         foreach ($parameters as $parameter_name => $info) {
175           $parameter = $function->getParameterByName($parameter_name)->setName($info['name'], TRUE);
176           if (isset($info['type'])) {
177             $plugin_id = '_rewriter:' . $info['type'];
178             if ($this->rewriters->hasDefinition($plugin_id)) {
179               $this->rewriters->createInstance($plugin_id)->rewrite($parameter);
180             }
181           }
182         }
183       }
184     }
185
186     $class_indexer = $target->getIndexer('class');
187     if ($class_indexer->has('DefaultController')) {
188       $controller = $class_indexer->get('DefaultController');
189     }
190     else {
191       $controller = $this->getController($target, $route);
192       $class_indexer->addFile($this->writeClass($target, $controller));
193     }
194
195     if ($indexer->has($route['title callback'])) {
196       if (! $controller->hasMethod($route['title callback'])) {
197         $indexer->get($route['title callback'])->cloneAsMethodOf($controller);
198       }
199     }
200
201     if ($indexer->has($route['access callback'])) {
202       $func = $indexer->get($route['access callback']);
203
204       $returns = $func->find(Filter::isInstanceOf('\Pharborist\ReturnStatementNode'));
205       foreach ($returns as $ret) {
206         $call = ClassMethodCallNode::create('\Drupal\Core\Access\AccessResult', 'allowedIf')->appendArgument($ret->getExpression());
207         $ret->replaceWith(ReturnStatementNode::create($call));
208       }
209
210       // The access callback always receives an $account parameter.
211       if ($func->hasParameter('account')) {
212         $func->getParameter('account')->setTypeHint('Drupal\Core\Session\AccountInterface');
213       }
214       else {
215         $account = ParameterNode::create('account')->setTypeHint('Drupal\Core\Session\AccountInterface');
216         $func->appendParameter($account);
217       }
218
219       if (! $controller->hasMethod($route['access callback'])) {
220         $func->cloneAsMethodOf($controller);
221       }
222     }
223
224     if ($indexer->has($route['page callback'])) {
225       if (! $controller->hasMethod($route['page callback'])) {
226         $indexer->get($route['page callback'])->cloneAsMethodOf($controller);
227       }
228     }
229
230     $this->writeClass($target, $controller);
231   }
232
233   protected function getController(TargetInterface $target, Drupal7Route $route) {
234     $render = [
235       '#theme' => 'dmu_controller',
236       '#module' => $target->id(),
237     ];
238     return $this->parse($render);
239   }
240
241 }