Example #1
0
 /**
  * Finds routes that may potentially match the request.
  *
  * This may return a mixed list of class instances, but all routes returned
  * must extend the core symfony route. The classes may also implement
  * RouteObjectInterface to link to a content document.
  *
  * This method may not throw an exception based on implementation specific
  * restrictions on the url. That case is considered a not found - returning
  * an empty array. Exceptions are only used to abort the whole request in
  * case something is seriously broken, like the storage backend being down.
  *
  * Note that implementations may not implement an optimal matching
  * algorithm, simply a reasonable first pass.  That allows for potentially
  * very large route sets to be filtered down to likely candidates, which
  * may then be filtered in memory more completely.
  *
  * @param Request $request A request against which to match.
  *
  * @return \Symfony\Component\Routing\RouteCollection with all urls that
  *      could potentially match $request. Empty collection if nothing can
  *      match.
  *
  * @todo Should this method's found routes also be included in the cache?
  */
 public function getRouteCollectionForRequest(Request $request)
 {
     // The '_system_path' has language prefix stripped and path alias resolved,
     // whereas getPathInfo() returns the requested path. In Drupal, the request
     // always contains a system_path attribute, but this component may get
     // adopted by non-Drupal projects. Some unit tests also skip initializing
     // '_system_path'.
     // @todo Consider abstracting this to a separate object.
     if ($request->attributes->has('_system_path')) {
         // _system_path never has leading or trailing slashes.
         $path = '/' . $request->attributes->get('_system_path');
     } else {
         // getPathInfo() always has leading slash, and might or might not have a
         // trailing slash.
         $path = rtrim($request->getPathInfo(), '/');
     }
     $collection = $this->getRoutesByPath($path);
     // Try rebuilding the router if it is necessary.
     if (!$collection->count() && $this->routeBuilder->rebuildIfNeeded()) {
         $collection = $this->getRoutesByPath($path);
     }
     return $collection;
 }
 /**
  * Rebuilds routers if necessary.
  *
  * @param \Symfony\Component\HttpKernel\Event\PostResponseEvent $event
  *   The event object.
  */
 public function onKernelTerminate(PostResponseEvent $event)
 {
     $this->routeBuilder->rebuildIfNeeded();
 }
 /**
  * {@inheritdoc}
  */
 public function getRoutesByPattern($pattern)
 {
     $path = RouteCompiler::getPatternOutline($pattern);
     $this->routeBuilder->rebuildIfNeeded();
     return $this->getRoutesByPath($path);
 }
 /**
  * Find all local tasks that appear on a named route.
  *
  * @param string $route_name
  *   The route for which to find local tasks.
  *
  * @return array
  *   Returns an array of task levels. Each task level contains instances
  *   of local tasks (LocalTaskInterface) which appear on the tab route.
  *   The array keys are the depths and the values are arrays of plugin
  *   instances.
  */
 public function getLocalTasksForRoute($route_name)
 {
     if (!isset($this->instances[$route_name])) {
         $this->instances[$route_name] = array();
         if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $route_name)) {
             $base_routes = $cache->data['base_routes'];
             $parents = $cache->data['parents'];
             $children = $cache->data['children'];
         } else {
             // Maybe some code asked to rebuild the routes, so rebuild the router
             // as we rely on having proper existing routes in dynamic local tasks.
             $this->routeBuilder->rebuildIfNeeded();
             $definitions = $this->getDefinitions();
             // We build the hierarchy by finding all tabs that should
             // appear on the current route.
             $base_routes = array();
             $parents = array();
             $children = array();
             foreach ($definitions as $plugin_id => $task_info) {
                 // Fill in the base_route from the parent to insure consistency.
                 if (!empty($task_info['parent_id']) && !empty($definitions[$task_info['parent_id']])) {
                     $task_info['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
                     // Populate the definitions we use in the next loop. Using a
                     // reference like &$task_info causes bugs.
                     $definitions[$plugin_id]['base_route'] = $definitions[$task_info['parent_id']]['base_route'];
                 }
                 if ($route_name == $task_info['route_name']) {
                     if (!empty($task_info['base_route'])) {
                         $base_routes[$task_info['base_route']] = $task_info['base_route'];
                     }
                     // Tabs that link to the current route are viable parents
                     // and their parent and children should be visible also.
                     // @todo - this only works for 2 levels of tabs.
                     // instead need to iterate up.
                     $parents[$plugin_id] = TRUE;
                     if (!empty($task_info['parent_id'])) {
                         $parents[$task_info['parent_id']] = TRUE;
                     }
                 }
             }
             if ($base_routes) {
                 // Find all the plugins with the same root and that are at the top
                 // level or that have a visible parent.
                 foreach ($definitions as $plugin_id => $task_info) {
                     if (!empty($base_routes[$task_info['base_route']]) && (empty($task_info['parent_id']) || !empty($parents[$task_info['parent_id']]))) {
                         // Concat '> ' with root ID for the parent of top-level tabs.
                         $parent = empty($task_info['parent_id']) ? '> ' . $task_info['base_route'] : $task_info['parent_id'];
                         $children[$parent][$plugin_id] = $task_info;
                     }
                 }
             }
             $data = array('base_routes' => $base_routes, 'parents' => $parents, 'children' => $children);
             $this->cacheBackend->set($this->cacheKey . ':' . $route_name, $data, Cache::PERMANENT, $this->cacheTags);
         }
         // Create a plugin instance for each element of the hierarchy.
         foreach ($base_routes as $base_route) {
             // Convert the tree keyed by plugin IDs into a simple one with
             // integer depth.  Create instances for each plugin along the way.
             $level = 0;
             // We used this above as the top-level parent array key.
             $next_parent = '> ' . $base_route;
             do {
                 $parent = $next_parent;
                 $next_parent = FALSE;
                 foreach ($children[$parent] as $plugin_id => $task_info) {
                     $plugin = $this->createInstance($plugin_id);
                     $this->instances[$route_name][$level][$plugin_id] = $plugin;
                     // Normally, l() compares the href of every link with the current
                     // path and sets the active class accordingly. But the parents of
                     // the current local task may be on a different route in which
                     // case we have to set the class manually by flagging it active.
                     if (!empty($parents[$plugin_id]) && $route_name != $task_info['route_name']) {
                         $plugin->setActive();
                     }
                     if (isset($children[$plugin_id])) {
                         // This tab has visible children
                         $next_parent = $plugin_id;
                     }
                 }
                 $level++;
             } while ($next_parent);
         }
     }
     return $this->instances[$route_name];
 }