Chris@0: viewStorage = $entity_type_manager->getStorage('view'); Chris@0: $this->state = $state; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Resets the internal state of the route subscriber. Chris@0: */ Chris@0: public function reset() { Chris@0: $this->viewsDisplayPairs = NULL; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function getSubscribedEvents() { Chris@0: $events = parent::getSubscribedEvents(); Chris@0: $events[RoutingEvents::FINISHED] = ['routeRebuildFinished']; Chris@0: // Ensure to run after the entity resolver subscriber Chris@0: // @see \Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber Chris@0: $events[RoutingEvents::ALTER] = ['onAlterRoutes', -175]; Chris@0: Chris@0: return $events; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets all the views and display IDs using a route. Chris@0: */ Chris@0: protected function getViewsDisplayIDsWithRoute() { Chris@0: if (!isset($this->viewsDisplayPairs)) { Chris@0: $this->viewsDisplayPairs = []; Chris@0: Chris@0: // @todo Convert this method to some service. Chris@0: $views = $this->getApplicableViews(); Chris@0: foreach ($views as $data) { Chris@0: list($view_id, $display_id) = $data; Chris@0: $this->viewsDisplayPairs[] = $view_id . '.' . $display_id; Chris@0: } Chris@0: $this->viewsDisplayPairs = array_combine($this->viewsDisplayPairs, $this->viewsDisplayPairs); Chris@0: } Chris@0: return $this->viewsDisplayPairs; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns a set of route objects. Chris@0: * Chris@0: * @return \Symfony\Component\Routing\RouteCollection Chris@0: * A route collection. Chris@0: */ Chris@0: public function routes() { Chris@0: $collection = new RouteCollection(); Chris@0: foreach ($this->getViewsDisplayIDsWithRoute() as $pair) { Chris@0: list($view_id, $display_id) = explode('.', $pair); Chris@0: $view = $this->viewStorage->load($view_id); Chris@0: // @todo This should have an executable factory injected. Chris@0: if (($view = $view->getExecutable()) && $view instanceof ViewExecutable) { Chris@0: if ($view->setDisplay($display_id) && $display = $view->displayHandlers->get($display_id)) { Chris@0: if ($display instanceof DisplayRouterInterface) { Chris@0: $this->viewRouteNames += (array) $display->collectRoutes($collection); Chris@0: } Chris@0: } Chris@0: $view->destroy(); Chris@0: } Chris@0: } Chris@0: Chris@0: $this->state->set('views.view_route_names', $this->viewRouteNames); Chris@0: return $collection; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function alterRoutes(RouteCollection $collection) { Chris@0: foreach ($this->getViewsDisplayIDsWithRoute() as $pair) { Chris@0: list($view_id, $display_id) = explode('.', $pair); Chris@0: $view = $this->viewStorage->load($view_id); Chris@0: // @todo This should have an executable factory injected. Chris@0: if (($view = $view->getExecutable()) && $view instanceof ViewExecutable) { Chris@0: if ($view->setDisplay($display_id) && $display = $view->displayHandlers->get($display_id)) { Chris@0: if ($display instanceof DisplayRouterInterface) { Chris@0: // If the display returns TRUE a route item was found, so it does not Chris@0: // have to be added. Chris@0: $view_route_names = $display->alterRoutes($collection); Chris@0: $this->viewRouteNames = $view_route_names + $this->viewRouteNames; Chris@0: foreach ($view_route_names as $id_display => $route_name) { Chris@0: $view_route_name = $this->viewsDisplayPairs[$id_display]; Chris@0: unset($this->viewsDisplayPairs[$id_display]); Chris@0: $collection->remove("views.$view_route_name"); Chris@0: } Chris@0: } Chris@0: } Chris@0: $view->destroy(); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Stores the new route names after they have been rebuilt. Chris@0: * Chris@0: * Callback for the RoutingEvents::FINISHED event. Chris@0: * Chris@0: * @see \Drupal\views\EventSubscriber::getSubscribedEvents() Chris@0: */ Chris@0: public function routeRebuildFinished() { Chris@0: $this->reset(); Chris@0: $this->state->set('views.view_route_names', $this->viewRouteNames); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns all views/display combinations with routes. Chris@0: * Chris@0: * @see \Drupal\views\Views::getApplicableViews() Chris@0: */ Chris@0: protected function getApplicableViews() { Chris@0: return Views::getApplicableViews('uses_route'); Chris@0: } Chris@0: Chris@0: }