4.6.x block.module _block_rehash($order_by = array('weight'))
4.7.x block.module _block_rehash()
5.x block.module _block_rehash()
6.x block.module _block_rehash($theme = NULL)
7.x block.module _block_rehash($theme = NULL)

Updates the 'block' DB table with the blocks currently exported by modules.

Parameters

$theme: The theme to rehash blocks for. If not provided, defaults to the currently used theme.

Return value

Blocks currently exported by modules.

5 calls to _block_rehash()
BlockHashTestCase::doRehash in modules/block/block.test
Performs a block rehash and checks several related assertions.
BlockHashTestCase::testBlockRehash in modules/block/block.test
Tests that block rehashing does not write to the database too often.
block_admin_display_prepare_blocks in modules/block/block.admin.inc
Prepares a list of blocks for display on the blocks administration page.
block_flush_caches in modules/block/block.module
Implements hook_flush_caches().
dashboard_show_disabled in modules/dashboard/dashboard.module
Ajax callback: Shows disabled blocks in the dashboard customization mode.

File

modules/block/block.module, line 373
Controls the visual building blocks a page is constructed with.

Code

function _block_rehash($theme = NULL) {
  global $theme_key;

  drupal_theme_initialize();
  if (!isset($theme)) {
    // If theme is not specifically set, rehash for the current theme.
    $theme = $theme_key;
  }
  $regions = system_region_list($theme);

  // These are the blocks the function will return.
  $blocks = array();
  // These are the blocks defined by code and modified by the database.
  $current_blocks = array();
  // These are {block}.bid values to be kept.
  $bids = array();
  $or = db_or();
  // Gather the blocks defined by modules.
  foreach (module_implements('block_info') as $module) {
    $module_blocks = module_invoke($module, 'block_info');
    $delta_list = array();
    foreach ($module_blocks as $delta => $block) {
      // Compile a condition to retrieve this block from the database.
      // Add identifiers.
      $delta_list[] = $delta;
      $block['module'] = $module;
      $block['delta'] = $delta;
      $block['theme'] = $theme;
      $current_blocks[$module][$delta] = $block;
    }
    if (!empty($delta_list)) {
      $condition = db_and()->condition('module', $module)->condition('delta', $delta_list);
      $or->condition($condition);
    }
  }
  // Save the blocks defined in code for alter context.
  $code_blocks = $current_blocks;
  $database_blocks = db_select('block', 'b', array('fetch' => PDO::FETCH_ASSOC))
    ->fields('b')
    ->condition($or)
    ->condition('theme', $theme)
    ->execute();
  $original_database_blocks = array();
  foreach ($database_blocks as $block) {
    $module = $block['module'];
    $delta = $block['delta'];
    $original_database_blocks[$module][$delta] = $block;
    // The cache mode can only by set from hook_block_info(), so that has
    // precedence over the database's value.
    if (isset($current_blocks[$module][$delta]['cache'])) {
      $block['cache'] = $current_blocks[$module][$delta]['cache'];
    }
    // Preserve info which is not in the database.
    $block['info'] = $current_blocks[$module][$delta]['info'];
    // Blocks stored in the database override the blocks defined in code.
    $current_blocks[$module][$delta] = $block;
    // Preserve this block.
    $bids[$block['bid']] = $block['bid'];
  }
  drupal_alter('block_info', $current_blocks, $theme, $code_blocks);
  foreach ($current_blocks as $module => $module_blocks) {
    foreach ($module_blocks as $delta => $block) {
      if (!isset($block['pages'])) {
        // {block}.pages is type 'text', so it cannot have a
        // default value, and not null, so we need to provide
        // value if the module did not.
        $block['pages'] = '';
      }
      // Make sure weight is set.
      if (!isset($block['weight'])) {
        $block['weight'] = 0;
      }
      if (!empty($block['region']) && $block['region'] != BLOCK_REGION_NONE && !isset($regions[$block['region']]) && $block['status'] == 1) {
        drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block['info'], '%region' => $block['region'])), 'warning');
        // Disabled modules are moved into the BLOCK_REGION_NONE later so no
        // need to move the block to another region.
        $block['status'] = 0;
      }
      // Set region to none if not enabled and make sure status is set.
      if (empty($block['status'])) {
        $block['status'] = 0;
        $block['region'] = BLOCK_REGION_NONE;
      }
      // There is no point saving disabled blocks. Still, we need to save them
      // because the 'title' attribute is saved to the {blocks} table.
      if (isset($block['bid'])) {
        // If the block has a bid property, it comes from the database and
        // the record needs to be updated, so set the primary key to 'bid'
        // before passing to drupal_write_record().
        $primary_keys = array('bid');
        // Remove a block from the list of blocks to keep if it became disabled.
        unset($bids[$block['bid']]);
      }
      else {
        $primary_keys = array();
      }
      // If the block is new or differs from the original database block, save
      // it. To determine whether there was a change it is enough to examine
      // the values for the keys in the original database record as that
      // contained every database field.
      if (!$primary_keys || array_diff_assoc($original_database_blocks[$module][$delta], $block)) {
        drupal_write_record('block', $block, $primary_keys);
        // Make it possible to test this.
        $block['saved'] = TRUE;
      }
      // Add to the list of blocks we return.
      $blocks[] = $block;
    }
  }
  if ($bids) {
    // Remove disabled that are no longer defined by the code from the
    // database.
    db_delete('block')
      ->condition('bid', $bids, 'NOT IN')
      ->condition('theme', $theme)
      ->execute();
  }
  return $blocks;
}