Index: modules/aggregator/aggregator.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.admin.inc,v
retrieving revision 1.14
diff -u -r1.14 aggregator.admin.inc
--- modules/aggregator/aggregator.admin.inc	16 Aug 2008 14:48:17 -0000	1.14
+++ modules/aggregator/aggregator.admin.inc	23 Aug 2008 10:21:19 -0000
@@ -7,40 +7,63 @@
  */
 
 /**
- * Menu callback; displays the aggregator administration page.
- */
-function aggregator_admin_overview() {
-  return aggregator_view();
-}
-
-/**
- * Displays the aggregator administration page.
+ * Menu callback; displays the aggregator feed overview page.
  *
  * @return
  *   The page HTML.
  */
-function aggregator_view() {
-  $result = db_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title');
+function aggregator_admin_overview() {
+  $result = pager_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.hash, f.etag, f.modified, f.image, f.block ORDER BY f.title', 50, 0, 'SELECT COUNT(*) FROM {aggregator_feed}');
 
-  $output = '<h3>' . t('Feed overview') . '</h3>';
+  $output = '';
 
   $header = array(t('Title'), t('Items'), t('Last update'), t('Next update'), array('data' => t('Operations'), 'colspan' => '3'));
   $rows = array();
   while ($feed = db_fetch_object($result)) {
-    $rows[] = array(l($feed->title, "aggregator/sources/$feed->fid"), format_plural($feed->items, '1 item', '@count items'), ($feed->checked ? t('@time ago', array('@time' => format_interval(time() - $feed->checked))) : t('never')), ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - time()))) : t('never')), l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"), l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"), l(t('update items'), "admin/content/aggregator/update/$feed->fid"));
+    $rows[] = array(
+      l($feed->title, "aggregator/sources/$feed->fid"),
+      format_plural($feed->items, '1 item', '@count items'),
+      ($feed->checked ? t('@time ago', array('@time' => format_interval(time() - $feed->checked))) : t('never')),
+      ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - time()))) : t('never')),
+      l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"),
+      l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"),
+      l(t('update items'), "admin/content/aggregator/update/$feed->fid"),
+    );
+  }
+  if (count($rows) == 0) {
+    $rows[] = array(array('data' => t('No feeds available.'), 'colspan' => '7'));
   }
   $output .= theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 50);
+
+  return $output;
+}
 
-  $result = db_query('SELECT c.cid, c.title, count(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title');
+/**
+ * Menu callback; displays the aggregator category overview page.
+ *
+ * @return
+ *   The page HTML.
+ */
+function aggregator_category_overview() {
+  $result = pager_query('SELECT c.cid, c.title, count(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title', 50, 0, 'SELECT COUNT(*) FROM {aggregator_category}');
 
-  $output .= '<h3>' . t('Category overview') . '</h3>';
+  $output = '';
 
   $header = array(t('Title'), t('Items'), t('Operations'));
   $rows = array();
   while ($category = db_fetch_object($result)) {
-    $rows[] = array(l($category->title, "aggregator/categories/$category->cid"), format_plural($category->items, '1 item', '@count items'), l(t('edit'), "admin/content/aggregator/edit/category/$category->cid"));
+    $rows[] = array(
+      l($category->title, "aggregator/categories/$category->cid"),
+      format_plural($category->items, '1 item', '@count items'),
+      l(t('edit'), "admin/content/aggregator/edit/category/$category->cid"),
+    );
+  }
+  if (count($rows) == 0) {
+    $rows[] = array(array('data' => t('No categories available.'), 'colspan' => '3'));
   }
   $output .= theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 50);
 
   return $output;
 }
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.389
diff -u -r1.389 aggregator.module
--- modules/aggregator/aggregator.module	16 Aug 2008 14:48:17 -0000	1.389
+++ modules/aggregator/aggregator.module	23 Aug 2008 10:21:19 -0000
@@ -18,8 +18,10 @@
       return $output;
     case 'admin/content/aggregator':
       $output = '<p>' . t('Thousands of sites (particularly news sites and blogs) publish their latest headlines and posts in feeds, using a number of standardized XML-based formats. Formats supported by the aggregator include <a href="@rss">RSS</a>, <a href="@rdf">RDF</a>, and <a href="@atom">Atom</a>.', array('@rss' => 'http://cyber.law.harvard.edu/rss/', '@rdf' => 'http://www.w3.org/RDF/', '@atom' => 'http://www.atomenabled.org')) . '</p>';
-      $output .= '<p>' . t('Current feeds are listed below, and <a href="@addfeed">new feeds may be added</a>. For each feed or feed category, the <em>latest items</em> block may be enabled at the <a href="@block">blocks administration page</a>.', array('@addfeed' => url('admin/content/aggregator/add/feed'), '@block' => url('admin/build/block'))) . '</p>';
+      $output .= '<p>' . t('Current feeds are listed below, and <a href="@addfeed">new feeds may be added</a>. For each feed, the <em>latest items</em> block may be enabled at the <a href="@block">blocks administration page</a>.', array('@addfeed' => url('admin/content/aggregator/add/feed'), '@block' => url('admin/build/block'))) . '</p>';
       return $output;
+    case 'admin/content/aggregator/list/categories':
+      return '<p>' . t('Current categories are listed below, and <a href="@addcategory">new categories may be added</a>. For each category, the <em>latest items</em> block may be enabled at the <a href="@block">blocks administration page</a>.', array('@addcategory' => url('admin/content/aggregator/add/category'), '@block' => url('admin/build/block'))) . '</p>';
     case 'admin/content/aggregator/add/feed':
       return '<p>' . t('Add a feed in RSS, RDF or Atom format. A feed may only have one entry.') . '</p>';
     case 'admin/content/aggregator/add/category':
@@ -87,6 +89,22 @@
     'page callback' => 'aggregator_admin_overview',
     'access arguments' => array('administer news feeds'),
   );
+  $items['admin/content/aggregator/list'] = array(
+    'title' => 'List',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/content/aggregator/list/feeds'] = array(
+    'title' => 'Feed overview',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/content/aggregator/list/categories'] = array(
+    'title' => 'Category overview',
+    'page callback' => 'aggregator_category_overview',
+    'access arguments' => array('administer news feeds'),
+    'type' => MENU_LOCAL_TASK,
+  );
   $items['admin/content/aggregator/add/feed'] = array(
     'title' => 'Add feed',
     'page callback' => 'drupal_get_form',
@@ -125,11 +143,6 @@
     'access arguments' => array('administer news feeds'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/content/aggregator/list'] = array(
-    'title' => 'List',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
-  );
   $items['admin/content/aggregator/settings'] = array(
     'title' => 'Settings',
     'page callback' => 'drupal_get_form',
@@ -147,7 +160,7 @@
   $items['aggregator/sources'] = array(
     'title' => 'Sources',
     'page callback' => 'aggregator_page_sources',
-    'access arguments' => array('access news feeds'),
+    'access callback' => '_aggregator_has_sources',
   );
   $items['aggregator/categories'] = array(
     'title' => 'Categories',
@@ -256,6 +269,16 @@
 }
 
 /**
+ * Find out whether there are any aggregator feeds.
+ *
+ * @return
+ *   TRUE if there is at least one feed and the user has access to them, FALSE otherwise.
+ */
+function _aggregator_has_sources() {
+  return user_access('access news feeds') && db_result(db_query('SELECT COUNT(*) FROM {aggregator_feed}'));
+}
+
+/**
  * Find out whether there are any aggregator categories.
  *
  * @return
