Frage

I'm building a module that manages ad units in the form of blocks that all need to be aware of each other and pass information around.

Thus I need to find a simple hook or other function to get a listing of every block that will be used on the page, so I can be sure to know the entire list of ad units on the page.

I've tried hook_block_list_alter() but this seems to return the ENTIRE list of blocks that exist in my Drupal install, with no designation of which blocks are actually going to be rendered or not on this page.

So, now what do I do?

War es hilfreich?

Lösung

I think it's got something to do with the order hook_block_list_alter() is called in but I'm not entirely sure. Either way the following code will get you a list of all blocks in the current page context. Be sure not to put this in a hook_block_list_alter() function or you'll get an exception caused by infinite nesting.

global $theme;
$all_regions = system_region_list($theme);
$blocks = array();
foreach (array_keys($all_regions) as $region) {
  $blocks += block_list($region);
}

If you only need the blocks in a particular region you can ditch most of the code above and just go with:

$blocks = block_list('region_name');

Andere Tipps

I ran into the same problem when calling block_list('content'). Looking at the code for this function I found it calls two other functions, _block_load_blocks() and _block_render_blocks(). The problem seems to occur in _block_render_blocks() as the display text is not added to the content object. This is different from the other block objects that pass through the function.

To get around this, instead of calling block_list(), I called _block_load_blocks() directly. This returns an array of blocks grouped by region, bypassing the _block_render_blocks() call. Now we can check for blocks in the content region without the content text disappearing. Huzzar!

I had a similar requirement when implementing an adserver (DFP). My solution was to define an array as a global variable, and include php code in each ad unit block that added a new element to the array.

Then, once all blocks on the page have been executed, you can simply access the global variable to see which ad blocks were called. Because the code to build the list of blocks being called is part of each block, it doesn't matter whether the blocks are displayed in a region, in a panel, or anywhere else.

In my case, I wanted to use the information to add scripts to the <head> section that reference only the add units from the blocks being placed. My complete solution was as follows:

1) Implement hook init to create a global variable in which to store information about which blocks are being displayed (you need to create a custom module to contain this code):

YOURMODULE_custom_init() {
  $GLOBALS['dfp-ads'] = array();
}

2) Enable the core php module

3) Add php code at the end of each ad block to add a row to the array created in step 1

<?php
   $GLOBALS['dfp-ads']['AD_OR_BLOCK_NAME_GOES_HERE']="AD SPECIFIC SCRIPT GOES HERE";
?>

4) Implement THEME_preprocess_html in my template.php file to access the global variable, build the script, and add the script to <head> section with a call to drupal_add_html_head

function YOURTHEME_preprocess_html(&$vars) {
   $inline_script = LOGIC TO ACCESS $GLOBALS['dfp-ads'] AND BUILD SCRIPT GOES HERE;
   $element = array(
      '#type' => 'markup',
      '#markup' => $inline_script,
   );

   drupal_add_html_head($element, 'google-dfp');
}

It sounds from your description that you don't need the list of ad blocks to build javascript for the head section, but instead want to use the information to modify the contents of the blocks themselves.

In that case insteaad of THEME_preprocess_html, you could try hook_page_alter(&page) The api page for that hook states that individual "Blocks may be referenced by their module/delta pair within a region:"

// The login block in the first sidebar region.
$page['sidebar_first']['user_login']['#block'];

Hope that helps someone!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top