1 admin_bar.inc admin_bar_tree_dynamic(array $expand_map)

Load menu link trees for router paths containing dynamic arguments.


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

Return value

An associative array whose keys are the parent paths of the menu router: paths given in $expand_map as well as the parent paths of any child link deeper down the tree. The parent paths are used in admin_bar_merge_tree() to check whether anything needs to be merged.

See also



core/modules/admin_bar/admin_bar.inc, line 183
Menu builder functions for Administration bar.


function admin_bar_tree_dynamic(array $expand_map) {
  $p_columns = array();
  for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) {
    $p_columns[] = 'p' . $i;

  // Fetch p* columns for all router paths to expand.
  $router_paths = array_keys($expand_map);
  $plids = db_select('menu_links', 'ml')
    ->fields('ml', $p_columns)
    ->condition('router_path', $router_paths)

  // Unlikely, but possible.
  if (empty($plids)) {
    return array();

  // Use queried plid columns to query sub-trees for the router paths.
  $query = db_select('menu_links', 'ml');
  $query->join('menu_router', 'm', 'ml.router_path = m.path');
    ->fields('m', array_diff(backdrop_schema_fields_sql('menu_router'), backdrop_schema_fields_sql('menu_links')));

  // The retrieved menu link trees have to be ordered by depth, so parents
  // always come before their children for the storage logic below.
  foreach ($p_columns as $column) {
    $query->orderBy($column, 'ASC');

  $db_or = db_or();
  foreach ($plids as $path_plids) {
    $db_and = db_and();
    // plids with value 0 may be ignored.
    foreach (array_filter($path_plids) as $column => $plid) {
      $db_and->condition($column, $plid);
  $result = $query
    ->fetchAllAssoc('mlid', PDO::FETCH_ASSOC);

  // Store dynamic links grouped by parent path for later merging and assign
  // placeholder expansion arguments.
  $tree_dynamic = array();
  foreach ($result as $mlid => $link) {
    // If contained in $expand_map, then this is a (first) parent, and we need
    // to store by the defined 'parent' path for later merging, as well as
    // provide the expansion map arguments to apply to the dynamic tree.
    if (isset($expand_map[$link['path']])) {
      $parent_path = $expand_map[$link['path']]['parent'];
      $link['expand_map'] = $expand_map[$link['path']]['arguments'];
    // Otherwise, just store this link keyed by its parent path; the expand_map
    // is automatically derived from parent paths.
    else {
      $parent_path = $result[$link['plid']]['path'];

    $tree_dynamic[$parent_path][] = $link;

  return $tree_dynamic;