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 30 Nov 2009 21:30:51 -0000
@@ -113,3 +113,7 @@
width: 30px;
height: 1.6em;
}
+
+#dashboard #block-node-recent div.content {
+ padding: 0 0 5px 1px;
+}
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 30 Nov 2009 21:30:51 -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.1170
diff -u -r1.1170 node.module
--- modules/node/node.module 29 Nov 2009 10:43:53 -0000 1.1170
+++ modules/node/node.module 30 Nov 2009 21:30:51 -0000
@@ -95,7 +95,7 @@
$output .= '
' . t('The Node module also enables you to create multiple versions of any content, and revert to older versions using the Revision information settings.') . '';
$output .= '' . t('User permissions') . '';
$output .= '' . t('The Node module makes a number of permissions available for each content type, which can be set by role on the permissions page.', array('@permissions' => url('admin/settings/permissions'))) . '';
- $output .= '';
+ $output .= '';
return $output;
case 'admin/content':
@@ -170,6 +170,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),
+ ),
);
}
@@ -981,7 +987,7 @@
}
// The changed timestamp is always updated for bookkeeping purposes (revisions, searching, ...)
$node->changed = REQUEST_TIME;
-
+
$node->timestamp = REQUEST_TIME;
$update_node = TRUE;
@@ -1016,30 +1022,30 @@
->condition('nid', $node->nid)
->execute();
}
-
+
// Restore the title field data structure after db storage.
$node->title = $title_field;
-
+
// Call the node specific callback (if any). This can be
// node_invoke($node, 'insert') or
// node_invoke($node, 'update').
node_invoke($node, $op);
-
+
// Save fields.
$function = "field_attach_$op";
$function('node', $node);
-
+
module_invoke_all('node_' . $op, $node);
-
+
// Update the node access table for this node.
node_access_acquire_grants($node);
-
+
// Clear internal properties.
unset($node->is_new);
-
+
// Clear the page and block caches.
cache_clear_all();
-
+
// Ignore slave server temporarily to give time for the
// saved node to be propagated to the slave.
db_ignore_slave();
@@ -1999,6 +2005,9 @@
$blocks['syndicate']['info'] = t('Syndicate');
// Not worth caching.
$blocks['syndicate']['cache'] = DRUPAL_NO_CACHE;
+
+ $blocks['recent']['info'] = t('Recent content');
+
return $blocks;
}
@@ -2006,13 +2015,141 @@
* 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') && ($nodes = node_get_recent(variable_get('node_recent_block_count', 10)))) {
+ $block['subject'] = t('Recent content');
+ $block['content'] = theme('node_recent_block', array(
+ 'nodes' => $nodes,
+ ));
+ }
+ break;
+ }
return $block;
}
/**
+ * Implements hook_block_configure().
+ */
+function node_block_configure($delta = '') {
+ $form = array();
+ if ($delta == 'recent') {
+ $form['node_recent_block_count'] = array(
+ '#type' => 'select',
+ '#title' => t('Number of recent content items to display'),
+ '#default_value' => variable_get('node_recent_block_count', 10),
+ '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
+ );
+ }
+ return $form;
+}
+
+/**
+ * Implementation of hook_block_save().
+ */
+function node_block_save($delta = '', $edit = array()) {
+ if ($delta == 'recent') {
+ variable_set('node_recent_block_count', $edit['node_recent_block_count']);
+ }
+}
+
+/**
+ * Find the most recent nodes that are available to the current user.
+ *
+ * @param $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) {
+ $query = db_select('node', 'n');
+
+ if (!user_access('bypass node access')) {
+ // If the user is able to view their own unpublished nodes, allow them
+ // to see these in addition to published nodes. Check that they actually
+ // have some unpublished nodes to view before adding the condition.
+ if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
+ $query->condition(db_or()
+ ->condition('n.status', NODE_PUBLISHED)
+ ->condition('n.nid', $own_unpublished, 'IN')
+ );
+ }
+ else {
+ // If not, restrict the query to published nodes.
+ $query->condition('n.status', NODE_PUBLISHED);
+ }
+ }
+ $nids = $query
+ ->fields('n', array('nid'))
+ ->orderBy('changed', 'DESC')
+ ->range(0, $number)
+ ->addTag('node_access')
+ ->execute()
+ ->fetchCol();
+
+ $nodes = node_load_multiple($nids);
+
+ return $nodes ? $nodes : array();
+}
+
+/**
+ * Returns a formatted list of recent nodes to be displayed in the recent content block.
+ *
+ * @return
+ * The recent content table HTML.
+ * @ingroup themeable
+ */
+function theme_node_recent_block($variables) {
+ $rows = array();
+ $output = '';
+
+ $l_options = array('query' => drupal_get_destination());
+ foreach ($variables['nodes'] as $node) {
+ $row = array();
+ $row[] = theme('node_recent_content', array('node' => $node));
+ $row[] = node_access('update', $node) ? l(t('edit'), 'node/' . $node->nid . '/edit', $l_options) : '';
+ $row[] = node_access('delete', $node) ? l(t('delete'), 'node/' . $node->nid . '/delete', $l_options) : '';
+ $rows[] = $row;
+ }
+
+ if ($rows) {
+ $output = theme('table', array('rows' => $rows));
+ $output .= '' . l(t('Show all content'), 'admin/content') . '
';
+ }
+
+ return $output;
+}
+
+/**
+ * Returns a formatted recent node to be displayed in the recent content block.
+ *
+ * @return
+ * The recent content node's HTML.
+ * @ingroup themeable
+ */
+function theme_node_recent_content($variables) {
+ $node = $variables['node'];
+
+ $output = '';
+ $output .= l($node->title[FIELD_LANGUAGE_NONE][0]['safe'], 'node/' . $node->nid);
+ $output .= theme('mark', array('type' => node_mark($node->nid, $node->changed)));
+ $output .= '
';
+ $output .= theme('username', array('account' => user_load($node->uid)));
+ $output .= '
';
+
+ return $output;
+}
+
+/**
* A generic function for generating RSS feeds from a set of nodes.
*
* @param $nids