Problem

Assigning a default 'region' in hook_block_info() does not enable the block when the module is enabled.

Proposed solution

When a module is enabled, automatically enable the blocks that have a non-empty region (and set their status = 1).

Details

  • hook_block_info() allows a module to define blocks using these properties:
    • status - Whether the module that defines the block is enabled - if not, then the (possibly configured) block is not exposed on the block overview page.
    • region - The default region to enable the block in.
    • weight - The default weight for the block within the region.
  • Modules that want to auto-enable one of their blocks need to define both region and status. Omitting one of both does not enable the block.
  • Installation profiles could additionally use a helper function to simplify the assignment of blocks to regions:
    • The powered-by block should be enabled in the default installation profile, but disabled in the minimal installation profile.
    • The search block should be in the Dashboard region of the administration theme and also enabled in another region of the default theme.
    • Some blocks should only be visible in some regions of the Dashboard (in the administration theme).

    However, this does not necessarily have to happen in this issue/patch already.

Related issues / Dependencies

  1. #1373312: Assign system_main block to 'content' region and help block to 'help' region by default (followup)
  2. #1227966: Dynamically-defined blocks are never removed from the site, even when they disappear from hook_block_info()

Original report

hook_block_list() supports defining blocks that should be enabled by default when the module is enabled. System blocks that are enabled by default (the content block, navigation, management, etc.) do not currently use this feature, partly because it is indeed broken.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Damien Tournoud’s picture

Status: Active » Needs review
FileSize
8.81 KB

This patch:
- adds a block_modules_enabled() that rehash all the enabled themes to activate the new blocks
- refactors _block_rehash() into a block_rehash_all() and a block_rehash($theme), and make it a public API function
- defines sane defaults in each module
- removes the manual activation in core default installation profiles

Status: Needs review » Needs work

The last submitted patch failed testing.

Damien Tournoud’s picture

Status: Needs work » Needs review
FileSize
10.35 KB

Interesting, this uncovered a bug in block_initialize_theme_blocks() in which disabled blocks assigned to the empty region ('') were reassigned to the default region of the theme. This wasn't showing up before because disabled blocks were not in the {block} table inside the simpletest environment because _block_rehash() was never called.

moshe weitzman’s picture

subscribe. this has long been a dark corner of drupal. time to clean it up!. what happens after install if the install profile does not have a left/right/footer region? i'm not sure what should happen - i guess the block should appear as disabled in the blocks ui.

moshe weitzman’s picture

Priority: Normal » Critical
Status: Needs review » Reviewed & tested by the community

I went through the installer and fiddled with block movement and all looks good here. The issue of blocks being placed into regions that the theme does not support is a separate issue. This issue is just bug fix.

Gábor Hojtsy’s picture

This looks like a pretty good improvement. From the code it looks like those, who would like to have a custom set of blocks (not what modules define by default) in an install profile could just add the blocks with disabled (status = 0) rows, and block_rehash() would obey existing block data anyway.

I am also happy to see the default enabled blocks feature actually work after so long :)

Two possibly minor nitpicks:

- you use static $theme_key, while drupal_static() is all the rage for better testability (even though the function has an argument to change the static, drupal_static() provides a generic way
- not sure I'd do a separate foreach() in system_block_list() on the two menu names, but instead do that via in_array() in the previous loop

Damien Tournoud’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
10.58 KB

- you use static $theme_key, while drupal_static() is all the rage for better testability (even though the function has an argument to change the static, drupal_static() provides a generic way

This is a callback function. The static is not a cache, but a way to pass information from the caller to the callback (a poorman's closure, if you may). There is zero point in using drupal_static() here. In this new patch, I even remove the other call to drupal_static() (this one had no reset, which is basically a bug).

- not sure I'd do a separate foreach() in system_block_list() on the two menu names, but instead do that via in_array() in the previous loop

Done.

Status: Needs review » Needs work

The last submitted patch failed testing.

Damien Tournoud’s picture

Status: Needs work » Needs review
FileSize
10.49 KB

I failed to save a file, apparently.

Damien Tournoud’s picture

Third time a charm?

Status: Needs review » Needs work

The last submitted patch failed testing.

moshe weitzman’s picture

A couple hunks are failing now. @Damien - could you reroll? This was RTBC before so not much left.

Nick_vh’s picture

We were just facing this issue and were planning to make a patch, but appearently it was already done :-)

Hope it can be commited before the codefreeze

sun’s picture

Issue tags: +API clean-up, +D7 API clean-up
+++ modules/block/block.admin.inc
@@ -124,9 +126,13 @@ function block_admin_display_form_submit($form, &$form_state) {
+function _block_compare($a = NULL, $b = NULL, $theme = NULL) {
+  static $theme_key, $regions;
+  if (isset($theme)) {
+    $theme_key = $theme;
+    $regions = NULL;
+    return;

That return looks superfluous to me.

+++ modules/block/block.module
@@ -285,16 +293,22 @@ function block_get_blocks_by_region($region) {
+function block_rehash_all() {
+  $themes = db_query("SELECT name FROM {system} WHERE type = :type AND status = :status", array(':type' => 'theme', ':status' => 1));

Why only enabled themes?

If there is a reason, we should explain in the PHPDoc description.

+++ modules/block/block.test
@@ -259,10 +259,11 @@ class NewDefaultThemeBlocks extends DrupalWebTestCase {
-      $this->assertEqual($blocks[$block->module][$block->delta], $block, t('Block matched'));
+      $this->assertEqual($blocks[$block->module][$block->delta], $block, t('Block matched: %module-%delta', array('%module' => $block->module, '%delta' => $block->delta)));

Since you're concatenating the placeholders here, it would be good to use @ instead of % placeholders, I think.

+++ profiles/default/default.profile
@@ -90,76 +90,6 @@ function default_profile_task_list() {
 function default_profile_tasks(&$task, $url) {
-  
-  // Enable some standard blocks.
-  $values = array(
-    array(
-      'module' => 'system',
-      'delta' => 'main',
-      'theme' => 'garland',
-      'status' => 1,
-      'weight' => 0,
-      'region' => 'content',
-      'pages' => '',
-      'cache' => -1,
-    ),

I really like those being removed... but I do wonder how install profiles will be able to setup blocks.

The more I think about that question (already asked moshe in IRC), the more I think the question doesn't belong into this issue... here, we're just moving the default block configuration, and apparently, both core install profiles are using the default settings exposed by core modules, so we just don't care. :)

This review is powered by Dreditor.

sun’s picture

Title: Drupal core blocks should be enable using standard mechanisms » Drupal core blocks should be enabled using standard mechanisms
Status: Needs work » Needs review
FileSize
12.9 KB

Re-rolled against latest HEAD with all suggestions.

Status: Needs review » Needs work

The last submitted patch failed testing.

sun’s picture

Status: Needs work » Needs review
FileSize
12.9 KB

That was part of the tutorial: In above demonstration, you see how the testbot behaves when code uses a constant that is not defined. The issue that we have ~13,000 passing tests, ~5,000 failing tests, but only ~13,000 tests in total is hopefully an already known issue, but for us, it really only matters to use constants that are defined.

:-P

Status: Needs review » Needs work

The last submitted patch failed testing.

moshe weitzman’s picture

Falures are due to region name changes. Also note that dashboard region now displays on the system blocks.

sun’s picture

Status: Needs work » Needs review
FileSize
14.17 KB

Hopefully, this should pass.

Status: Needs review » Needs work

The last submitted patch failed testing.

sun’s picture

This patch would really help the UX team in cleaning up the interface... Bojhan struggled to find the place where the Search block's title is setup in #607410: Remove Search this site , and yeah, it's a total WTF.

sun’s picture

Issue tags: -D7 API clean-up

.

dcor’s picture

FileSize
72.67 KB

Hi, just wondering if there's an update on this topic - I'm going through the motions of setting up a site in D7 and installing a theme (in this case Basic 7.x) and I'm getting a lovely set of error messages just from trying to add existing blocks (I haven't created any of my own) to my test site. See attached photo of the error message.

"Notice: Undefined index: region in block_admin_display_form_submit() (line 121 of /home/orchidil/public_html/scor/modules/block/block.admin.inc)."

Also, whatever changes I've made results in these error messages plus "The block settings have been updated" and yet, when I reload the page in both firefox and safari (not-logged-in)... I see absolutely no difference. What I'm looking for is for the little log-in block to vanish as an example.

sun.core’s picture

Search block is not enabled upon installing the module. It should, or shouldn't it? This patch should fix it.

sun.core’s picture

Version: 7.x-dev » 8.x-dev
catch’s picture

Priority: Critical » Major

Downgrading all D8 criticals to major per http://drupal.org/node/45111

Damien Tournoud’s picture

Version: 8.x-dev » 7.x-dev

Bugs cannot target D8, as the tree is not open yet.

webchick’s picture

Version: 7.x-dev » 8.x-dev
Category: bug » task
yoroy’s picture

Issue tags: +Novice

Tagging novice for a straight reroll of #20 using Git.

Niklas Fiekas’s picture

Just tried it. Rerolling this isn't trivial (but maybe still novice) since lot's of code has been refactored in the meantime.

Niklas Fiekas’s picture

Status: Needs work » Needs review
FileSize
11.96 KB

Alright, let's try this one.

Status: Needs review » Needs work

The last submitted patch, 512464-block-rehash.patch, failed testing.

Niklas Fiekas’s picture

Two intresting failures: How can we handle admin themes and the dashboard? Is the secound assertion still valid?

yoroy’s picture

Thanks for taking this on Niklas. I'll see if somebody can help this move along (I can't :-)

Niklas Fiekas’s picture

Issue summary: View changes

Summarize issue.

Niklas Fiekas’s picture

Status: Needs work » Active

Maybe:

- *   - 'region': (optional) Initial value for theme region within which this
- *     block is set. Most modules do not provide an initial value, and
- *     any value provided can be modified by a user on the block configuration
- *     screen. Note: If you set a region that isn't available in the currently
- *     enabled theme, the block will be disabled.
+ *   - 'regions': (optional) Array of region names. If one of them is available
+ *     in the theme this will be the default region for the block. Otherwise
+ *     the block will be disabled by default.
+ *     Any value provided can be modified by a user on the block configuration
+ *     screen.


No ... better idea. Will try it out and write it down and maybe discuss in IRC shortly.

sun’s picture

I'm no longer sure whether we actually want to do this, because it hard-codes a range of assumptions that only apply to core profiles and core themes.

yoroy’s picture

Status: Active » Needs work

I asked sun for some clarification in IRC:

Perhaps the actual way forward rather is to provide a more simple helper function for installation profiles to enable blocks. One essential consequence of the change proposal is that a module's blocks are automatically enabled when you install the module.

And I'm not necessarily sure whether we really want that. E.g., if you install Book module or Poll module or whatever, then the Book Navigation and Latest Poll blocks would or could be automatically enabled.

Meanwhile I think that auto-enabling blocks makes only sense for certain/common "edge-cases", such as the main content, help, or user menu block. I.e., the essential stuff only.

Niklas Fiekas’s picture

This issue is about two things:

  1. region in hook_block_info() is buggy and doesn't work as expected.
  2. Use region to give lot's of blocks default regions.

Since 2 is questionable, should we just get 1 in? Maybe together with #1373312: Assign system_main block to 'content' region and help block to 'help' region by default (followup)? We can always do 2 later or differently.

Niklas Fiekas’s picture

Issue summary: View changes

Reword proposed solution.

sun’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Issue summary: View changes

Updated issue summary.

sun’s picture

Title: Drupal core blocks should be enabled using standard mechanisms » Auto-enable a block's 'status' with a non-empty 'region' when a module is installed

Agreed. I've updated/rewritten the issue summary.

Niklas Fiekas’s picture

Status: Needs work » Needs review
FileSize
2.51 KB

Reroll with just that.

Status: Needs review » Needs work

The last submitted patch, 512464-block-rehash-2.patch, failed testing.

sun’s picture

Component: base system » block.module
Priority: Major » Normal
Status: Needs work » Needs review
Issue tags: -Novice
FileSize
1.59 KB

mmm, not sure what remains of that except for the hook_modules_enabled() implementation.

I guess that attached patch is what we actually want to change here. As outlined in the summary, this somewhat depends on #1373312: Assign system_main block to 'content' region and help block to 'help' region by default (followup)

sun’s picture

Issue tags: -API clean-up
Niklas Fiekas’s picture

Issue tags: +API clean-up
benjy’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll
benjy’s picture

Issue summary: View changes

Updated issue summary.

benjy’s picture

Issue summary: View changes
Status: Needs work » Fixed

This has already been fixed in HEAD.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.