Programmatically Set Node Type Visibility for Blocks

If you've ever created a block with hook_block_info you know that the visibility options are limited to just pages. In my case, I wanted to set my block to only appear on certain node types. The challenge is that you can't do it from hook_block_info because node type visibility isn't dictated by the block module, it's provided by the node module.
But fear not, there is a way! If you want to add content type based visibility for your block, you can do so in the .install file of your module using hook_install.

/**
 * Implements hook_install().
 */
function example_install() {
  // Install our custom block visibility settings per node type
  $query = db_insert('block_node_type')
    ->fields(array('type', 'module', 'delta'))
    ->values(array(
      'type' => 'my-node-type',
      'module' => 'example', // My module name
      'delta' => 'my-block-delta', // Same delta used in hook_block_info
    ))
    ->execute(); 
}

 

And that's it! When you install your module, your block will appear on that node type's pages. If you need to specify more than one node type, you need to insert a new record for each, because the type column only accepts one entry. Of course, all this can be altered by the user in the block configuration page.

So if you want to control your own block visibility that can't be changed from the configuration page, you might want to mess with hook_block_list_alter instead.

 

Update: Removed unneeded hook_uninstall() code. The node module already removes all entries in the block_node_type table for the module being uninstalled.