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
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
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
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
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"
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
By Jove, man, great idea! Thanks!
I'm guessing that to use this, I would:
$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
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
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
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
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?
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
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
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
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
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
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!
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
Glad you were able to get something working! I think that Context is sort of light weight in comparison to Panels and Views.