? no_op_in_hook_block_2.patch
? no_op_in_hook_block_part2.patch
? sites
Index: modules/block/block.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v
retrieving revision 1.31
diff -u -p -r1.31 block.admin.inc
--- modules/block/block.admin.inc	22 Nov 2008 11:14:48 -0000	1.31
+++ modules/block/block.admin.inc	16 Dec 2008 20:17:22 -0000
@@ -171,14 +171,14 @@ function block_admin_configure(&$form_st
   );
 
   // Module-specific block configurations.
-  if ($settings = module_invoke($module, 'block', 'configure', $delta)) {
+  if ($settings = module_invoke($module, 'block_configure', $delta)) {
     foreach ($settings as $k => $v) {
       $form['block_settings'][$k] = $v;
     }
   }
 
   // Get the block subject for the page title.
-  $info = module_invoke($module, 'block', 'list');
+  $info = module_invoke($module, 'block_list');
   if (isset($info[$delta])) {
     drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])), PASS_THROUGH);
   }
@@ -285,7 +285,7 @@ function block_admin_configure_submit($f
     foreach (array_filter($form_state['values']['roles']) as $rid) {
       db_query("INSERT INTO {block_role} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_state['values']['module'], $form_state['values']['delta']);
     }
-    module_invoke($form_state['values']['module'], 'block', 'save', $form_state['values']['delta'], $form_state['values']);
+    module_invoke($form_state['values']['module'], 'block_save', $form_state['values']['delta'], $form_state['values']);
     drupal_set_message(t('The block configuration has been saved.'));
     cache_clear_all();
     $form_state['redirect'] = 'admin/build/block';
Index: modules/block/block.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.api.php,v
retrieving revision 1.1
diff -u -p -r1.1 block.api.php
--- modules/block/block.api.php	25 Nov 2008 02:37:31 -0000	1.1
+++ modules/block/block.api.php	16 Dec 2008 20:17:22 -0000
@@ -12,87 +12,85 @@
  */
 
 /**
- * Declare a block or set of blocks.
+ * List of all blocks defined by the module.
  *
  * Any module can export a block (or blocks) to be displayed by defining
  * the _block hook. This hook is called by theme.inc to display a block,
  * and also by block.module to procure the list of available blocks.
  *
- * @param $op
- *   What kind of information to retrieve about the block or blocks.
- *   Possible values:
- *   - 'list': A list of all blocks defined by the module.
- *   - 'configure': Configuration form for the block.
- *   - 'save': Save the configuration options.
- *   - 'view': Process the block when enabled in a region in order to view its contents.
- * @param $delta
- *   Which block to return (not applicable if $op is 'list'). This is a
- *   descriptive string used to identify blocks within each module and also
- *   within the theme system. The $delta for each block is defined within
- *   the array that your module returns when $op is 'list' (see below).
- * @param $edit
- *   If $op is 'save', the submitted form data from the configuration form.
  * @return
- *   - If $op is 'list': An associative array whose keys define the $delta
- *     for each block and whose values contain the block descriptions. Each
- *     block description is itself an associative array, with the following
- *     key-value pairs:
- *     - 'info': (required) The human-readable name of the block.
- *     - 'cache': A bitmask of flags describing how the block should behave with
- *       respect to block caching. The following shortcut bitmasks are provided
- *       as constants in block.module:
- *       - BLOCK_CACHE_PER_ROLE (default): The block can change depending on the
- *         roles the user viewing the page belongs to.
- *       - BLOCK_CACHE_PER_USER: The block can change depending on the user
- *         viewing the page. This setting can be resource-consuming for sites
- *         with large number of users, and should only be used when
- *         BLOCK_CACHE_PER_ROLE is not sufficient.
- *       - BLOCK_CACHE_PER_PAGE: The block can change depending on the page
- *         being viewed.
- *       - BLOCK_CACHE_GLOBAL: The block is the same for every user on every
- *         page where it is visible.
- *       - BLOCK_NO_CACHE: The block should not get cached.
- *     - 'weight', 'status', 'region', 'visibility', 'pages':
- *       You can give your blocks an explicit weight, enable them, limit them to
- *       given pages, etc. These settings will be registered when the block is first
- *       loaded at admin/block, and from there can be changed manually via block
- *       administration.
- *       Note that if you set a region that isn't available in a given theme, the
- *       block will be registered instead to that theme's default region (the first
- *       item in the _regions array).
- *   - If $op is 'configure': optionally return the configuration form.
- *   - If $op is 'save': return nothing.
- *   - If $op is 'view': return an array which must define a 'subject' element
- *     and a 'content' element defining the block indexed by $delta.
- *
- * The functions mymodule_display_block_exciting and _amazing, as used in the
- * example, should of course be defined somewhere in your module and return the
- * content you want to display to your users. If the "content" element is empty,
- * no block will be displayed even if "subject" is present.
+ *   An associative array whose keys define the $delta
+ *   for each block and whose values contain the block descriptions. Each
+ *   block description is itself an associative array, with the following
+ *   key-value pairs:
+ *   - 'info': (required) The human-readable name of the block.
+ *   - 'cache': A bitmask of flags describing how the block should behave with
+ *     respect to block caching. The following shortcut bitmasks are provided
+ *     as constants in block.module:
+ *     - BLOCK_CACHE_PER_ROLE (default): The block can change depending on the
+ *       roles the user viewing the page belongs to.
+ *     - BLOCK_CACHE_PER_USER: The block can change depending on the user
+ *       viewing the page. This setting can be resource-consuming for sites
+ *       with large number of users, and should only be used when
+ *       BLOCK_CACHE_PER_ROLE is not sufficient.
+ *     - BLOCK_CACHE_PER_PAGE: The block can change depending on the page
+ *       being viewed.
+ *     - BLOCK_CACHE_GLOBAL: The block is the same for every user on every
+ *       page where it is visible.
+ *     - BLOCK_NO_CACHE: The block should not get cached.
+ *   - 'weight', 'status', 'region', 'visibility', 'pages':
+ *     You can give your blocks an explicit weight, enable them, limit them to
+ *     given pages, etc. These settings will be registered when the block is first
+ *     loaded at admin/block, and from there can be changed manually via block
+ *     administration.
+ *     Note that if you set a region that isn't available in a given theme, the
+ *     block will be registered instead to that theme's default region (the first
+ *     item in the _regions array).
  *
  * After completing your blocks, do not forget to enable them in the
  * block admin menu.
  *
  * For a detailed usage example, see block_example.module.
  */
-function hook_block($op = 'list', $delta = '', $edit = array()) {
-  if ($op == 'list') {
-    $blocks['exciting'] = array(
-      'info' => t('An exciting block provided by Mymodule.'),
-      'weight' => 0,
-      'status' => 1,
-      'region' => 'left',
-      // BLOCK_CACHE_PER_ROLE will be assumed for block 0.
-    );
+function hook_block_list() {
+  $blocks['exciting'] = array(
+    'info' => t('An exciting block provided by Mymodule.'),
+    'weight' => 0,
+    'status' => 1,
+    'region' => 'left',
+    // BLOCK_CACHE_PER_ROLE will be assumed for block 0.
+  );
 
-    $blocks['amazing'] = array(
-      'info' => t('An amazing block provided by Mymodule.'),
-      'cache' => BLOCK_CACHE_PER_ROLE | BLOCK_CACHE_PER_PAGE,
-    );
+  $blocks['amazing'] = array(
+    'info' => t('An amazing block provided by Mymodule.'),
+    'cache' => BLOCK_CACHE_PER_ROLE | BLOCK_CACHE_PER_PAGE,
+  );
 
-    return $blocks;
-  }
-  elseif ($op == 'configure' && $delta == 'exciting') {
+  return $blocks;
+}
+
+/**
+ * Configuration form for the block.
+ *
+ * Any module can export a block (or blocks) to be displayed by defining
+ * the _block hook. This hook is called by theme.inc to display a block,
+ * and also by block.module to procure the list of available blocks.
+ *
+ * @param $delta
+ *   Which block to return. This is a descriptive string used to identify 
+ *   blocks within each module and also within the theme system.
+ *   The $delta for each block is defined within the array that your module
+ *   returns when the hook_block_list() implementation is called.
+ * @return
+ *   Optionally return the configuration form.
+ *
+ * After completing your blocks, do not forget to enable them in the
+ * block admin menu.
+ *
+ * For a detailed usage example, see block_example.module.
+ */
+function hook_block_configure($delta = '') {
+  if ($delta == 'exciting') {
     $form['items'] = array(
       '#type' => 'select',
       '#title' => t('Number of items'),
@@ -101,26 +99,76 @@ function hook_block($op = 'list', $delta
     );
     return $form;
   }
-  elseif ($op == 'save' && $delta == 'exciting') {
+}
+
+/**
+ * Save the configuration options.
+ *
+ * Any module can export a block (or blocks) to be displayed by defining
+ * the _block hook. This hook is called by theme.inc to display a block,
+ * and also by block.module to procure the list of available blocks.
+ *
+ * @param $delta
+ *   Which block to save the settings for. This is a descriptive string used
+ *   to identify blocks within each module and also within the theme system.
+ *   The $delta for each block is defined within the array that your module
+ *   returns when the hook_block_list() implementation is called.
+ * @param $edit
+ *   The submitted form data from the configuration form.
+ *
+ * After completing your blocks, do not forget to enable them in the
+ * block admin menu.
+ *
+ * For a detailed usage example, see block_example.module.
+ */
+function hook_block_save($delta = '', $edit = array()) {
+  if ($delta == 'exciting') {
     variable_set('mymodule_block_items', $edit['items']);
   }
-  elseif ($op == 'view') {
-    switch ($delta) {
-      case 'exciting':
-        $block = array(
-          'subject' => t('Default title of the exciting block'),
-          'content' => mymodule_display_block_exciting(),
-        );
-        break;
-      case 'amazing':
-        $block = array(
-          'subject' => t('Default title of the amazing block'),
-          'content' => mymodule_display_block_amazing(),
-        );
-        break;
-    }
-    return $block;
+}
+
+/**
+ * Process the block when enabled in a region in order to view its contents.
+ *
+ * Any module can export a block (or blocks) to be displayed by defining
+ * the _block hook. This hook is called by theme.inc to display a block,
+ * and also by block.module to procure the list of available blocks.
+ *
+ * @param $delta
+ *   Which block to return. This is a descriptive string used to identify 
+ *   blocks within each module and also within the theme system.
+ *   The $delta for each block is defined within the array that your module
+ *   returns when the hook_block_list() implementation is called.
+ * @return
+ *   An array which must define a 'subject' element and a 'content' element
+ *   defining the block indexed by $delta.
+ *
+ * The functions mymodule_display_block_exciting and _amazing, as used in the
+ * example, should of course be defined somewhere in your module and return the
+ * content you want to display to your users. If the "content" element is empty,
+ * no block will be displayed even if "subject" is present.
+ *
+ * After completing your blocks, do not forget to enable them in the
+ * block admin menu.
+ *
+ * For a detailed usage example, see block_example.module.
+ */
+function hook_block_view($delta = '') {
+  switch ($delta) {
+    case 'exciting':
+      $block = array(
+        'subject' => t('Default title of the exciting block'),
+        'content' => mymodule_display_block_exciting(),
+      );
+      break;
+    case 'amazing':
+      $block = array(
+        'subject' => t('Default title of the amazing block'),
+        'content' => mymodule_display_block_amazing(),
+      );
+      break;
   }
+  return $block;
 }
 
 /**
Index: modules/block/block.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.install,v
retrieving revision 1.16
diff -u -p -r1.16 block.install
--- modules/block/block.install	3 Dec 2008 16:32:21 -0000	1.16
+++ modules/block/block.install	16 Dec 2008 20:17:22 -0000
@@ -166,4 +166,11 @@ function block_schema() {
   $schema['cache_block']['description'] = 'Cache table for the Block module to store already built blocks, identified by module, delta, and various contexts which may change the block, such as theme, locale, and caching mode defined for the block.';
 
   return $schema;
-}
\ No newline at end of file
+}
+
+/**
+ * Refresh the block cache.
+ */
+function block_update_7000() {
+  return array();
+}
Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.315
diff -u -p -r1.315 block.module
--- modules/block/block.module	15 Nov 2008 08:23:07 -0000	1.315
+++ modules/block/block.module	16 Dec 2008 20:17:22 -0000
@@ -180,42 +180,55 @@ function _block_themes_access($theme) {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
- * Generates the administrator-defined blocks for display.
+ * Generates a list of the administrator-defined blocks.
  */
-function block_block($op = 'list', $delta = 0, $edit = array()) {
-  switch ($op) {
-    case 'list':
-      $blocks = array();
-
-      $result = db_query('SELECT bid, info FROM {box} ORDER BY info');
-      while ($block = db_fetch_object($result)) {
-        $blocks[$block->bid]['info'] = $block->info;
-        // Not worth caching.
-        $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE;
-      }
-      return $blocks;
+function block_block_list() {
+  $blocks = array();
 
-    case 'configure':
-      $box = array('format' => FILTER_FORMAT_DEFAULT);
-      if ($delta) {
-        $box = block_box_get($delta);
-      }
-      if (filter_access($box['format'])) {
-        return block_box_form($box);
-      }
-      break;
+  $result = db_query('SELECT bid, info FROM {box} ORDER BY info');
+  while ($block = db_fetch_object($result)) {
+    $blocks[$block->bid]['info'] = $block->info;
+    // Not worth caching.
+    $blocks[$block->bid]['cache'] = BLOCK_NO_CACHE;
+  }
+  return $blocks;
+}
 
-    case 'save':
-      block_box_save($edit, $delta);
-      break;
-
-    case 'view':
-      $block = db_fetch_object(db_query('SELECT body, format FROM {box} WHERE bid = %d', $delta));
-      $data['content'] = check_markup($block->body, $block->format, '', FALSE);
-      return $data;
+/**
+ * Implementation of hook_block_configure().
+ *
+ * Generates the configure for administrator-defined blocks.
+ */
+function block_block_configure($delta = 0, $edit = array()) {
+  $box = array('format' => FILTER_FORMAT_DEFAULT);
+  if ($delta) {
+    $box = block_box_get($delta);
   }
+  if (filter_access($box['format'])) {
+    return block_box_form($box);
+  }
+}
+
+/**
+ * Implementation of hook_block_save().
+ *
+ * Saves administrator-defined blocks.
+ */
+function block_block_save($delta = 0, $edit = array()) {
+  block_box_save($edit, $delta);
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Generates the administrator-defined blocks for display.
+ */
+function block_block_view($delta = 0, $edit = array()) {
+  $block = db_fetch_object(db_query('SELECT body, format FROM {box} WHERE bid = %d', $delta));
+  $data['content'] = check_markup($block->body, $block->format, '', FALSE);
+  return $data;
 }
 
 /**
@@ -239,8 +252,8 @@ function _block_rehash() {
   // Valid region names for the theme.
   $regions = system_region_list($theme_key);
 
-  foreach (module_implements('block') as $module) {
-    $module_blocks = module_invoke($module, 'block', 'list');
+  foreach (module_implements('block_list') as $module) {
+    $module_blocks = module_invoke($module, 'block_list');
     if ($module_blocks) {
       foreach ($module_blocks as $delta => $block) {
         if (empty($old_blocks[$module][$delta])) {
@@ -349,7 +362,7 @@ function block_user_form(&$edit, &$accou
     $result = db_query("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom != 0 AND (r.rid IN (" . db_placeholders($rids) . ") OR r.rid IS NULL) ORDER BY b.weight, b.module", $rids);
     $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE);
     while ($block = db_fetch_object($result)) {
-      $data = module_invoke($block->module, 'block', 'list');
+      $data = module_invoke($block->module, 'block_list');
       if ($data[$block->delta]['info']) {
         $return = TRUE;
         $form['block'][$block->module][$block->delta] = array('#type' => 'checkbox', '#title' => check_plain($data[$block->delta]['info']), '#default_value' => isset($account->block[$block->module][$block->delta]) ? $account->block[$block->module][$block->delta] : ($block->custom == 1));
@@ -483,7 +496,7 @@ function _block_render_blocks($region_bl
           $array = $cache->data;
         }
         else {
-          $array = module_invoke($block->module, 'block', 'view', $block->delta);
+          $array = module_invoke($block->module, 'block_view', $block->delta);
           if (isset($cid)) {
             cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY);
           }
Index: modules/block/block.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.test,v
retrieving revision 1.6
diff -u -p -r1.6 block.test
--- modules/block/block.test	25 Nov 2008 13:14:26 -0000	1.6
+++ modules/block/block.test	16 Dec 2008 20:17:22 -0000
@@ -2,6 +2,8 @@
 // $Id: block.test,v 1.6 2008/11/25 13:14:26 dries Exp $
 
 class BlockTestCase extends DrupalWebTestCase {
+  protected $regions;
+
   function getInfo() {
     return array(
       'name' => t('Block functionality'),
@@ -16,6 +18,14 @@ class BlockTestCase extends DrupalWebTes
     // Create and login user
     $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer filters'));
     $this->drupalLogin($admin_user);
+
+    // Define the exising regions
+    $this->regions = array();
+    $this->regions[] = array('name' => 'header', 'id' => 'header-region');
+    $this->regions[] = array('name' => 'left', 'id' => 'sidebar-left');
+    $this->regions[] = array('name' => 'content', 'id' => 'center');
+    $this->regions[] = array('name' => 'right', 'id' => 'sidebar-right');
+    $this->regions[] = array('name' => 'footer');
   }
 
   /**
@@ -36,17 +46,12 @@ class BlockTestCase extends DrupalWebTes
     // Check to see if the box was created by checking that it's in the database..
     $this->assertNotNull($bid, t('Box found in database'));
 
-    // Set the created box to a specific region.
-    // TODO: Implement full region checking.
-    $edit = array();
-    $edit['block_' . $bid . '[region]'] = 'left';
-    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
-
-    // Confirm that the box was moved to the proper region.
-    $this->assertText(t('The block settings have been updated.'), t('Box successfully moved to left region.'));
-
-    // Confirm that the box is being displayed.
-    $this->assertText(t($box['title']), t('Box successfully being displayed on the page.'));
+    // Check if the block can be moved to all availble regions.
+    $box['module'] = 'block';
+    $box['delta'] = $bid;
+    foreach ($this->regions as $region) {
+      $this->moveBlockToRegion($box, $region);
+    }
 
     // Delete the created box & verify that it's been deleted and no longer appearing on the page.
     $this->drupalPost('admin/build/block/delete/' . $bid, array(), t('Delete'));
@@ -94,17 +99,10 @@ class BlockTestCase extends DrupalWebTes
     // Check to see if the block was created by checking that it's in the database.
     $this->assertNotNull($bid, t('Block found in database'));
 
-    // Set the created block to a specific region.
-    $edit = array();
-    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = 'left';
-    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
-
-    // Confirm that the block was moved to the proper region.
-    // TODO: Implement full region checking.
-    $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to left region.'));
-
-    // Confirm that the block is being displayed.
-    $this->assertText(t($block['title']), t('Block successfully being displayed on the page.'));
+    // Check if the block can be moved to all availble regions.
+    foreach ($this->regions as $region) {
+      $this->moveBlockToRegion($block, $region);
+    }
 
     // Set the block to the disabled region.
     $edit = array();
@@ -115,16 +113,41 @@ class BlockTestCase extends DrupalWebTes
     $this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
     $this->assertNoText(t($block['title']), t('Block no longer appears on page.'));
 
+    // Confirm that the regions xpath is not availble
+    $xpath = '//div[@id="block-block-' . $bid . '"]/*';
+    $this->assertNoFieldByXPath($xpath, FALSE, t('Box found in no regions. '));
+
     // For convenience of developers, put the navigation block back.
     $edit = array();
     $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = 'left';
     $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
-    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to left region.'));
 
     $this->drupalPost('admin/build/block/configure/' . $block['module'] . '/' . $block['delta'], array('title' => 'Navigation'), t('Save block'));
     $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
   }
 
+  function moveBlockToRegion($block, $region) {
+    // If an id for an region hasn't been specified, we assume it's the same as the name.
+    if (!(isset($region['id']))) {
+      $region['id'] = $region['name'];
+    }
+
+    // Set the created block to a specific region.
+    $edit = array();
+    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = $region['name'];
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block was moved to the proper region.
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array( '%region_name'=> $region['name'])));
+
+    // Confirm that the block is being displayed.
+    $this->assertText(t($block['title']), t('Block successfully being displayed on the page.'));
+
+    // Confirm that the box was found at the proper region.
+    $xpath = '//div[@id="' . $region['id'] . '"]//div[@id="block-' . $block['module'] . '-' . $block['delta'] . '"]/*';
+    $this->assertFieldByXPath($xpath, FALSE, t('Box found in %region_name region.', array('%region_name' => $region['name'])));
+  }
 }
 
 class NonDefaultBlockAdmin extends DrupalWebTestCase {
Index: modules/blog/blog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v
retrieving revision 1.313
diff -u -p -r1.313 blog.module
--- modules/blog/blog.module	9 Dec 2008 11:30:23 -0000	1.313
+++ modules/blog/blog.module	16 Dec 2008 20:17:22 -0000
@@ -165,25 +165,28 @@ function _blog_post_exists($account) {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Displays the most recent 10 blog titles.
  */
-function blog_block($op = 'list', $delta = '') {
+function blog_block_list() {
+  $block['recent']['info'] = t('Recent blog posts');
+  return $block;
+}
+
+/**
+ * Implementation of hook_block_view().
+ */
+function blog_block_view($delta = '') {
   global $user;
-  if ($op == 'list') {
-    $block['recent']['info'] = t('Recent blog posts');
-    return $block;
-  }
-  elseif ($op == 'view') {
-    if (user_access('access content')) {
-      $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, 10);
-      if ($node_title_list = node_title_list($result)) {
-        $block['content'] = $node_title_list;
-        $block['content'] .= theme('more_link', url('blog'), t('Read the latest blog entries.'));
-        $block['subject'] = t('Recent blog posts');
-        return $block;
-      }
+
+  if (user_access('access content')) {
+    $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, 10);
+    if ($node_title_list = node_title_list($result)) {
+      $block['content'] = $node_title_list;
+      $block['content'] .= theme('more_link', url('blog'), t('Read the latest blog entries.'));
+      $block['subject'] = t('Recent blog posts');
+      return $block;
     }
   }
 }
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.477
diff -u -p -r1.477 book.module
--- modules/book/book.module	9 Dec 2008 11:30:24 -0000	1.477
+++ modules/book/book.module	16 Dec 2008 20:17:23 -0000
@@ -180,84 +180,104 @@ function book_init() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Displays the book table of contents in a block when the current page is a
  * single-node view of a book node.
  */
-function book_block($op = 'list', $delta = '', $edit = array()) {
+function book_block_list() {
   $block = array();
-  switch ($op) {
-    case 'list':
-      $block['navigation']['info'] = t('Book navigation');
-      $block['navigation']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
-
-      return $block;
-
-    case 'view':
-      $current_bid = 0;
-      if ($node = menu_get_object()) {
-        $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid'];
-      }
-
-      if (variable_get('book_block_mode', 'all pages') == 'all pages') {
-        $block['subject'] = t('Book navigation');
-        $book_menus = array();
-        $pseudo_tree = array(0 => array('below' => FALSE));
-        foreach (book_get_books() as $book_id => $book) {
-          if ($book['bid'] == $current_bid) {
-            // If the current page is a node associated with a book, the menu
-            // needs to be retrieved.
-            $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book));
-          }
-          else {
-            // Since we know we will only display a link to the top node, there
-            // is no reason to run an additional menu tree query for each book.
-            $book['in_active_trail'] = FALSE;
-            $pseudo_tree[0]['link'] = $book;
-            $book_menus[$book_id] = menu_tree_output($pseudo_tree);
-          }
-        }
-        $block['content'] = theme('book_all_books_block', $book_menus);
+  $block['navigation']['info'] = t('Book navigation');
+  $block['navigation']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
+
+  return $block;
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Displays the book table of contents in a block when the current page is a
+ * single-node view of a book node.
+ */
+function book_block_view($delta = '') {
+  $block = array();
+  $current_bid = 0;
+  if ($node = menu_get_object()) {
+    $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid'];
+  }
+
+  if (variable_get('book_block_mode', 'all pages') == 'all pages') {
+    $block['subject'] = t('Book navigation');
+    $book_menus = array();
+    $pseudo_tree = array(0 => array('below' => FALSE));
+    foreach (book_get_books() as $book_id => $book) {
+      if ($book['bid'] == $current_bid) {
+        // If the current page is a node associated with a book, the menu
+        // needs to be retrieved.
+        $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book));
       }
-      elseif ($current_bid) {
-        // Only display this block when the user is browsing a book.
-        $select = db_select('node');
-        $select->addField('node', 'title');
-        $select->condition('nid', $node->book['bid']);
-        $select->addTag('node_access');
-        $title = $select->execute()->fetchField();
-        // Only show the block if the user has view access for the top-level node.
-        if ($title) {
-          $tree = menu_tree_all_data($node->book['menu_name'], $node->book);
-          // There should only be one element at the top level.
-          $data = array_shift($tree);
-          $block['subject'] = theme('book_title_link', $data['link']);
-          $block['content'] = ($data['below']) ? menu_tree_output($data['below']) : '';
-        }
+      else {
+        // Since we know we will only display a link to the top node, there
+        // is no reason to run an additional menu tree query for each book.
+        $book['in_active_trail'] = FALSE;
+        $pseudo_tree[0]['link'] = $book;
+        $book_menus[$book_id] = menu_tree_output($pseudo_tree);
       }
+    }
+    $block['content'] = theme('book_all_books_block', $book_menus);
+  }
+  elseif ($current_bid) {
+    // Only display this block when the user is browsing a book.
+    $select = db_select('node');
+    $select->addField('node', 'title');
+    $select->condition('nid', $node->book['bid']);
+    $select->addTag('node_access');
+    $title = $select->execute()->fetchField();
+    // Only show the block if the user has view access for the top-level node.
+    if ($title) {
+      $tree = menu_tree_all_data($node->book['menu_name'], $node->book);
+      // There should only be one element at the top level.
+      $data = array_shift($tree);
+      $block['subject'] = theme('book_title_link', $data['link']);
+      $block['content'] = ($data['below']) ? menu_tree_output($data['below']) : '';
+    }
+  }
 
-      return $block;
+  return $block;
+}
 
-    case 'configure':
-      $options = array(
-        'all pages' => t('Show block on all pages'),
-        'book pages' => t('Show block only on book pages'),
-      );
-      $form['book_block_mode'] = array(
-        '#type' => 'radios',
-        '#title' => t('Book navigation block display'),
-        '#options' => $options,
-        '#default_value' => variable_get('book_block_mode', 'all pages'),
-        '#description' => t("If <em>Show block on all pages</em> is selected, the block will contain the automatically generated menus for all of the site's books. If <em>Show block only on book pages</em> is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The <em>Page specific visibility settings</em> or other visibility settings can be used in addition to selectively display this block."),
-        );
+/**
+ * Implementation of hook_block_configure().
+ *
+ * Displays the book table of contents in a block when the current page is a
+ * single-node view of a book node.
+ */
+function book_block_configure($delta = '') {
+  $block = array();
+  $options = array(
+    'all pages' => t('Show block on all pages'),
+    'book pages' => t('Show block only on book pages'),
+  );
+  $form['book_block_mode'] = array(
+    '#type' => 'radios',
+    '#title' => t('Book navigation block display'),
+    '#options' => $options,
+    '#default_value' => variable_get('book_block_mode', 'all pages'),
+    '#description' => t("If <em>Show block on all pages</em> is selected, the block will contain the automatically generated menus for all of the site's books. If <em>Show block only on book pages</em> is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The <em>Page specific visibility settings</em> or other visibility settings can be used in addition to selectively display this block."),
+    );
 
-      return $form;
+  return $form;
+}
 
-    case 'save':
-      variable_set('book_block_mode', $edit['book_block_mode']);
-      break;
-  }
+/**
+ * Implementation of hook_block_save().
+ *
+ * Displays the book table of contents in a block when the current page is a
+ * single-node view of a book node.
+ */
+function book_block_save($delta = '', $edit = array()) {
+  $block = array();
+  variable_set('book_block_mode', $edit['book_block_mode']);
 }
 
 /**
Index: modules/book/book.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.test,v
retrieving revision 1.5
diff -u -p -r1.5 book.test
--- modules/book/book.test	5 Dec 2008 22:18:44 -0000	1.5
+++ modules/book/book.test	16 Dec 2008 20:17:23 -0000
@@ -153,3 +153,33 @@ class BookTestCase extends DrupalWebTest
     return $node;
   }
 }
+
+class BookBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the book navigation block is available.'),
+      'group' => t('Book'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('book');
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testBookNavigationBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/book/navigation', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['book_navigation[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.670
diff -u -p -r1.670 comment.module
--- modules/comment/comment.module	9 Dec 2008 11:30:24 -0000	1.670
+++ modules/comment/comment.module	16 Dec 2008 20:17:24 -0000
@@ -261,39 +261,53 @@ function comment_perm() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Generates a block with the most recent comments.
  */
-function comment_block($op = 'list', $delta = '', $edit = array()) {
-  switch ($op) {
-    case 'list':
-      $blocks['recent']['info'] = t('Recent comments');
-
-      return $blocks;
-
-    case 'configure':
-      $form['comment_block_count'] = array(
-        '#type' => 'select',
-        '#title' => t('Number of recent comments'),
-        '#default_value' => variable_get('comment_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('Number of comments displayed in the <em>Recent comments</em> block.'),
-      );
+function comment_block_list() {
+  $blocks['recent']['info'] = t('Recent comments');
 
-      return $form;
+  return $blocks;
+}
 
-    case 'save':
-      variable_set('comment_block_count', (int)$edit['comment_block_count']);
-      break;
+/**
+ * Implementation of hook_block_configure().
+ *
+ * Generates a block with the most recent comments.
+ */
+function comment_block_configure($delta = '') {
+  $form['comment_block_count'] = array(
+    '#type' => 'select',
+    '#title' => t('Number of recent comments'),
+    '#default_value' => variable_get('comment_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('Number of comments displayed in the <em>Recent comments</em> block.'),
+  );
 
-    case 'view':
-      if (user_access('access comments')) {
-        $block['subject'] = t('Recent comments');
-        $block['content'] = theme('comment_block');
+  return $form;
+}
 
-        return $block;
-      }
+/**
+ * Implementation of hook_block_save().
+ *
+ * Generates a block with the most recent comments.
+ */
+function comment_block_save($delta = '', $edit = array()) {
+  variable_set('comment_block_count', (int)$edit['comment_block_count']);
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Generates a block with the most recent comments.
+ */
+function comment_block_view($delta = '') {
+  if (user_access('access comments')) {
+    $block['subject'] = t('Recent comments');
+    $block['content'] = theme('comment_block');
+
+    return $block;
   }
 }
 
Index: modules/comment/comment.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.test,v
retrieving revision 1.20
diff -u -p -r1.20 comment.test
--- modules/comment/comment.test	28 Nov 2008 09:34:42 -0000	1.20
+++ modules/comment/comment.test	16 Dec 2008 20:17:24 -0000
@@ -546,3 +546,33 @@ class CommentApprovalTest extends Commen
     $this->assertTrue($this->commentExists($anonymous_comment4), t('Anonymous comment visible.'));
   }
 }
+
+class CommentBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the recent comments block is available.'),
+      'group' => t('Comment'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('comment');
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testRecentCommentBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/comment/recent', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['comment_recent[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.476
diff -u -p -r1.476 forum.module
--- modules/forum/forum.module	13 Dec 2008 14:05:11 -0000	1.476
+++ modules/forum/forum.module	16 Dec 2008 20:17:25 -0000
@@ -466,50 +466,67 @@ function forum_form_alter(&$form, $form_
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Generates a block containing the currently active forum topics and the
  * most recently added forum topics.
  */
-function forum_block($op = 'list', $delta = '', $edit = array()) {
-  switch ($op) {
-    case 'list':
-      $blocks['active']['info'] = t('Active forum topics');
-      $blocks['new']['info'] = t('New forum topics');
-      return $blocks;
-
-    case 'configure':
-      $form['forum_block_num_' . $delta] = array('#type' => 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_' . $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
-      return $form;
+function forum_block_list() {
+  $blocks['active']['info'] = t('Active forum topics');
+  $blocks['new']['info'] = t('New forum topics');
+  return $blocks;
+}
 
-    case 'save':
-      variable_set('forum_block_num_' . $delta, $edit['forum_block_num_' . $delta]);
-      break;
+/**
+ * Implementation of hook_block_configure().
+ *
+ * Generates a block containing the currently active forum topics and the
+ * most recently added forum topics.
+ */
+function forum_block_configure($delta = '') {
+  $form['forum_block_num_' . $delta] = array('#type' => 'select', '#title' => t('Number of topics'), '#default_value' => variable_get('forum_block_num_' . $delta, '5'), '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)));
+  return $form;
+}
 
-    case 'view':
-      if (user_access('access content')) {
-        switch ($delta) {
-          case 'active':
-            $title = t('Active forum topics');
-            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY l.last_comment_timestamp DESC");
-            $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_active', '5'));
-            $content = node_title_list($result);
-            break;
-
-          case 'new':
-            $title = t('New forum topics');
-            $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY n.nid DESC");
-            $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_new', '5'));
-            $content = node_title_list($result);
-            break;
-        }
-
-        if (!empty($content)) {
-          $block['subject'] = $title;
-          $block['content'] = $content . theme('more_link', url('forum'), t('Read the latest forum topics.'));
-          return $block;
-        }
-      }
+/**
+ * Implementation of hook_block_save().
+ *
+ * Generates a block containing the currently active forum topics and the
+ * most recently added forum topics.
+ */
+function forum_block_save($delta = '', $edit = array()) {
+  variable_set('forum_block_num_' . $delta, $edit['forum_block_num_' . $delta]);
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Generates a block containing the currently active forum topics and the
+ * most recently added forum topics.
+ */
+function forum_block_view($delta = '') {
+  if (user_access('access content')) {
+    switch ($delta) {
+      case 'active':
+        $title = t('Active forum topics');
+        $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY l.last_comment_timestamp DESC");
+        $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_active', '5'));
+        $content = node_title_list($result);
+        break;
+
+      case 'new':
+        $title = t('New forum topics');
+        $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY n.nid DESC");
+        $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_new', '5'));
+        $content = node_title_list($result);
+        break;
+    }
+
+    if (!empty($content)) {
+      $block['subject'] = $title;
+      $block['content'] = $content . theme('more_link', url('forum'), t('Read the latest forum topics.'));
+      return $block;
+    }
   }
 }
 
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.233
diff -u -p -r1.233 locale.module
--- modules/locale/locale.module	9 Dec 2008 11:36:03 -0000	1.233
+++ modules/locale/locale.module	16 Dec 2008 20:17:25 -0000
@@ -570,20 +570,25 @@ function locale_js_alter(&$javascript) {
 // Language switcher block
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  * Displays a language switcher. Translation links may be provided by other modules.
  */
-function locale_block($op = 'list', $delta = '') {
-  if ($op == 'list') {
-    $block['language-switcher']['info'] = t('Language switcher');
-    // Not worth caching.
-    $block['language-switcher']['cache'] = BLOCK_NO_CACHE;
-    return $block;
-  }
+function locale_block_list() {
+  $block['language-switcher']['info'] = t('Language switcher');
+  // Not worth caching.
+  $block['language-switcher']['cache'] = BLOCK_NO_CACHE;
+  return $block;
+}
 
-  // Only show if we have at least two languages and language dependent
-  // web addresses, so we can actually link to other language versions.
-  elseif ($op == 'view' && variable_get('language_count', 1) > 1 && variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE) != LANGUAGE_NEGOTIATION_NONE) {
+/**
+ * Implementation of hook_block_view().
+ *
+ * Displays a language switcher. Translation links may be provided by other modules.
+ * Only show if we have at least two languages and language dependent
+ * web addresses, so we can actually link to other language versions.
+ */
+function locale_block_view($delta = '') {
+  if (variable_get('language_count', 1) > 1 && variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE) != LANGUAGE_NEGOTIATION_NONE) {
     $path = drupal_is_front_page() ? '<front>' : $_GET['q'];
     $languages = language_list('enabled');
     $links = array();
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.175
diff -u -p -r1.175 menu.module
--- modules/menu/menu.module	13 Nov 2008 05:54:35 -0000	1.175
+++ modules/menu/menu.module	16 Dec 2008 20:17:25 -0000
@@ -257,28 +257,35 @@ function menu_reset_item($item) {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  */
-function menu_block($op = 'list', $delta = '') {
+function menu_block_list() {
   $menus = menu_get_menus();
   // The Navigation menu is handled by the user module.
   unset($menus['navigation']);
-  if ($op == 'list') {
-    $blocks = array();
-    foreach ($menus as $name => $title) {
-      // Default "Navigation" block is handled by user.module.
-      $blocks[$name]['info'] = check_plain($title);
-      // Menu blocks can't be cached because each menu item can have
-      // a custom access callback. menu.inc manages its own caching.
-      $blocks[$name]['cache'] = BLOCK_NO_CACHE;
-    }
-    return $blocks;
-  }
-  elseif ($op == 'view') {
-    $data['subject'] = check_plain($menus[$delta]);
-    $data['content'] = menu_tree($delta);
-    return $data;
+
+  $blocks = array();
+  foreach ($menus as $name => $title) {
+    // Default "Navigation" block is handled by user.module.
+    $blocks[$name]['info'] = check_plain($title);
+    // Menu blocks can't be cached because each menu item can have
+    // a custom access callback. menu.inc manages its own caching.
+    $blocks[$name]['cache'] = BLOCK_NO_CACHE;
   }
+  return $blocks;
+}
+
+/**
+ * Implementation of hook_block_view().
+ */
+function menu_block_view($delta = '') {
+  $menus = menu_get_menus();
+  // The Navigation menu is handled by the user module.
+  unset($menus['navigation']);
+
+  $data['subject'] = check_plain($menus[$delta]);
+  $data['content'] = menu_tree($delta);
+  return $data;
 }
 
 /**
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1001
diff -u -p -r1.1001 node.module
--- modules/node/node.module	5 Dec 2008 22:18:45 -0000	1.1001
+++ modules/node/node.module	16 Dec 2008 20:17:26 -0000
@@ -1792,21 +1792,23 @@ function node_revision_list($node) {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  */
-function node_block($op = 'list', $delta = '') {
-  if ($op == 'list') {
-    $blocks['syndicate']['info'] = t('Syndicate');
-    // Not worth caching.
-    $blocks['syndicate']['cache'] = BLOCK_NO_CACHE;
-    return $blocks;
-  }
-  elseif ($op == 'view') {
-    $block['subject'] = t('Syndicate');
-    $block['content'] = theme('feed_icon', url('rss.xml'), t('Syndicate'));
+function node_block_list() {
+  $blocks['syndicate']['info'] = t('Syndicate');
+  // Not worth caching.
+  $blocks['syndicate']['cache'] = BLOCK_NO_CACHE;
+  return $blocks;
+}
 
-    return $block;
-  }
+/**
+ * Implementation of hook_block_view().
+ */
+function node_block_view($delta = '') {
+  $block['subject'] = t('Syndicate');
+  $block['content'] = theme('feed_icon', url('rss.xml'), t('Syndicate'));
+
+  return $block;
 }
 
 /**
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.11
diff -u -p -r1.11 node.test
--- modules/node/node.test	12 Dec 2008 16:18:31 -0000	1.11
+++ modules/node/node.test	16 Dec 2008 20:17:26 -0000
@@ -507,3 +507,33 @@ class NodeTitleXSSTestCase extends Drupa
     $this->assertNoRaw($xss, t('Harmful tags are escaped when editing a node.'));
   }
 }
+
+class NodeBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the syndicate block is available.'),
+      'group' => t('Node'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testSearchFormBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/node/syndicate', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['node_syndicate[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.280
diff -u -p -r1.280 poll.module
--- modules/poll/poll.module	9 Dec 2008 11:30:24 -0000	1.280
+++ modules/poll/poll.module	16 Dec 2008 20:17:27 -0000
@@ -136,29 +136,35 @@ function _poll_menu_access($node, $perm,
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Generates a block containing the latest poll.
  */
-function poll_block($op = 'list', $delta = '') {
+function poll_block_list() {
   if (user_access('access content')) {
-    if ($op == 'list') {
-      $blocks['recent']['info'] = t('Most recent poll');
-      return $blocks;
-    }
-    elseif ($op == 'view') {
-      // Retrieve the latest poll.
-      $record = db_query_range(db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = :status AND p.active = :active ORDER BY n.created DESC"), array(':status' => 1, ':active' => 1), 0, 1)->fetch();
-      if ($record) {
-        $poll = node_load($record->nid);
-        if ($poll->nid) {
-          $poll = poll_view($poll, TRUE, FALSE, TRUE);
-        }
+    $blocks['recent']['info'] = t('Most recent poll');
+    return $blocks;
+  }
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Generates a block containing the latest poll.
+ */
+function poll_block_view($delta = '') {
+  if (user_access('access content')) {
+    // Retrieve the latest poll.
+    $record = db_query_range(db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = :status AND p.active = :active ORDER BY n.created DESC"), array(':status' => 1, ':active' => 1), 0, 1)->fetch();
+    if ($record) {
+      $poll = node_load($record->nid);
+      if ($poll->nid) {
+        $poll = poll_view($poll, TRUE, FALSE, TRUE);
       }
-      $block['subject'] = t('Poll');
-      $block['content'] = drupal_render($poll->content);
-      return $block;
     }
+    $block['subject'] = t('Poll');
+    $block['content'] = drupal_render($poll->content);
+    return $block;
   }
 }
 
Index: modules/poll/poll.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.test,v
retrieving revision 1.12
diff -u -p -r1.12 poll.test
--- modules/poll/poll.test	5 Dec 2008 22:18:45 -0000	1.12
+++ modules/poll/poll.test	16 Dec 2008 20:17:27 -0000
@@ -124,3 +124,32 @@ class PollVoteTestCase extends PollTestC
   }
 }
 
+class PollBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the most recent poll block is available.'),
+      'group' => t('Poll'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('poll');
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testRecentBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/poll/recent', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['poll_recent[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
Index: modules/profile/profile.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v
retrieving revision 1.247
diff -u -p -r1.247 profile.module
--- modules/profile/profile.module	5 Dec 2008 12:50:28 -0000	1.247
+++ modules/profile/profile.module	16 Dec 2008 20:17:27 -0000
@@ -126,70 +126,79 @@ function profile_menu() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  */
-function profile_block($op = 'list', $delta = '', $edit = array()) {
+function profile_block_list() {
+  $blocks['author-information']['info'] = t('Author information');
+  $blocks['author-information']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
+  return $blocks;
+}
 
-  if ($op == 'list') {
-    $blocks['author-information']['info'] = t('Author information');
-    $blocks['author-information']['cache'] = BLOCK_CACHE_PER_PAGE | BLOCK_CACHE_PER_ROLE;
-    return $blocks;
-  }
-  elseif ($op == 'configure') {
-    // Compile a list of fields to show
-    $fields = array();
-    $result = db_query('SELECT name, title, weight, visibility FROM {profile_field} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
-    while ($record = db_fetch_object($result)) {
-      $fields[$record->name] = check_plain($record->title);
-    }
-    $fields['user_profile'] = t('Link to full user profile');
-    $form['profile_block_author_fields'] = array(
-      '#type' => 'checkboxes',
-      '#title' => t('Profile fields to display'),
-      '#default_value' => variable_get('profile_block_author_fields', array()),
-      '#options' => $fields,
-      '#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the <a href="@profile-admin">profile field configuration</a> are available.', array('@profile-admin' => url('admin/user/profile'))),
-    );
-    return $form;
-  }
-  elseif ($op == 'save') {
-    variable_set('profile_block_author_fields', $edit['profile_block_author_fields']);
+/**
+ * Implementation of hook_block_configure().
+ */
+function profile_block_configure($delta = '') {
+  // Compile a list of fields to show
+  $fields = array();
+  $result = db_query('SELECT name, title, weight, visibility FROM {profile_field} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
+  while ($record = db_fetch_object($result)) {
+    $fields[$record->name] = check_plain($record->title);
   }
-  elseif ($op == 'view') {
-    if (user_access('access user profiles')) {
-      $output = '';
-      if ((arg(0) == 'node') && is_numeric(arg(1)) && (arg(2) == NULL)) {
-        $node = node_load(arg(1));
-        $account = user_load(array('uid' => $node->uid));
-
-        if ($use_fields = variable_get('profile_block_author_fields', array())) {
-          // Compile a list of fields to show.
-          $fields = array();
-          $result = db_query('SELECT name, title, type, visibility, weight FROM {profile_field} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
-          while ($record = db_fetch_object($result)) {
-            // Ensure that field is displayed only if it is among the defined block fields and, if it is private, the user has appropriate permissions.
-            if (isset($use_fields[$record->name]) && $use_fields[$record->name]) {
-              $fields[] = $record;
-            }
-          }
-        }
+  $fields['user_profile'] = t('Link to full user profile');
+  $form['profile_block_author_fields'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Profile fields to display'),
+    '#default_value' => variable_get('profile_block_author_fields', array()),
+    '#options' => $fields,
+    '#description' => t('Select which profile fields you wish to display in the block. Only fields designated as public in the <a href="@profile-admin">profile field configuration</a> are available.', array('@profile-admin' => url('admin/user/profile'))),
+  );
+  return $form;
+}
 
-        if (!empty($fields)) {
-          $profile = _profile_update_user_fields($fields, $account);
-          $output .= theme('profile_block', $account, $profile, TRUE);
-        }
+/**
+ * Implementation of hook_block_save().
+ */
+function profile_block_save($delta = '', $edit = array()) {
+  variable_set('profile_block_author_fields', $edit['profile_block_author_fields']);
+}
+
+/**
+ * Implementation of hook_block_view().
+ */
+function profile_block_view($delta = '') {
+  if (user_access('access user profiles')) {
+    $output = '';
+    if ((arg(0) == 'node') && is_numeric(arg(1)) && (arg(2) == NULL)) {
+      $node = node_load(arg(1));
+      $account = user_load(array('uid' => $node->uid));
 
-        if (isset($use_fields['user_profile']) && $use_fields['user_profile']) {
-          $output .= '<div>' . l(t('View full user profile'), 'user/' . $account->uid) . '</div>';
+      if ($use_fields = variable_get('profile_block_author_fields', array())) {
+        // Compile a list of fields to show.
+        $fields = array();
+        $result = db_query('SELECT name, title, type, visibility, weight FROM {profile_field} WHERE visibility IN (%d, %d) ORDER BY weight', PROFILE_PUBLIC, PROFILE_PUBLIC_LISTINGS);
+        while ($record = db_fetch_object($result)) {
+          // Ensure that field is displayed only if it is among the defined block fields and, if it is private, the user has appropriate permissions.
+          if (isset($use_fields[$record->name]) && $use_fields[$record->name]) {
+            $fields[] = $record;
+          }
         }
       }
 
-      if ($output) {
-        $block['subject'] = t('About %name', array('%name' => $account->name));
-        $block['content'] = $output;
-        return $block;
+      if (!empty($fields)) {
+        $profile = _profile_update_user_fields($fields, $account);
+        $output .= theme('profile_block', $account, $profile, TRUE);
+      }
+
+      if (isset($use_fields['user_profile']) && $use_fields['user_profile']) {
+        $output .= '<div>' . l(t('View full user profile'), 'user/' . $account->uid) . '</div>';
       }
     }
+
+    if ($output) {
+      $block['subject'] = t('About %name', array('%name' => $account->name));
+      $block['content'] = $output;
+      return $block;
+    }
   }
 }
 
Index: modules/profile/profile.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.test,v
retrieving revision 1.9
diff -u -p -r1.9 profile.test
--- modules/profile/profile.test	5 Dec 2008 12:50:28 -0000	1.9
+++ modules/profile/profile.test	16 Dec 2008 20:17:27 -0000
@@ -289,6 +289,36 @@ class ProfileTestAutocomplete extends Pr
   }
 }
 
+class ProfileBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the author-information block is available.'),
+      'group' => t('Profile'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('profile');
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testAuthorInformationBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/profile/author-information', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['profile_author-information[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
+
   /**
    * TODO:
    * - Test field visibility
Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.278
diff -u -p -r1.278 search.module
--- modules/search/search.module	9 Dec 2008 11:30:24 -0000	1.278
+++ modules/search/search.module	16 Dec 2008 20:17:27 -0000
@@ -158,16 +158,20 @@ function search_perm() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  */
-function search_block($op = 'list', $delta = '') {
-  if ($op == 'list') {
-    $blocks['form']['info'] = t('Search form');
-    // Not worth caching.
-    $blocks['form']['cache'] = BLOCK_NO_CACHE;
-    return $blocks;
-  }
-  elseif ($op == 'view' && user_access('search content')) {
+function search_block_list() {
+  $blocks['form']['info'] = t('Search form');
+  // Not worth caching.
+  $blocks['form']['cache'] = BLOCK_NO_CACHE;
+  return $blocks;
+}
+
+/**
+ * Implementation of hook_block_view().
+ */
+function search_block_view($delta = '') {
+  if (user_access('search content')) {
     $block['content'] = drupal_get_form('search_block_form');
     $block['subject'] = t('Search');
     return $block;
Index: modules/search/search.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.test,v
retrieving revision 1.12
diff -u -p -r1.12 search.test
--- modules/search/search.test	2 Dec 2008 21:24:34 -0000	1.12
+++ modules/search/search.test	16 Dec 2008 20:17:28 -0000
@@ -333,3 +333,33 @@ class SearchRankingTestCase extends Drup
     }
   }
 }
+
+class SearchBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block availability'),
+      'description' => t('Check if the search form block is available.'),
+      'group' => t('Search'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('search');
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  function testSearchFormBlock() {
+    // Set block title to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/search/form', array('title' => $this->randomName(8)), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the block to a region to confirm block is availble.
+    $edit = array();
+    $edit['search_form[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+  }
+}
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.650
diff -u -p -r1.650 system.module
--- modules/system/system.module	28 Nov 2008 09:25:59 -0000	1.650
+++ modules/system/system.module	16 Dec 2008 20:17:28 -0000
@@ -836,51 +836,71 @@ function system_user_timezone(&$edit, &$
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  *
  * Generate a block with a promotional link to Drupal.org.
  */
-function system_block($op = 'list', $delta = '', $edit = NULL) {
+function system_block_list() {
   $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png';
-  switch ($op) {
-    case 'list':
-      $blocks['powered-by'] = array(
-        'info' => t('Powered by Drupal'),
-        'weight' => '10',
-         // Not worth caching.
-        'cache' => BLOCK_NO_CACHE,
-      );
-      return $blocks;
-    case 'configure':
-      drupal_add_js(drupal_get_path('module', 'system') .'/system.js');
-      // Compile a list of fields to show
-      $form['wrapper']['color'] = array(
-        '#type' => 'select',
-        '#title' => t('Badge color'),
-        '#default_value' => variable_get('drupal_badge_color', 'powered-blue'),
-        '#options' => array('powered-black' => t('Black'), 'powered-blue' => t('Blue'), 'powered-gray' => t('Gray')),
-      );
-      $form['wrapper']['size'] = array(
-        '#type' => 'select',
-        '#title' => t('Badge size'),
-        '#default_value' => variable_get('drupal_badge_size', '80x15'),
-        '#options' => array('80x15' => t('Small'), '88x31' => t('Medium'), '135x42' => t('Large')),
-      );
-      $form['wrapper']['preview'] = array(
-        '#type' => 'item',
-        '#title' => 'Preview',
-        '#markup' => theme('image', $image_path, t('Powered by Drupal, an open source content management system'), t('Powered by Drupal, an open source content management system'), array('class' => 'powered-by-preview'), FALSE),
-      );
-      return $form;
-    case 'save':
-      variable_set('drupal_badge_color', $edit['color']);
-      variable_set('drupal_badge_size', $edit['size']);
-      break;
-    case 'view':
-      $block['subject'] = NULL; // Don't display a title
-      $block['content'] = theme('system_powered_by', $image_path);
-      return $block;
-  }
+  $blocks['powered-by'] = array(
+    'info' => t('Powered by Drupal'),
+    'weight' => '10',
+     // Not worth caching.
+    'cache' => BLOCK_NO_CACHE,
+  );
+  return $blocks;
+}
+
+/**
+ * Implementation of hook_block_configure().
+ *
+ * Generate a block with a promotional link to Drupal.org.
+ */
+function system_block_configure($delta = '') {
+  $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png';
+  drupal_add_js(drupal_get_path('module', 'system') .'/system.js');
+  // Compile a list of fields to show
+  $form['wrapper']['color'] = array(
+    '#type' => 'select',
+    '#title' => t('Badge color'),
+    '#default_value' => variable_get('drupal_badge_color', 'powered-blue'),
+    '#options' => array('powered-black' => t('Black'), 'powered-blue' => t('Blue'), 'powered-gray' => t('Gray')),
+  );
+  $form['wrapper']['size'] = array(
+    '#type' => 'select',
+    '#title' => t('Badge size'),
+    '#default_value' => variable_get('drupal_badge_size', '80x15'),
+    '#options' => array('80x15' => t('Small'), '88x31' => t('Medium'), '135x42' => t('Large')),
+  );
+  $form['wrapper']['preview'] = array(
+    '#type' => 'item',
+    '#title' => 'Preview',
+    '#markup' => theme('image', $image_path, t('Powered by Drupal, an open source content management system'), t('Powered by Drupal, an open source content management system'), array('class' => 'powered-by-preview'), FALSE),
+  );
+  return $form;
+}
+
+/**
+ * Implementation of hook_block_save().
+ *
+ * Generate a block with a promotional link to Drupal.org.
+ */
+function system_block_save($delta = '', $edit = NULL) {
+  $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png';
+  variable_set('drupal_badge_color', $edit['color']);
+  variable_set('drupal_badge_size', $edit['size']);
+}
+
+/**
+ * Implementation of hook_block_view().
+ *
+ * Generate a block with a promotional link to Drupal.org.
+ */
+function system_block_view($delta = '') {
+  $image_path = 'misc/' . variable_get('drupal_badge_color', 'powered-blue') . '-' . variable_get('drupal_badge_size', '80x15') . '.png';
+  $block['subject'] = NULL; // Don't display a title
+  $block['content'] = theme('system_powered_by', $image_path);
+  return $block;
 }
 
 /**
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.30
diff -u -p -r1.30 system.test
--- modules/system/system.test	9 Dec 2008 07:16:10 -0000	1.30
+++ modules/system/system.test	16 Dec 2008 20:17:29 -0000
@@ -631,3 +631,55 @@ class FrontPageTestCase extends DrupalWe
     $this->assertText(t('On front page.'), t('Path is the front page.'));
   }
 }
+
+class SystemBlockTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Block functionality'),
+      'description' => t('Configure and move powered-by block.'),
+      'group' => t('System'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Create and login user
+    $admin_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($admin_user);
+  }
+
+  /**
+   * Test displaying and hiding the powered-by block.
+   */
+  function testPoweredByBlock() {
+    // Set block title and some settings to confirm that the interface is availble.
+    $this->drupalPost('admin/build/block/configure/system/powered-by', array('title' => $this->randomName(8), 'color' => 'powered-black', 'size' => '135x42'), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+
+    // Set the powered-by block to the footer region.
+    $edit = array();
+    $edit['system_powered-by[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+
+    // Confirm that the block is being displayed.
+    $this->assertRaw('id="block-system-powered-by"', t('Block successfully being displayed on the page.'));
+
+    // Set the block to the disabled region.
+    $edit = array();
+    $edit['system_powered-by[region]'] = '-1';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block is hidden.
+    $this->assertNoRaw('id="block-system-powered-by"', t('Block no longer appears on page.'));
+
+    // For convenience of developers, set the block to it's default settings.
+    $edit = array();
+    $edit['system_powered-by[region]'] = 'footer';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->drupalPost('admin/build/block/configure/system/powered-by', array('title' => '', 'color' => 'powered-blue', 'size' => '80x15'), t('Save block'));
+  }
+
+}
+
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.944
diff -u -p -r1.944 user.module
--- modules/user/user.module	29 Nov 2008 09:33:51 -0000	1.944
+++ modules/user/user.module	16 Dec 2008 20:17:29 -0000
@@ -733,112 +733,135 @@ function user_login_block() {
 }
 
 /**
- * Implementation of hook_block().
+ * Implementation of hook_block_list().
  */
-function user_block($op = 'list', $delta = '', $edit = array()) {
+function user_block_list() {
   global $user;
 
-  if ($op == 'list') {
-    $blocks['login']['info'] = t('User login');
-    // Not worth caching.
-    $blocks['login']['cache'] = BLOCK_NO_CACHE;
-
-    $blocks['navigation']['info'] = t('Navigation');
-    // Menu blocks can't be cached because each menu item can have
-    // a custom access callback. menu.inc manages its own caching.
-    $blocks['navigation']['cache'] = BLOCK_NO_CACHE;
-
-    $blocks['new']['info'] = t('Who\'s new');
-
-    // Too dynamic to cache.
-    $blocks['online']['info'] = t('Who\'s online');
-    $blocks['online']['cache'] = BLOCK_NO_CACHE;
-    return $blocks;
-  }
-  elseif ($op == 'configure' && $delta == 'new') {
-    $form['user_block_whois_new_count'] = array(
-      '#type' => 'select',
-      '#title' => t('Number of users to display'),
-      '#default_value' => variable_get('user_block_whois_new_count', 5),
-      '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
-    );
-    return $form;
-  }
-  elseif ($op == 'configure' && $delta == 'online') {
-    $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval');
-    $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.'));
-    $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.'));
+  $blocks['login']['info'] = t('User login');
+  // Not worth caching.
+  $blocks['login']['cache'] = BLOCK_NO_CACHE;
 
-    return $form;
-  }
-  elseif ($op == 'save' && $delta == 'new') {
-    variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']);
+  $blocks['navigation']['info'] = t('Navigation');
+  // Menu blocks can't be cached because each menu item can have
+  // a custom access callback. menu.inc manages its own caching.
+  $blocks['navigation']['cache'] = BLOCK_NO_CACHE;
+
+  $blocks['new']['info'] = t('Who\'s new');
+
+  // Too dynamic to cache.
+  $blocks['online']['info'] = t('Who\'s online');
+  $blocks['online']['cache'] = BLOCK_NO_CACHE;
+  return $blocks;
+}
+
+/**
+ * Implementation of hook_block_configure().
+ */
+function user_block_configure($delta = '') {
+  global $user;
+
+  switch($delta) {
+    case 'new':
+      $form['user_block_whois_new_count'] = array(
+        '#type' => 'select',
+        '#title' => t('Number of users to display'),
+        '#default_value' => variable_get('user_block_whois_new_count', 5),
+        '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
+      );
+      return $form;
+
+    case 'online':
+      $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval');
+      $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.'));
+      $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.'));
+      return $form;
   }
-  elseif ($op == 'save' && $delta == 'online') {
-    variable_set('user_block_seconds_online', $edit['user_block_seconds_online']);
-    variable_set('user_block_max_list_count', $edit['user_block_max_list_count']);
+}
+
+/**
+ * Implementation of hook_block_save().
+ */
+function user_block_save($delta = '', $edit = array()) {
+  global $user;
+
+  switch ($delta) {
+    case 'new':
+      variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']);
+      break;
+
+    case 'online':
+      variable_set('user_block_seconds_online', $edit['user_block_seconds_online']);
+      variable_set('user_block_max_list_count', $edit['user_block_max_list_count']);
+      break;
   }
-  elseif ($op == 'view') {
-    $block = array();
+}
 
-    switch ($delta) {
-      case 'login':
-        // For usability's sake, avoid showing two login forms on one page.
-        if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
+/**
+ * Implementation of hook_block_view().
+ */
+function user_block_view($delta = '') {
+  global $user;
 
-          $block['subject'] = t('User login');
-          $block['content'] = drupal_get_form('user_login_block');
-        }
-        return $block;
+  $block = array();
 
-      case 'navigation':
-        if ($menu = menu_tree()) {
-          $block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation');
-          $block['content'] = $menu;
-        }
-        return $block;
+  switch ($delta) {
+    case 'login':
+      // For usability's sake, avoid showing two login forms on one page.
+      if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
 
-      case 'new':
-        if (user_access('access content')) {
-          // Retrieve a list of new users who have subsequently accessed the site successfully.
-          $items = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', array(), 0, variable_get('user_block_whois_new_count', 5))->fetchAll();
-          $output = theme('user_list', $items);
+        $block['subject'] = t('User login');
+        $block['content'] = drupal_get_form('user_login_block');
+      }
+      return $block;
 
-          $block['subject'] = t('Who\'s new');
-          $block['content'] = $output;
-        }
-        return $block;
+    case 'navigation':
+      if ($menu = menu_tree()) {
+        $block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation');
+        $block['content'] = $menu;
+      }
+      return $block;
+
+    case 'new':
+      if (user_access('access content')) {
+        // Retrieve a list of new users who have subsequently accessed the site successfully.
+        $items = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', array(), 0, variable_get('user_block_whois_new_count', 5))->fetchAll();
+        $output = theme('user_list', $items);
 
-      case 'online':
-        if (user_access('access content')) {
-          // Count users active within the defined period.
-          $interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900);
-
-          // Perform database queries to gather online user lists.  We use s.timestamp
-          // rather than u.access because it is much faster.
-          $anonymous_count = drupal_session_count($interval);
-          $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField();
-
-          // Format the output with proper grammar.
-          if ($anonymous_count == 1 && $authenticated_count == 1) {
-            $output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
-          }
-          else {
-            $output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
-          }
-
-          // Display a list of currently online users.
-          $max_users = variable_get('user_block_max_list_count', 10);
-          if ($authenticated_count && $max_users) {
-            $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', array(':interval' => $interval), 0, $max_users)->fetchAll();
-            $output .= theme('user_list', $items, t('Online users'));
-          }
+        $block['subject'] = t('Who\'s new');
+        $block['content'] = $output;
+      }
+      return $block;
 
-          $block['subject'] = t('Who\'s online');
-          $block['content'] = $output;
+    case 'online':
+      if (user_access('access content')) {
+        // Count users active within the defined period.
+        $interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900);
+
+        // Perform database queries to gather online user lists.  We use s.timestamp
+        // rather than u.access because it is much faster.
+        $anonymous_count = drupal_session_count($interval);
+        $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField();
+
+        // Format the output with proper grammar.
+        if ($anonymous_count == 1 && $authenticated_count == 1) {
+          $output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
         }
-        return $block;
-    }
+        else {
+          $output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
+        }
+
+        // Display a list of currently online users.
+        $max_users = variable_get('user_block_max_list_count', 10);
+        if ($authenticated_count && $max_users) {
+          $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', array(':interval' => $interval), 0, $max_users)->fetchAll();
+          $output .= theme('user_list', $items, t('Online users'));
+        }
+
+        $block['subject'] = t('Who\'s online');
+        $block['content'] = $output;
+      }
+      return $block;
   }
 }
 
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.22
diff -u -p -r1.22 user.test
--- modules/user/user.test	25 Nov 2008 13:14:29 -0000	1.22
+++ modules/user/user.test	16 Dec 2008 20:17:30 -0000
@@ -647,7 +647,7 @@ class UserBlocksUnitTests extends Drupal
     $this->insertSession();
 
     // Test block output.
-    $block = user_block('view', 'online');
+    $block = user_block_view('online');
     $this->drupalSetContent($block['content']);
     $this->assertRaw(t('%members and %visitors', array('%members' => '2 users', '%visitors' => '2 guests')), t('Correct number of online users (2 users and 2 guests).'));
     $this->assertText($user1->name, t('Active user 1 found in online list.'));
