All pastes #339556 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-02-04 04:34 UTC
rendered paste body
/**
 * Handles dynamic path translation and menu access control.
 * 
 * When a user arrives on a page such as node/5, this function determines
 * what "5" corresponds to, by inspecting the page's menu path definition,
 * node/[node_form_arg]. This will call node_form_arg(MENU_HANDLE_REQUEST, 5)
 * and get back the correspodning node object.
 *
 * It also works in reverse, to allow the display of tabs and menu items which
 * contain these dynamic arguments, translating node/[node_form_arg] to node/5.
 * 
 * @param $item
 *   A menu item object
 * @param $map
 *   An array of path arguments (ex: array('node', 5))
 * @param $operation
 *   The operation to perform:
 *   - MENU_HANDLE_REQUEST: An incoming page reqest; map to appropriate callback.
 *   - MENU_RENDER_LINK: Render an internal path as a link.
 *   - MENU_RENDER_TAB: Render an internal path as a tab.
 */
function _menu_access($item, $map, $direction = MENU_INCOMING) {
  $path = '';
  // Check if there are dynamic arguments in the path that need to be calculated.
  if ($item->replacements) {
    $replacements = unserialize($item->replacements);
    $path_map = ($direction == MENU_INCOMING) ? $map : explode('/', $item->path);
    foreach ($replacements as $index => $function) {
      // Translate place-holders into real values; for example, translate [user_current] to 5.
      if ($direction == MENU_OUTGOING) {
        if ($return = $function(MENU_OUTGOING, !empty($map[$index]) ? $map[$index] : '')) {
          $path_map[$index] = $return;
        }
      }
      // Map replacement value.
      $return = $function(MENU_INCOMING, !empty($path_map[$index]) ? $path_map[$index] : '');

      // If callback returned an error, trigger 404.
      if ($return === FALSE) {
        return array(FALSE, FALSE, '');
      }
      $map[$index] = $return;
    }
    // Re-join the path with the new replacement value.
    if ($direction == MENU_OUTGOING ) {
      $path = implode('/', $path_map);
    }
  }

  // Determine access callback, which will decide whether or not the current user has
  // access to this path.
  $callback = $item->access_callback;

  // Check for a blanket TRUE or FALSE.
  if (is_numeric($callback)) {
    return array($callback, $map, $path);
  }

  $arguments = menu_unserialize($item->access_arguments, $map);
  // As call_user_func_array is quite slow and user_access is a very common
  // callback, it is worth making a special case for it.
  if ($callback == 'user_access') {
    $access = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
    return array($access, $map, $path);
  }
  return array(call_user_func_array($callback, $arguments), $map, $path);
}