? 301902_where_is_my_content.patch
? drushrc.php
? sites/all/modules
? sites/all/themes
? sites/default/files
? sites/default/settings.php
Index: modules/node/node.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v
retrieving revision 1.37
diff -u -p -r1.37 node.admin.inc
--- modules/node/node.admin.inc	19 Jan 2009 10:46:51 -0000	1.37
+++ modules/node/node.admin.inc	31 Jan 2009 06:44:31 -0000
@@ -166,8 +166,11 @@ function node_filters() {
 
 /**
  * Build query for node administration filters based on session.
+ *
+ * @param $for_user
+ *  TRUE if building a list of nodes owned by the current user.
  */
-function node_build_filter_query() {
+function node_build_filter_query($for_user) {
   $filters = node_filters();
 
   // Build query
@@ -195,6 +198,13 @@ function node_build_filter_query() {
     }
     $args[] = $value;
   }
+
+  // Filter for a specific user at 'My content'.
+  if ($for_user) {
+    $where[] = 'n.uid = %d';
+    $args[] = $GLOBALS['user']->uid;
+  }
+
   $where = count($where) ? 'WHERE ' . implode(' AND ', $where) : '';
 
   return array('where' => $where, 'join' => $join, 'args' => $args);
@@ -254,6 +264,12 @@ function node_filter_form() {
     $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
   }
 
+  $form['filters']['my_content'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Restrict to only my content.'),
+    '#default_value' => 1,
+  );
+
   drupal_add_js('misc/form.js');
 
   return $form;
@@ -303,6 +319,7 @@ function theme_node_filters($form) {
   $output .= '</dl>';
   $output .= '<div class="container-inline" id="node-admin-buttons">' . drupal_render($form['buttons']) . '</div>';
   $output .= '</li></ul>';
+  $output .= drupal_render($form['my_content']);
 
   return $output;
 }
@@ -440,30 +457,38 @@ function _node_mass_update_batch_finishe
 
 /**
  * Menu callback: content administration.
+ *
+ * @param $for_user
+ *   TRUE if building a list of nodes owned by the current user.
  */
-function node_admin_content($form_state) {
+function node_admin_content($form_state, $for_user = FALSE) {
   if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
     return node_multiple_delete_confirm($form_state, array_filter($form_state['values']['nodes']));
   }
   $form = node_filter_form();
 
   $form['#theme'] = 'node_filter_form';
-  $form['admin'] = node_admin_nodes();
+  $form['admin'] = node_admin_nodes($for_user);
 
   return $form;
 }
 
 /**
  * Form builder: Builds the node administration overview.
+ *
+ * @param $for_user
+ *   TRUE if building a list of nodes owned by the current user.
  */
-function node_admin_nodes() {
+function node_admin_nodes($for_user = FALSE) {
   // Enable language column if translation module is enabled
   // or if we have any node with language.
-  $multilanguage = (module_exists('translation') || db_result(db_query("SELECT COUNT(*) FROM {node} WHERE language != ''")));
+  $multilanguage = (module_exists('translation') || db_query("SELECT COUNT(*) FROM {node} WHERE language != ''")->fetchField());
 
   // Build the sortable table header.
   $header = array();
-  $header[] = theme('table_select_header_cell');
+  if (user_access('administer nodes') && user_access('bypass node access')) {
+    $header[] = theme('table_select_header_cell');
+  }
   $header[] = array('data' => t('Title'), 'field' => 'n.title');
   $header[] = array('data' => t('Type'), 'field' => 'n.type');
   $header[] = array('data' => t('Author'), 'field' => 'u.name');
@@ -480,10 +505,11 @@ function node_admin_nodes() {
   );
 
   // Build the query and load the nodes we want to display.
-  $filter = node_build_filter_query();
+  $filter = node_build_filter_query($for_user);
 
   $sort = tablesort_sql($header, '', 'n.changed DESC');
-  $result = pager_query(db_rewrite_sql('SELECT n.*, u.name FROM {node} n '. $filter['join'] .' INNER JOIN {users} u ON n.uid = u.uid '. $filter['where'] . $sort), 50, 0, NULL, $filter['args']);
+  $nids = pager_query(db_rewrite_sql('SELECT n.nid FROM {node} n ' . $filter['join'] . $filter['where'] . $sort), 50, 0, NULL, $filter['args'])->fetchCol();
+  $nodes = node_load_multiple($nids);
 
   // Build the 'Update options' form.
   $form['options'] = array(
@@ -491,6 +517,7 @@ function node_admin_nodes() {
     '#title' => t('Update options'),
     '#prefix' => '<div class="container-inline">',
     '#suffix' => '</div>',
+    '#access' => user_access('administer nodes') && user_access('bypass node access'),
   );
   $options = array();
   foreach (module_invoke_all('node_operations') as $operation => $array) {
@@ -509,9 +536,9 @@ function node_admin_nodes() {
 
   $languages = language_list();
   $destination = drupal_get_destination();
-  $nodes = array();
-  while ($node = db_fetch_object($result)) {
-    $nodes[$node->nid] = '';
+  $nids = array();
+  foreach ($nodes as $node) {
+    $nids[$node->nid] = ''; 
     $options = empty($node->language) ? array() : array('language' => $languages[$node->language]);
     $form['title'][$node->nid] = array('#markup' => l($node->title, 'node/' . $node->nid, $options) . ' ' . theme('mark', node_mark($node->nid, $node->changed)));
     $form['name'][$node->nid] =  array('#markup' => check_plain(node_get_types('name', $node)));
@@ -521,12 +548,14 @@ function node_admin_nodes() {
     if ($multilanguage) {
       $form['language'][$node->nid] = array('#markup' => empty($node->language) ? t('Language neutral') : t($languages[$node->language]->name));
     }
-    $form['operations'][$node->nid] = array('#markup' => l(t('edit'), 'node/' . $node->nid . '/edit', array('query' => $destination)));
+    $form['operations'][$node->nid] = array('#markup' => l(t('edit'), 'node/' . $node->nid . '/edit', array('query' => $destination)), '#access' => node_access('update', $node));
   }
   $form['nodes'] = array(
     '#type' => 'checkboxes',
-    '#options' => $nodes,
+    '#options' => $nids,
+    '#access' => user_access('administer nodes') && user_access('bypass node access'),
   );
+
   $form['pager'] = array('#markup' => theme('pager', NULL, 50, 0));
   $form['#theme'] = 'node_admin_nodes';
   return $form;
@@ -591,7 +620,10 @@ function theme_node_admin_nodes($form) {
     $rows = array();
     foreach (element_children($form['title']) as $key) {
       $row = array();
-      $row[] = drupal_render($form['nodes'][$key]);
+
+      if (user_access('administer nodes') && user_access('bypass node access')) {
+        $row[] = drupal_render($form['nodes'][$key]);
+      }
       $row[] = drupal_render($form['title'][$key]);
       $row[] = drupal_render($form['name'][$key]);
       $row[] = drupal_render($form['username'][$key]);
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1020
diff -u -p -r1.1020 node.module
--- modules/node/node.module	28 Jan 2009 07:34:30 -0000	1.1020
+++ modules/node/node.module	31 Jan 2009 06:44:31 -0000
@@ -71,6 +71,7 @@ function node_help($path, $arg) {
       $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@node">Node module</a>.', array('@node' => 'http://drupal.org/handbook/modules/node/')) . '</p>';
       return $output;
     case 'admin/content/node':
+    case 'admin/content/node/all':
       return ' '; // Return a non-null value so that the 'more help' link is shown.
     case 'admin/build/types':
       return '<p>' . t('Below is a list of all the content types on your site. All posts that exist on your site are instances of one of these content types.') . '</p>';
@@ -1262,6 +1263,10 @@ function node_perm() {
       'title' => t('Access content'),
       'description' => t('View published content.'),
     ),
+    'access content overview' => array(
+      'title' => t('Access content overview'),
+      'description' => t('List and filter available content from the administrative content pages.'),
+    ),
     'bypass node access' => array(
       'title' => t('Bypass node access'),
       'description' => t('View, edit and delete all site content. Users with this permission will bypass any content-related access control. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
@@ -1614,14 +1619,22 @@ function node_menu() {
     'title' => 'Content',
     'description' => "View, edit, and delete your site's content.",
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('node_admin_content'),
-    'access arguments' => array('administer nodes'),
+    'page arguments' => array('node_admin_content', TRUE),
+    'access callback' => 'node_content_page_access',
   );
 
-  $items['admin/content/node/overview'] = array(
-    'title' => 'List',
+  $items['admin/content/node/user'] = array(
+    'title' => 'My content',
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
+  );
+
+  $items['admin/content/node/all'] = array(
+    'title' => 'All content',
+    'description' => "View, edit, and delete your site's content.",
+    'page arguments' => array('node_admin_content'),
+    'access callback' => 'node_content_page_access',
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 5,
   );
 
   $items['admin/content/node-settings'] = array(
@@ -2282,6 +2295,33 @@ function node_access($op, $node, $accoun
 }
 
 /**
+ * Checks whether the current user has access to the content list page.
+ */
+function node_content_page_access() {
+  // Users with administer nodes automatically get this page.
+  if (user_access('administer nodes')) {
+    return TRUE;
+  }
+  
+  // If the user has no permission to access content, deny.
+  if (!user_access('access content') || !user_access('access content overview')) {
+    return FALSE;
+  }
+
+  $types = node_get_types('types');
+  foreach ($types as $type) {
+    $permissions = node_list_permissions(check_plain($type->type));
+    foreach (array_keys($permissions) as $permission) {
+      if (user_access($permission)) {
+        return TRUE;
+      }
+    }
+  }
+
+  return FALSE;
+}
+
+/**
  * Generate an SQL join clause for use in fetching a node listing.
  *
  * @param $node_alias
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.16
diff -u -p -r1.16 node.test
--- modules/node/node.test	28 Jan 2009 07:34:30 -0000	1.16
+++ modules/node/node.test	31 Jan 2009 06:44:31 -0000
@@ -635,3 +635,48 @@ class NodeRSSContentTestCase extends Dru
     $this->assertText($test_text, t('Extra node content appears in RSS feed.'));
   }
 }
+
+class ContentAdminPagesCase extends DrupalWebTestCase {
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+     return array(
+      'name' => t('Content Admin Pages'),
+      'description' => t('Create users and content to test the content admin pages functionality.'),
+      'group' => t('Node'),
+    );
+  }
+  function setUp() {
+    parent::setUp();
+     $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer nodes', 'bypass node access'));
+     $this->base_user = $this->drupalCreateUser(array('access content overview', 'edit own page content', 'create page content'));
+  }
+  function testContentAdminPages() {
+    $this->drupalLogin($this->admin_user);
+
+    // Ensure the admin user can edit any content.
+    $created_node = $this->drupalCreateNode(array('type' => 'page'));
+    $this->drupalGet('admin/content/node');
+    $this->assertResponse(200);
+    $this->drupalGet('admin/content/node/all');
+    $this->assertResponse(200);
+    $this->assertText('edit', t('Admin user has edit link.'));
+    $this->drupalLogout();
+
+    // Ensure users don't see edit links for content they don't have rights to edit.
+    $this->drupalLogin($this->base_user);
+    $this->drupalGet('admin/content/node/all');
+    $this->assertResponse(200);
+    $this->assertText($created_node->title, t('Edit links disabled without edit permissions.'));
+    $this->assertNoText('edit', t('Edit links do not show up for users without rights.'));
+
+    // Ensure users content shows up on their 'My Content' page, and they have edit links.
+    $user_node = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user->uid));
+    $this->drupalGet('admin/content/node');
+    $this->assertText($user_node->title, t("User's own content is displayed."));
+    $this->assertNoText($created_node->title, t('Nodes not belonging to user are not displayed.'));
+
+  }
+}
+
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.304
diff -u -p -r1.304 system.install
--- modules/system/system.install	25 Jan 2009 16:46:05 -0000	1.304
+++ modules/system/system.install	31 Jan 2009 06:44:31 -0000
@@ -364,6 +364,7 @@ function system_install() {
   // Authenticated role permissions.
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'access comments');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'access content');
+  db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'access content overview');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'post comments');
   db_query("INSERT INTO {role_permission} (rid, permission) VALUES (%d, '%s')", 2, 'post comments without approval');
 
Index: profiles/default/default.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v
retrieving revision 1.36
diff -u -p -r1.36 default.profile
--- profiles/default/default.profile	14 Jan 2009 21:16:21 -0000	1.36
+++ profiles/default/default.profile	31 Jan 2009 06:44:32 -0000
@@ -153,6 +153,8 @@ function default_profile_tasks(&$task, $
   menu_link_save($link);
   $link = array('link_path' => 'admin/build/menu-customize/secondary-menu/add', 'link_title' => 'Add a secondary menu link', 'menu_name' => 'secondary-menu');
   menu_link_save($link);
+  $link = array('link_path' => 'admin/content/node', 'link_title' => 'View content', 'menu_name' => 'navigation', 'plid' => 0, 'weight' => '3');
+   menu_link_save($link);
 }
 
 /**
