Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.369
diff -u -r1.369 menu.inc
--- includes/menu.inc	17 Dec 2009 13:10:18 -0000	1.369
+++ includes/menu.inc	29 Dec 2009 21:52:02 -0000
@@ -337,19 +337,24 @@
  * is '12345', 1 will be replaced with '12345'. So the result will
  * be array('node_load', '12345').
  *
- * @param @data
+ * @param $data
  *   A serialized array.
- * @param @map
+ * @param $map
  *   An array of potential replacements.
+ * @param $callback_context
+ *   A string value to use for the %context placeholder argument.
  * @return
  *   The $data array unserialized and mapped.
  */
-function menu_unserialize($data, $map) {
+function menu_unserialize($data, $map, $callback_context = NULL) {
   if ($data = unserialize($data)) {
     foreach ($data as $k => $v) {
       if (is_int($v)) {
         $data[$k] = isset($map[$v]) ? $map[$v] : '';
       }
+      elseif ($v === '%context') {
+        $data[$k] = $callback_context;
+      }
     }
     return $data;
   }
@@ -411,7 +416,8 @@
       ->addTag('menu_get_item')
       ->execute()->fetchAssoc();
     if ($router_item) {
-      $map = _menu_translate($router_item, $original_map);
+      $callback_context = ($path == $_GET['q']) ? 'page' : NULL;
+      $map = _menu_translate($router_item, $original_map, $callback_context);
       $router_item['original_map'] = $original_map;
       if ($map === FALSE) {
         $router_items[$path] = FALSE;
@@ -419,8 +425,8 @@
       }
       if ($router_item['access']) {
         $router_item['map'] = $map;
-        $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map), array_slice($map, $router_item['number_parts']));
-        $router_item['theme_arguments'] = array_merge(menu_unserialize($router_item['theme_arguments'], $map), array_slice($map, $router_item['number_parts']));
+        $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map, $callback_context), array_slice($map, $router_item['number_parts']));
+        $router_item['theme_arguments'] = array_merge(menu_unserialize($router_item['theme_arguments'], $map, $callback_context), array_slice($map, $router_item['number_parts']));
       }
     }
     $router_items[$path] = $router_item;
@@ -557,10 +563,12 @@
  *   A menu router or menu link item
  * @param $map
  *   An array of path arguments (ex: array('node', '5'))
+ * @param $callback_context
+ *   A string value to use for the %context placeholder argument.
  * @return
  *   $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.
  */
-function _menu_check_access(&$item, $map) {
+function _menu_check_access(&$item, $map, $callback_context = NULL) {
   // Determine access callback, which will decide whether or not the current
   // user has access to this path.
   $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
@@ -569,7 +577,7 @@
     $item['access'] = (bool)$callback;
   }
   else {
-    $arguments = menu_unserialize($item['access_arguments'], $map);
+    $arguments = menu_unserialize($item['access_arguments'], $map, $callback_context);
     // 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') {
@@ -597,6 +605,8 @@
  * @param $link_translate
  *   TRUE if we are translating a menu link item; FALSE if we are
  *   translating a menu router item.
+ * @param $callback_context
+ *   A string value to use for the %context placeholder argument.
  * @return
  *   No return value.
  *   $item['title'] is localized according to $item['title_callback'].
@@ -606,7 +616,7 @@
  *   When doing link translation and the $item['options']['attributes']['title']
  *   (link title attribute) matches the description, it is translated as well.
  */
-function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
+function _menu_item_localize(&$item, $map, $link_translate = FALSE, $callback_context = NULL) {
   $callback = $item['title_callback'];
   $item['localized_options'] = $item['options'];
   // All 'class' attributes are assumed to be an array during rendering, but
@@ -639,7 +649,7 @@
         $item['title'] = $callback($item['title']);
       }
       else {
-        $item['title'] = call_user_func_array($callback, menu_unserialize($item['title_arguments'], $map));
+        $item['title'] = call_user_func_array($callback, menu_unserialize($item['title_arguments'], $map, $callback_context));
       }
       // Avoid calling check_plain again on l() function.
       if ($callback == 'check_plain') {
@@ -683,6 +693,8 @@
  * @param $to_arg
  *   Execute $item['to_arg_functions'] or not. Use only if you want to render a
  *   path from the menu table, for example tabs.
+ * @param $callback_context
+ *   A string value to use for the %context placeholder argument.
  * @return
  *   Returns the map with objects loaded as defined in the
  *   $item['load_functions']. $item['access'] becomes TRUE if the item is
@@ -690,7 +702,7 @@
  *   If an error occurs during calling the load_functions (like trying to load
  *   a non existing node) then this function return FALSE.
  */
-function _menu_translate(&$router_item, $map, $to_arg = FALSE) {
+function _menu_translate(&$router_item, $map, $to_arg = FALSE, $callback_context = NULL) {
   if ($to_arg && !empty($router_item['to_arg_functions'])) {
     // Fill in missing path elements, such as the current uid.
     _menu_link_map_translate($map, $router_item['to_arg_functions']);
@@ -713,11 +725,11 @@
   }
   $router_item['href'] = implode('/', $link_map);
   $router_item['options'] = array();
-  _menu_check_access($router_item, $map);
+  _menu_check_access($router_item, $map, $callback_context);
 
   // For performance, don't localize an item the user can't access.
   if ($router_item['access']) {
-    _menu_item_localize($router_item, $map);
+    _menu_item_localize($router_item, $map, FALSE, $callback_context);
   }
 
   return $map;
@@ -794,11 +806,11 @@
         $item['access'] = FALSE;
         return FALSE;
       }
-      _menu_check_access($item, $map);
+      _menu_check_access($item, $map, 'link');
     }
     // For performance, don't localize a link the user can't access.
     if ($item['access']) {
-      _menu_item_localize($item, $map, TRUE);
+      _menu_item_localize($item, $map, TRUE, 'link');
     }
   }
 
@@ -1680,7 +1692,7 @@
     $root_path = $router_item['path'];
 
     foreach ($result as $item) {
-      _menu_translate($item, $map, TRUE);
+      _menu_translate($item, $map, TRUE, 'local task');
       if ($item['tab_parent']) {
         // All tabs, but not the root page.
         $children[$item['tab_parent']][$item['path']] = $item;
@@ -1899,7 +1911,7 @@
     $key = drupal_substr($item['path'], $parent_length);
 
     // Denormalize and translate the contextual link.
-    _menu_translate($item, $map, TRUE);
+    _menu_translate($item, $map, TRUE, 'contextual link');
     if (!$item['access']) {
       continue;
     }
