Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.362
diff -u -p -r1.362 menu.inc
--- includes/menu.inc	11 Nov 2009 08:28:50 -0000	1.362
+++ includes/menu.inc	11 Nov 2009 22:46:42 -0000
@@ -1446,7 +1446,20 @@ function theme_menu_local_task($variable
  */
 function theme_menu_local_action($variables) {
   $link = $variables['element']['#link'];
-  return '<li>' . l($link['title'], $link['href'], $link['localized_options']) . "</li>\n";
+
+  $output = '<li>';
+  if (isset($link['href'])) {
+    $output .= l($link['title'], $link['href'], isset($link['localized_options']) ? $link['localized_options'] : array());
+  }
+  elseif (!empty($link['localized_options']['html'])) {
+    $output .= $link['title'];
+  }
+  else {
+    $output .= check_plain($link['title']);
+  }
+  $output .= "</li>\n";
+
+  return $output;
 }
 
 /**
@@ -1798,6 +1811,10 @@ function menu_local_tasks($level = 0) {
       'root_path' => $root_path,
     );
   }
+  // @todo If there are no tabs, there can still be actions!
+  elseif (!empty($data['actions']['output'])) {
+    return array('actions' => $data['actions']) + $empty;
+  }
   return $empty;
 }
 
Index: modules/blog/blog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v
retrieving revision 1.341
diff -u -p -r1.341 blog.module
--- modules/blog/blog.module	8 Nov 2009 10:02:41 -0000	1.341
+++ modules/blog/blog.module	11 Nov 2009 21:39:07 -0000
@@ -125,6 +125,23 @@ function blog_menu() {
 }
 
 /**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function blog_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+  // Add "Create new blog entry" as local action.
+  if ($root_path == 'blog') {
+    $item = menu_get_item('node/add/blog');
+    if ($item['access']) {
+      $item['title'] = t('Create new blog entry');
+      $data['actions']['output'][] = array(
+        '#theme' => 'menu_local_action',
+        '#link' => $item,
+      );
+    }
+  }
+}
+
+/**
  * Access callback for user blog pages.
  */
 function blog_page_user_access($account) {
Index: modules/blog/blog.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.pages.inc,v
retrieving revision 1.24
diff -u -p -r1.24 blog.pages.inc
--- modules/blog/blog.pages.inc	1 Nov 2009 21:26:44 -0000	1.24
+++ modules/blog/blog.pages.inc	11 Nov 2009 21:35:24 -0000
@@ -70,15 +70,6 @@ function blog_page_last() {
   global $user;
   $build = array();
 
-  if (user_access('create blog content')) {
-    $items[] = l(t('Create new blog entry.'), "node/add/blog");
-    $build['blog_actions'] = array(
-      '#items' => $items,
-      '#theme' => 'item_list',
-      '#weight' => -1,
-    );
-  }
-
   $query = db_select('node', 'n')->extend('PagerDefault');
   $nids = $query
     ->fields('n', array('nid', 'sticky', 'created'))
Index: modules/blog/blog.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.test,v
retrieving revision 1.22
diff -u -p -r1.22 blog.test
--- modules/blog/blog.test	8 Nov 2009 10:02:41 -0000	1.22
+++ modules/blog/blog.test	11 Nov 2009 21:35:13 -0000
@@ -187,7 +187,7 @@ class BlogTestCase extends DrupalWebTest
     $this->assertResponse(200);
     $this->assertTitle('Blogs | Drupal', t('Blog page was displayed'));
     $this->assertText(t('Home'), t('Breadcrumbs were displayed'));
-    $this->assertLink(t('Create new blog entry.'));
+    $this->assertLink(t('Create new blog entry'));
 
     // Confirm a blog page was displayed per user.
     $this->drupalGet('blog/' . $user->uid);
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.532
diff -u -p -r1.532 forum.module
--- modules/forum/forum.module	8 Nov 2009 19:11:56 -0000	1.532
+++ modules/forum/forum.module	11 Nov 2009 22:44:33 -0000
@@ -134,6 +134,62 @@ function forum_menu() {
   return $items;
 }
 
+/**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+  global $user;
+
+  // Add "Post new [content-type]" links as local actions.
+  if ($root_path == 'forum') {
+    $tid = (isset($router_item['page_arguments'][0]) ? $router_item['page_arguments'][0] : 0);
+    $forums = forum_get_forums($tid);
+    $parents = taxonomy_get_parents_all($tid);
+    if ($forums || $parents) {
+      $vid = variable_get('forum_nav_vocabulary', 0);
+      $vocabulary = taxonomy_vocabulary_load($vid);
+
+      $links = array();
+      // Loop through all bundles for forum taxonomy vocabulary field.
+      $field = field_info_field('taxonomy_' . $vocabulary->machine_name);
+      foreach ($field['bundles']['node'] as $type) {
+        if (node_access('create', $type)) {
+          $links[$type] = array(
+            '#theme' => 'menu_local_action',
+            '#link' => array(
+              'title' => t('Post new @node_type', array('@node_type' => node_type_get_name($type))),
+              'href' => 'node/add/' . str_replace('_', '-', $type) . '/' . $tid,
+            ),
+          );
+        }
+      }
+      if (empty($links)) {
+        // Authenticated user does not have access to create new topics.
+        if ($user->uid) {
+          $links['disallowed'] = array(
+            '#theme' => 'menu_local_action',
+            '#link' => array(
+              'title' => t('You are not allowed to post new content in the forum.'),
+            ),
+          );
+        }
+        // Anonymous user does not have access to create new topics.
+        else {
+          $links['login'] = array(
+            '#theme' => 'menu_local_action',
+            '#link' => array(
+              'title' => t('<a href="@login">Login</a> to post new content in the forum.', array(
+                '@login' => url('user/login', array('query' => drupal_get_destination())),
+              )),
+              'localized_options' => array('html' => TRUE),
+            ),
+          );
+        }
+      }
+      $data['actions']['output'] = array_merge($data['actions']['output'], $links);
+    }
+  }
+}
 
 /**
  * Implement hook_init().
@@ -645,6 +701,11 @@ function forum_url_outbound_alter(&$path
  *   Array of object containing the forum information.
  */
 function forum_get_forums($tid = 0) {
+  $cache = &drupal_static(__FUNCTION__, array());
+
+  if (isset($cache[$tid])) {
+    return $cache[$tid];
+  }
 
   $forums = array();
   $vid = variable_get('forum_nav_vocabulary', 0);
@@ -706,6 +767,8 @@ function forum_get_forums($tid = 0) {
     $forums[$forum->tid] = $forum;
   }
 
+  $cache[$tid] = $forums;
+
   return $forums;
 }
 
@@ -844,32 +907,6 @@ function template_preprocess_forums(&$va
   drupal_set_title($title);
 
   if ($variables['forums_defined'] = count($variables['forums']) || count($variables['parents'])) {
-    // Format the "post new content" links listing.
-    $forum_types = array();
-
-    // Loop through all bundles for forum taxonomy vocabulary field.
-    $field = field_info_field('taxonomy_' . $vocabulary->machine_name);
-    foreach ($field['bundles']['node'] as $type) {
-      // Check if the current user has the 'create' permission for this node type.
-      if (node_access('create', $type)) {
-        // Fetch the "General" name of the content type;
-        // Push the link with title and url to the array.
-        $forum_types[$type] = array('title' => t('Post new @node_type', array('@node_type' => node_type_get_name($type))), 'href' => 'node/add/' . str_replace('_', '-', $type) . '/' . $variables['tid']);
-      }
-    }
-
-    if (empty($forum_types)) {
-      // The user is logged-in; but denied access to create any new forum content type.
-      if ($user->uid) {
-        $forum_types['disallowed'] = array('title' => t('You are not allowed to post new content in the forum.'));
-      }
-      // The user is not logged-in; and denied access to create any new forum content type.
-      else {
-        $forum_types['login'] = array('title' => t('<a href="@login">Login</a> to post new content in the forum.', array('@login' => url('user/login', array('query' => drupal_get_destination())))), 'html' => TRUE);
-      }
-    }
-    $variables['links'] = $forum_types;
-
     if (!empty($variables['forums'])) {
       $variables['forums'] = theme('forum_list', $variables);
     }
@@ -903,8 +940,7 @@ function template_preprocess_forums(&$va
 
   }
   else {
-    drupal_set_title(t('No forums defined'), PASS_THROUGH);
-    $variables['links'] = array();
+    drupal_set_title(t('No forums defined'));
     $variables['forums'] = '';
     $variables['topics'] = '';
   }
Index: modules/forum/forums.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forums.tpl.php,v
retrieving revision 1.6
diff -u -p -r1.6 forums.tpl.php
--- modules/forum/forums.tpl.php	9 Oct 2009 00:59:59 -0000	1.6
+++ modules/forum/forums.tpl.php	11 Nov 2009 21:42:05 -0000
@@ -7,9 +7,6 @@
  * containers as well as forum topics.
  *
  * Variables available:
- * - $links: An array of links that allow a user to post new forum topics.
- *   It may also contain a string telling a user they must log in in order
- *   to post.
  * - $forums: The forums to display (as processed by forum-list.tpl.php)
  * - $topics: The topics to display (as processed by forum-topic-list.tpl.php)
  * - $forums_defined: A flag to indicate that the forums are configured.
@@ -20,7 +17,6 @@
 ?>
 <?php if ($forums_defined): ?>
 <div id="forum">
-  <?php print theme('links', array('links' => $links)); ?>
   <?php print $forums; ?>
   <?php print $topics; ?>
 </div>
Index: modules/node/node.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v
retrieving revision 1.76
diff -u -p -r1.76 node.admin.inc
--- modules/node/node.admin.inc	3 Nov 2009 05:27:18 -0000	1.76
+++ modules/node/node.admin.inc	11 Nov 2009 21:23:41 -0000
@@ -391,11 +391,6 @@ function node_admin_content($form, $form
   if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
     return node_multiple_delete_confirm($form, $form_state, array_filter($form_state['values']['nodes']));
   }
-  // Show the 'add new content' link.
-  $form['add_content'] = array(
-    '#access' => _node_add_access(),
-    '#markup' => theme('links', array('links' => array(array('title' => t('Add new content'), 'href' => 'node/add')), 'attributes' => array('class' => array('action-links')))),
-  );
   $form[] = node_filter_form();
   $form['#submit'][] = 'node_filter_form_submit';
   $form['#theme'] = 'node_filter_form';
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1166
diff -u -p -r1.1166 node.module
--- modules/node/node.module	8 Nov 2009 10:02:41 -0000	1.1166
+++ modules/node/node.module	11 Nov 2009 21:28:25 -0000
@@ -1920,6 +1920,22 @@ function node_menu() {
 }
 
 /**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function node_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+  // Add "Add new content" as local action.
+  if ($root_path == 'admin/content') {
+    $item = menu_get_item('node/add');
+    if ($item['access']) {
+      $data['actions']['output'][] = array(
+        '#theme' => 'menu_local_action',
+        '#link' => $item,
+      );
+    }
+  }
+}
+
+/**
  * Title callback for a node type.
  */
 function node_type_page_title($type) {
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.537
diff -u -p -r1.537 taxonomy.module
--- modules/taxonomy/taxonomy.module	11 Nov 2009 17:10:49 -0000	1.537
+++ modules/taxonomy/taxonomy.module	11 Nov 2009 21:55:05 -0000
@@ -599,6 +599,12 @@ function taxonomy_get_parents($tid, $key
  * Find all ancestors of a given term ID.
  */
 function taxonomy_get_parents_all($tid) {
+  $cache = &drupal_static(__FUNCTION__, array());
+
+  if (isset($cache[$tid])) {
+    return $cache[$tid];
+  }
+
   $parents = array();
   if ($term = taxonomy_term_load($tid)) {
     $parents[] = $term;
@@ -608,6 +614,9 @@ function taxonomy_get_parents_all($tid) 
       $n++;
     }
   }
+
+  $cache[$tid] = $parents;
+
   return $parents;
 }
 
