I'm looking at the best way to theme certain types (in the entity sense) of bean blocks. I was hoping I'd just be able to create separate .tpl files for each but it doesn't seem like the Bean's entity type gets factored into the candidate names. Right now I only see:

  • block__REGION-NAME
  • block__bean
  • block__bean__BLOCK-LABEL

Is this just due to the underlying block system? Could Bean do an alter and offer more choices?

Update: I'd looked at the possibility of extending bean_plugin and implementing a view() function that called a wrapper theme function but since the bean's I'm using are exported using hook_bean_admin_ui_types() they get the default handler. I guess I could move them over to hook_bean_types() but this seems like a common usage that should be better supported.

Comments

drewish’s picture

Issue summary: View changes

list the candidates i'm seeing

indytechcook’s picture

Since bean is an entity you should theme the bean, not the block.

So you can use hook_preprocess_bean()

function template_preprocess_bean(&$vars) {
$vars['theme_hook_suggestions'][] = 'bean__' . $vars['type'];
}

might work. One of my team mates is going to respond also.

indytechcook’s picture

I'm very open to suggestions also. I write the low level APIs on our projects :)

drewish’s picture

This might be a kind of noob question but where is bean's theme function called? Does the Entity API handle that? I see it registered but I'm wondering where we'd add a candidate other than in the template. I'd rather have the templates work across themes if possible.

indytechcook’s picture

The Entity module adds the template suggestions.

function template_preprocess_entity() {
.
. 
  // Add suggestions.
  $variables['theme_hook_suggestions'][] = $entity_type;
  $variables['theme_hook_suggestions'][] = $entity_type . '__' . $bundle;
  $variables['theme_hook_suggestions'][] = $entity_type . '__' . $bundle . '__' . $variables['view_mode'];
  if ($id = entity_id($entity_type, $entity)) {
    $variables['theme_hook_suggestions'][] = $entity_type . '__' . $id;
  }
.
.
}

?>

drewish’s picture

Hummm I was looking at the list of calls inside devel_themer and not seeing entity called. I'll give that a try. We're doing it inside context so I wonder if that has an effect.

indytechcook’s picture

Thanks. I'd love some insite to some better theming for bean if you have any suggestions.

indytechcook’s picture

So it looks like the theme suggestions are made but the it's not registering the preprocess. I'm not sure why.

https://skitch.com/indytechcook/gphj5/welcome-to-beans.dev-beans.dev

drewish’s picture

Ah okay so putting the bean.tpl.php in the theme got the call showing up… not sure why it wasn't there before. I'm going to play around with this a bit more I might change it to a support request and close it.

drewish’s picture

Oh I think this might have something to do with the preprocess: #939462-6: Specific preprocess functions for theme hook suggestions are not invoked

paulhhowells’s picture

When using Display Suite there is a need for the original issue that started this thread, i.e. a need to theme:

  • block__bean__BEAN-TYPE

While (as mentioned in the thread above) it is best to theme plain vanilla beans with bean.tpl rather than block.tpl, using Display Suite will result in bean.tpl being completely overridden and block.tpl being used. Themers will then want to style block.tpl to be in harmony with the bean type (and the DS style applied to it).

I am having a go at adding to the theme_hook_suggestions for block:

<?php

function themename_preprocess_block(&$variables) {
  if (!empty($variables['block']->module)) {
    if (isset($variables['elements']['bean'])) { 

        $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . $variables['elements']['bean'][4]['#bundle'];

        // kpr($variables);    
    }
  }
}

?>

This works, but only for one particular bean. Within $variables['elements']['bean'] the data that is needed to get the bean-type is nested within a number which is different for each bean. In this example the number is [4]:

$variables['elements']['bean'][4]

Obviously this code will not work if there is more than one bean, or the bean has a different number. It’s a start, but not much use in practice.

So my questions are:

  • How to discover what that number is for each bean (from within template_preprocess_block), or
  • How to discover the bean-type / #bundle without needing to know the bean number?

I will be overjoyed if I can get this working because Beans with DS are an incredible combination! FWIW I’m a designer & themer, not a module developer, so I apologize if I have missed something obvious.

paulhhowells’s picture

The following code enables block__bean__BEAN-TYPE as a block.tpl theme suggestion (when pasted into a theme’s template.php file).

However, I would love to have comments:

  • is it okay to do it like this?
  • is there a better way?
  • is the code fragile, breaking all known drupal best practices and about to explode when the Bean module is next updated???

many thanks
Paul

<?php

/*
 * Implements template_preprocess_block
 *
 * enable bean blocks to be themed by bean-type:
 * i.e. block__bean__BEAN-TYPE.tpl
 */
function themename_preprocess_block(&$variables) {

  // select Bean Blocks and ignore other Blocks
  if (!empty($variables['block']->module) && isset($variables['elements']['bean'])) {

    $bean_array = $variables['elements']['bean'];
    foreach($bean_array as $value) {
    // if you want to debug the $key you can use: foreach($bean_array as $key=>$value)

      if (is_array($value)) {
        if (!empty($value['#bundle'])) {

          // kpr($key);
          // kpr($value['#bundle']);

          $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . $value['#bundle'];
          break;
        }
      }
    }
  }
}

?>
indytechcook’s picture

@paul, that's really interesting. I'd be willing to add this to bean if other people agree. Also, please update http://drupal.org/node/1434622 with findings.

paulhhowells’s picture

@indytechcook thanks! I have refined the code slightly and added a comment at: http://drupal.org/node/1434622#comment-6761032 I hope others agree, it would be really great if this was added to the bean module.

rooby’s picture

For reference, this is what I have been using (seems like some of the variable validation in the previous examples are not really needed IMO but maybe mine is too assuming?):

Adds bean type class & template suggestion:

<?php
/**
* Override or insert variables into the block templates.
*/
function YOURTHEME_preprocess_block(&$variables) {
  // For bean blocks.
  if ($variables['block']->module == 'bean') {
    // Get the bean elements.
    $beans = $variables['elements']['bean'];
    // There is only 1 bean per block.
    $bean = $beans[reset(element_children($beans))];
    // Add bean type classes to the block.
    $variables['classes_array'][] = drupal_html_class('block-bean-' . $bean['#bundle']);
    // Add template suggestions for bean types.
    $variables['theme_hook_suggestions'][] = 'block__bean__' . $bean['#bundle'];
  }
}
?>
rooby’s picture

Has anyone had any luck with getting MYTHEME_preprocess_bean() to fire?

Even when I have bean.tpl.php in my theme I can't get the preprocess to fire.

Or are we doomed by #939462: Specific preprocess functions for theme hook suggestions are not invoked?

rooby’s picture

Here is less pretty workaround:

<?php
function MYTHEME_preprocess_entity(&$variables) {
  // This is a hack to work around drupal.org/node/939462, which means
  // the bean preprocess function isn't called.
  if ($variables['entity_type'] == 'bean') {
    MYTHEME_preprocess_bean($variables);
  }
}
?>

Alternatively you could just use template_preprocess_entity for now and be done with it.

[EDIT] Edited to lessen the alarmist wording :)

seafront’s picture

@rooby why is that dodgy?

rooby’s picture

Well it isn't really. I use it in a few sites and I'm not worried about it.

But it's not as nice a solution as we could have #939462: Specific preprocess functions for theme hook suggestions are not invoked

paulhhowells’s picture

It seems like Context Module (and presumably others?) will break the code I originally tried.

I’m keeping a gist updated here:
https://gist.github.com/paulhhowells/4722363

Which at the moment looks like:

<?php
/**
 * Implements template_preprocess_block
 *
 * enable bean blocks to be themed by bean-type:
 * i.e. block__bean__BEAN-TYPE.tpl
 */
function THEMENAME_preprocess_block(&$variables) {
 
  $block = $variables['block'];
  $block_module = $block->module;
  $elements = $variables['elements'];
 
  // Add Bean Type to Theme Hook Suggestions
  // enable bean blocks to be themed by bean-type: i.e. block__bean__BEAN-TYPE.tpl
 
  // select Bean Blocks and ignore other Blocks
  if (!empty($block_module) && ($block_module == 'bean')) {
 
    // the location of the Bean array within $variables is a moving target
    // e.g. use of the Context Module will change it's location
    if (array_key_exists('bean', $elements)) {
      $bean_array = $elements['bean'];
    } else if (array_key_exists('bean', $elements['content'])) {
      $bean_array = $elements['content']['bean'];
    }
 
    // test that the Bean array has been found
    if ($bean_array) {
      $mystery_key_array = element_children($bean_array);
      if ($mystery_key_array) {
        $bean = $bean_array[$mystery_key_array[0]];

        if (!empty($bean['#bundle'])) {
          $variables['theme_hook_suggestions'][] = 'block__' . $block_module . '__' . $bean['#bundle'];
        }
      }
    }
  }
}
?>

note to self: I must try @rooby’s solution

paulhhowells’s picture

Issue summary: View changes

adding some discussion of hook_bean_admin_ui_types() vs hook_bean_types().

saltednut’s picture

Issue summary: View changes
Status: Active » Fixed

Using bean--[machine-name]--[view-mode].tpl.php works as of the latest release.

Status: Fixed » Closed (fixed)

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

paskainos’s picture

I noticed Devel Themer is now presenting the following tpl candidate files:

  • bean--[bean-block-label].tpl.php
  • bean--[bean-block-type]--default.tpl.php
  • bean--[bean-block-type].tpl.php

This also presents bean.tpl.php as the base candidate template file.