Index: modules/dashboard/dashboard.css =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.css,v retrieving revision 1.3 diff -u -r1.3 dashboard.css --- modules/dashboard/dashboard.css 21 Nov 2009 17:42:00 -0000 1.3 +++ modules/dashboard/dashboard.css 27 Nov 2009 23:23:12 -0000 @@ -113,3 +113,7 @@ width: 30px; height: 1.6em; } + +#dashboard #block-node-recent div.content { + padding: 0 0 5px 1px; +} \ No newline at end of file Index: profiles/default/default.install =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.install,v retrieving revision 1.18 diff -u -r1.18 default.install --- profiles/default/default.install 10 Nov 2009 17:27:54 -0000 1.18 +++ profiles/default/default.install 27 Nov 2009 23:23:13 -0000 @@ -121,6 +121,16 @@ 'cache' => -1, ), array( + 'module' => 'node', + 'delta' => 'recent', + 'theme' => 'seven', + 'status' => 1, + 'weight' => 10, + 'region' => 'dashboard_main', + 'pages' => '', + 'cache' => -1, + ), + array( 'module' => 'user', 'delta' => 'new', 'theme' => 'seven', Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1169 diff -u -r1.1169 node.module --- modules/node/node.module 19 Nov 2009 04:00:47 -0000 1.1169 +++ modules/node/node.module 27 Nov 2009 23:23:13 -0000 @@ -165,6 +165,12 @@ 'node_admin_overview' => array( 'variables' => array('name' => NULL, 'type' => NULL), ), + 'node_recent_block' => array( + 'variables' => array('nodes' => NULL), + ), + 'node_recent_content' => array( + 'variables' => array('node' => NULL), + ), ); } @@ -1994,6 +2000,9 @@ $blocks['syndicate']['info'] = t('Syndicate'); // Not worth caching. $blocks['syndicate']['cache'] = DRUPAL_NO_CACHE; + + $blocks['recent']['info'] = t('Recent content'); + return $blocks; } @@ -2001,13 +2010,140 @@ * Implement hook_block_view(). */ function node_block_view($delta = '') { - $block['subject'] = t('Syndicate'); - $block['content'] = theme('feed_icon', array('url' => url('rss.xml'), 'title' => t('Syndicate'))); + $block = array(); + switch ($delta) { + case 'syndicate': + $block['subject'] = t('Syndicate'); + $block['content'] = theme('feed_icon', array('url' => url('rss.xml'), 'title' => t('Syndicate'))); + break; + + case 'recent': + if (user_access('access content')) { + $block['subject'] = t('Recent content'); + $block['content'] = theme('node_recent_block', array( + 'nodes' => node_get_recent(variable_get('node_recent_block_count', 10)), + )); + } + break; + } return $block; } /** + * Find the most recent nodes that are available to the current user. + * + * @todo Decide on best place for this function within the file + * @param integer $number + * (optional) The maximum number of nodes to find. Defaults to 10. + * @return + * An array of partial node objects or an empty array if there are no recent + * nodes visible to the current user. + */ +function node_get_recent($number = 10) { + // Can't use node_load_multiple() due to inability to limit + // and order results - would return all nodes if we used it + $nodes = db_select('node', 'n') + // Are there any other fields which should be returned for this? + ->fields('n', array('uid', 'nid', 'type', 'status', 'title', 'changed')) + // Should we set status as a condition? Isn't the point of the + // module that users do not "lose" content they have created... + ->condition('status', NODE_PUBLISHED) + ->orderBy('created', 'DESC') + ->range(0, $number) + ->addTag('node_access') + ->execute() + ->fetchAll(PDO::FETCH_OBJ); + return $nodes ? $nodes : array(); +} + +/** + * Returns a formatted list of recent nodes to be displayed in the recent content block. + * + * @todo Decide on best place for this function within the file + * @return + * The recent content table HTML. + * @ingroup themeable + */ +function theme_node_recent_block($variables) { + $rows = array(); + + foreach ($variables['nodes'] as $node) { + $cells = array(); + $cells[] = theme('node_recent_content', array('node' => $node)); + + // node_access() calls done here as themers may not want + // operations available in the block, thus reducing processing + // time for those instances - can change if feedback dictates. + $cells[] = node_access('update', $node) ? l(t('edit'), 'node/' . $node->nid . '/edit') : ''; + $cells[] = node_access('delete', $node) ? l(t('delete'), 'node/' . $node->nid . '/delete') : ''; + $rows[] = $cells; + } + + if ($rows) { + $output = theme('table', array('rows' => $rows)); + + // TODO?: Apply a class to this link to match spec + // see: http://drupal.org/node/337947#comment-2294824 + $output .= l(t('Show all content'), 'admin/content'); + } + else { + $output = t('No content available.'); + } + + return $output; +} + +/** + * Returns a formatted list of recent nodes to be displayed in the recent content block. + * + * @todo Decide on best place for this function within the file + * @return + * The recent content table HTML. + * @ingroup themeable + */ +function theme_node_recent_content($variables) { + $node = $variables['node']; + + // TODO: Add classes to div blocks to allow themers to modify without + // overriding theme function, need input on class names to use + $output = '