? .DS_Store
? .patch
? administer_dashboard-376103-2.patch
? administer_dashboard-376103-3.patch
? administer_dashboard.patch
? head.db
? mate
? modules/.DS_Store
? modules/user/.DS_Store
? sites/.DS_Store
? sites/all/.DS_Store
? sites/all/modules/.DS_Store
? sites/all/modules/devel
? sites/all/modules/permission_test
? sites/all/modules/permission_test 2.zip
? sites/all/modules/permission_test.zip
? sites/default/files
? sites/default/settings.php
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.692
diff -u -p -r1.692 comment.module
--- modules/comment/comment.module	7 Feb 2009 20:10:40 -0000	1.692
+++ modules/comment/comment.module	18 Feb 2009 05:55:31 -0000
@@ -303,6 +303,32 @@ function comment_block_view($delta = '')
 }
 
 /**
+ * Implementation of hook_widgets().
+ */
+function comment_widgets() {
+  $widgets = array();
+
+  $widgets['recent-comments'] = array(
+    'title' => t('Recent comments'),
+    'callback' => 'comment_widget_recent_comments',
+  );
+
+  return $widgets;
+}
+
+/**
+ * Recent comments widget. Displays a list of 5 recent comments.
+ */
+function comment_widget_recent_comments() {
+  $list = array();
+  foreach (comment_get_recent(5) as $comment) {
+    $list[] = l($comment->subject, 'node/' . $comment->nid, array('fragment' => 'comment-' . $comment->cid)) . ' <small>' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->timestamp))) .'</small>';
+  }
+
+  return theme('item_list', $list, NULL, 'ul', array('class' => 'menu'));
+}
+
+/**
  * Find the most recent comments that are available to the current user.
  *
  * This is done in two steps:
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1024
diff -u -p -r1.1024 node.module
--- modules/node/node.module	13 Feb 2009 02:27:59 -0000	1.1024
+++ modules/node/node.module	18 Feb 2009 05:55:31 -0000
@@ -1894,6 +1894,70 @@ function node_block_view($delta = '') {
 }
 
 /**
+ * Implementation of hook_widgets().
+ */
+function node_widgets() {
+  $widgets = array();
+
+  $widgets['recent-posts'] = array(
+    'title' => t('Recent posts'),
+    'callback' => 'node_widget_recent_posts',
+  );
+
+  $widgets['create-links'] = array(
+    'title' => t('Create links'),
+    'callback' => 'node_widget_create_links',
+  );
+
+  $widgets['content-summary'] = array(
+    'title' => t('Content summary'),
+    'callback' => 'node_widget_content_summary',
+  );
+
+  return $widgets;
+}
+
+/**
+ * Recent posts widget. Display a list of the 5 most recent posts.
+ */
+function node_widget_recent_posts() {
+  $nodes = db_query_range(db_rewrite_sql('SELECT nt.name, n.title, n.nid FROM {node} n INNER JOIN {node_type} nt USING(type) ORDER BY n.created DESC'), 0, 5);
+  $list = array();
+
+  foreach ($nodes as $node) {
+    $list[] = l($node->title, 'node/'. $node->nid) .' <small>('. $node->name .')</small>';
+  }
+
+  return theme('item_list', $list, NULL, 'ul', array('class' => 'menu'));
+}
+
+/**
+ * Content summary widget. Displays a list of number of posts per content type.
+ */
+function node_widget_content_summary() {
+  $types = db_query('SELECT nt.name, COUNT(n.nid) AS count_nid FROM {node} n INNER JOIN {node_type} nt USING(type) GROUP BY type');
+  $rows = array();
+  foreach ($types as $type) {
+    $rows[] = array($type->name, $type->count_nid .' posts');
+  }
+  return theme('table', array(), $rows);
+}
+
+/**
+ * Create links widget. Display a list of create links.
+ */
+function node_widget_create_links() {
+  $types = db_query('SELECT name, type FROM {node_type}');
+  $list = array();
+  foreach ($types as $type) {
+    $list[] = l('Add '. $type->name, 'node/add/' . $type->type);
+  }
+
+  return theme('item_list', $list, NULL, 'ul', array('class' => 'menu'));
+}
+
+
+/**
  * A generic function for generating RSS feeds from a set of nodes.
  *
  * @param $nids
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.125
diff -u -p -r1.125 system.admin.inc
--- modules/system/system.admin.inc	11 Feb 2009 05:33:18 -0000	1.125
+++ modules/system/system.admin.inc	18 Feb 2009 05:55:32 -0000
@@ -10,55 +10,69 @@
  * Menu callback; Provide the administration overview page.
  */
 function system_main_admin_page($arg = NULL) {
-  // If we received an argument, they probably meant some other page.
-  // Let's 404 them since the menu system cannot be told we do not
-  // accept arguments.
-  if (isset($arg) && substr($arg, 0, 3) != 'by-') {
-    return drupal_not_found();
-  }
-
   // Check for status report errors.
   if (system_status(TRUE) && user_access('administer site configuration')) {
     drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
   }
   $blocks = array();
-  if ($admin = db_fetch_array(db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin' AND module = 'system'"))) {
-    $result = db_query("
-      SELECT m.*, ml.*
-      FROM {menu_links} ml
-      INNER JOIN {menu_router} m ON ml.router_path = m.path
-      WHERE ml.link_path != 'admin/help' AND menu_name = '%s' AND ml.plid = %d AND hidden = 0", $admin);
-    while ($item = db_fetch_array($result)) {
-      _menu_link_translate($item);
-      if (!$item['access']) {
-        continue;
-      }
-      // The link 'description' either derived from the hook_menu 'description'
-      // or entered by the user via menu module is saved as the title attribute.
-      if (!empty($item['localized_options']['attributes']['title'])) {
-        $item['description'] = $item['localized_options']['attributes']['title'];
-      }
-      $block = $item;
-      $block['content'] = '';
-      if ($item['block_callback'] && function_exists($item['block_callback'])) {
-        $function = $item['block_callback'];
-        $block['content'] .= $function();
-      }
-      $block['content'] .= theme('admin_block_content', system_admin_menu_block($item));
-      // Prepare for sorting as in function _menu_tree_check_access().
-      // The weight is offset so it is always positive, with a uniform 5-digits.
-      $blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
-    }
-  }
-  if ($blocks) {
-    ksort($blocks);
-    return theme('admin_page', $blocks);
+  $widgets = variable_get('system_main_widgets', array());
+  $system_widgets = module_invoke_all('widgets');
+  foreach ($widgets as $widget => $enabled) {
+    if (!$enabled || !isset($system_widgets[$widget]) ) {
+      continue;
+    }
+    $blocks[] = array(
+      'title' => $system_widgets[$widget]['title'] .' <small>'. l('[X]', 'admin/remove-widget/'. $widget) .'</small>',
+      'content' => $system_widgets[$widget]['callback'](),
+    );
   }
-  else {
-    return t('You do not have any administrative items.');
+  return theme('admin_page', $blocks);
+}
+
+/**
+ * Menu callback; Add a widget.
+ */
+function system_main_admin_add_widget(&$form_state) {
+  $form = array();
+  $options = array();
+  $widgets = module_invoke_all('widgets');
+  foreach ($widgets as $id => $widget) {
+    $options[$id] = $widget['title'];
   }
+
+  $form['widget'] = array(
+    '#type' => 'radios',
+    '#title' => t('Widget'),
+    '#options' => $options,
+    '#default_value' => -1,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit', 
+    '#value' => t('Add'),
+  );
+  
+  return $form;
 }
 
+/**
+ * Submit function: add a widget.
+ */
+function system_main_admin_add_widget_submit($form, &$form_state) {
+  $widgets = variable_get('system_main_widgets', array());
+  $widgets[$form_state['values']['widget']] = TRUE;
+  variable_set('system_main_widgets', $widgets);
+  $form_state['redirect'] = 'admin';
+}
+
+/**
+ * Menu callback; Remove a widget.
+ */
+function system_main_admin_remove_widget($widget) {
+  $widgets = variable_get('system_main_widgets', array());
+  $widgets[$widget] = FALSE;
+  variable_set('system_main_widgets', $widgets);
+  drupal_goto('admin');
+}
 
 /**
  * Provide a single block from the administration menu as a page.
@@ -82,40 +96,6 @@ function system_admin_menu_block_page() 
 }
 
 /**
- * Menu callback; prints a listing of admin tasks for each installed module.
- */
-function system_admin_by_module() {
-
-  $modules = module_rebuild_cache();
-  $menu_items = array();
-  $help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
-
-  foreach ($modules as $file) {
-    $module = $file->name;
-    if ($module == 'help') {
-      continue;
-    }
-
-    $admin_tasks = system_get_module_admin_tasks($module);
-
-    // Only display a section if there are any available tasks.
-    if (count($admin_tasks)) {
-
-      // Check for help links.
-      if ($help_arg && module_invoke($module, 'help', "admin/help#$module", $help_arg)) {
-        $admin_tasks[100] = l(t('Get help'), "admin/help/$module");
-      }
-
-      // Sort.
-      ksort($admin_tasks);
-
-      $menu_items[$file->info['name']] = array($file->info['description'], $admin_tasks);
-    }
-  }
-  return theme('system_admin_by_module', $menu_items);
-}
-
-/**
  * Menu callback; displays a module's settings page.
  */
 function system_settings_overview() {
@@ -1915,9 +1895,15 @@ function theme_admin_block($block) {
       $block[title]
     </h3>
     <div class="body">
-      <p class="description">
-        $block[description]
-      </p>
+EOT;
+  if (isset($block['description'])) {
+    $output .= <<< EOT
+    <p class="description">
+      $block[description]
+    </p>
+EOT;
+  }
+  $output .= <<< EOT
       $block[content]
     </div>
   </div>
@@ -1984,8 +1970,6 @@ function theme_admin_page($blocks) {
   }
 
   $output = '<div class="admin clear-block">';
-  $output .= theme('system_compact_link');
-
   foreach ($container as $id => $data) {
     $output .= '<div class="' . $id . ' clear-block">';
     $output .= $data;
@@ -1995,52 +1979,6 @@ function theme_admin_page($blocks) {
   return $output;
 }
 
-/**
- * Theme output of the dashboard page.
- *
- * @param $menu_items
- *   An array of modules to be displayed.
- * @ingroup themeable
- */
-function theme_system_admin_by_module($menu_items) {
-  $stripe = 0;
-  $output = '';
-  $container = array('left' => '', 'right' => '');
-  $flip = array('left' => 'right', 'right' => 'left');
-  $position = 'left';
-
-  // Iterate over all modules
-  foreach ($menu_items as $module => $block) {
-    list($description, $items) = $block;
-
-    // Output links
-    if (count($items)) {
-      $block = array();
-      $block['title'] = $module;
-      $block['content'] = theme('item_list', $items);
-      $block['description'] = t($description);
-
-      if ($block_output = theme('admin_block', $block)) {
-        if (!isset($block['position'])) {
-          // Perform automatic striping.
-          $block['position'] = $position;
-          $position = $flip[$position];
-        }
-        $container[$block['position']] .= $block_output;
-      }
-    }
-  }
-
-  $output = '<div class="admin clear-block">';
-  foreach ($container as $id => $data) {
-    $output .= '<div class="' . $id . ' clear-block">';
-    $output .= $data;
-    $output .= '</div>';
-  }
-  $output .= '</div>';
-
-  return $output;
-}
 
 /**
  * Theme requirements status report.
Index: modules/system/system.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.css,v
retrieving revision 1.53
diff -u -p -r1.53 system.css
--- modules/system/system.css	5 Dec 2008 12:50:28 -0000	1.53
+++ modules/system/system.css	18 Feb 2009 05:55:32 -0000
@@ -111,6 +111,9 @@ div.ok, tr.ok {
   padding: 0;
   list-style: disc;
 }
+.item-list ul.menu li {
+  list-style: none;
+}
 ol.task-list li.active {
   font-weight: bold;
 }
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.667
diff -u -p -r1.667 system.module
--- modules/system/system.module	11 Feb 2009 05:33:18 -0000	1.667
+++ modules/system/system.module	18 Feb 2009 05:55:32 -0000
@@ -465,19 +465,27 @@ function system_menu() {
     'access arguments' => array('access administration pages'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/by-task'] = array(
-    'title' => 'By task',
+  $items['admin/dashboard'] = array(
+    'title' => 'Dashboard',
     'page callback' => 'system_main_admin_page',
     'access arguments' => array('access administration pages'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
-  $items['admin/by-module'] = array(
-    'title' => 'By module',
-    'page callback' => 'system_admin_by_module',
+  $items['admin/add-widget'] = array(
+    'title' => 'Add widget',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_main_admin_add_widget'),
     'access arguments' => array('access administration pages'),
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
   );
+  $items['admin/remove-widget/%'] = array(
+    'title' => 'Remove widget',
+    'page callback' => 'system_main_admin_remove_widget',
+    'page arguments' => array(2),
+    'access arguments' => array('access administration pages'),
+    'type' => MENU_CALLBACK,
+  );
   $items['admin/content'] = array(
     'title' => 'Content management',
     'description' => "Manage your site's content.",
@@ -2238,6 +2246,52 @@ function system_timezone($abbreviation =
 }
 
 /**
+ * Implementation of hook_widgets().
+ */
+function system_widgets() {
+  $widgets = array();
+
+  $widgets['status-report'] = array(
+    'title' => 'Status report',
+    'callback' => 'system_admin_widget_status_report',
+  );
+
+  return $widgets;
+}
+
+/**
+ * Status report widget. Displays a status report.
+ */
+function system_admin_widget_status_report() {
+  // Load .install files
+  include_once DRUPAL_ROOT . '/includes/install.inc';
+  drupal_load_updates();
+
+  // Check run-time requirements and status information.
+  $requirements = module_invoke_all('requirements', 'runtime');
+  usort($requirements, '_system_sort_requirements');
+  $classes = array(
+    REQUIREMENT_INFO => 'info',
+    REQUIREMENT_OK => 'ok',
+    REQUIREMENT_WARNING => 'warning',
+    REQUIREMENT_ERROR => 'error',
+  );
+  foreach ($requirements as $key => $requirement) {
+    $severity = isset($requirement['severity']) ? (int)$requirement['severity'] : 0;
+    if ($severity == REQUIREMENT_INFO || $severity == REQUIREMENT_OK) {
+      unset($requirements[$key]);
+    }
+  }
+  if (empty($requirements)) {
+    $requirements[] = array(
+      'title' => t('Status'),
+      'value' => t('Perfect!'),
+    );
+  }
+  return theme('status_report', $requirements);
+}
+
+/**
  * Format the Powered by Drupal text.
  *
  * @ingroup themeable
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.39
diff -u -p -r1.39 system.test
--- modules/system/system.test	11 Feb 2009 05:33:18 -0000	1.39
+++ modules/system/system.test	18 Feb 2009 05:55:32 -0000
@@ -321,73 +321,6 @@ class CronRunTestCase extends DrupalWebT
   }
 }
 
-class AdminOverviewTestCase extends DrupalWebTestCase {
-  /**
-   * Implementation of getInfo().
-   */
-  function getInfo() {
-    return array(
-      'name' => t('Admin overview'),
-      'description' => t('Confirm that the admin overview page appears as expected.'),
-      'group' => t('System')
-    );
-  }
-
-  /**
-   * Test the overview page by task.
-   */
-  function testAdminOverview() {
-    $admin_user1 = $this->drupalCreateUser(array('access administration pages'));
-    $this->drupalLogin($admin_user1);
-
-    $this->drupalGet('admin');
-    $this->checkOverview();
-
-    $this->drupalGet('admin/by-module');
-    $this->checkOverview();
-
-    // Comments on permissions follow the format: [task], [module] that the permission relates to.
-    $permissions = array();
-    $permissions[] = 'access administration pages';
-    $permissions[] = 'administer comments'; // Content management, Comment.
-    $permissions[] = 'administer blocks'; // Site building, Block.
-    $permissions[] = 'administer filters'; // Site configuration, Filter.
-    $permissions[] = 'administer users'; // User management, User.
-    $permissions[] = 'access site reports'; // Reports, Database logging.
-    $admin_user2 = $this->drupalCreateUser($permissions);
-    $this->drupalLogin($admin_user2);
-
-    $this->drupalGet('admin');
-    $this->checkOverview(array(t('Content management'), t('User management'), t('Reports'), t('Site building'), t('Site configuration')));
-
-    $this->drupalGet('admin/by-module');
-    $this->checkOverview(array(t('Comment'), t('Block'), t('Filter'), t('User'), t('Database logging')));
-  }
-
-  /**
-   * Check the overview page panels.
-   *
-   * @param array $panels List of panels to be found.
-   */
-  function checkOverview(array $panels = array()) {
-    if ($this->parse()) {
-      $found = 0;
-      $extra = 0;
-      $divs = $this->xpath("//div[@class='admin-panel']");
-      foreach ($divs as $panel) {
-        if (in_array(trim($panel->h3), $panels)) {
-          $found++;
-        }
-        else {
-          $extra++;
-        }
-      }
-      $this->assertTrue(count($panels) == $found, t('Required panels found.'));
-      $this->assertFalse($extra, t('No extra panels found.'));
-    }
-  }
-}
-
 class AdminMetaTagTestCase extends DrupalWebTestCase {
   /**
    * Implementation of getInfo().
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.963
diff -u -p -r1.963 user.module
--- modules/user/user.module	9 Feb 2009 07:36:15 -0000	1.963
+++ modules/user/user.module	18 Feb 2009 05:55:32 -0000
@@ -1030,6 +1030,34 @@ function user_block_view($delta = '') {
 }
 
 /**
+ * Implementation of hook_widgets().
+ */
+function user_widgets() {
+  $widgets = array();
+
+  $widgets['new-users'] = array(
+    'title' => t('New users'),
+    'callback' => 'user_widget_new_users',
+  );
+
+  return $widgets;
+}
+
+/**
+ * New users widget. Displays a list of the 5 newest users.
+ */
+function user_widget_new_users() {
+  $users = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', array(), 0, 5);
+  if (!empty($users)) {
+    foreach ($users as $user) {
+      $items[] = theme('username', $user);
+    }
+    return theme('item_list', $items, NULL, 'ul', array('class' => 'menu'));
+  }
+}
+
+
+/**
  * Process variables for user-picture.tpl.php.
  *
  * The $variables array contains the following arguments:
