You are here

og_menu.module in Organic Groups Menu (OG Menu) 7.3

Integrates Menu with Organic Groups. Lots of menu forms duplication in OG context.

File

og_menu.module
View source
<?php

/**
 * @file
 * Integrates Menu with Organic Groups.
 * Lots of menu forms duplication in OG context.
 */

/**
 * Implements hook_permission().
 */
function og_menu_permission() {
  return array(
    'administer og menu configuration' => array(
      'title' => t('Administer OG Menu configuration'),
      'description' => t('Grant access to the global OG Menu configuration.'),
    ),
    'administer og menu' => array(
      'title' => t('Administer OG menus'),
      'description' => t('Administer custom menus for all groups.'),
    ),
  );
}

/**
 * Implements hook_og_permission().
 */
function og_menu_og_permission() {
  return array(
    'administer og menu' => array(
      'title' => t('Administer OG menus'),
      'description' => t('Administer custom menus in the group context'),
    ),
  );
}

/**
 * Implements hook_og_ui_get_group_admin().
 *
 */
function og_menu_og_ui_get_group_admin($group_type, $gid) {
  $items = array();
  if (og_user_access($group_type, $gid, 'administer og menu')) {
    $items['menus'] = array(
      'title' => t('Menus'),
      'description' => t('Manage group menus.'),
      'href' => 'admin/menus',
    );
  }
  return $items;
}

/**
 * Implements hook_help().
 */
function og_menu_help($path, $arg) {
  if ($path == 'admin/structure/menu/og_menu' && !variable_get('og_menu_hide_help', FALSE)) {
    return '<p>' . t('Add new menus on the <a href="@menu">Menu administration page</a>.', array(
      '@menu' => url('admin/structure/menu'),
    )) . '</p>';
  }
  if ($path == 'group/%/%/admin/menus' && module_exists('block') && !variable_get('og_menu_hide_help', FALSE)) {
    if (!variable_get('og_menu_show_blocks', FALSE)) {
      return '<p>' . t('With the current setting, OG Menus will not be exposed as blocks on the blocks administration page. Use the OG Menu supplied menu blocks on the !blocks_page.', array(
        '!blocks_page' => l(t('Blocks administration page'), 'admin/structure/block'),
      )) . '</p>';
    }
    else {
      return '<p>' . t('Each menu has a corresponding block that is managed on the !blocks_page.', array(
        '!blocks_page' => l(t('Blocks administration page'), 'admin/structure/block'),
      )) . '</p>';
    }
  }
}

/**
 * Implements hook_menu().
 */
function og_menu_menu() {
  $items = array();
  $items['group/%/%/admin/menus'] = array(
    'title' => 'Menus',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_menu_overview_form',
      1,
      2,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
    ),
    'weight' => 10,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/list'] = array(
    'title' => 'List menus',
    'weight' => -10,
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['group/%/%/admin/menus/add'] = array(
    'title' => 'Add menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_edit_menu_form',
      'add',
      1,
      2,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'new-menu',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu'] = array(
    'title' => 'Customize menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_overview_form',
      1,
      2,
      5,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'list-menu',
      5,
    ),
    'type' => MENU_CALLBACK,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu/list'] = array(
    'title' => 'List links',
    'weight' => -10,
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'context' => MENU_CONTEXT_INLINE,
  );
  $items['group/%/%/admin/menus/%menu/add'] = array(
    'title' => 'Add link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_edit_item_form',
      'add',
      1,
      2,
      5,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'add-menu-item',
      5,
    ),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu/edit'] = array(
    'title' => 'Edit menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_edit_menu_form',
      'edit',
      1,
      2,
      5,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'edit-menu',
      5,
    ),
    'type' => MENU_LOCAL_TASK,
    'context' => MENU_CONTEXT_INLINE,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu/delete'] = array(
    'title' => 'Delete menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_delete_menu_confirm',
      5,
      1,
      2,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'delete-menu',
      5,
    ),
    'type' => MENU_CALLBACK,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu/item/%menu_link/edit'] = array(
    'title' => 'Edit menu link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_edit_item_form',
      'edit',
      1,
      2,
      5,
      7,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'edit-menu-item',
      5,
      7,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['group/%/%/admin/menus/%menu/item/%menu_link/delete'] = array(
    'title' => 'Delete menu link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_delete_item_form',
      7,
      1,
      2,
      5,
    ),
    'access callback' => 'og_menu_access',
    'access arguments' => array(
      1,
      2,
      'delete-menu-item',
      5,
      7,
    ),
    'type' => MENU_CALLBACK,
    'weight' => 1,
    'file' => 'og_menu.pages.inc',
  );
  $items['admin/config/group/og_menu'] = array(
    'title' => 'OG menu settings',
    'description' => 'Configuration for Organic groups menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_menu_config_form',
    ),
    'access arguments' => array(
      'administer og menu configuration',
    ),
    'file' => 'og_menu.admin.inc',
  );
  $items['admin/config/group/og_menu/settings'] = array(
    'title' => 'Settings',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['admin/structure/menu/og_menu'] = array(
    'title' => 'List OG menus',
    'description' => 'Add new organic groups menus to your site, edit existing ones, and rename and reorganize menu links.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'og_admin_menu_overview_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer menu',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'og_menu.pages.inc',
  );
  $items['og_menu/autocomplete'] = array(
    'page callback' => '_og_menu_autocomplete',
    'access arguments' => array(
      'og_menu_access',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_theme_registry_alter().
 */
function og_menu_theme_registry_alter(&$theme_registry) {
  $theme_registry['block']['theme paths'][] = drupal_get_path('module', 'og_menu');
}

/**
 * Implements hook_theme().
 */
function og_menu_theme() {
  return array(
    'og_menu_menu_overview_form' => array(
      'file' => 'og_menu.pages.inc',
      'render element' => 'form',
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function og_menu_block_info() {
  $blocks = array(
    'og_single_menu_block' => array(
      'info' => t('OG Menu : single'),
      'cache' => DRUPAL_NO_CACHE,
    ),
    'og_multi_menu_block' => array(
      'info' => t('OG Menu : multiple'),
      'cache' => DRUPAL_NO_CACHE,
    ),
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function og_menu_block_view($delta = '') {
  $block = array();
  $context = og_context();
  if ($delta == 'og_single_menu_block' && $context) {
    $menus = og_menu_get_group_menus(array(
      $context['group_type'] => array(
        $context['gid'],
      ),
    ));
    $menu = array_shift($menus);
    if ($menu) {
      if (variable_get('og_menu_block_links', FALSE)) {
        $block['subject'] = l($menu['title'], $menu['group_type'] . '/' . $menu['gid']);
      }
      else {
        $block['subject'] = check_plain($menu['title']);
      }
      $block['content'] = menu_tree($menu['menu_name']);

      // Add contextual links.
      if ($block['content']) {
        if (in_array($menu['menu_name'], array_keys(menu_get_menus()))) {
          $block['content']['#contextual_links']['og_menu'] = array(
            'group/' . $context['group_type'] . '/' . $context['gid'] . '/admin/menus',
            array(
              $menu['menu_name'],
            ),
          );
        }
      }
    }
  }
  elseif ($delta == 'og_multi_menu_block' && $context) {
    drupal_add_css(drupal_get_path('module', 'og_menu') . '/og_menu.css');
    $menus = og_menu_get_group_menus(array(
      $context['group_type'] => array(
        $context['gid'],
      ),
    ));
    $plural = count($menus) > 1 ? TRUE : FALSE;
    $block['content'] = array();
    foreach ($menus as $menu) {
      $title = check_plain($menu['title']);
      if (variable_get('og_menu_block_links', FALSE)) {
        $title = l($menu['title'], $menu['group_type'] . '/' . $menu['gid']);
      }
      if ($tree = menu_tree($menu['menu_name'])) {
        if ($plural) {
          $block['subject'] = '';
          if (!isset($block['content']['#markup'])) {
            $block['content']["#markup"] = '';
          }
          $block['content']["#markup"] .= '<div class="block-og-menu-inset">' . '<h2 class="block-title">' . $title . '</h2>' . render($tree) . '</div>';
        }
        else {
          $block['subject'] = $title;
          $tree = menu_tree($menu['menu_name']);
          $block['content'] = $tree;
        }
      }
    }

    // Add contextual links for first menu.
    // @TODO Find a proper solution for displaying contextual links for all menus.
    if ($block['content']) {
      if (!isset($block['content']['#contextual_links'])) {
        if (in_array($menu['menu_name'], array_keys(menu_get_menus()))) {
          $block['content']['#contextual_links']['og_menu'] = array(
            'group/' . $context['group_type'] . '/' . $context['gid'] . '/admin/menus',
            array(
              $menu['menu_name'],
            ),
          );
        }
      }
    }
  }
  return $block;
}

/**
 * Implements hook_field_extra_fields().
 */
function og_menu_field_extra_fields() {
  $extra = array();
  foreach (node_type_get_types() as $type) {
    if (og_is_group_type('node', $type->type)) {

      // We only need to enable OG Menu on group types.
      $extra['node'][$type->type] = array(
        'form' => array(
          'og_menu' => array(
            'label' => t('OG Menu'),
            'description' => t('Enable OG Menu'),
            'weight' => 0,
          ),
        ),
      );
    }
  }
  return $extra;
}

/**
 * Returns the current group context's nid.
 */
function og_menu_get_context() {
  $context = og_context();
  return isset($context['gid']) ? $context['gid'] : 0;
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * Alter the node form's menu form.
 * We modify the forms for group content and group content types.
 */
function og_menu_form_node_form_alter(&$form, &$form_state) {
  $type = $form['#node']->type;

  // Group type.
  if (og_is_group_type('node', $type)) {
    if (!variable_get('og_menu_hide_create_option', FALSE)) {
      $form['og_menu'] = array(
        '#type' => 'checkbox',
        '#title' => t('Enable menu for this group'),
        '#default_value' => $form['#node']->og_menu,
        '#description' => t('Check to create a menu for this group. Uncheck to delete all menus associated with this group.'),
      );

      // @todo If we're going to delete all of the groups menus,
      //       we should ask the user for confirmation

      //$form['#submit'][] = 'og_menu_group_form_validate';
    }
    else {
      $form['#node']->og_menu = TRUE;
    }
  }
  if (og_is_group_content_type('node', $type) && variable_get('og_menu_enable_' . $type, FALSE) && isset($form['#node']->storage['og_menu'])) {

    // Available menus were discovered in og_menu_node_prepare().
    $menus = $form['#node']->storage['og_menu'];
    $list = array();
    if (!empty($menus)) {
      $settings['mlid'] = empty($form['#node']->menu['mlid']) ? 0 : $form['#node']->menu['mlid'];
      $settings['administer_group'] = user_access('administer group');
      foreach ($menus as $menu) {
        $list[$menu['menu_name']] = $menu['title'];
        $settings['menus'][$menu['menu_name']] = $menu['gid'];
      }

      // Get the group audience fields so we can make the javascript aware of
      // them.
      $settings['group_audience_fields'] = array_keys(og_get_group_audience_fields('node', $type));
      $fields = array();
      foreach (og_get_group_audience_fields('node', $type) as $field_name => $label) {
        $field = field_info_field($field_name);
        $instance = field_info_instance('node', $field_name, $type);

        // Group the data we need in the client side js code.
        // Notice: 'default' is a reserved word in js, so we use 'normal' instead.
        // This is currently the only widget in OG.
        if ($instance['widget']['type'] == 'og_complex') {
          $default_selector = $field_name . '[' . $form[$field_name]['#language'] . '][0][default]';
          $admin_selector = $field_name . '[' . $form[$field_name]['#language'] . '][0][admin]';
          $fields[$field_name]['normal'] = $instance['settings']['behaviors']['og_widget']['default']['widget_type'];
          $fields[$field_name]['normal_selector'] = $default_selector;
          $fields[$field_name]['admin'] = $instance['settings']['behaviors']['og_widget']['admin']['widget_type'];
          $fields[$field_name]['admin_selector'] = $admin_selector;
        }
        else {
          $default_selector = $field_name . '[' . $form[$field_name]['#language'] . ']';
          $fields[$field_name]['normal'] = $instance['widget']['type'];
          $fields[$field_name]['normal_selector'] = $default_selector;
        }
        $fields[$field_name]['cardinality'] = $field['cardinality'];

        // Field is visible by default.
        $fields[$field_name]['visibility'] = TRUE;

        // When using entity reference pre-populate, the field may be hidden.
        $context = og_context();
        if (isset($context['group_type']) && isset($instance['settings']['behaviors']['prepopulate']['action']) && $instance['settings']['behaviors']['prepopulate']['action'] == 'hide' && $context['group_type'] == $field['settings']['target_type']) {
          $fields[$field_name]['visibility'] = $context['gid'];
        }
      }
      $settings['group_audience_fields'] = $fields;

      // Perhaps we want to exclude certain fields.
      drupal_alter('og_menu_audience_fields', $settings['group_audience_fields'], $type);

      // If user has administer menu permission, also show other menu options.
      $settings['standard_parent_options'] = array();
      if (user_access('administer menu')) {

        // Gets menus available to this content type.
        $type_menus = variable_get('menu_options_' . $type, array(
          'main-menu' => 'main-menu',
        ));
        $available_menus = array();

        // Get all existing menus with their name.
        $result = db_query("SELECT menu_name, title FROM {menu_custom} ORDER BY title");
        while ($menu = $result
          ->fetchObject()) {
          if (in_array($menu->menu_name, $type_menus)) {
            $available_menus[$menu->menu_name] = $menu->title;
          }
        }
        $settings['standard_parent_options'] = menu_parent_options($available_menus, $type);

        // We want to merge the menus the user has available anyway and the OG
        // ones.
        $merged_list = array_merge($available_menus, $list);
      }
      else {
        $merged_list = $list;
      }
      $link = $form['#node']->menu;

      // Menu parent options will format the list in a way Drupal expects and
      // give children, etc.
      $options = menu_parent_options($merged_list, array(
        'mlid' => 0,
      ));

      // If user does not have administer menu, this field set wont be created.
      if (!isset($form['menu'])) {
        if (empty($options)) {
          return;
        }
        _og_menu_add_menufieldset($form, $options);
      }
      $settings['parent_options'] = $options;
      if ($nid = $form['nid']['#value']) {
        $form['menu']['link']['parent']['#default_value'] = $link['menu_name'] . ':' . $link['plid'];
      }
      $form['menu']['#access'] = !empty($options);
      $form['menu']['#attached']['js'][] = drupal_get_path('module', 'og_menu') . '/og_menu.js';
      $form['menu']['#attached']['js'][] = array(
        'data' => array(
          'ogMenu' => $settings,
        ),
        'type' => 'setting',
      );
      $form['menu']['#settings'] = $merged_list;
      $form['menu']['link']['parent']['#options'] = $options;
      if (!user_access('administer menu')) {
        $form['#validate'][] = 'og_menu_node_form_validate';
      }
    }
  }
}

/**
 * Implements hook_form_FORMID_alter().
 */
function og_menu_form_menu_edit_menu_alter(&$form, &$form_state) {
  $types = node_type_get_types();
  $gtypes = array();
  foreach ($types as $type) {
    if (og_is_group_type('node', $type->type)) {
      $gtypes[] = $type->type;
    }
  }
  $types = $gtypes;
  if (count($types) > 0) {
    $options = array(
      '' => '--',
    );

    // Populate gids.
    if (user_access('administer group')) {
      $query = db_select('node', 'n');
      $query
        ->distinct();
      $query
        ->join('og_membership', 'og', 'n.nid = og.gid');
      $query
        ->fields('og', array(
        'gid',
      ));
      $query
        ->fields('n', array(
        'title',
      ));
      $result = $query
        ->execute();
      foreach ($result as $group) {
        $options[$group->gid] = $group->title;
      }
    }
    else {
      global $user;
      $gids = og_menu_get_node_groups('user', $user);
      $groups = node_load_multiple($gids);
      if (!empty($groups)) {
        foreach ($groups as $gid => $group) {
          $options[$gid] = $group->title;
        }
      }
    }
    $ogm = db_select('og_menu', 'gid')
      ->fields('gid')
      ->condition('menu_name', $form['menu_name']['#default_value'], '=')
      ->execute()
      ->fetchAssoc();
    $gid = $ogm['gid'];
    $og = $gid ? entity_load_single('node', $gid) : NULL;

    // Add menu og assignment to the form.
    switch (variable_get('og_menu_assignment', 'autocomplete')) {
      case 'autocomplete':
        $form['og_menu_gid'] = array(
          '#title' => t('Enable this menu for the following group'),
          '#type' => 'textfield',
          '#default_value' => !is_null($gid) ? $og->title . ' [gid:' . $gid . ']' : '',
          '#autocomplete_path' => 'og_menu/autocomplete',
        );
        break;
      case 'select':
        $form['og_menu_gid'] = array(
          '#title' => t('Enable this menu for the following group'),
          '#type' => 'select',
          '#options' => $options,
          '#default_value' => !is_null($gid) ? $gid : '',
          '#weight' => 1,
        );
        break;
    }
    if (!user_access('administer menu')) {
      $form['og_menu_gid']['#required'] = TRUE;
    }
    if (!isset($form['submit']['#weight'])) {
      $form['submit']['#weight'] = 2;
    }
    $form['#submit'][] = 'og_menu_edit_menu_form_submit';
  }
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * Integration with menu module for node type admin page.
 * Hides OG Menus from available menu settings.
 */
function og_menu_form_node_type_form_alter(&$form, &$form_state) {
  if (!variable_get('og_menu_show_nodetype', FALSE)) {

    // Remove OG Menus from the list by default.
    $query = db_select('menu_custom', 'mc');
    $query
      ->join('og_menu', 'ogm', 'ogm.menu_name = mc.menu_name');
    $query
      ->fields('mc', array(
      'menu_name',
    ));
    $result = $query
      ->execute()
      ->fetchCol();
    foreach ($result as $ogblock) {
      unset($form['menu']['menu_options']['#options'][$ogblock]);
    }
  }

  // Provide a setting to enable OG Menus on this content type.
  $form['menu']['og_menu_enable'] = array(
    '#type' => 'checkbox',
    '#title' => t("Enable for OG Menus"),
    '#default_value' => variable_get('og_menu_enable_' . $form['#node_type']->type, FALSE),
    '#description' => t("Allow nodes of this content type to be added to OG Menus."),
  );
  if (!og_is_group_content_type('node', $form['#node_type']->type)) {
    $form['menu']['og_menu_enable']['#description'] .= ' <strong>';
    $form['menu']['og_menu_enable']['#description'] .= t("This setting will not\n      have any effect until you enable this type as Group Content");
    $form['menu']['og_menu_enable']['#description'] .= '</strong>';
  }
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * Integration with Menu Position module for menu_position config page.
 * Hides OG Menus from available parent options settings.
 */
function og_menu_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'menu_position_add_rule_form' || $form_id == 'menu_position_edit_rule_form') {
    if (!variable_get('og_menu_show_menuposition', FALSE)) {
      $mlid = !empty($form_state['#menu-position-rule']['mlid']) ? $form_state['#menu-position-rule']['mlid'] : NULL;
      $menus = menu_get_menus();

      // @todo convert to new database api functions
      $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")
        ->fetchCol();
      foreach ($result as $ogblock) {
        unset($menus[$ogblock]);
      }

      // Parent menu item.
      if ($mlid) {
        $options = menu_parent_options($menus, menu_link_load($mlid));
      }
      else {
        $options = menu_parent_options($menus, array(
          'mlid' => 0,
        ));
      }
      $form['plid']['#options'] = $options;
    }
  }
}

/**
 * Implements hook_form_FORMID_alter().
 */
function og_menu_form_block_admin_display_form_alter(&$form, &$form_state) {

  // Only show og menu blocks on the block admin page if the user wants it.
  if (!variable_get('og_menu_show_blocks', FALSE)) {

    // @todo convert to new database api functions
    $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")
      ->fetchCol();
    foreach ($result as $ogblock) {
      unset($form['blocks']['menu_' . $ogblock]);
    }
  }
}

/**
 * Implements hook_form_FORMID_alter().
 */
function og_menu_form_menu_delete_menu_confirm_alter(&$form, &$form_state) {
  $form['#submit'][] = 'og_menu_delete_menu_confirm_submit';
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * Integration with homebox module.
 * Hides OG Menus from Homebox config page.
 */
function og_menu_form_homebox_admin_display_form_alter(&$form, &$form_state) {
  if (!variable_get('og_menu_show_homebox', FALSE)) {

    // @todo convert to new database api functions
    $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")
      ->fetchCol();
    foreach ($result as $ogblock) {
      unset($form['menu_' . $ogblock]);
    }
  }
}

/**
 * Implements hook_admin_menu_output_alter().
 *
 * Integration with admin_menu module.
 * Remove OG Menus from Admin Menu as this adds a lot of clutter.
 */
function og_menu_admin_menu_output_alter(&$content) {
  if (isset($content['menu']['admin/structure']['admin/structure/menu'])) {
    foreach ($content['menu']['admin/structure']['admin/structure/menu'] as $key => $menu) {
      if (preg_match('/^admin\\/structure\\/menu\\/manage\\/(\\S+)$/', $key, $matches)) {
        $result = db_query("SELECT distinct ogm.gid FROM {og_menu} as ogm where ogm.menu_name = :key", array(
          ':key' => $matches[1],
        ))
          ->fetchCol();
        if (isset($result[0])) {
          unset($content['menu']['admin/structure']['admin/structure/menu'][$key]);
        }
      }
    }
  }
}

/**
 * Implements hook_node_prepare().
 */
function og_menu_node_prepare($node) {
  $type = $node->type;

  // $node is a group type.
  if (og_is_group_type('node', $type)) {

    // New node.
    if (empty($node->nid)) {
      $node->og_menu = (bool) variable_get('og_menu_create_by_default', FALSE);
    }
    else {
      $menus = og_menu_get_group_menus(array(
        'node' => array(
          $node->nid,
        ),
      ));
      $node->og_menu = !empty($menus);
    }
  }

  // $node is a group content type.
  if (og_is_group_content_type('node', $type) && variable_get('og_menu_enable_' . $type, FALSE)) {
    $context = og_context();
    $menus = array();
    $groups = array();

    // Get all groups that have menus we can add links to.
    if (!variable_get('og_menu_context_limit', FALSE)) {
      $og_fields = og_get_group_audience_fields('node', $type);
      foreach ($og_fields as $field_name => $label) {
        $field = field_info_field($field_name);
        $target_type = $field['settings']['target_type'];

        // The handler delivers all available targets for each content type, skip
        // the ids if we already have that type's results.
        if (empty($groups[$target_type])) {
          $instance = field_info_instance('node', $field_name, $type);

          // Using the handler allows us to get user options from OG without
          // running through all the user's groups.
          $ids = entityreference_get_selection_handler($field, $instance)
            ->getReferencableEntities();
          if (!empty($ids)) {
            $field_gids = array();
            foreach ($ids as $key => $values) {
              $field_gids += $values;
            }

            // Users with global administer menu or administer og menu permission can access everything.
            if (!(user_access('administer menu') || user_access('administer og menu'))) {
              if (!empty($field_gids)) {
                foreach ($field_gids as $gid => $name) {

                  // Check if user has access to the specific menu
                  if (!og_user_access($target_type, $gid, 'administer og menu')) {
                    unset($field_gids[$gid]);
                  }
                }
              }
            }

            // Create an array similar to what og_get_entity_groups() returns.
            if (!empty($field_gids)) {
              $groups[$target_type] = array_keys($field_gids);
            }
          }
        }
      }
    }
    else {
      if (!empty($context)) {
        if (user_access('administer og menu') || og_user_access($context['group_type'], $context['gid'], 'administer og menu')) {
          $groups[$context['group_type']] = array(
            $context['gid'],
          );
        }
      }
    }

    // Get all menus for available groups.
    if (!empty($groups)) {
      $menus = og_menu_get_group_menus($groups);
    }

    // Store the menus for later use in form_alter and form_validate
    $node->storage['og_menu'] = $menus;

    // $node is not a new node and menu link is not set.
    if (!empty($node->nid) && empty($node->menu['link_title']) && !empty($menus)) {
      $menu_names = array();
      foreach ($menus as $menu) {
        $menu_names[] = $menu['menu_name'];
      }

      // This query comes from menu.modules node_prepare, and is how it does it.
      $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' AND menu_name IN (:type_menus) ORDER BY mlid ASC", 0, 1, array(
        ':path' => 'node/' . $node->nid,
        ':type_menus' => $menu_names,
      ))
        ->fetchField();
      if ($mlid) {

        // We've found something, so load the item and set that in the node
        // form.
        $item = menu_link_load($mlid);
        $options = menu_parent_options(array(
          $item['menu_name'],
        ), $item);
        if (!empty($options)) {
          $node->menu = $item;

          // Find the depth limit for the parent select.
          if (!isset($node->menu['parent_depth_limit'])) {
            $node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu);
          }
        }
      }
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function og_menu_node_insert($node) {
  if (og_is_group('node', $node)) {
    if (isset($node->og_menu) && $node->og_menu) {
      menu_save(array(
        'menu_name' => 'menu-og-' . $node->nid,
        'title' => $node->title,
        'description' => t('OG Menu for') . ' ' . check_plain($node->title),
      ));
      og_menu_update_menu('menu-og-' . $node->nid, $node->nid, 'node');
    }
  }
}

/**
 * Implements hook_node_update().
 */
function og_menu_node_update($node) {
  if (og_is_group('node', $node)) {
    if (isset($node->og_menu)) {
      if ($node->og_menu) {
        $menu = og_menu_get_group_menus(array(
          'node' => array(
            $node->nid,
          ),
        ));
        if (empty($menu)) {
          menu_save(array(
            'menu_name' => 'menu-og-' . $node->nid,
            'title' => $node->title,
            'description' => t('OG Menu for') . ' ' . check_plain($node->title),
          ));
          og_menu_update_menu('menu-og-' . $node->nid, $node->nid, 'node');
        }
      }
      else {

        // Delete the associated menus.
        // We can't assume that the menu name is 'menu-og-[gid]'.
        // we need to look up menus associated with this group.
        $result = db_select('og_menu', 'm')
          ->fields('m', array(
          'menu_name',
        ))
          ->condition('gid', $node->nid, '=')
          ->condition('group_type', 'node', '=')
          ->execute();
        while ($record = $result
          ->fetchAssoc()) {
          $menu = menu_load($record['menu_name']);
          menu_delete($menu);
          og_menu_delete_menu($record['menu_name']);
        }
      }
    }
  }
}

/**
 * Implements hook_node_delete().
 */
function og_menu_node_delete($node) {
  if (og_is_group_type('node', $node->type)) {

    /* We need to be careful here. As users can create menu of whatever name,
     * we can't just delete from menu_custom looking for 'menu-og-' . [gid]
     * we need the gid of the group being deleted, see if its an og associated
     * menu from og_menu and then from that menu name, delete it.
     */
    $result = db_select('og_menu', 'm')
      ->fields('m', array(
      'menu_name',
    ))
      ->condition('gid', $node->nid, '=')
      ->condition('group_type', 'node', '=')
      ->execute();
    while ($record = $result
      ->fetchAssoc()) {
      $menu = menu_load($record['menu_name']);
      menu_delete($menu);
      og_menu_delete_menu($record['menu_name']);
    }
  }
}

/**
 * Validation handler for OG group node forms.
 *
 * We will only end up here if we have confirmed that the node is a group type
 * content
 */
function og_menu_node_form_validate($form, &$form_state) {

  // If the user didn't ask for a menu, we have nothing to do.
  if (!isset($form_state['values']['menu']['enabled']) || $form_state['values']['menu']['enabled'] !== 1) {
    return;
  }

  // Available menus were discovered in og_menu_node_prepare().
  $menus = $form['#node']->storage['og_menu'];
  $parents = explode(':', $form_state['values']['menu']['parent']);
  $parent = $parents[0];
  $gids = array();
  $has_menu_access = FALSE;
  $group_is_set = FALSE;
  foreach (og_get_group_audience_fields('node', $form_state['values']['type']) as $field_name => $label) {
    if (isset($form_state['values'][$field_name][LANGUAGE_NONE])) {
      $group_is_set = TRUE;
      foreach ($form_state['values'][$field_name][LANGUAGE_NONE] as $item => $gid) {
        $gids[] = $gid['target_id'];
      }
    }
  }
  if (!$group_is_set) {

    // It's possible that the user doesn't have permission to change
    // the group audience once a piece of content has been created.
    // In this case, we need to look it up.
    $gids = og_get_entity_groups('node', $form_state['node']);
  }
  foreach ($menus as $menu) {
    if ($menu['menu_name'] == $parent) {

      // Check if user has access to the chosen menu parent.
      $has_menu_access = TRUE;

      // Check if menu belongs to one of the selected groups.
      if (!in_array($menu['gid'], $gids)) {
        form_set_error('og_groups', t('The menu you chose does not belong to the selected groups.'));
      }
    }
  }
  if (!$has_menu_access) {
    form_set_error('menu][parent', t('You cannot add menu links to this menu. Choose another parent menu.'));
  }
}

/**
 * Updates internal record of group's menu id.
 */
function og_menu_update_menu($menu_name, $gid, $group_type) {
  db_merge('og_menu')
    ->key(array(
    'menu_name' => $menu_name,
  ))
    ->fields(array(
    'gid' => $gid,
    'group_type' => $group_type,
  ))
    ->execute();
}

/**
 * Deletes menus for og menu table.
 */
function og_menu_delete_menu($menu_name) {
  db_delete('og_menu')
    ->condition('menu_name', $menu_name)
    ->execute();
}

/**
 * Returns accessible menus for a given user or gids in a structured array.
 *
 * @param array $groups
 *   An optional array of groups as returned by og_get_entity_groups().
 * @param StdClass $user
 *   An optional array of the user object.
 *
 * @return array
 *   A structured array with menus list.
 */
function og_menu_get_group_menus($groups = NULL, $user = NULL) {
  if (!isset($groups)) {
    $groups = og_get_entity_groups('user', $user);
  }
  $menus = array();
  $query = db_select('og_menu', 'om');
  $query
    ->join('menu_custom', 'm', 'om.menu_name = m.menu_name');
  $query
    ->fields('om', array(
    'gid',
    'group_type',
    'menu_name',
  ))
    ->fields('m', array(
    'title',
  ));
  $gids_condition = db_or();
  foreach ($groups as $group_type => $group_gids) {
    if (!empty($group_gids)) {

      // This should never be empty?
      $group_gids_condition = db_and()
        ->condition('om.gid', $group_gids, 'IN')
        ->condition('om.group_type', $group_type, '=');
      $gids_condition
        ->condition($group_gids_condition);
    }
  }
  if ($gids_condition
    ->count() > 0) {
    $query
      ->condition($gids_condition);
  }
  $query
    ->orderBy('weight', 'asc');
  $result = $query
    ->execute();
  while ($record = $result
    ->fetchAssoc()) {
    $menus[] = $record;
  }
  return $menus;
}

/**
 * Returns menus for a given gid and group_type in a structured array.
 *
 * @param $gid
 *   The group id.
 * @param $group_type
 *   The group type.
 *
 * @return array
 *   A structured array with menus list.
 */
function og_menu_get_menus($group_type, $gid) {

  // If function arguments are empty, return.
  if (empty($gid) || empty($group_type)) {
    return;
  }
  $q = db_select('og_menu', 'om');
  $q
    ->join('menu_custom', 'm', 'om.menu_name = m.menu_name');
  return $q
    ->fields('om', array(
    'gid',
    'menu_name',
  ))
    ->fields('m', array(
    'title',
    'description',
  ))
    ->fields('om', array(
    'weight',
  ))
    ->condition('om.group_type', $group_type)
    ->condition('om.gid', $gid)
    ->orderBy('om.weight')
    ->execute()
    ->fetchAllAssoc('menu_name');
}

/**
 * Access function.
 */
function og_menu_access($group_type, $gid, $op = NULL, $menu = NULL, $menu_item = NULL) {

  // Make sure that gid is id of an organic group.
  if (!og_is_group($group_type, $gid)) {
    return FALSE;
  }

  // Make sure that menu, is an og_menu-menu and belongs to the given group
  // of given group type.
  if ($menu) {
    $query = db_select('og_menu', 'ogm');
    $query
      ->condition('ogm.gid', $gid, '=');
    $query
      ->condition('ogm.menu_name', $menu['menu_name'], '=');
    $query
      ->condition('ogm.group_type', $group_type, '=');
    $count = $query
      ->countQuery()
      ->execute()
      ->fetchField();
    if (!$count) {
      return FALSE;
    }

    // Make sure, that menu-item is an item of the og_menu-menu.
    if ($menu_item && $menu['menu_name'] != $menu_item['menu_name']) {
      return FALSE;
    }
  }
  if (user_access('administer menu')) {
    return TRUE;
  }
  elseif (user_access('administer og menu') || og_user_access_entity('administer og menu', $group_type, $gid)) {
    if ($op == 'new-menu') {
      $query = db_select('og_menu', 'ogm');
      $query
        ->condition('ogm.gid', $gid, '=');
      $count = $query
        ->countQuery()
        ->execute()
        ->fetchField();
      $max = variable_get('og_menu_max_menus_per_group', 1);
      if ($max > 0 && $count >= $max) {
        return FALSE;
      }
      else {
        return TRUE;
      }
    }
    else {

      // Return true for all other cases edit menu, add/edit links.
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Generic redirect function.
 */
function og_menu_redirect($form, &$form_state) {
  $group_type = $form['og_menu_group_type']['#value'];
  $gid = $form['og_menu_gid']['#value'];
  $menu_name = $form['og_menu_name']['#value'];
  $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu_name;
}

/**
 * Submit handler used on various forms.
 */
function og_menu_edit_menu_form_submit($form, &$form_state) {
  $menu_name = $form_state['values']['menu_name'];
  $gid = $form_state['values']['og_menu_gid'];
  if (!empty($gid)) {

    // If this is a new menu.
    if ($form['#insert']) {
      $menu_name = 'menu-' . $menu_name;
    }
    if (is_numeric($gid)) {
      og_menu_update_menu($menu_name, $gid, 'node');
    }
    else {
      preg_match('/^(?:\\s*|(.*) )?\\[\\s*gid\\s*:\\s*(\\d+)\\s*\\]$/', $gid, $matches);
      if (!empty($matches)) {
        $gid = $matches[count($matches) - 1];
        if (is_numeric($gid)) {
          og_menu_update_menu($menu_name, $gid, 'node');
        }
      }
      else {
        drupal_set_message(t('Cannot assign menu to invalid group, please retry'), 'error');
      }
    }
  }
  else {
    db_delete('og_menu')
      ->condition('menu_name', $menu_name)
      ->execute();
  }
}

/**
 * Submit handler used on various forms.
 */
function og_menu_delete_menu_confirm_submit($form, &$form_state) {
  $menu = $form['#menu'];
  og_menu_delete_menu($menu['menu_name']);
}

/**
 * Submit handler used on various forms.
 */
function og_menu_delete_menu_confirm_submit_redirect($form, &$form_state) {
  $group_type = $form['og_menu_group_type']['#value'];
  $gid = $form['og_menu_gid']['#value'];
  $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus';
}

/**
 * Implements hook_menu_delete().
 *
 * Looks like og_menu did not used to catch the case where a menu item was
 * deleted in the admin area, and forgot to delete it's own db_record
 */
function og_menu_menu_delete($menu) {
  db_delete('og_menu')
    ->condition('menu_name', $menu['menu_name'])
    ->execute();
}

/**
 * Override menu.module's menu_overview_page().
 *
 * We do this so that we can filter out og_menu created menus from the listing
 * so that we don't flood the admin pages.
 *
 * @todo get this into og_menu_pages.inc
 */
function og_admin_standard_menu_overview_page() {
  $result = db_query("SELECT *\n                      FROM {menu_custom} mc\n                      WHERE NOT EXISTS (SELECT om.menu_name\n                      FROM {og_menu} om\n                      WHERE om.menu_name = mc.menu_name)\n                      ORDER BY title;", array(), array(
    'fetch' => PDO::FETCH_ASSOC,
  ));
  $header = array(
    t('Title'),
    array(
      'data' => t('Operations'),
      'colspan' => '3',
    ),
  );
  $rows = array();
  foreach ($result as $menu) {
    $row = array(
      theme('menu_admin_overview', array(
        'title' => $menu['title'],
        'name' => $menu['menu_name'],
        'description' => $menu['description'],
      )),
    );
    $row[] = array(
      'data' => l(t('list links'), 'admin/structure/menu/manage/' . $menu['menu_name']),
    );
    $row[] = array(
      'data' => l(t('edit menu'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/edit'),
    );
    $row[] = array(
      'data' => l(t('add link'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/add'),
    );
    $rows[] = $row;
  }
  return theme('table', array(
    'header' => $header,
    'rows' => $rows,
  ));
}

/**
 * Implements hook_menu_alter().
 *
 * We use this to override the /admin/structure/menu callback and replace it
 * with our own og_admin_menu_overview_page().
 */
function og_menu_menu_alter(&$items) {
  $items['admin/structure/menu']['page callback'] = 'og_admin_standard_menu_overview_page';
  $items['admin/structure/menu']['file'] = 'og_menu.module';
  $items['admin/structure/menu']['module'] = 'og_menu';
}

/**
 * Retrieve auto-complete suggestions for organic groups.
 */
function _og_menu_autocomplete($string) {
  $matches = array();
  $query = db_select('node', 'n');
  $query
    ->distinct();
  $query
    ->join('og_membership', 'og', 'n.nid = og.gid');
  $query
    ->fields('og', array(
    'gid',
  ));
  $query
    ->fields('n', array(
    'title',
  ));
  $query
    ->condition('n.title', '%' . db_like($string) . '%', 'LIKE');
  $query
    ->range(0, 10);
  $return = $query
    ->execute();
  foreach ($return as $row) {
    $matches[$row->title . " [gid:{$row->gid}]"] = '<div class="og-autocomplete">' . $row->title . '</div>';
  }

  // Return for json.
  drupal_json_output($matches);
}

/**
 * Return a list of node groups corresponding to nodes.
 *
 * @see og_get_entity_groups()
 *
 * @param string $group_type
 *   The entity type .eg node, user
 * @param object $object
 *   The object in question .eg node user
 *
 * @return array
 *   The gids corresponding to the criteria or empty
 */
function og_menu_get_node_groups($group_type, $object) {
  $groups = og_get_entity_groups($group_type, $object);
  if (!empty($groups['node'])) {
    $gids = $groups['node'];
  }
  else {
    $gids = array();
  }
  return $gids;
}

/**
 * Adds a standard menu fieldset to a form, mainly copied from menu.module.
 *
 * @param array $form
 *   The form we will add a menu field set to.
 * @param array $options
 */
function _og_menu_add_menufieldset(&$form, $options) {
  $link = $form['#node']->menu;
  $form['menu'] = array(
    '#type' => 'fieldset',
    '#title' => t('Menu settings'),
    '#collapsible' => TRUE,
    '#collapsed' => !$link['link_title'],
    '#group' => 'additional_settings',
    '#attached' => array(
      'js' => array(
        drupal_get_path('module', 'menu') . '/menu.js',
      ),
    ),
    '#tree' => TRUE,
    '#weight' => -2,
    '#attributes' => array(
      'class' => array(
        'menu-link-form',
      ),
    ),
  );
  $form['menu']['enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Provide a menu link'),
    '#default_value' => (int) (bool) $link['mlid'],
  );
  $form['menu']['link'] = array(
    '#type' => 'container',
    '#parents' => array(
      'menu',
    ),
    '#states' => array(
      'invisible' => array(
        'input[name="menu[enabled]"]' => array(
          'checked' => FALSE,
        ),
      ),
    ),
  );

  // Populate the element with the link data.
  foreach (array(
    'mlid',
    'module',
    'hidden',
    'has_children',
    'customized',
    'options',
    'expanded',
    'hidden',
    'parent_depth_limit',
  ) as $key) {
    $form['menu']['link'][$key] = array(
      '#type' => 'value',
      '#value' => $link[$key],
    );
  }
  $form['menu']['link']['link_title'] = array(
    '#type' => 'textfield',
    '#title' => t('Menu link title'),
    '#default_value' => $link['link_title'],
  );
  $form['menu']['link']['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Description'),
    '#default_value' => isset($link['options']['attributes']['title']) ? $link['options']['attributes']['title'] : '',
    '#rows' => 1,
    '#description' => t('Shown when hovering over the menu link.'),
  );
  $default = $link['mlid'] ? $link['menu_name'] . ':' . $link['plid'] : NULL;
  if (!isset($options[$default])) {
    $array = array_keys($options);
    $default = reset($array);
  }
  $form['menu']['link']['parent'] = array(
    '#type' => 'select',
    '#title' => t('Parent item'),
    '#default_value' => $default,
    '#options' => $options,
    '#attributes' => array(
      'class' => array(
        'menu-parent-select',
      ),
    ),
  );
  $form['menu']['link']['weight'] = array(
    '#type' => 'weight',
    '#title' => t('Weight'),
    '#delta' => 50,
    '#default_value' => $link['weight'],
    '#description' => t('Menu links with smaller weights are displayed before links with larger weights.'),
  );
}

Functions

Namesort descending Description
og_admin_standard_menu_overview_page Override menu.module's menu_overview_page().
og_menu_access Access function.
og_menu_admin_menu_output_alter Implements hook_admin_menu_output_alter().
og_menu_block_info Implements hook_block_info().
og_menu_block_view Implements hook_block_view().
og_menu_delete_menu Deletes menus for og menu table.
og_menu_delete_menu_confirm_submit Submit handler used on various forms.
og_menu_delete_menu_confirm_submit_redirect Submit handler used on various forms.
og_menu_edit_menu_form_submit Submit handler used on various forms.
og_menu_field_extra_fields Implements hook_field_extra_fields().
og_menu_form_alter Implements hook_form_FORMID_alter().
og_menu_form_block_admin_display_form_alter Implements hook_form_FORMID_alter().
og_menu_form_homebox_admin_display_form_alter Implements hook_form_FORMID_alter().
og_menu_form_menu_delete_menu_confirm_alter Implements hook_form_FORMID_alter().
og_menu_form_menu_edit_menu_alter Implements hook_form_FORMID_alter().
og_menu_form_node_form_alter Implements hook_form_FORMID_alter().
og_menu_form_node_type_form_alter Implements hook_form_FORMID_alter().
og_menu_get_context Returns the current group context's nid.
og_menu_get_group_menus Returns accessible menus for a given user or gids in a structured array.
og_menu_get_menus Returns menus for a given gid and group_type in a structured array.
og_menu_get_node_groups Return a list of node groups corresponding to nodes.
og_menu_help Implements hook_help().
og_menu_menu Implements hook_menu().
og_menu_menu_alter Implements hook_menu_alter().
og_menu_menu_delete Implements hook_menu_delete().
og_menu_node_delete Implements hook_node_delete().
og_menu_node_form_validate Validation handler for OG group node forms.
og_menu_node_insert Implements hook_node_insert().
og_menu_node_prepare Implements hook_node_prepare().
og_menu_node_update Implements hook_node_update().
og_menu_og_permission Implements hook_og_permission().
og_menu_og_ui_get_group_admin Implements hook_og_ui_get_group_admin().
og_menu_permission Implements hook_permission().
og_menu_redirect Generic redirect function.
og_menu_theme Implements hook_theme().
og_menu_theme_registry_alter Implements hook_theme_registry_alter().
og_menu_update_menu Updates internal record of group's menu id.
_og_menu_add_menufieldset Adds a standard menu fieldset to a form, mainly copied from menu.module.
_og_menu_autocomplete Retrieve auto-complete suggestions for organic groups.