You are here

function admin_menu_merge_tree in Administration menu 7.3

Same name and namespace in other branches
  1. 8.3 admin_menu.inc \admin_menu_merge_tree()

Walk through the entire menu tree and merge in expanded dynamic menu links.

Parameters

&$tree: A menu tree structure as returned by menu_tree_all_data().

$tree_dynamic: A dynamic menu tree structure as returned by admin_menu_tree_dynamic().

$expand_map: An array containing menu router path placeholder expansion argument mappings.

See also

hook_admin_menu_map()

admin_menu_tree_dynamic()

menu_tree_all_data()

1 call to admin_menu_merge_tree()
_admin_menu_tree in ./admin_menu.inc
Build the full administration menu tree from static and expanded dynamic items.

File

./admin_menu.inc, line 149
Menu builder functions for Administration menu.

Code

function admin_menu_merge_tree(array &$tree, array $tree_dynamic, array $expand_map) {
  foreach ($tree as $key => $data) {
    $path = $data['link']['router_path'];

    // Recurse into regular menu tree.
    if ($tree[$key]['below']) {
      admin_menu_merge_tree($tree[$key]['below'], $tree_dynamic, $expand_map);
    }

    // Nothing to merge, if this parent path is not in our dynamic tree.
    if (!isset($tree_dynamic[$path])) {
      continue;
    }

    // Add expanded dynamic items.
    foreach ($tree_dynamic[$path] as $link) {

      // If the dynamic item has custom placeholder expansion parameters set,
      // use them, otherwise keep current.
      if (isset($link['expand_map'])) {

        // If there are currently no expansion parameters, we may use the new
        // set immediately.
        if (empty($expand_map)) {
          $current_expand_map = $link['expand_map'];
        }
        else {

          // Otherwise we need to filter out elements that differ from the
          // current set, i.e. that are not in the same path.
          $current_expand_map = array();
          foreach ($expand_map as $arguments) {
            foreach ($arguments as $placeholder => $value) {
              foreach ($link['expand_map'] as $new_arguments) {

                // Skip the new argument if it doesn't contain the current
                // replacement placeholders or if their values differ.
                if (!isset($new_arguments[$placeholder]) || $new_arguments[$placeholder] != $value) {
                  continue;
                }
                $current_expand_map[] = $new_arguments;
              }
            }
          }
        }
      }
      else {
        if (!empty($current_expand_map)) {
          $expand_map = $current_expand_map;
        }
      }

      // Skip dynamic items without expansion parameters.
      if (empty($current_expand_map)) {
        continue;
      }

      // Expand anonymous to named placeholders.
      // @see _menu_load_objects()
      $path_args = explode('/', $link['path']);
      $load_functions = unserialize($link['load_functions']);
      if (is_array($load_functions)) {
        foreach ($load_functions as $index => $function) {
          if ($function) {
            if (is_array($function)) {
              $function = key($function);
            }

            // Add the loader function name minus "_load".
            $placeholder = '%' . substr($function, 0, -5);
            $path_args[$index] = $placeholder;
          }
        }
      }
      $path_dynamic = implode('/', $path_args);

      // Create new menu items using expansion arguments.
      foreach ($current_expand_map as $arguments) {

        // Create the cartesian product for all arguments and create new
        // menu items for each generated combination thereof.
        foreach (admin_menu_expand_args($arguments) as $replacements) {
          $newpath = strtr($path_dynamic, $replacements);

          // Skip this item, if any placeholder could not be replaced.
          // Faster than trying to invoke _menu_translate().
          if (strpos($newpath, '%') !== FALSE) {
            continue;
          }
          $map = explode('/', $newpath);
          $item = admin_menu_translate($link, $map);

          // Skip this item, if the current user does not have access.
          if (empty($item)) {
            continue;
          }

          // Build subtree using current replacement arguments.
          $new_expand_map = array();
          foreach ($replacements as $placeholder => $value) {
            $new_expand_map[$placeholder] = array(
              $value,
            );
          }
          admin_menu_merge_tree($item, $tree_dynamic, array(
            $new_expand_map,
          ));
          $tree[$key]['below'] += $item;
        }
      }
    }

    // Sort new subtree items.
    ksort($tree[$key]['below']);
  }
}