Further modules included.
[yaffs-website] / web / modules / contrib / drupalmoduleupgrader / src / Routing / HookMenu.php
1 <?php
2
3 namespace Drupal\drupalmoduleupgrader\Routing;
4
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;
10
11 /**
12  * This class is a conversion map for hook_menu().
13  *
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.
17  *
18  * All this is absolutely READ-ONLY. Nothing in the target module is changed.
19  */
20 class HookMenu {
21
22   /**
23    * The source routes (from Drupal 7).
24    *
25    * @var RouterInterface
26    */
27   protected $sourceRoutes;
28
29   /**
30    * The destination routes (as in a routing.yml file).
31    *
32    * @var RouterInterface
33    */
34   protected $destinationRoutes;
35
36   /**
37    * Maps Drupal 7 paths to Drupal 8 route names.
38    *
39    * @var string[]
40    */
41   protected $routeMap = [];
42
43   /**
44    * @var \Drupal\drupalmoduleupgrader\TargetInterface
45    */
46   protected $target;
47
48   /**
49    * The route converters' plugin manager.
50    *
51    * @var \Drupal\Component\Plugin\PluginManagerInterface
52    */
53   protected $routeConverters;
54
55   /**
56    * Constructs a HookMenu object.
57    *
58    * @param \Drupal\drupalmoduleupgrader\TargetInterface $target
59    *  The target module.
60    * @param \Drupal\Component\Plugin\PluginManagerInterface $route_converters
61    *   The route converters.
62    */
63   public function __construct(TargetInterface $target, PluginManagerInterface $route_converters) {
64     $this->target = $target;
65     $this->routeConverters = $route_converters;
66
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());
74     }
75   }
76
77   /**
78    * Returns the collection of routes in the source.
79    *
80    * @return RouterInterface
81    *   The requested link collection.
82    */
83   public function getSourceRoutes() {
84     if (empty($this->sourceRoutes)) {
85       $this->sourceRoutes = new Drupal7Router();
86
87       $items = call_user_func($this->target->id() . '_menu');
88       foreach ($items as $path => $item) {
89         $this->sourceRoutes->addRoute(new Drupal7Route($path, $item));
90       }
91
92       // Now that all routes have been loaded, tell them to resolve their
93       // hierarchical relationships.
94       $this->sourceRoutes->finalize();
95     }
96     return $this->sourceRoutes;
97   }
98
99   /**
100    * Returns the collection of routes in the destination.
101    *
102    * @return RouterInterface
103    *   The requested route collection.
104    */
105   public function getDestinationRoutes() {
106     if (empty($this->destinationRoutes)) {
107       $this->destinationRoutes = $this->buildDestinationRoutes();
108     }
109     return $this->destinationRoutes;
110   }
111
112   /**
113    * Returns the destination route for the given source path.
114    *
115    * @param string $path
116    *   The source path, as defined in hook_menu().
117    *
118    * @return \Drupal\drupalmoduleupgrader\Routing\Drupal8\RouteWrapper|NULL
119    *   The destination route.
120    */
121   public function getDestinationRoute($path) {
122     return $this->getDestinationRoutes()->get($this->routeMap[$path]);
123   }
124
125   /**
126    * Builds the Drupal 8 router by running the Drupal 7 router items through
127    * the appropriate route converters.
128    *
129    * @return RouterInterface
130    */
131   private function buildDestinationRoutes() {
132     // @todo These are currently hardcoded on the D7 -> D8 conversion. Make this
133     //   configurable.
134     $router = new Drupal8Router();
135     $this->routeMap = [];
136
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')) {
141         continue;
142       }
143
144       // Get the appropriate route converter, which will build the route
145       // definition.
146       $plugin_id = $route['page callback'];
147       if (!$this->routeConverters->hasDefinition($plugin_id)) {
148         $plugin_id = 'default';
149       }
150
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();
155     }
156     $router->finalize();
157
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];
163       }
164     }
165
166     return $router;
167   }
168
169 }