'Drupal 8 - Programmatically disable or enable link on main navigation

This concerns Drupal 8. I'm trying to manage a link item on the main navigation. I want to enable/disable an item, programmatically. I searched but cannot find how to do that. I found MenuLinkManager, MenuLinkContent, but I can't do what I want. Thank you all for your help.



Solution 1:[1]

To Disable/Enable Menu items means show/hide it. So, we can do it via below code in theme file

/**
 * Implements hook_preprocess_menu().
 */
function theme_preprocess_menu(&$variables) {
  if (isset($variables['menu_name']) && $variables['menu_name'] === 'main') {
    foreach($variables['items'] as $key => $item) {
      $path = $item['url']->toString();
      switch($path) {
        case '/menupath':
          unset($variables['items'][$key]); //Remove menu item
        break;          
      }           
    }
  }
} 

Solution 2:[2]

Assuming you actually want to remove the link I would use hook_menu_links_discovered_alter()

For example:

/**
 * Implements hook_menu_links_discovered_alter().
 *
 * @param array $links
 *   An array of links.
 */
function HOOK_menu_links_discovered_alter(array &$links): void {
  unset($links['machine_name_to_remove']);
}

Solution 3:[3]

You can install the module Special Menu Items https://www.drupal.org/project/special_menu_items

Or do it in your theme_link function in your template.php

function myTheme_link($variables) {
  if ((isset($variables['path']) && ($variables['path'] == $_GET['q'] || ($variables['path'] == '<front>' && drupal_is_front_page())))) {

    return ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text']));
  } else {
    return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>';
  }
}

Solution 4:[4]

You need to exclude the menu from cache if you are going to alter it dynamically:

/**
 * Implements hook_preprocess_HOOK().
 */
function YOUR_MODULE_preprocess_menu(&$variables) {
  foreach ($variables['items'] as $key => $item) {
    if ($key == 'depot_opm.document_demande_existant_tabs') {
      unset($variables['items'][$key]);
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function YOUR_MODULE_preprocess_block(&$variables) {
  // Disable the cache of the menu block.
  if($variables['derivative_plugin_id'] == 'tabs-documents') {
    $variables['#cache']['max-age'] = 0;
  }
}

Solution 5:[5]

This is what worked for me: tested with Drupal 9.3.9 (April 2022).

/**
 * Implements hook_menu_links_discovered_alter().
 */
function MY_MODULE_menu_links_discovered_alter(&$links) {
  $links['standard.front_page']['enabled'] = 0;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vernit Gupta
Solution 2 Felix Eve
Solution 3 hoover_D
Solution 4 Achraf JEDAY
Solution 5 Achraf JEDAY