0

I need to create an array in my custom module that contains data from multiple blocks. something like this:

array(
  'block_1' => array(
    'subject'=>'Block Subject Here',
    'body'=>'Full block body html here',
  ),

  'custom_module_block' => array(
    'subject'=>'Block Subject Here',
    'body'=>'Full block body html here',
  ),

  'another_block_machinename' => array(
    'subject'=>'Block Subject Here',
    'body'=>'Full block body html here',
  ),
);

In order to do this, i need to be able to programmatically load block content, being able to access and handle each block's subject and body in order to populate my array.

Imagine the node equivalent being a simple node_load(); where you can easily access $node->title and $node->body from within the loaded node.

I'm not able to find any functions that make loading this block data possible. Neither block_load() nor module_invoke() get me all the data I need (specifically the block subject).

So, how do I load a block's subject and body programmatically so I can use it in my custom module?

  • Is this array limited to blocks added from Admin -> structure -> blocks? – Vishal Patil Mar 24 '15 at 13:48
  • No, the block data can come from any module in the system, not necessarily from block.module. Updated the code to be less specific. – Feature Mar 24 '15 at 13:51
0
/**
 * Implements hook_block_view().
 */
function hook_block_view($delta = '') {
  $block = array();

  switch ($delta) {
    case 'block_1':

      $block['subject'] = NULL;
      $block['content'] = 'Full block body html here';
      break;

    case 'block_2':

      $block['subject'] = 'Block Subject Here';
      $block['content'] = 'Full block body html here';
      break;

    case 'block_3':

      $block['subject'] = 'Block Subject Here';
      $block['content'] = 'Full block body html here';
      break;

  }
  return $block;
}

Based on https://api.drupal.org/api/drupal/modules%21block%21block.api.php/function/hook_block_view/7

  • I don't think this is what I'm looking for. hook_block_view lets you act on a block as it's being displayed (altering data or other display aspects). I want to load the data for the block for my own purposes, not display the block. Unless I'm misunderstanding the application of how I use this to populate my own array of block data and re-use that array, I don't think this answers the question. – Feature Mar 24 '15 at 14:02
0

Contrary to a statement in my initial question, module_invoke() DOES return the subject of the block...but ONLY if there's block content ($block['content'])! This means if you're trying to load a block with empty content (for example a Views block without results), the block subject returned from module_invoke will always be empty.

So, as long as the block has content, this will return both block subject and block content (turn this into a loop to load multiple blocks);

$block_array = array();      
$loaded_block = module_invoke('module_name', 'block_view', 'block_delta');
$block_array[]['title'] = $loaded_block['subject'];
$block_array[]['content'] = $loaded_block['content']['#markup'];
0

Use following code to get list:

$result = db_select('block', 'b')
            ->fields('b')
            ->execute()
            ->fetchAll();
$arr = array();
    foreach ($result as $key => $row){
        $block = module_invoke($row->module, 'block_view', $row->delta);
        $arr[$key]['content'] = render($block['content']);
        $arr[$key]['subject'] = $block['subject'];
    }
  • I just tested this and it has the same problem as mentioned in the original question: the use of module_invoke doesn't actually give us the block's 'subject' and $row->title in the database only gives us a subject if the user has overridden the default subject and entered in a custom one on the blocks page...in the code above, $arr[$key]['subject'] is always empty (unless there's a custom overridden subject, which I can't count on) – Feature Mar 24 '15 at 14:22
0

Given the assumption that you know what blocks you want to load, and you just want the arrays back that would be displayed (for your own purposes, as you said,) I think you can just "view" the blocks to create the array.

$blocks = array();
$blocks[] = block_block_view(1);
$blocks[] = views_block_view('viewname-blockname');
$blocks[] = custom_module_block_view('delta');
return $blocks;

Wouldn't that work?

Edited to add:

This returns an array like this:

Array
(
    [0] => Array
        (
            [subject] => Simple Block Title
            [content] => <p>This is block(1).</p>
        )
    [1] => Array
        (
            [subject] => View title
            [content] => <div class="view">All the view content, probably as markup.</div>
        )
    [2] => Array
        (
            [subject] => Title of my custom block
            [content] => Array
                (
                    [#theme] => item_list
                    [#items] => Array
                        (
                            [0] => My custom block returns a render array
                            [1] => Markup is for theme layer
                            [2] => This is a silly example
                        )
                )
        )
)

Of course, you can specify array keys when you add $blocks[] items if you need more than just numeric. Either way, as you can see, this returns the subject and content separately, not all mixed together.

  • Unfortunately no, because I need the Subject and Body separately. This will return all the markup (subject and body together) rather than allowing me to split them apart and use them as needed. – Feature Mar 24 '15 at 22:53
  • Ah, I see what you're doing with the updated code you added...and yeah, this looks like it could work. Item [2] in the array seems a little unpredictable (not sure if this is 'real world' or not) as I'd have to be able to get usable [content] in a predictable way. I found the module_include() approach to yield the most predictable results once I understood an empty block would return no subject. Thanks for chiming in! – Feature Mar 26 '15 at 19:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.