1

(Note: the code and module names have been simplified for demonstration)

I have a number of custom modules in a Drupal 7 site. One of the modules (a 'base' module enabled during site installation) creates a custom menu (operations-menu) along with a hook (hook_operations_menu()) for customizing the menu. Other custom modules (I'll refer to them as implementing modules) with a need to add menu links into the operations-menu can simply implement hook_operations_menu() and return the appropriate menu item definitions.

Example: Assuming my base module is called 'base' and my implementing module is called 'implements'.

base.module

/**
* Implements hook_modules_enabled()
*/
function base_modules_enabled($modules) {
  $links = [];
  foreach ($modules as $module) {
    $module_links = module_invoke($module, 'operations_menu');
    if(is_array($module_links))
      $links = array_merge($links, $module_links);
  }
  foreach ($links as $link) {
    menu_link_save($link);
  }
}

implementing.module

/**
* Implements hook_operations_menu()
*/
function implementing_operations_menu() {
  $links = [];

  // Define menu links here

  return $links;
}

/**
 * Implements hook_menu()
 */
function implementing_menu(){
  $items = [];

  // Define menu callbacks, etc.

  return $items;
}

This strategy works well to maintain a modularized custom menu with one exception. For some reason, when enabling the implementing module, base_modules_enabled() is called before implementing_menu(). This is a problem since some menu links defined in implementing_operations_menu() depend on routing established in implementing_menu().

I've checked the source code, and module_enable() invokes hook_modules_enabled() at the very end. I don't understand how hook_menu() is getting called after hook_modules_enabled() and not before.

Any assistance is greatly appreciated!

1 Answer 1

1

So, here's the solution. Hopefully it helps save someone else some time. As it turns out, hook_menu() is not invoked during module enabling. As such, I had to force a menu rebuild which invokes hook_menu() and ensures all the proper routes exist prior to building my menu links.

base.module>

/**
* Implements hook_modules_enabled()
*/
function base_modules_enabled($modules) {
  menu_rebuild(); // <--- Added this line to force hook_menu() to be called first
  $links = [];
  foreach ($modules as $module) {
    $module_links = module_invoke($module, 'operations_menu');
    if(is_array($module_links))
      $links = array_merge($links, $module_links);
  }
  foreach ($links as $link) {
    menu_link_save($link);
  }
}

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.