Index: modules/block/block.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v retrieving revision 1.90 diff -u -p -r1.90 block.admin.inc --- modules/block/block.admin.inc 10 Oct 2010 20:11:21 -0000 1.90 +++ modules/block/block.admin.inc 3 Nov 2010 17:38:53 -0000 @@ -291,6 +291,7 @@ function block_admin_configure($form, &$ ); $theme_default = variable_get('theme_default', 'bartik'); + $admin_theme = variable_get('admin_theme'); foreach (list_themes() as $key => $theme) { // Only display enabled themes if ($theme->status) { @@ -300,9 +301,18 @@ function block_admin_configure($form, &$ ':theme' => $key, ))->fetchField(); + // Use a meaningful title for the main site theme and administrative + // theme. + $theme_title = $theme->info['name']; + if ($key == $theme_default) { + $theme_title = t('!theme (default theme)', array('!theme' => $theme_title)); + } + elseif ($admin_theme && $key == $admin_theme) { + $theme_title = t('!theme (administration theme)', array('!theme' => $theme_title)); + } $form['regions'][$key] = array( '#type' => 'select', - '#title' => $theme->info['name'], + '#title' => $theme_title, '#default_value' => !empty($region) && $region != -1 ? $region : NULL, '#empty_value' => BLOCK_REGION_NONE, '#options' => system_region_list($key, REGIONS_VISIBLE), Index: modules/block/block.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.api.php,v retrieving revision 1.13 diff -u -p -r1.13 block.api.php --- modules/block/block.api.php 13 Aug 2010 12:25:14 -0000 1.13 +++ modules/block/block.api.php 3 Nov 2010 17:38:53 -0000 @@ -57,6 +57,12 @@ * - DRUPAL_CACHE_GLOBAL: The block is the same for every user on every * page where it is visible. * - DRUPAL_NO_CACHE: The block should not get cached. + * - 'properties': (optional) Array of additional metadata to add to the + * block. Common properties include: + * - 'administrative': Boolean which categorizes this block as usable in + * an administrative context. This might include blocks which help an + * administrator approve/deny comments, or view recently created + * user accounts. * - 'weight': (optional) Initial value for the ordering weight of this block. * Most modules do not provide an initial value, and any value provided can * be modified by a user on the block configuration screen. Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.360 diff -u -p -r1.360 blog.module --- modules/blog/blog.module 30 Aug 2010 05:58:46 -0000 1.360 +++ modules/blog/blog.module 3 Nov 2010 17:38:53 -0000 @@ -190,6 +190,7 @@ function _blog_post_exists($account) { */ function blog_block_info() { $block['recent']['info'] = t('Recent blog posts'); + $block['recent']['properties']['administrative'] = TRUE; return $block; } Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.909 diff -u -p -r1.909 comment.module --- modules/comment/comment.module 28 Oct 2010 17:40:30 -0000 1.909 +++ modules/comment/comment.module 3 Nov 2010 17:38:54 -0000 @@ -402,6 +402,7 @@ function comment_permission() { */ function comment_block_info() { $blocks['recent']['info'] = t('Recent comments'); + $blocks['recent']['properties']['administrative'] = TRUE; return $blocks; } Index: modules/dashboard/dashboard.css =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.css,v retrieving revision 1.14 diff -u -p -r1.14 dashboard.css --- modules/dashboard/dashboard.css 30 Aug 2010 00:22:03 -0000 1.14 +++ modules/dashboard/dashboard.css 3 Nov 2010 17:38:54 -0000 @@ -37,6 +37,10 @@ -webkit-border-radius: 4px; } +#dashboard .dashboard-add-other-blocks { + margin: 1em 0; +} + #dashboard .ui-sortable { border: 2px dashed #ccc; padding: 10px; @@ -66,7 +70,6 @@ background-color: #E0E0D8; border: #ccc 1px solid; padding: 10px; - min-height: 90px; } #dashboard #disabled-blocks { Index: modules/dashboard/dashboard.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.module,v retrieving revision 1.40 diff -u -p -r1.40 dashboard.module --- modules/dashboard/dashboard.module 21 Oct 2010 11:55:08 -0000 1.40 +++ modules/dashboard/dashboard.module 3 Nov 2010 17:38:54 -0000 @@ -9,7 +9,7 @@ function dashboard_help($path, $arg) { case 'admin/help#dashboard': $output = ''; $output .= '

' . t('About') . '

'; - $output .= '

' . t('The Dashboard module provides a Dashboard page in the administrative interface for organizing administrative tasks and navigation, and tracking information within your site. The Dashboard page contains blocks, which you can add to and arrange using the drag and drop interface that appears when you click on the Customize dashboard link. For more information, see the online handbook entry for Dashboard module.', array('@handbook' => 'http://drupal.org/handbook/modules/dashboard', '@dashboard' => url('admin/dashboard'))) . '

'; + $output .= '

' . t('The Dashboard module provides a Dashboard page in the administrative interface for organizing administrative tasks and navigation, and tracking information within your site. The Dashboard page contains blocks, which you can add to and arrange using the drag and drop interface that appears when you click on the Customize dashboard link. Within this interface, some blocks which are not primarily used for site administration do not appear by default, but can still be added to the dashboard via the Add other blocks link. For more information, see the online handbook entry for Dashboard module.', array('@handbook' => 'http://drupal.org/handbook/modules/dashboard', '@dashboard' => url('admin/dashboard'))) . '

'; $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Tracking user activity') . '
'; @@ -22,7 +22,7 @@ function dashboard_help($path, $arg) { case 'admin/dashboard/configure': // @todo This assumes the current page is being displayed using the same // theme that the dashboard is displayed in. - $output = '

' . t('Rearrange blocks for display on the dashboard. Disabling a block makes it available on the main blocks administration page.', array('@dashboard-url' => url('admin/dashboard'), '@blocks-url' => url("admin/structure/block/list/{$GLOBALS['theme_key']}"))) . '

'; + $output = '

' . t('Rearrange blocks for display on the dashboard. Removing a block from the dashboard makes it available on the main blocks administration page.', array('@dashboard-url' => url('admin/dashboard'), '@blocks-url' => url("admin/structure/block/list/{$GLOBALS['theme_key']}"))) . '

'; return $output; } } @@ -90,6 +90,25 @@ function dashboard_permission() { } /** + * Implements hook_block_info_alter(). + */ +function dashboard_block_info_alter(&$blocks, $theme, $code_blocks) { + $admin_theme = variable_get('admin_theme'); + if (($admin_theme && $theme == $admin_theme) || (!$admin_theme && $theme == variable_get('theme_default', 'bartik'))) { + foreach ($blocks as $module => &$module_blocks) { + foreach ($module_blocks as $delta => &$block) { + // Make administrative blocks that are not already in use elsewhere + // available for the dashboard. + if (empty($block['status']) && (empty($block['region']) || $block['region'] == BLOCK_REGION_NONE) && !empty($code_blocks[$module][$delta]['properties']['administrative'])) { + $block['status'] = 1; + $block['region'] = 'dashboard_hidden'; + } + } + } + } +} + +/** * Implements hook_block_list_alter(). * * Skip rendering dashboard blocks when not on the dashboard page itself. This @@ -121,6 +140,10 @@ function dashboard_page_build(&$page) { // region into it. $page['content']['dashboard'] = array('#theme_wrappers' => array('dashboard')); foreach (dashboard_regions() as $region) { + // Do not show dashboard blocks that are disabled. + if ($region == 'dashboard_hidden') { + continue; + } // Insert regions even when they are empty, so that they will be // displayed when the dashboard is being configured. $page['content']['dashboard'][$region] = !empty($page[$region]) ? $page[$region] : array(); @@ -177,7 +200,15 @@ function dashboard_page_build(&$page) { */ function dashboard_system_info_alter(&$info, $file, $type) { if ($type == 'theme') { - $info['regions'] += dashboard_region_descriptions(); + // Add the dashboard regions (the "hidden" region should always appear last + // in the list, for usability reasons). + $dashboard_regions = dashboard_region_descriptions(); + if (isset($dashboard_regions['dashboard_hidden'])) { + $hidden_region = $dashboard_regions['dashboard_hidden']; + unset($dashboard_regions['dashboard_hidden']); + $dashboard_regions['dashboard_hidden'] = $hidden_region; + } + $info['regions'] += $dashboard_regions; // Indicate that these regions are intended to be displayed whenever the // dashboard is displayed in an overlay. This information is provided for // any module that might need to use it, not just the core Overlay module. @@ -312,12 +343,23 @@ function dashboard_form_block_admin_disp $form['block_regions']['#value'] = array_diff_key($form['block_regions']['#value'], $dashboard_regions); foreach (element_children($form['blocks']) as $i) { $block = &$form['blocks'][$i]; - if (isset($block['region']['#default_value']) && isset($dashboard_regions[$block['region']['#default_value']])) { + if (isset($block['region']['#default_value']) && isset($dashboard_regions[$block['region']['#default_value']]) && $block['region']['#default_value'] != 'dashboard_hidden') { $block['#access'] = FALSE; } elseif (isset($block['region']['#options'])) { $block['region']['#options'] = array_diff_key($block['region']['#options'], $dashboard_regions); } + // Show hidden dashboard blocks as disabled on the main block + // administration form, so that they are available to place in other + // regions of the theme. Note that when the form is submitted, any such + // blocks which still remain disabled will immediately be put back in the + // 'dashboard_hidden' region, because dashboard_block_info_alter() is + // called when the blocks are rehashed. Fortunately, this is the exact + // behavior we want. + if ($block['region']['#default_value'] == 'dashboard_hidden') { + // @todo These do not wind up in correct alphabetical order. + $block['region']['#default_value'] = NULL; + } } } } @@ -370,6 +412,9 @@ function dashboard_form_block_add_block_ */ function template_preprocess_dashboard_admin_display_form(&$variables) { template_preprocess_block_admin_display_form($variables); + if (isset($variables['block_regions'][BLOCK_REGION_NONE])) { + $variables['block_regions'][BLOCK_REGION_NONE] = t('Other available blocks'); + } } /** @@ -431,8 +476,9 @@ function dashboard_regions() { */ function dashboard_dashboard_regions() { return array( - 'dashboard_main' => 'Dashboard main', - 'dashboard_sidebar' => 'Dashboard sidebar', + 'dashboard_main' => 'Dashboard (main)', + 'dashboard_sidebar' => 'Dashboard (sidebar)', + 'dashboard_hidden' => 'Dashboard (hidden)', ); } @@ -445,9 +491,9 @@ 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 blocks that are marked as disabled for the dashboard. foreach ($blocks as $key => $block) { - if ($block['theme'] != $theme_key || (!empty($block['status']) && !empty($block['region']))) { + if ($block['theme'] != $theme_key || $block['region'] != 'dashboard_hidden') { unset($blocks[$key]); } } @@ -496,7 +542,7 @@ function dashboard_update() { parse_str($_REQUEST['regions'], $regions); foreach ($regions as $region_name => $blocks) { if ($region_name == 'disabled_blocks') { - $region_name = ''; + $region_name = 'dashboard_hidden'; } foreach ($blocks as $weight => $block_string) { // Parse the query string to determine the block's module and delta. @@ -507,12 +553,7 @@ function dashboard_update() { $block->region = $region_name; $block->weight = $weight; - if (empty($region_name)) { - $block->status = 0; - } - else { - $block->status = 1; - } + $block->status = 1; db_merge('block') ->key(array( @@ -603,6 +644,8 @@ function theme_dashboard_disabled_blocks foreach ($blocks as $block) { $output .= theme('dashboard_disabled_block', array('block' => $block)); } + $output .= '
'; + $output .= '

' . l(t('Add other blocks'), 'admin/dashboard/configure') . '

'; $output .= ''; return $output; } Index: modules/dashboard/dashboard.test =================================================================== RCS file: /cvs/drupal/drupal/modules/dashboard/dashboard.test,v retrieving revision 1.7 diff -u -p -r1.7 dashboard.test --- modules/dashboard/dashboard.test 31 Oct 2010 21:36:24 -0000 1.7 +++ modules/dashboard/dashboard.test 3 Nov 2010 17:38:54 -0000 @@ -112,4 +112,30 @@ class DashboardBlocksTestCase extends Dr $this->drupalGet('admin/dashboard'); $this->assertRaw($custom_block['title'], t('Block still appears on the dashboard.')); } + + /** + * Test that defining a block with ['properties']['administrative'] = TRUE + * adds it as an available block for the dashboard. + */ + function testBlockAvailability() { + // Test "Recent comments", which should be available (defined as + // "administrative") but not enabled. + $this->drupalGet('admin/dashboard'); + $this->assertNoText(t('Recent comments'), t('"Recent comments" not on dashboard.')); + $this->drupalGet('admin/dashboard/drawer'); + $this->assertText(t('Recent comments'), t('Drawer of disabled blocks includes a block defined as "administrative".')); + $this->assertNoText(t('Syndicate'), t('Drawer of disabled blocks excludes a block not defined as "administrative".')); + $this->drupalGet('admin/dashboard/configure'); + $elements = $this->xpath('//select[@id=:id]//option[@selected="selected"]', array(':id' => 'edit-blocks-comment-recent-region')); + $this->assertTrue($elements[0]['value'] == 'dashboard_hidden', t('A block defined as "administrative" defaults to dashboard_hidden.')); + + // Now enable the block on the dashboard. + $values = array(); + $values['blocks[comment_recent][region]'] = 'dashboard_main'; + $this->drupalPost('admin/dashboard/configure', $values, t('Save blocks')); + $this->drupalGet('admin/dashboard'); + $this->assertText(t('Recent comments'), t('"Recent comments" was placed on dashboard.')); + $this->drupalGet('admin/dashboard/drawer'); + $this->assertNoText(t('Recent comments'), t('Drawer of disabled blocks excludes enabled blocks.')); + } } Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.579 diff -u -p -r1.579 forum.module --- modules/forum/forum.module 6 Oct 2010 13:38:40 -0000 1.579 +++ modules/forum/forum.module 3 Nov 2010 17:38:54 -0000 @@ -623,10 +623,12 @@ function forum_block_info() { $blocks['active'] = array( 'info' => t('Active forum topics'), 'cache' => DRUPAL_CACHE_CUSTOM, + 'properties' => array('administrative' => TRUE), ); $blocks['new'] = array( 'info' => t('New forum topics'), 'cache' => DRUPAL_CACHE_CUSTOM, + 'properties' => array('administrative' => TRUE), ); return $blocks; } Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1315 diff -u -p -r1.1315 node.module --- modules/node/node.module 31 Oct 2010 12:45:27 -0000 1.1315 +++ modules/node/node.module 3 Nov 2010 17:38:55 -0000 @@ -2075,6 +2075,7 @@ function node_block_info() { $blocks['syndicate']['cache'] = DRUPAL_NO_CACHE; $blocks['recent']['info'] = t('Recent content'); + $blocks['recent']['properties']['administrative'] = TRUE; return $blocks; } Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.359 diff -u -p -r1.359 poll.module --- modules/poll/poll.module 25 Oct 2010 15:51:21 -0000 1.359 +++ modules/poll/poll.module 3 Nov 2010 17:38:55 -0000 @@ -133,6 +133,7 @@ function _poll_menu_access($node, $perm, */ function poll_block_info() { $blocks['recent']['info'] = t('Most recent poll'); + $blocks['recent']['properties']['administrative'] = TRUE; return $blocks; } Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.365 diff -u -p -r1.365 search.module --- modules/search/search.module 20 Oct 2010 01:31:07 -0000 1.365 +++ modules/search/search.module 3 Nov 2010 17:38:55 -0000 @@ -143,6 +143,7 @@ function search_block_info() { $blocks['form']['info'] = t('Search form'); // Not worth caching. $blocks['form']['cache'] = DRUPAL_NO_CACHE; + $blocks['form']['properties']['administrative'] = TRUE; return $blocks; } Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.1213 diff -u -p -r1.1213 user.module --- modules/user/user.module 23 Oct 2010 15:30:34 -0000 1.1213 +++ modules/user/user.module 3 Nov 2010 17:38:55 -0000 @@ -1273,10 +1273,13 @@ function user_block_info() { $blocks['login']['cache'] = DRUPAL_NO_CACHE; $blocks['new']['info'] = t('Who\'s new'); + $blocks['new']['properties']['administrative'] = TRUE; // Too dynamic to cache. $blocks['online']['info'] = t('Who\'s online'); $blocks['online']['cache'] = DRUPAL_NO_CACHE; + $blocks['online']['properties']['administrative'] = TRUE; + return $blocks; }