4

I have been trying to disable a menu item "standard.front_page" using the following code:

db_query("UPDATE {menu_tree} SET enabled = 0 WHERE id LIKE 'standard.front_page';");
db_query("DELETE FROM {cache_menu};");

It works fine till I do a cache rebuild using drush cr. Once I do a cache rebuild the menu item again comes back.

Can anyone please suggest a good way of doing the above?

4
  • What are you actually trying to accomplish?
    – mradcliffe
    Commented Jun 21, 2016 at 17:07
  • 2
    Tip: using db queries to change behaviors like that is not recommended because it bypasses the framework.
    – Eyal
    Commented Jun 21, 2016 at 19:53
  • 1
    You will probably need to implement an alter hook or an event subscriber service.
    – Eyal
    Commented Jun 21, 2016 at 19:55
  • What would be a suggested way of doing it.
    – GeekTantra
    Commented Jun 22, 2016 at 9:06

3 Answers 3

7

You can retrieve the Drupal menu link & cache services to programmatically change the menu link status. Something like this example function:

function menu_state_toggle($menu_id, $enabled = TRUE) {
  $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
  $front_page_link = $menu_link_manager->getDefinition($menu_id);
  $front_page_link['enabled'] = $enabled ? 1 : 0; 
  $menu_link_manager->updateDefinition($menu_id, $front_page_link);
  $cache = \Drupal::cache('menu');
  $cache->deleteAll();
}

menu_state_toggle('standard.front_page', FALSE);
1
  • 1
    $enabled ? 1 : 0 can just be replaced with (int) $enabled.
    – apaderno
    Commented Dec 17, 2017 at 17:01
2

As a post-migrate cleanup step, I needed to remove a few nominated items from our main menu. Other settings (views, imported via config management) were going to take over the role that used to be static pages. Here is how it went:

/**
 * Startup changes for upgrading from the migrated base site to D8 version.
 */
function drupalorgnz_upgrade_install() {
  // From the base upgrade, remove the static pages that were in the main menu
  // as they were replaced with proper views pages.
  // The 'pages' still exist, and are used as intro text blocks in the
  // news views blocks,
  // but relinquish their menu items and paths.
  // Zap the legacy /companies and /showcases nodes.
  $old_nids = [517,518];
  foreach ($old_nids as $nid) {
    $node = \Drupal\node\Entity\Node::load($nid);
    // Zap out the path_alias and the menu item to anonymize this node.
    $node->path->delete();

    // That was easy.
    // Next hugely trickier.
    // This is BS. Eventually found the method in menu_ui_node_predelete()
    /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
    $result = $menu_link_manager->loadLinksByRoute('entity.node.canonical', ['node' => $node->id()]);
    if (!empty($result)) {
      foreach ($result as $id => $instance) {
        if ($instance->isDeletable() && strpos($id, 'menu_link_content:') === 0) {
          $instance->deleteLink();
        }
      }
    }
    $node->save();
  }
}
1

If you simply want to disable a link, but still have it appear on the menu, use route:<nolink> as link path in the menu item.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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