Score:1

How to get parameter from dynamic route in route subscriber

ng flag

I am trying to restrict access for non admin users on admin/structure/menu so that only admins can create any new links via admin/structure/menu.
Now I want that for one special menu with the ID "Focus" the "Add Link" button is available for another role too.

Here is a Screenshot of the actual backend with the "Add Link" still availabe. I want this to be gone for Hauptnavigation but not for Fokusnavigation. enter image description here

Same thing when you click on a Menu. You get an "Add Link" button. I can disable this with me code below, but I don't know how to allow it for non Admin Roles again. enter image description here

I can get the menu->id() in the my_menu.module file, with the same code like in the routesubscriber below but somehow it doesn't work in the routesubscriber. Drush CR returns an

PHP Fatal error:  Uncaught Error: Call to a member function id() on null in /var/www/html/web/modules/custom/my_menu/src/Routing/RouteSubscriber.php:31                                                                                                                
Stack trace:                                                                                                                                                                                                                                                           
#0 /var/www/html/web/core/lib/Drupal/Core/Routing/RouteSubscriberBase.php(37): Drupal\my_menu\Routing\RouteSubscriber->alterRoutes(Object(Symfony\Component\Routing\RouteCollection))                                                                                  
#1 [internal function]: Drupal\Core\Routing\RouteSubscriberBase->onAlterRoutes(Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))                                              
#2 /var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func(Array, Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#3 /var/www/html/web/core/lib/Drupal/Core/Routing/RouteBuilder.php(189): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Drupal\Core\Routing\RouteBuildEvent), 'routing.route_a...')                                                   
 in /var/www/html/web/modules/custom/my_menu/src/Routing/RouteSubscriber.php on line 31       

Are there other ways to get the value? What am I doing wrong.
Here is my code.

<?php

namespace Drupal\my_menu\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\Routing\RouteCollection;
use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Class RouteSubscriber
 *
 * hiding menu editing components for non-admins
 *
 * @package Drupal\hw_menu\Routing
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection) {


    if ($route = $collection->get('entity.menu.add_link_form')) {

  //    dpm($route->getRequirements());

      $menu instanceof \Drupal\system\Entity\Menu;
      $menu = \Drupal::routeMatch()->getParameter('menu');
      if($menu->id() != 'focus') {
        $route->setRequirement('_role', 'administrator');
      }
    //  dpm($route->getRequirements());
    }

  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // Run after content_translation, which has priority -210.
    $events[RoutingEvents::ALTER] = ['onAlterRoutes', -230];
    return $events;
  }

}
Jaypan avatar
de flag
Your post isn't very clear. Who are 'they'? What is 'focus'? What are you trying to do? You've shown some code, but not given the clear goal, or even clearly explained what is not working. You've told us how you're trying to do something, and shown code that does something, but you never explained clearly what the end goal is in human terms.
ng flag
Sorry, thougt it should be clear by reading the code. Will add further details for humans.
Jaypan avatar
de flag
I still don't see your actual goal, other than trying to solve some coding issue. But why are you even doing this coding? What is your goal for the front-end user? Without knowing what you want the expected behavior to be, we can't tell you where you're going wrong, we can't even tell you if you are on the right track with your approach, or going the entirely wrong direction altogether. There are 10 ways do do anything in Drupal.
cn flag
Route definitions don't contain parameter values, those are only available when a route is built. The literal answer to what I think your question is, is to add a custom access callback for the route (as described [here](https://www.drupal.org/docs/8/api/routing-system/access-checking-on-routes/custom-route-access-checking)), but there might be a more robust way to solve the problem if you can edit the question to provide some more context
ng flag
Added some more explanation. I really don't know how to explain it better or even simpler.
Score:1
ng flag

Would say that you code is failing because there is no menu entity available since the menu parameter converter works when the route gets resolved as commented by @Clive not during route build, which is when the alter event is fired.

On the other hand, why don't you use the Administer menus and menu links permission from core to deny your non-admin user's access to the menu administration? Also you can use Simple Menu Permissions or the Menu Admin per Menu modules if you want more control over your menus.

But if you still want to handle the menu access by yourself you can do that implementing your own access check using the route subscriber you have already.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.