Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.902 diff -u -p -r1.902 comment.module --- modules/comment/comment.module 3 Oct 2010 01:15:33 -0000 1.902 +++ modules/comment/comment.module 3 Oct 2010 07:54:32 -0000 @@ -442,6 +442,17 @@ function comment_block_view($delta = '') } /** + * Implements hook_dashboard_blocks(). + */ +function comment_dashboard_blocks() { + return array( + 'comment' => array( + 'recent' => DASHBOARD_BLOCK_AVAILABLE, + ), + ); +} + +/** * Redirects comment links to the correct page depending on comment settings. * * Since comments are paged there is no way to guarantee which page a comment Index: modules/dashboard/dashboard.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.api.php,v retrieving revision 1.1 diff -u -p -r1.1 dashboard.api.php --- modules/dashboard/dashboard.api.php 18 Oct 2009 11:20:26 -0000 1.1 +++ modules/dashboard/dashboard.api.php 3 Oct 2010 07:54:32 -0000 @@ -39,5 +39,22 @@ function hook_dashboard_regions_alter($r } /** + * Specifies blocks available to display on the dashboard. + * + * @return + * Array keyed by [module][delta]. Values should be DASHBOARD_BLOCK_DEFAULT + * if the block should show up by default, or DASHBOARD_BLOCK_AVAILABLE if + * the block should be available but not shown by default. + */ +function hook_dashboard_blocks() { + return array( + 'my_module' => array( + 'my_delta' => DASHBOARD_BLOCK_DEFAULT, + 'my_other_delta' => DASHBOARD_BLOCK_AVAILABLE, + ), + ); +} + +/** * @} End of "addtogroup hooks". */ Index: modules/dashboard/dashboard.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.module,v retrieving revision 1.39 diff -u -p -r1.39 dashboard.module --- modules/dashboard/dashboard.module 3 Oct 2010 00:14:57 -0000 1.39 +++ modules/dashboard/dashboard.module 3 Oct 2010 07:54:32 -0000 @@ -2,6 +2,16 @@ // $Id: dashboard.module,v 1.39 2010/10/03 00:14:57 dries Exp $ /** + * Show the block by default on the dashboard. + */ +define('DASHBOARD_BLOCK_DEFAULT', 1); + +/** + * The block is available to place on the dashboard. + */ +define('DASHBOARD_BLOCK_AVAILABLE', 2); + +/** * Implements hook_help(). */ function dashboard_help($path, $arg) { @@ -185,6 +195,37 @@ function dashboard_system_info_alter(&$i } /** + * Implements hook_block_info_alter(). + * + * Assigns blocks to the dashboard_main region of the admin theme if they are + * currently disabled and specified by hook_dashboard_blocks() as a default + * block. This auto-assignment will only be attempted once per module/delta + * to allow the region assignment to be overridden by the user. + */ +function dashboard_block_info_alter(&$blocks, $theme, $code_blocks) { + if (!$theme = variable_get('admin_theme')) { + global $theme_key; + $theme = $theme_key; + } + $dashboard_blocks = module_invoke_all('dashboard_blocks'); + $auto_assign_once = variable_get('dashboard_autoassign_once', array()); + + foreach ($blocks as $module => &$module_blocks) { + foreach ($module_blocks as $delta => &$block) { + if ($block['theme'] != $theme) { + continue; + } + if (empty($block['status']) && (empty($block['region']) || $block['region'] == BLOCK_REGION_NONE) && isset($dashboard_blocks[$module][$delta]) && $dashboard_blocks[$module][$delta] == DASHBOARD_BLOCK_DEFAULT && empty($auto_assign_once[$module][$delta])) { + $block['status'] = 1; + $block['region'] = 'dashboard_main'; + } + $auto_assign_once[$module][$delta] = TRUE; + } + } + variable_set('dashboard_autoassign_once', $auto_assign_once); +} + +/** * Implements hook_theme(). */ function dashboard_theme() { @@ -281,14 +322,16 @@ function dashboard_admin_blocks() { module_load_include('inc', 'block', 'block.admin'); // Prepare the blocks for the current theme, and remove those that are - // currently displayed in non-dashboard regions. + // currently displayed in non-dashboard regions, or are not returned by + // hook_dashboard_blocks(). // @todo This assumes the current page is being displayed using the same // theme that the dashboard is displayed in. $blocks = block_admin_display_prepare_blocks($theme_key); $dashboard_regions = dashboard_region_descriptions(); $regions_to_remove = array_diff_key(system_region_list($theme_key, REGIONS_VISIBLE), $dashboard_regions); + $dashboard_blocks = module_invoke_all('dashboard_blocks'); foreach ($blocks as $id => $block) { - if (isset($regions_to_remove[$block['region']])) { + if (isset($regions_to_remove[$block['region']]) || (empty($dashboard_blocks[$block['module']][$block['delta']]) && !in_array($block['region'], dashboard_regions()))) { unset($blocks[$id]); } } @@ -356,6 +399,62 @@ function dashboard_form_block_admin_conf $region['#options'] = array_diff_key($region['#options'], $dashboard_regions); } } + + // Provide a block setting to control dashboard visibility. + $form['settings']['dashboard_visibility'] = array( + '#type' => 'checkbox', + '#title' => t('Enable on dashboard'), + '#default_value' => FALSE, + ); + // If the block is currently assigned to a non-dashboard region, give a note + // to the user that the region and setting are not compatible. + $current_region = $form['regions'][$theme_key]['#default_value']; + if (!empty($current_region) && !in_array($current_region, dashboard_regions())) { + $form['settings']['dashboard_visibility']['#description'] = t('Note: the block must be unassigned from a region in the @theme theme to enable it on the dashboard.', array('@theme' => $form['regions'][$theme_key]['#title'])); + } + // Set the default value based on whether the block is in a dashboard region. + elseif (in_array($current_region, dashboard_regions())) { + $form['settings']['dashboard_visibility']['#default_value'] = TRUE; + } + $form['#validate'][] = 'dashboard_form_block_admin_configure_validate'; + $form['#submit'] = array_merge(array('dashboard_form_block_admin_configure_submit'), $form['#submit']); +} + +/** + * Form validation handler for block configuration form. + */ +function dashboard_form_block_admin_configure_validate($form, &$form_state) { + global $theme_key; + drupal_theme_initialize(); + + // Ensure that the dashboard visibility flag is only settable if the block + // hasn't been assigned to a non-dashboard region. + $selected_region = $form_state['values']['regions'][$theme_key]; + if ($form_state['values']['dashboard_visibility'] && $selected_region != BLOCK_REGION_NONE && !in_array($selected_region, dashboard_regions())) { + form_set_error('regions][' . $theme_key, t('To enable this block on the dashboard, you must first unassign the block from the @theme theme.', array('@theme' => $form['regions'][$theme_key]['#title']))); + } +} + +/** + * Form submission handler for block configuration form. + */ +function dashboard_form_block_admin_configure_submit($form, &$form_state) { + global $theme_key; + drupal_theme_initialize(); + + // Cause the block to be added/removed from the dashboard based on the + // dashboard visibility setting. + $region = &$form_state['values']['regions'][$theme_key]; + if ($form_state['values']['dashboard_visibility']) { + // Add the block to the dashboard if not already assigned to a region. + if ($region == BLOCK_REGION_NONE) { + $region = 'dashboard_main'; + drupal_set_message(t('Block added to the dashboard.')); + } + } + elseif (in_array($region, dashboard_regions())) { + $region = BLOCK_REGION_NONE; + } } /** @@ -445,9 +544,11 @@ function dashboard_show_disabled() { // Blocks are not necessarily initialized at this point. $blocks = _block_rehash(); - // Limit the list to disabled blocks for the current theme. + // Limit the list to disabled blocks for the current theme which are + // specified in hook_dashboard_blocks(). + $available_blocks = module_invoke_all('dashboard_blocks'); foreach ($blocks as $key => $block) { - if ($block['theme'] != $theme_key || (!empty($block['status']) && !empty($block['region']))) { + if ($block['theme'] != $theme_key || (!empty($block['status']) && !empty($block['region'])) || !isset($available_blocks[$block['module']][$block['delta']])) { unset($blocks[$key]); } } Index: modules/dashboard/dashboard.test =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.test,v retrieving revision 1.5 diff -u -p -r1.5 dashboard.test --- modules/dashboard/dashboard.test 14 Sep 2010 21:51:01 -0000 1.5 +++ modules/dashboard/dashboard.test 3 Oct 2010 07:54:32 -0000 @@ -43,6 +43,7 @@ class DashboardBlocksTestCase extends Dr $custom_block['title'] = $this->randomName(8); $custom_block['body[value]'] = $this->randomName(32); $custom_block['regions[stark]'] = 'dashboard_main'; + $custom_block['dashboard_visibility'] = TRUE; $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block')); // Ensure admin access. @@ -79,4 +80,24 @@ class DashboardBlocksTestCase extends Dr $this->assertTrue(empty($elements), t('%region is not an available choice on the block configuration page.', array('%region' => $region))); } } + + /** + * Test that implementing hook_dashboard_blocks() affects the list of blocks + * visible and available on the dashboard. + */ + function testDashboardHooks() { + // Enable our test module and flush caches. This *should* trigger a block + // rehash and add our new default block to the dashboard. + module_enable(array('dashboard_test'), FALSE); + drupal_flush_all_caches(); + $this->drupalGet('admin/structure/dashboard'); + // test1 should show up and be enabled on the dashboard. + $elements = $this->xpath('//select[@id=:id]//option[@value=:value]', array(':id' => 'edit-blocks-dashboard-test-test1-region', ':value' => 'dashboard_main')); + $this->assertTrue(!empty($elements[0]['selected']), t('Default dashboard block defined successfully.')); + // test2 should be available for the dashboard, but not enabled. + $elements = $this->xpath('//select[@id=:id]//option[@selected=:value]', array(':id' => 'edit-blocks-dashboard-test-test2-region', ':value' => 'selected')); + $this->assertTrue($this->assertText('test2') && (empty($elements) || $elements[0]['value'] == BLOCK_REGION_NONE), t('Available dashboard block defined successfully.')); + // test3 should not show up in the UI. + $this->assertNoText('test3', t('Blocks not defined by hook_dashboard_blocks() don\'t show up in dashboard UI by default.')); + } } Index: modules/dashboard/tests/dashboard_test.info =================================================================== RCS file: modules/dashboard/tests/dashboard_test.info diff -N modules/dashboard/tests/dashboard_test.info --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dashboard/tests/dashboard_test.info 3 Oct 2010 07:54:32 -0000 @@ -0,0 +1,8 @@ +; $Id$ +name = Dashboard test +description = Tests dashboard hooks. +package = Testing +version = VERSION +core = 7.x +files[] = dashboard_test.module +hidden = TRUE Index: modules/dashboard/tests/dashboard_test.module =================================================================== RCS file: modules/dashboard/tests/dashboard_test.module diff -N modules/dashboard/tests/dashboard_test.module --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/dashboard/tests/dashboard_test.module 3 Oct 2010 07:54:32 -0000 @@ -0,0 +1,43 @@ + array( + 'test1' => DASHBOARD_BLOCK_DEFAULT, + 'test2' => DASHBOARD_BLOCK_AVAILABLE, + ), + ); +} + +/** + * Implements hook_block_info(). + */ +function dashboard_test_block_info() { + return array( + 'test1' => array( + 'info' => 'test1', + ), + 'test2' => array( + 'info' => 'test2', + ), + 'test3' => array( + 'info' => 'test3', + ), + ); +} + +/** + * Implements hook_block_view(). + */ +function dashboard_test_block_view() { + return array('content' => 'test content'); +} Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1304 diff -u -p -r1.1304 node.module --- modules/node/node.module 3 Oct 2010 01:15:33 -0000 1.1304 +++ modules/node/node.module 3 Oct 2010 07:54:32 -0000 @@ -2103,6 +2103,17 @@ function node_block_save($delta = '', $e } /** + * Implements hook_dashboard_blocks(). + */ +function node_dashboard_blocks() { + return array( + 'node' => array( + 'recent' => DASHBOARD_BLOCK_DEFAULT, + ), + ); +} + +/** * Find the most recent nodes that are available to the current user. * * @param $number Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.363 diff -u -p -r1.363 search.module --- modules/search/search.module 1 Oct 2010 15:24:18 -0000 1.363 +++ modules/search/search.module 3 Oct 2010 07:54:32 -0000 @@ -157,6 +157,17 @@ function search_block_view($delta = '') } /** + * Implements hook_dashboard_blocks(). + */ +function search_dashboard_blocks() { + return array( + 'search' => array( + 'form' => DASHBOARD_BLOCK_DEFAULT, + ), + ); +} + +/** * Implements hook_menu(). */ function search_menu() { Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.1205 diff -u -p -r1.1205 user.module --- modules/user/user.module 3 Oct 2010 01:15:34 -0000 1.1205 +++ modules/user/user.module 3 Oct 2010 07:54:33 -0000 @@ -1377,6 +1377,18 @@ function user_block_view($delta = '') { } /** + * Implements hook_dashboard_blocks(). + */ +function user_dashboard_blocks() { + return array( + 'user' => array( + 'new' => DASHBOARD_BLOCK_DEFAULT, + 'online' => DASHBOARD_BLOCK_AVAILABLE, + ), + ); +} + +/** * Process variables for user-picture.tpl.php. * * The $variables array contains the following arguments: