/** * 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 indexes => path arguments. (ex: array(tracker, 5)) * @param $direction * The direction in which the menu item is coming; either: * - MENU_INCOMING: The path that is currently being loaded. * - MENU_OUTGOING: A path that needs to be shown to the user. */ 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); }