? 301902_normal_user_content_overview.diff
? dev7.kpf
? sites/all/modules
? 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.33
diff -u -r1.33 node.admin.inc
--- modules/node/node.admin.inc	11 Jan 2009 21:19:17 -0000	1.33
+++ modules/node/node.admin.inc	13 Jan 2009 20:37:20 -0000
@@ -166,8 +166,12 @@
 
 /**
  * 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) {
+  global $user;
   $filters = node_filters();
 
   // Build query
@@ -195,6 +199,13 @@
     }
     $args[] = $value;
   }
+
+  // Filter for a specific user at 'My content'.
+  if ($for_user) {
+    $where[] = 'n.uid = %d';
+    $args[] = $user->uid;
+  }
+
   $where = count($where) ? 'WHERE ' . implode(' AND ', $where) : '';
 
   return array('where' => $where, 'join' => $join, 'args' => $args);
@@ -435,30 +446,38 @@
 
 /**
  * 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 != ''")));
 
   // 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');
@@ -475,10 +494,10 @@
   );
 
   // 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']);
+  $result = pager_query(db_rewrite_sql('SELECT n.nid FROM {node} n ' . $filter['join'] . $filter['where'] . $sort), 50, 0, NULL, $filter['args']);
 
   // Build the 'Update options' form.
   $form['options'] = array(
@@ -486,6 +505,7 @@
     '#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) {
@@ -505,8 +525,10 @@
   $languages = language_list();
   $destination = drupal_get_destination();
   $nodes = array();
-  while ($node = db_fetch_object($result)) {
-    $nodes[$node->nid] = '';
+  while ($nid = db_result($result)) {
+    $node = node_load($nid);
+    $nodes[$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)));
@@ -516,12 +538,14 @@
     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,
+    '#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;
@@ -586,7 +610,10 @@
     $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.1010
diff -u -r1.1010 node.module
--- modules/node/node.module	8 Jan 2009 08:42:12 -0000	1.1010
+++ modules/node/node.module	13 Jan 2009 20:37:20 -0000
@@ -71,6 +71,7 @@
       $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>';
@@ -1249,6 +1250,10 @@
       '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.'))),
@@ -1601,14 +1606,22 @@
     '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(
@@ -2229,6 +2242,33 @@
 }
 
 /**
+ * Checks whether the current user has access to the content list page.
+ */
+function node_content_page_access() {
+  // If the user has no permission to access content, deny.
+  if (!user_access('access content')) {
+    return FALSE;
+  }
+
+  if (!user_access('access content overview')) {
+    return FALSE;
+  }
+
+  $types = node_get_types('types');
+  foreach ($types as $type) {
+    $permissions = node_list_permissions(check_plain($type->type));
+    $permissions['administer nodes'] = 'administer nodes';
+    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.14
diff -u -r1.14 node.test
--- modules/node/node.test	9 Jan 2009 16:19:55 -0000	1.14
+++ modules/node/node.test	13 Jan 2009 20:37:20 -0000
@@ -598,4 +598,48 @@
     $node = $this->drupalGetNodeByTitle($edit['title']);
     $this->assertNoRaw(theme('node_submitted', $node), t('Post information is not displayed.'));
   }
-}
\ No newline at end of file
+}
+
+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('Unprivileged users can view content.'));
+    $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('Users own content is displayed'));
+    $this->assertNoText($created_node->title, t('Nodes not belong to user are not displayed'));
+
+  }
+}
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.296
diff -u -r1.296 system.install
--- modules/system/system.install	9 Jan 2009 16:19:55 -0000	1.296
+++ modules/system/system.install	13 Jan 2009 20:37:20 -0000
@@ -362,6 +362,7 @@
   // 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.33
diff -u -r1.33 default.profile
--- profiles/default/default.profile	9 Jan 2009 16:19:55 -0000	1.33
+++ profiles/default/default.profile	13 Jan 2009 20:37:20 -0000
@@ -153,6 +153,8 @@
   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);
 }
 
 /**
