Hello,

Just wanted to know if it's possible to create a custom block in Drupal 7 without using the block hooks hook_block_info() or hook_block_configure() etc.

My requirement is adding dynamic blocks to the Drupal system.

I am a newbie in Drupal, so please excuse me if this is sort of a very basic question and discussed previously.

Thanks in advance...

Comments

srutheesh’s picture

There is one options in the drupal admin section...
1. Go to the path sitename/?q=admin/settings/block
2. The is one menu called 'add new block' , click on that.
3. It is very user frinendly , check it .

Have a great day...

pratip.ghosh’s picture

Thanks, but i wanted to create a custom block programmatically, i.e. by using code.
I hope i make myself clear here...

-- Pratip Ghosh

WorldFallz’s picture

i'm not sure what you're asking-- 'block' is a drupal concept and they are created with the hook_block_* functions. If you don't want to use those functions then, by definition, you're not creating a block. Just put a snippet of code wherever you want.

srutheesh’s picture

I hope you are not familiar with drupal ...

In the above mentioned method , you can insert your own code like php/html etc.... Other wise you might use hook_block...

Try this modules too , i hope what you are searching it is here ...
http://drupal.org/project/nodeblock
http://drupal.org/project/nodeasblock
You can create a block as node ...

Hope you can understand....

pratip.ghosh’s picture

I think either i am not understanding or i am not able to explain my problem. Let me try again:

function fevm_block_info() 
{    
	$blocks['test_block'] = array(
		// info: The name of the block.
		'info' => t('Test Block'),
	);
	return $blocks;
}

function fevm_block_view($delta = '') 
{
	// The $delta parameter tells us which block is being requested.
	switch ($delta) 
	{
		case 'test_block':
			// Create your block content here
			$block['subject'] = t('This is just a test block created programatically');
			$block['content'] = 'This should contain the condition for this block.';
			break;
	}

	return $block;
}

This is how a block is created programmatically if i am not wrong. But this functions will be called internally from the system whenever i load this module, i.e. without any user interaction.

What i want is to write function(s) that create blocks within Drupal system only when i call them. I will pass the block properties (title, content etc.) as parameter while calling these function(s).

Was that helpful?

-- Pratip Ghosh

N1ghteyes’s picture

Are you looking to make a block based on a condition? or are you looking to do something like loop through a bunch of records and output a new block for a new record.

Both of which are possible using any hook that is called outside of a .install file, as its run every time the hook is called, rather than being a one off. (as far as I know).

There shouldn't be any reason you cant dynamically build new blocks and configurations for those blocks inside the hooks, so long as it returns an array in the right format.

pratip.ghosh’s picture

Right, i am trying to create a block when i wish, calling a function like that of the block_hook ones based on parameters like block title, description etc. The block should only be created when i call those function(s) and not like the block_hook.

Does this clear things up?

-- Pratip Ghosh

N1ghteyes’s picture

i think so yes,

unfortunately so far as I know, its not reasonably possible to do what you want, at least not without tearing Drupal apart, but I feel you might be misunderstanding a little of how blocks work.

I'm assuming you want to create a new block, every time, say, a form is filled in? you could then in theory have a foreach() in hook block that will create a block every time there is a new record in the DB, or you could use a while() or any other number of standard PHP functions.

When a block is created its not automatically put somewhere on the site (unless you have specified that in the code), it goes into your block list where you can then do any number of things with it (configure, edit, assign to regions etc).

Under what conditions are you trying to create the block?

pratip.ghosh’s picture

Yes, you understood my requirement. If more explanations are needed you can view that at http://drupal.org/node/1709954#comment-6306220

If it's not a big trouble for you, can you kindly provide the code within the foreach/while loop that you were talking about from where a block is created dynamically.

And for the last part of your reply, yes i know that the block thus created would not be assigned to any region. But that's ok for now with me. I just want to create the block with it's title and description.

Thanks a lot to all of you for your co-operation...

-- Pratip Ghosh

N1ghteyes’s picture

Ok, so;

this can be done with what you have above, with a few changes.
The below code is a very basic take on a way you -could- output the result of a form submission as dynamically created blocks. This code is Drupal 7 Specific

function fevm_block_info() {
//select the database data for your saved input form. in this case the table simply contains ID, title, content and subject, no condition given as i dont know if your looking for something specific or just some data. you -HAVE- to interact with the database to get the form data, unless you really want to mess with $_SESSION for temporary blocks

//fetchAll will return an object containing all the results (fetchAssoc returns an array, one row as a time)

      $form_for_block = db_select('your_stored_form_data', 'ysfd')
                                            ->fields('ysfd')
                                            ->execute()
                                            ->fetchAll();

//loop through each returned row and build the blocks
      foreach($form_for_block as $block_data){
//strip the spaces from the title to add underscores (for block machine name)
        $macname = str_replace(' ','_', $block_data->title);
//assuming ID is unique int here, using to make sure we always have a unique block name:
	$blocks[$block_data->ID.'_'.$macname] = array(
// info: The name of the block.
		'info' => t($block_data->title),
	);
      }
	return $blocks;
}

function fevm_block_view($delta = '') {
// The $delta parameter tells us which block is being requested.
$form_view_block = db_select('your_stored_form_data', 'ysfd')
                                            ->fields('ysfd')
                                            ->execute()
                                            ->fetchAll();

//loop through each returned row and get the block machine names (as created above)
      foreach($form_view_block as $view_block){
//strip the spaces from the title to add underscores (for block machine name so we get a name that matches a block we made)
        $macname = str_replace(' ','_', $view_block->title);
	         switch ($delta) {
		 case '$block_data->ID.'_'.$macname':
// Create your block content here
			$block['subject'] = t($view_block->subject);
//using content as generic text, but you could check the content of the block in the foreach, and do something based on it, then use the result as the content here.
			$block['content'] = $view_block->content;
			break;
	         }
        }
	return $block;
}

you could have multiple foreach() statements, so long as the returned array is built as drupal expects.

Side note: i wrote the above in the reply box, so if there are any syntax errors with it i apologise. its designed as an example rather than functioning code.

N1ght

N1ghteyes’s picture

this code would create a block for each form submission saved into a DB table. you could add extra processing to search for a certain piece of data within the row, for example a location, and you could do something like this inside the foreach:

if($view_block->content == 'England'){
    //do something here
}
$block['content'] = 'The result of the If statement';

//return the block with the new content

In that way you could create dynamic blocks based on form submissions and certain perimeters. (for example a hidden field in a form or a check list)

N1ght

pratip.ghosh’s picture

Thank you very much for the idea. I figure, that if I HAVE to do it by calling the hook, then it's better to store the block infos in a temporary table, and when the hook gets fired, it reads through this table, fetches records waiting to be inserted in the Drupal block table, creates the block and thereafter deletes the record from the table.

Thanks to all of you for your support...

Cheers!!!

-- Pratip Ghosh

N1ghteyes’s picture

Just a note on the above :)

The block only exists while the hook is calling it. if the record is removed form the db, then the block will go too :)

But if thats the aim here, then your right thats by far the best solution for you :)

N1ght

pratip.ghosh’s picture

Actually i will be deleting the record from the self-created temporary table and not from the Drupal system block table.

Thanks...

-- Pratip Ghosh

N1ghteyes’s picture

ah, yea ok :)

early morning and all >.<, that makes more sense :D

sorry for the confusion there :) and glad i could help with a workable solution

srutheesh’s picture

I hope you are not familiar with drupal ...

In the above mentioned method , you can insert your own code like php/html etc.... Other wise you might use hook_block...

Try this modules too , i hope what you are searching it is here ...
http://drupal.org/project/nodeblock
http://drupal.org/project/nodeasblock
You can create a block as node ...

Otherwise you can create the block by using your own function with db_query and variables by using the table 'block_custom', But you might take care on creating this by your own code , it may effect the drupal normal functionality ...

Check this code

  $delta = db_insert('block_custom')
    ->fields(array(
      'body' => $form_state['values']['body']['value'],
      'info' => $form_state['values']['info'],
      'format' => $form_state['values']['body']['format'],
    ))
    ->execute();
  // Store block delta to allow other modules to work with new block.
  $form_state['values']['delta'] = $delta;

  $query = db_insert('block')->fields(array('visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache'));
  foreach (list_themes() as $key => $theme) {
    if ($theme->status) {
      $query->values(array(
        'visibility' => (int) $form_state['values']['visibility'],
        'pages' => trim($form_state['values']['pages']),
        'custom' => (int) $form_state['values']['custom'],
        'title' => $form_state['values']['title'],
        'module' => $form_state['values']['module'],
        'theme' => $theme->name,
        'status' => 0,
        'weight' => 0,
        'delta' => $delta,
        'cache' => DRUPAL_NO_CACHE,
      ));
    }
  }
  $query->execute();

  $query = db_insert('block_role')->fields(array('rid', 'module', 'delta'));
  foreach (array_filter($form_state['values']['roles']) as $rid) {
    $query->values(array(
      'rid' => $rid,
      'module' => $form_state['values']['module'],
      'delta' => $delta,
    ));
  }
  $query->execute();

  // Store regions per theme for this block
  foreach ($form_state['values']['regions'] as $theme => $region) {
    db_merge('block')
      ->key(array('theme' => $theme, 'delta' => $delta, 'module' => $form_state['values']['module']))
      ->fields(array(
        'region' => ($region == BLOCK_REGION_NONE ? '' : $region),
        'pages' => trim($form_state['values']['pages']),
        'status' => (int) ($region != BLOCK_REGION_NONE),
      ))
      ->execute();
  }

  drupal_set_message(t('The block has been created.'));

Hope you can understand....

pratip.ghosh’s picture

Thanks a lot for your help.

I considered the option of creating a new block directly in the DB level. Thanks anyways. This i would keep as my last option. But was just wondering that is'nt there something in drupal (like tweaking/replicating the block_hook a little, so as to call when needed) that does it without this writing DB level code?

Again i may be severely wrong approached, but something tells me it's possible, because i think this is a very obvious requirement that a developer may often face.

Thanks a lot again to all of you for your prompt replies...

-- Pratip Ghosh

srutheesh’s picture

Always welcome... This code work only in drupal 7

fab01’s picture

This chunk of code has been grabbed from here:
https://api.drupal.org/api/drupal/modules!block!block.admin.inc/function...
It's part of Block Api.
Before posting "copy-past" code I think it should be useful to provide a CORRECT and FULLY CLEAR documentation in order to avoid loss of time for newbies to search (maybe not so) obvious information!
I really can't see the reason to truncate the function name from the Api function code above.

leex’s picture

Hey Pratip,

I know this question is 2 years old but the answer is quite simple.

You just programmatically submit the block add form, passing to it the data you want.

/**
 * Programmatically creates a DB level block.
 *
 * Using the settings below a block is created programmatically.
 * To find out which other settings are available, use hook_form_alter
 * on block_add_block_form to check the $form_state['input'] values and
 * insert them into the $form_state['values'] array with your custom value.
 */
function mycustomfunction_create_block($title = '', $description = '') {

  form_load_include($form_state, 'inc', 'block', 'block.admin');

  $form_state = array();
  $form_state['values'] = array(
    'title' => $title,
    'info' => $description,
    'visibility' => '0',
    'pages' => NULL,
    'custom' => '0',
    // The block isn't visible initially
    'regions' => array(
        'seven' => '-1',
        'stark' => '-1',
      ),
    'body' => array(
        'value' => '<p>Don\'t bite your nails!.</p>',
        'format' => 'filtered_html',
      ),
  );
  // Submit the form programmatically.
  drupal_form_submit('block_add_block_form', $form_state);

}
atolborg’s picture

@leex: thank for your great answer!

For some reason I can't set format to anything but "plain_text". If I try to set it to either "full_html" or "filtered_html" I get the following error:

WD form: Illegal choice filtered_html in Text format element. An illegal choice has been detected. Please contact the site administrator.

I do have both formats enabled, and if I test the input using dpm($form_state) in hook_form_alter the format is set to "full_html". Weird?

kalidasan’s picture

   'body' => array(
      'value' => 'Don\'t bite your nails!.',
      'format' => 'filtered_html', // Remove Or hide this value while create.
    ),

---------------------------------------------------------

   // After block creation, just run below code to update format.
   $block_updated = db_update('block_custom')
    ->fields(array(
      'format' => 'full_html',
    ))
    ->condition('info', $info) // You can use bid too.
    ->execute();
Shashwat Purav’s picture

Also if anyone wants to update the created block programatically:

/**
 * Programmatically updates a DB level block.
 */

  $bid = GET_THE_BID_OF_THE_BLOCK;
  form_load_include($form_state, 'inc', 'block', 'block.admin');

  $form_state = array();
  $form_state['values'] = array(
    'title' => $title,
    'info' => $description,
    'visibility' => '0',
    'pages' => NULL,
    'custom' => '0',
    // The block isn't visible initially
    'regions' => array(
        'seven' => '-1',
        'stark' => '-1',
      ),
    'body' => array(
        'value' => 'Don\'t bite your nails!.',
        'format' => 'filtered_html',
      ),
  );
  // Submit the form programmatically.
  drupal_form_submit('block_admin_configure', $form_state, 'block', $bid);

Thank You,
Shashwat Purav