9

I want to alter the menu link in Drupal 8. In Drupal 7 we can achieve this using hook_translated_menu_link_alter().

function module_translated_menu_link_alter(&$item, $map) {
  global $user;

  if (!empty($item['access'])) {
    // Administrator will access all menu's.
    if (strpos(current_path(), 'admin/structure/menu/manage/' . $item['menu_name']) === 0 && user_access('administer menu')) {
      return;
    }
    // If userid is equal to menu user id.
    if ($user->uid == 1) {
      $access = 'UNBLOCK';
      break;
    }
   // Block menu.
    else {
      $access = 'BLOCK';
    }
    // Access FALSE if Menu not for USER.
    if ($access == 'BLOCK') {
      $item['access'] = FALSE;
    }
  }
}

In Drupal 7 I am hiding/disabling menu based on some conditions like the user ID.

Similarly, I want to alter the menu link in Drupal 8. How can I achieve it?

2
  • On this page if you scroll to end before comments, it has stated hook_translated_menu_link_alter() has been replaced by hook_menu_link_load(), I do not know whether it is right or wrong, I just found this. Might be you can make out. If, let me also know.
    – CodeNext
    Aug 12, 2016 at 22:05
  • Maybe helpful: drupal.stackexchange.com/questions/204582/… Feb 23, 2019 at 15:38

2 Answers 2

4

HOOK_link_alter would be one D8 equivalent to hook_translated_menu_link_alter:

/**
 * Implements hook_link_alter().
 *
 * @inheritdoc
 */
function HOOK_link_alter(&$variables) {
  $url = $variables['url'];
  // Check url is routed in Drupal.
  if ($url->isRouted()) {
    // Load the current user by user ID.
    $currentUser = User::load(\Drupal::currentUser()->id());
    // Check access.
    $urlAccess = $url->access();
    // Get url options.
    $urlOptions = $url->getOptions();
    // Your code here.
  }
}

See Drupal 8 class URL for more API info.

However, you could use Hook_preprocess_HOOK() as such:

/**
 * Implements hook_preprocess_hook().
 *
 * @inheritdoc
 */
function HOOK_preprocess_menu(&$variables) {
  if (isset($variables['menu_name']) && $variables['menu_name'] === 'menu_name') {
    foreach($variables['items'] as $key => $item) {
      $url = $item['url']->toString();
      if ($url == '/user') {
        // Remove menu item.
        unset($variables['items'][$key]);
      }
    }
  }
}

Just checking path above, but it shows you can hide a single menu item based on certain criteria.


For the access restrictions, depending on your needs, you might look at routing and permissions based on the entity instead of the menu item and let Drupal handle the menu item display.

For menu access by role look at this module: https://www.drupal.org/project/menu_item_role_access

1
  • hook_link_alter() is not thought as replacement of hook_translated_menu_link_alter() since there are only few keys that can be altered, and the access key is not one of those.
    – apaderno
    Apr 6, 2020 at 14:40
0

From drupal.org on /node/2122241:

Altering menu links and adding menu links dynamically

Statically defined menu items may be altered using hook_menu_links_discovered_alter() (but note there is no hook_menu_link_discovered(), the menu links are built from the .yml files as explained above). This hook may also be used to add new dynamic menu items.

More often, you may want to use a deriver class to add new menu link plugins. For example Views provided menu links are added in views.links.menu.yml, which specifies the deriver class \Drupal\views\Plugin\Derivative\ViewsMenuLink.

Finally, you can use the plugin manager directly to add, update, and remove definitions.

You could probably use hook_menu_links_discovered_alter for your scenario.


Edit: You want to edit the permission to access that link, so it automatically does not show up in the menu.

Read on drupal.org: /node/2311427

Drupal 8

In Drupal 8, you can support dynamic permissions by referencing a function that will dynamically define those permissions. This callback defines the permissions for core's filter module.

// in filter.permissions.yml


permission_callbacks:
  - Drupal\filter\FilterPermissions::permissions

// in FilterPermissions.php

class FilterPermissions {
  public function permissions() {
    $permissions = [];
    // Generate permissions for each text format. Warn the administrator that any
    // of them are potentially unsafe.
    /** @var \Drupal\filter\FilterFormatInterface[] $formats */
    $formats = $this->entityManager->getStorage('filter_format')->loadByProperties(['status' => TRUE]);
    uasort($formats, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
    foreach ($formats as $format) {
      if ($permission = $format->getPermissionName()) {
        $permissions[$permission] = [
          'title' => $this->t('Use the @label text format', ['@url' => $format->url(), '@label' => $format->label()]),
          'description' => String::placeholder($this->t('Warning: This permission may have security implications depending on how the text format is configured.')),
        ];
      }
    }
    return $permissions;
  }
}

You should also read this article https://www.lullabot.com/articles/what-happened-to-hook_menu-in-drupal-8 (scroll down to "Access Control" and "Hook_Menu_Alter").

I hope this helps.

2
  • 1
    Tried this hook_menu_links_discovered_alter, but this is not useful to hide menu. Kindly check that this hook is only useful for The link definitions to be altered.
    – Ajay Reddy
    Aug 8, 2016 at 11:04
  • Referring to above article, I tried that but that will give only access denied, it wont hide menu.
    – Ajay Reddy
    Aug 8, 2016 at 12:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.