3 namespace Drupal\drupalmoduleupgrader\Routing;
5 use Drupal\Component\Plugin\PluginManagerInterface;
6 use Drupal\drupalmoduleupgrader\Routing\Drupal7\Router as Drupal7Router;
7 use Drupal\drupalmoduleupgrader\Routing\Drupal7\RouteWrapper as Drupal7Route;
8 use Drupal\drupalmoduleupgrader\Routing\RouterBase as Drupal8Router;
9 use Drupal\drupalmoduleupgrader\TargetInterface;
12 * This class is a conversion map for hook_menu().
14 * It will compile a router object for hook_menu(), and resolve the inherent
15 * hierarchies where possible. It will also build the corresponding Drupal 8
16 * routes by invoking the appropriate route converters.
18 * All this is absolutely READ-ONLY. Nothing in the target module is changed.
23 * The source routes (from Drupal 7).
25 * @var RouterInterface
27 protected $sourceRoutes;
30 * The destination routes (as in a routing.yml file).
32 * @var RouterInterface
34 protected $destinationRoutes;
37 * Maps Drupal 7 paths to Drupal 8 route names.
41 protected $routeMap = [];
44 * @var \Drupal\drupalmoduleupgrader\TargetInterface
49 * The route converters' plugin manager.
51 * @var \Drupal\Component\Plugin\PluginManagerInterface
53 protected $routeConverters;
56 * Constructs a HookMenu object.
58 * @param \Drupal\drupalmoduleupgrader\TargetInterface $target
60 * @param \Drupal\Component\Plugin\PluginManagerInterface $route_converters
61 * The route converters.
63 public function __construct(TargetInterface $target, PluginManagerInterface $route_converters) {
64 $this->target = $target;
65 $this->routeConverters = $route_converters;
67 // If the hook_menu() implementation doesn't exist, get the implementation
68 // from the indexer and eval it into existence. It's the calling code's
69 // responsibility to ensure that the implementation doesn't contain anything
70 // which will blow up on execution.
71 $hook = $target->id() . '_menu';
72 if (! function_exists($hook)) {
73 eval($target->getIndexer('function')->get('hook_menu')->getText());
78 * Returns the collection of routes in the source.
80 * @return RouterInterface
81 * The requested link collection.
83 public function getSourceRoutes() {
84 if (empty($this->sourceRoutes)) {
85 $this->sourceRoutes = new Drupal7Router();
87 $items = call_user_func($this->target->id() . '_menu');
88 foreach ($items as $path => $item) {
89 $this->sourceRoutes->addRoute(new Drupal7Route($path, $item));
92 // Now that all routes have been loaded, tell them to resolve their
93 // hierarchical relationships.
94 $this->sourceRoutes->finalize();
96 return $this->sourceRoutes;
100 * Returns the collection of routes in the destination.
102 * @return RouterInterface
103 * The requested route collection.
105 public function getDestinationRoutes() {
106 if (empty($this->destinationRoutes)) {
107 $this->destinationRoutes = $this->buildDestinationRoutes();
109 return $this->destinationRoutes;
113 * Returns the destination route for the given source path.
115 * @param string $path
116 * The source path, as defined in hook_menu().
118 * @return \Drupal\drupalmoduleupgrader\Routing\Drupal8\RouteWrapper|NULL
119 * The destination route.
121 public function getDestinationRoute($path) {
122 return $this->getDestinationRoutes()->get($this->routeMap[$path]);
126 * Builds the Drupal 8 router by running the Drupal 7 router items through
127 * the appropriate route converters.
129 * @return RouterInterface
131 private function buildDestinationRoutes() {
132 // @todo These are currently hardcoded on the D7 -> D8 conversion. Make this
134 $router = new Drupal8Router();
135 $this->routeMap = [];
137 foreach ($this->getSourceRoutes() as $path => $route) {
138 /** @var Drupal7\RouteWrapper $route */
139 // If the route hasn't got a page callback...don't even try.
140 if (!$route->containsKey('page callback')) {
144 // Get the appropriate route converter, which will build the route
146 $plugin_id = $route['page callback'];
147 if (!$this->routeConverters->hasDefinition($plugin_id)) {
148 $plugin_id = 'default';
151 /** @var Drupal8\RouteWrapper $d8_route */
152 $d8_route = $this->routeConverters->createInstance($plugin_id)->buildRouteDefinition($this->target, $route);
153 $router->addRoute($d8_route);
154 $this->routeMap[$path] = $d8_route->getIdentifier();
158 foreach ($this->getSourceRoutes()->getDefaultLocalTasks() as $path => $route) {
159 /** @var Drupal7\RouteWrapper $route */
160 if ($route->hasParent()) {
161 $parent = (string) $route->getParent()->getPath();
162 $this->routeMap[$path] = $this->routeMap[$parent];