Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1027 diff -u -p -r1.1027 node.module --- modules/node/node.module 26 Feb 2009 07:30:27 -0000 1.1027 +++ modules/node/node.module 7 Mar 2009 21:52:43 -0000 @@ -1880,6 +1880,7 @@ function node_block_list() { $blocks['syndicate']['info'] = t('Syndicate'); // Not worth caching. $blocks['syndicate']['cache'] = BLOCK_NO_CACHE; + $blocks['recent']['info'] = t('Recent content'); return $blocks; } @@ -1887,12 +1888,54 @@ function node_block_list() { * Implementation of hook_block_view(). */ function node_block_view($delta = '') { - $block['subject'] = t('Syndicate'); - $block['content'] = theme('feed_icon', url('rss.xml'), t('Syndicate')); - + $block = array(); + + switch ($delta) { + case 'syndicate': + $block['subject'] = t('Syndicate'); + $block['content'] = theme('feed_icon', url('rss.xml'), t('Syndicate')); + break; + + case 'recent': + if (user_access('access content')) { + $block['subject'] = t('Recent content'); + $items = array(); + $select = db_select('node', 'n') + ->fields('n', array('created', 'nid', 'title')) + ->orderBy('created', 'DESC') + ->range(0, variable_get('node_recent_block_count', 10)) + ->addTag('node_access') + ->execute(); + while ($node = $select->fetch(PDO::FETCH_ASSOC)) { + $item = l($node['title'], 'node/' . $node['nid']); + $item .= '
'; + $item .= t('@time ago', array('@time' => format_interval(REQUEST_TIME - $node['created']))); + $items[] = $item; + } + if (count($items)) { + $block['content'] = theme('item_list', $items); + } + } + break; + + } return $block; } +function node_block_configure($delta = '') { + $form = array(); + if ($delta == 'recent') { + $form['node_recent_block_count'] = array( + '#type' => 'select', + '#title' => t('Amount of recent content'), + '#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)), + '#description' => t('Pieces of content displayed in the Recently posted block.'), + ); + } + return $form; +} + /** * A generic function for generating RSS feeds from a set of nodes. * Index: modules/node/node.test =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.test,v retrieving revision 1.16 diff -u -p -r1.16 node.test --- modules/node/node.test 28 Jan 2009 07:34:30 -0000 1.16 +++ modules/node/node.test 7 Mar 2009 21:52:43 -0000 @@ -18,6 +18,11 @@ class NodeLoadMultipleUnitTest extends D parent::setUp(); $web_user = $this->drupalCreateUser(array('create article content', 'create page content')); $this->drupalLogin($web_user); + // Disable the "recent content" block, it will mess up our assertions if enabled. + db_delete('block') + ->condition('module', 'node') + ->condition('delta', 'recent') + ->execute(); } /** @@ -635,3 +640,101 @@ class NodeRSSContentTestCase extends Dru $this->assertText($test_text, t('Extra node content appears in RSS feed.')); } } + +class RecentContentBlockTestCase extends DrupalWebTestCase { + protected $nodes; + + /** + * Implementation of getInfo(). + */ + function getInfo() { + return array( + 'name' => t('Recent content block'), + 'description' => t('Test to make sure the recent content block works properly; it makes sure that nodes appear there, in the correct order, and the settings work properly.'), + 'group' => t('Node'), + ); + } + + function setUp() { + // Clear the static $nodes cache. + $this->nodes = array(); + parent::setUp(); + } + + /** + * Test the recent content block with a few nodes, less than the maximum. + */ + function testRecentContentBlock() { + $this->createTestNodes(3); + $this->assertRecentContent(); + } + + /** + * Test the recent content block with a lot of nodes, moer than the maximum. + */ + function testRecentContentBlockOverflow() { + $this->createTestNodes(18); + $this->assertRecentContent(); + } + + /** + * Test the recent content block with a non-standard maximum number of nodes. + */ + function testRecentContentBlockSettings() { + variable_set('node_recent_block_count', 20); + $this->createTestNodes(18); + $this->assertRecentContent(); + } + + /** + * Test the recent content block with a non-standard maximum number of nodes, + * and have more nodes than that custom maximum. + */ + function testRecentContentBlockSettingsOverflow() { + variable_set('node_recent_block_count', 5); + $this->createTestNodes(18); + $this->assertRecentContent(); + } + + /** + * Create a number of nodes, and store them in the protected $nodes array. + * + * @param $count + * The number of nodes to create. + */ + protected function createTestNodes($count) { + $time = REQUEST_TIME - 600; + for ($i = 0; $i < $count; $i++) { + $this->nodes[($count - $i) - 1] = $this->drupalCreateNode(array('created' => REQUEST_TIME + $i)); + } + } + + /** + * Helper assertion that makes sure the nodes appear on the block correctly. + */ + protected function assertRecentContent() { + $this->refreshVariables(); + $count = variable_get('node_recent_block_count', 10); + $this->drupalGet(''); + $results = $this->elements->xpath('//div[@id="block-node-recent"]'); + $div = $results[0]; + if (!count($this->nodes)) { + $this->assertFalse($div, t('Block does not appear when no nodes exist.')); + return; + } + $this->assertTrue($div, t('Block appears when several nodes exist.')); + $title = $div->h2; + $this->assertEqual($title, t('Recently posted'), t('Title of the block matches correctly.')); + // Under the block div, we have the
, and then another + // div surrounding the themed item list before we get to the ul. + $ul = $div->div->div->ul; + $this->assertEqual(count($ul->li), min(count($this->nodes), $count), t('The correct number of nodes are shown.')); + for ($i = 0; $i < $count; $i++) { + if (isset($this->nodes[$i])) { + $list_item = $ul->li[$i]; + $link = $list_item->a; + $this->assertEqual($link, $this->nodes[$i]->title, t('The correct node title is shown.')); + } + } + } +} Index: modules/search/search.test =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.test,v retrieving revision 1.15 diff -u -p -r1.15 search.test --- modules/search/search.test 22 Jan 2009 04:49:58 -0000 1.15 +++ modules/search/search.test 7 Mar 2009 21:52:44 -0000 @@ -252,6 +252,13 @@ class SearchAdvancedSearchForm extends D // and searching has to happen in the same request, so running the shutdown // function manually is needed to finish the indexing process. search_update_totals(); + + // Remove the "recent content" block because it will mess up our assertions + // later if enabled. + db_delete('block') + ->condition('module', 'node') + ->condition('delta', 'recent') + ->execute(); } /** Index: modules/tracker/tracker.test =================================================================== RCS file: /cvs/drupal/drupal/modules/tracker/tracker.test,v retrieving revision 1.6 diff -u -p -r1.6 tracker.test --- modules/tracker/tracker.test 9 Feb 2009 16:27:35 -0000 1.6 +++ modules/tracker/tracker.test 7 Mar 2009 21:52:44 -0000 @@ -20,6 +20,12 @@ class TrackerTest extends DrupalWebTestC $permissions = array('access comments', 'post comments', 'post comments without approval'); $this->user = $this->drupalCreateUser($permissions); $this->other_user = $this->drupalCreateUser($permissions); + // Remove the "recent content" block because it will mess up our assertions + // later on if enabled. + db_delete('block') + ->condition('module', 'node') + ->condition('delta', 'recent') + ->execute(); } /** Index: profiles/default/default.profile =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v retrieving revision 1.37 diff -u -p -r1.37 default.profile --- profiles/default/default.profile 3 Feb 2009 12:30:14 -0000 1.37 +++ profiles/default/default.profile 7 Mar 2009 21:52:44 -0000 @@ -91,9 +91,10 @@ function default_profile_task_list() { */ function default_profile_tasks(&$task, $url) { - // Enable 3 standard blocks. + // Enable 4 standard blocks. db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'user', 'login', 'garland', 1, 0, 'left', '', -1); db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'user', 'navigation', 'garland', 1, 0, 'left', '', -1); + db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'node', 'recent', 'garland', 1, 0, 'left', '', -1); db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'system', 'powered-by', 'garland', 1, 10, 'footer', '', -1); // Insert default user-defined node types into the database. For a complete