Show default block in a region

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
Screenack's picture

I'd like to have a specific block show in a region if there is no theme > block specified for that region. Notzach recommend the Context module, but that might be overkill for this single use case.

Here's the scenario:
I'm using the genesis theme, and the region is "secondary_content". This region will always have one block, the superfish menu block. The balance of available menus will be determined by settings on my theme's block page.

There are circumstances where no condition is met other than the superfish menu, and I'd like to have a default block show for when the only block present is the superfish menu block.

I'm guessing I can do this in template.php? Like a simple if statement?

Thanks!
Kyle

Comments

AFAIK, there is no way to

sheena_d's picture

AFAIK, there is no way to display a block from template.php (other than something horribly hacky, potentially dangerous and a resource drain, since you shouldn't be accessing the DB from the theme). The only solution I can think of that does not involve the context module would be a simple CSS hack. Make the Superfish block the last (bottom) block in the sidebar, and use this CSS (may vary depending on what classes are assigned to blocks in your theme):

.block + .block-superfish {
  display: none;
}

that will hide the Superfish block if any blocks come before it.

You can do it in php. The

dpickerel's picture

You can do it in php. The problem is that by the time it gets to your theme page everything is in html, so testing for just one block can be a bit of a challenge.

Maybe something like
print $secondary_content;
if(strlen($secondary_content) < $somenum) {

$block = module_invoke('module_name', 'block', 'view', 'block_delta');
print $block['content'];
}

block_list

ajross's picture

You could check the number of blocks in the region in the theme's page preprocess function using block_list(). Then, depending on the result, pass whatever info you need as a variable to the page template. For example, the variable could just contain a class name and you could print it in one of the outer divs of the secondary content region. Then just add the heights and backgrounds you need in your stylesheet.

Interesting

Screenack's picture

OK, a few more questions:
How do I access region $page['secondary_content'] from template.php? block_list($page['secondary_content']) errors (out of scope)
How do I pass, say, the variable "$printDefault" (here, set to true) back to page.tpl.php?

Getting warmer; thanks!
Kyle

Just use 'secondary_content"

cgmonroe's picture

The block_list() function just uses the region name, e.g. block_list('secondary_content').

This will return an array of blocks in that region. So you can do something like:

$sc_blocks = block_list('secondary_content');
// Test if there is only one block in the region
if ( ! empty($sc_blocks) && count($sc_blocks) == 1  ) {
   // add stuff to section 
}

You know, it might be easier to use this as a PhP test to display the block or not in the block configuration settings.

Using "Show Blocks on specific pages" feature

Screenack's picture

By Jove, man, great idea! Thanks!

I'm guessing that to use this, I would:

  1. Switch to the block I wish to make as "default"
  2. Select "Pages on which this PHP code returns TRUE (experts only)"
  3. Paste the modified version in, below
  4. I presume I need to add "return true;" in order for this to work.

$sc_blocks = block_list('secondary_content');
// Test if there is only one block in the region
if ( ! empty($sc_blocks) && count($sc_blocks) == 1  ) {
   return true; 
}

almost there

ajross's picture

Yes, that should work (using it to control display of a block). And more straightforward than what I initially suggested. If you did want to control the styling of the region through CSS instead, you would do something more like this in template.php:

function themename_preprocess_page(&$vars) {
  $block_count = count(block_list('secondary_content'));
  if($block_count>1) {                            
     $vars['block_check'] = 'your-class-name';
  }
}

and then wherever you wanted to add the class in your page template:

<?php print $block_check; ?>

Probably no need for you to do all that since you can just selectively display a block instead. But in case you decide you want to style the region differently via CSS, this is a way to accomplish that.

So flippin' close! This is

Screenack's picture

So flippin' close!

This is working as I expect on all BUT the home/front page. I'm not sure why, but the logic fails there.

So, I'm trying:

$sc_blocks = block_list('secondary_content');
// Test if there is only one block in the region
if (drupal_is_front_page()) {
  return false;
} elseif ( ! empty($sc_blocks) && count($sc_blocks) == 1 ) {
   return true; 
}

But it still shows on the front page. What am I missing?

A little more digging

Screenack's picture

Well, it was kinda working, I was getting a "false" false result.

Turns out that the php code I entered simply wasn't returning true.

Here's the rub:

$sc_blocks = block_list('secondary_content');

If I run only that, I go into a memory-leaking loop until WSOD.

So, I tried:
$sc_blocks = block_list($page['secondary_content']);

Same result.

I'm guessing that I'm not calling the region by the correct name? How does one do so from the "Show block on specific pages" field, when using the PHP Code option?

Thanks for helping me through this!
Kyle

loop

ajross's picture

I'm guessing the problem is that the function block_list has to check the visibility settings for blocks in the region to determine how many are displayed. Thus, your PHP code is run but that calls block_list again, and so on... I think you probably just can't use the function in this context.

CSS to the rescue?

Screenack's picture

dpickerel: would I put that in page.tpl.php instead?

Sheena: I love the simplicity of this approach, although I failed to be clear in what I want to do. My goal is to always show the superfish menus, but enable a default block.

Most common scenario:

|----- secondary-content region --------|  ^
||-------------------------------------||  |
|| superfish menu block always shows   ||  |
||-------------------------------------|| height: 220px
||-------------------------------------||  |
|| user-selected section-header block  ||  |
||-------------------------------------||  |
|--------------------------------------||  v

What I want to avoid

|----- secondary-content region --------|  ^
||-------------------------------------||  |
||      superfish menu block           ||  |
||                                     ||  |
||-------------------------------------|| height: 30px
|                                       |  |
|   (no user-selected section-header    |  |
|           block present)              |  |
|                                       |  |
|---------------------------------------|  v

Your suggestion gives me an idea:

Set the secondary region to to min-height which is superfish menus + section-header block. Then set the background-image of the region to the image contents that show in the section-header block. The downside is some display oddities when the user-selected block renders over the region div, as well as the loading of unnecessary page data (since this the exceptional case, not the mainstream event for a site page)

How are you rendering this

sheena_d's picture

How are you rendering this "user-selected section-header block" ? Is it not possible to set a default, or to set the block to display even if there is no choice? Then you could substitute a background image on that block that would be covered up by the user-selected image if it is available.

I feel like you're trying to avoid complexity by not using the context module, but you're adding in a huge new level of complexity by moving to preprocess functions for something that seems very simple and superficial (having an image in a certain place).

By "rendering" I mean as the

Screenack's picture

By "rendering" I mean as the result of how the theme's blocks are configured, i.e., in the admin/structure/block/manage/nodeblock/23/configure

I agree about avoid needless complexity, re: using preprocess functions. I like cgmonroe's thoughts on doing this via visibility settings > show block on specific pages > "php code returns true" which I almost have working, except as noted in that part of this thread.

Thanks again!
Kyle

Are you calling block_list

dpickerel's picture

Are you calling block_list from the template page? It's probably creating the block, which causes the template page, which calls block_list, which .... becoming recursive.
You probably need to set up the block in your template.php's phptemplate_preprocess() function.
Use block_list to get the block, then assign the result of the region in a variable. $vars['myname'] becomes just $myname by the time it gets to running your template file.
So in your page.tpl.php you just
print $myname;

but in the phptemplate_preprocess() function put in all of the code to build your block.
function phptemplate_preprocess() {
(pseudocode)
$block_result = block_list
$var['myname'] = $block_result[ "superfish block"];
if(count($block_list < 2){
$var['myname'] .= $default_block;
} else {
$var['myname'] .= loop go get rest of $block_result;
}
}

page.tpl.php
if(!empty($myname)) {
print $myname;
}
The code varies a little from theme to theme, so it's hard to guess just how you're set up.
make any sense at all?

Thanks

Screenack's picture

Thanks for the careful explanation, but I'm running the code from the "Show block on specific pages" field, when using the PHP Code option.

Hi Kyle, Just wanted to add

JuliaKM's picture

Hi Kyle,

Just wanted to add another vote for Context module. One problem I've found with adding PHP code to blocks, especially when your site has a ton of blocks, is that it can be hard to remember where your block modifications are coming from. Context module makes it easy to see all of your special conditions in one place.

Julia

Thanks!

Screenack's picture

Thanks, Julia. I've settled on something Sheena suggested, but even more simple: using a min-height on the affected region. Some pages won't have an image there, but those are admin-pages, so this is acceptable.

I understand that Context offers a potentially better block-manager than the Drupal default, but, the concern I have with Context is similar to Panels; in a broad sense, these modules add as many questions as they answer. It took the third major iteration of Views to hammer out their UI into something that is now a delight to use. I'm expecting something similar with Context and Panels as they evolve.

Glad you were able to get

JuliaKM's picture

Glad you were able to get something working! I think that Context is sort of light weight in comparison to Panels and Views.

triDUG

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: