I was watching the development videos (Video: Developing farmOS) and it was mentioned briefly at the end of the first one that it is possible to have a page appear as a tab (i.e. alongside “Dashboard”, “Quick forms” and “Reports”). Is there a short example to work from or some documentation that would help me get started with adding such a tab for a custom module? Any pointers or nudges in the right direction would be appreciated. Thanks.
I think I figured this out… If it is of interest to anyone later the key insights were:
- Use the farm/reportsandfarm/quickmodules as a guide.
- In hook_menuuse:$items['farm/tabs'] = ...wheretabsis the name that appears in the URL.
- Changes to the hook_menumethod appear to require a module off/on cycle to take effect.
- Changes to the page callbackmethod are live and do not require a module off/on cycle.
Here is a minimum implementation of a new tab with 2 sub-tabs that can appear in the www/sites/all/modules/ directory.
<?php
/**
 * @file
 * Tab Test module.
 */
 function tab_test_permission() {
   return array(
     'view tab test' => array(
       'title' => t('View tab_test'),
     ),
     'configure tab test' => array(
       'title' => t('Configure tab_test'),
     ),
   );
 }
 function tab_test_farm_access_perms($role) {
   $perms = array();
   // Load the list of farm roles.
   $roles = farm_access_roles();
   // If this role has 'edit' access, allow them to see these tabs.
   if (!empty($roles[$role]['access']['edit'])) {
     $perms[] = 'view tab test';
   }
   // If this role has 'config' access, allow them to also configure tab test.
   if (!empty($roles[$role]['access']['config'])) {
     $perms[] = 'configure tab test';
   }
   return $perms;
 }
 /**
 * Implements hook_menu().
 */
function tab_test_menu() {
  $items = array();
  $items['farm/tabs'] = array(
    'title' => 'Tabs',
    'page callback' => 'tab_test_view',
    'access arguments' => array('view tab test'),
    'type' => MENU_LOCAL_TASK,
  );
  $items['farm/tabs/info'] = array(
    'title' => 'Info',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -100,
  );
  $items['farm/tabs/info2'] = array(
    'title' => 'Info2',
    'type' => MENU_LOCAL_TASK,
    'page callback' => 'tab_test_view2',
    'access arguments' => array('view tab test'),
    'weight' => 100,
  );
  return $items;
};
// Changes to the callback functions below are live.  
// The function for the callback set above requires a module off/on cycle.
function tab_test_view() {
  return t('Select a tab from the menu above.');
};
function tab_test_view2() {
  return t('Some different other stuff.');
};
Hi @braught - welcome to the farmOS forum!
Sounds like you figured it out. Well done! 
For future reference, the documentation for Drupal 7’s hook_menu() is available here: https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_menu/7.x
Changes to the
hook_menumethod appear to require a module off/on cycle to take effect.
The menu router item information is only read when Drupal has reason to believe changes have been made to it, and are then stored in the {menu_router} table for faster lookups. Enabling modules triggers this, as you noticed. You can also simply submit the modules form (/admin/module) without turning any off/on to achieve the same affect. Alternatively, if you have Drush installed, you can run drush cc menu.
Note: this all changes in Drupal 9 / farmOS 2.x (in active development), but the concepts are mostly the same. This might help when it comes time to upgrade: https://www.lullabot.com/articles/what-happened-to-hook_menu-in-drupal-8
Hope that helps! Thanks for sharing your lessons with the community!