
attractive, usable web applications
Richard's Blog - Design, coding and life in Japan
Creating multiple blocks easily in a Drupal module
Submitted by Richard on Wed, 05/26/2010 - 15:25In my latest Drupal project, we needed to be able to easily add new blocks to the main module based application, but also to be able to them easily in the theme folder. The theme based block templates will be altered regularly by designers to fit is with the site and its style. The module specific blocks will not be changed as it is a part of the applications core.
I will refer to the module name as MYMODULE and the theme name as MYTHEME from now on.
In my MYMODULE.module file I create the following hook_block and regi
function MYMODULE_block($op = 'list', $delta = 0, $edit = array()) {
$block = array();
if ($op == 'list') {
$block['block_cart']['info'] = t('Header Cart');
$block['block_cart']['cache'] = BLOCK_NO_CACHE;
$block['block_cart']['region'] = 'mini_cart';
$block['block_cart']['status'] = TRUE;
$block['block_left_search']['info'] = t('Left Search');
$block['block_left_search']['cache'] = BLOCK_NO_CACHE;
$block['block_left_search']['region'] = 'left';
$block['block_left_search']['status'] = TRUE;
$block['left_search']['weight'] = '-9';
}
else if ($op == 'view') {
$themes = takara_theme();
if(isset($themes['block_'.$delta])) {
$block = array('content'= theme('block_'.$delta));
}
}
return $block;
}
I then go and create my MYMODULE_theme with a few changes and a function at the end to auto process where I want some of the blocks to live by default
function MYMODULE_theme(){
define('MODULE_BLOCK', drupal_get_path('module', 'MYMODULE').'/themes/block');
define('THEME_INCLUDES', path_to_theme().'/includes');
$themes = array(
'block_cart'=>array(),
'block_left_search'=>array(),
);
return process_themes($themes);
}
I then add the following processing function to be able to add template files in a default directory
function process_themes($themes){
$remove=array('block_');
foreach($themes as $key=>&$theme){
if(!isset($theme['path'])){
elseif(substr($key,0,6)=='block_') {
$theme['path']=MODULE_BLOCK;
}
}
if(isset($theme['path'])&&!isset($theme['template'])){
$theme['template']=str_replace($remove, '', $key);
}
if(!isset($theme['arguments'])){
$theme['arguments']=array();
}
}
return $themes;
}
Now once your theme registry cache is refreshed you can the following files:
- /MYMODULES/theme/blocks/left_menu.tpl.php
- /MYMODULES/theme/blocks/cart.tpl.php
This works easily if these are static files or if you want them in this directory, but I have purposefully allowed this path to only be used as an optional over-ride should your theme path should not be set. If you want your template files accessible as /MYTHEME/includes/left_menu.tpl.php, you can add the following in your hook_theme function.
function MYMODULE_theme(){
define('MODULE_BLOCK', drupal_get_path('module', 'MYMODULE').'/themes/block');
define('THEME_INCLUDES', path_to_theme().'/includes');
$themes = array(
'block_left_search'=>array('path' => THEME_INCLUDES),
'block_cart'=>array(),
);
return process_themes($themes);
}
This is again good if these are only static files, but I am sure you will probably want to be using data from an the database or a data source. This is where we use the preprocess function. If I want to inject cart detail contents into the mini-cart above I can do the following. (I am getting data from a json data source and have saved the contents in the global $json_data)
function MYMODULE_preprocess_block_cart(&$vars){
GLOBAL $json_data;
$vars['cart'] = $json_data->cart;
$vars['costs'] = $json_data->costs;
}
The block_cart part of the function name is taken directly from the theme you registered in hook theme.
Now I can happily read data from my block template /MYMODULES/theme/blocks/cart.tpl.php
<fieldset>
<legend>Cart Contents</legend>
<?php if(!empty($cart->cart_items)): ?>
<table>
<?php foreach($cart->cart_items as $cart_item): ?>
<tr>
<td colspan="3"><?php echo strip_tags($cart_item->title); ?></td>
</tr>
<tr>
<td><?php echo $cart_item->qty; ?></td>
<td><?php echo $cart_item->category.':'.$cart_item->maker; ?></td>
<td><?php echo $cart_item->price; ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php print theme('MYMODULE_costs', $costs); ?>
<?php else: ?>
<p><?php echo t('The cart is empty'); ?></p>
<?php endif; ?>
</fieldset>
Tags:
Recent Blog Posts
- Why you should use Rails 3 and not Django 5th Sep 10, 12:28
- Doctrine 2 and why you should use it! 29th Jul 10, 15:23
- How to localize your main blog listing page using Drupal 26th Jun 10, 11:46
- Creating Rails like template helpers in Django 24th Jun 10, 22:01
- Error: No module named messagesdjango.contrib.contenttypes 22nd Jun 10, 22:00
Post new comment