You are here

function menu_select_form_alter in Menu Select 7

Implements hook_form_alter().

File

./menu_select.module, line 36
Expands the node menu select field functionality by adding filters and an expandable hierarchy.

Code

function menu_select_form_alter(&$form, &$form_state) {

  // Target the Menu Position form and parent
  if (module_exists('menu_position') && ($form['#id'] == 'menu-position-add-rule-form' || $form['#id'] == 'menu-position-edit-rule-form')) {
    $menu_select_form =& $form;
    $menu_select_parent =& $form['plid'];
  }

  // Target the Menu Item form and parent
  if ($form['#id'] == 'menu-edit-item' && isset($form['parent'])) {
    $menu_select_form =& $form;
    $menu_select_parent =& $form['parent'];
  }

  // Target any form that contains menu, menu link, and menu link parent
  if (isset($form['menu']) && isset($form['menu']['link']) && isset($form['menu']['link']['parent'])) {
    $menu_select_form =& $form['menu']['link'];
    $menu_select_parent =& $form['menu']['link']['parent'];
  }
  if (isset($menu_select_form) && isset($menu_select_parent)) {
    $items =& $menu_select_parent;
    $menu = array();

    // The array of nested menu items
    $map = array();

    // An mkey to title lookup
    $depth = 0;

    // Array of pointers for accessing previous depths of the 2d array.
    // $pointers[0] will always point to $menu and the pointer at $pointer[1]
    // will always be a root item
    $pointers = array();
    $pointers[] =& $menu;

    // Iterate through the flat array and try to parse out a multi-dimensional structure
    foreach ($items['#options'] as $mkey => $label) {

      // Process root item labels
      if (strpos($label, '<') === 0) {
        $label = substr($label, 1, strlen($label) - 2);
      }

      // Ascertain depth by the number of dashes before the label.
      // None is root/1, two is first level/2, etc
      $parts = explode(' ', $label);
      if (count($parts) > 1 && $parts[0][1] === '-') {
        $new_depth = substr_count($parts[0], '-') / 2 + 1;
      }
      else {
        $new_depth = 1;
      }

      // Insert menu items into the $menu array using the appropriate pointer
      if ($new_depth > $depth) {

        // Inserting a new child item
        $pointers[$new_depth - 1][$mkey] = array();
        $pointers[] =& $pointers[$depth][$mkey];
      }
      elseif ($new_depth < $depth) {

        // Going up ($depth - $new_depth) level(s) and inserting a sibling
        $pointers = array_slice($pointers, 0, $new_depth);
        $pointers[$new_depth - 1][$mkey] = array();
        $pointers[] =& $pointers[$new_depth - 1][$mkey];
      }
      else {

        // Inserting a sibling
        $pointers[$new_depth - 1][$mkey] = array();

        // Change the pointer at this level so if the next item is a child it's inserted under this item
        $pointers[$depth] =& $pointers[$new_depth - 1][$mkey];
      }
      $map[$mkey] = trim(substr($label, ($new_depth - 1) * 2));
      $depth = $new_depth;
    }

    //_menu_select_debug_tree($menu, $map);
    $cut_off = variable_get('menu_select_cut_off', 30);
    $menu_options = array();
    foreach ($menu as $mkey => $children) {
      $menu_options[$mkey] = $map[$mkey];
    }

    // Set the default menu
    $default_menu = key($menu_options);

    // Change the default menu if the menu item belongs to a menu that isn't the default
    if (isset($items['#default_value']) && !empty($items['#default_value'])) {
      $default_value = explode(':', $items['#default_value']);
      $default_value = $default_value[0] . ':0';
      if (array_key_exists($default_value, $menu_options)) {
        $default_menu = $default_value;
      }
    }
    $menu_select_form['#attached']['js'][] = drupal_get_path('module', 'menu_select') . '/js/menu_select.js';
    $menu_select_form['#attached']['js'][] = array(
      'data' => array(
        'menu_select' => compact('menu', 'map', 'cut_off'),
      ),
      'type' => 'setting',
    );
    $menu_select_form['#attached']['css'][] = drupal_get_path('module', 'menu_select') . '/css/menu_select_icons.css';
    $menu_select_form['#attached']['css'][] = drupal_get_path('module', 'menu_select') . '/css/menu_select.css';

    // For debugging purposes

    /*
    $menu_select_form['#collapsed'] = false;
    $menu_select_form['#enabled']['#default_value'] = 1;
    $menu_select_form['#enabled']['#value'] = 1;
    $menu_select_form['#states']['invisible']['input[name="menu[enabled]"']['checked'] = true;
    */

    // Give everything a weight so we can insert our parent select widget in where Parent item should be
    $weight = 0;
    foreach ($menu_select_form as &$item) {
      if (is_array($item) && isset($item['#type'])) {
        $item['#weight'] = ++$weight;
      }
    }

    // Push actions to the bottom again
    $menu_select_form['actions']['#weight'] = $weight + 51;

    // Add a custom class to the existing menu parent select
    $menu_select_parent['#attributes']['class'][] = 'menu-select-menu-parent';

    // Build new form element
    $menu_select_form['menu_select'] = array(
      '#type' => 'fieldset',
      '#title' => t('Parent item'),
      '#collapsible' => FALSE,
      '#collapsed' => FALSE,
      '#weight' => $menu_select_parent['#weight'],
      '#attributes' => array(
        'class' => array(
          'element-invisible',
          'menu-select-menu-select',
        ),
      ),
      'preview' => array(
        '#type' => 'item',
        '#title' => t('Menu link position'),
        '#markup' => '<span class="menu-select-parent-menu-title" title="' . $default_menu . '">' . $map[$default_menu] . '</span> / <span class="menu-select-position-preview"></span> <span class="current-menu-item">' . t('Current menu item') . '</span>',
        '#description' => t('Preview of the menu item\'s hierarchy compared to its parent(s).'),
      ),
      'select_menu_link_position' => array(
        '#type' => 'fieldset',
        '#title' => t('Select menu link position'),
        '#collapsible' => FALSE,
        '#collapsed' => FALSE,
        '#attributes' => array(
          'class' => array(
            'menu-select-select-menu-link-position',
          ),
        ),
        'parent_menu' => array(
          '#type' => 'select',
          '#title' => t('Menu'),
          '#options' => $menu_options,
          '#description' => t('Select which menu you would like this item to belong to.'),
          '#default_value' => $default_menu,
          '#attributes' => array(
            'class' => array(
              'menu-select-parent-menu',
            ),
          ),
        ),
        'parent_menu_item' => array(
          '#type' => 'item',
          '#title' => t('Menu hierarchy'),
          '#markup' => '<div class="menu-select-menu-hierarchy"></div>',
          '#description' => t('Select the menu item\'s parent from the hierarchy above.'),
        ),
      ),
    );
    if (variable_get('menu_select_search_enabled', 0) === 1) {
      if (isset($form['type']['#value'])) {
        $type = $form['type']['#value'];
      }
      else {
        $type = '';
      }
      $menu_select_form['menu_select']['select_menu_link_position']['parent_menu_item_search'] = array(
        '#type' => 'textfield',
        '#title' => t('Search'),
        '#autocomplete_path' => 'menu-select/autocomplete/' . $type,
        '#description' => 'Alternatively, use this autocomplete search to find the menu item\'s parent and select it.',
        '#attributes' => array(
          'class' => array(
            'menu-select-parent-menu-item-search',
          ),
        ),
      );
    }
  }
}