Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.456 diff -u -r1.456 theme.inc --- includes/theme.inc 16 Dec 2008 22:05:50 -0000 1.456 +++ includes/theme.inc 27 Dec 2008 22:23:53 -0000 @@ -2048,5 +2048,5 @@ $variables['template_files'][] = 'block-' . $variables['block']->region; $variables['template_files'][] = 'block-' . $variables['block']->module; - $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta; + $variables['template_files'][] = 'block-' . $variables['block']->block_id; } Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.949 diff -u -r1.949 user.module --- modules/user/user.module 23 Dec 2008 14:18:31 -0000 1.949 +++ modules/user/user.module 27 Dec 2008 22:24:48 -0000 @@ -739,26 +739,87 @@ */ function user_block_list() { global $user; - - $blocks['login']['info'] = t('User login'); - // Not worth caching. - $blocks['login']['cache'] = BLOCK_NO_CACHE; - - $blocks['navigation']['info'] = t('Navigation'); - // Menu blocks can't be cached because each menu item can have - // a custom access callback. menu.inc manages its own caching. - $blocks['navigation']['cache'] = BLOCK_NO_CACHE; - - $blocks['new']['info'] = t('Who\'s new'); - - // Too dynamic to cache. - $blocks['online']['info'] = t('Who\'s online'); - $blocks['online']['cache'] = BLOCK_NO_CACHE; + + $blocks['user_login'] = array( + 'title' => t('User login'), + 'block callback' => 'drupal_get_form', + 'block arguments' => array('user_login_block'), + 'access callback' => '_user_block_login_access', + 'description' => t('Provides the user login box.'), + 'cache' => BLOCK_NO_CACHE // Not worth caching. + ); + $blocks['user_navigation'] = array( + 'title' => t('Navigation'), + 'block callback' => 'menu_tree', + 'title callbacl' => '_user_block_navigation_title', + 'description' => t('Provides the main interactive menu for the site.'), + 'cache' => BLOCK_NO_CACHE // Not worth caching. + ); + $blocks['user_new'] = array( + 'title' => t('Who \'s new'), + 'access arguments' => array('access content'), + 'block callback' => '_user_block_new', + 'description' => t('Provides a list of new users who have subsequently accessed the site successfully.'), + ); + $blocks['user_online'] = array( + 'title' => t('Who \'s online'), + 'access arguments' => array('access content'), + 'block callback' => '_user_block_online', + 'description' => t('Provides a list of users active within the defined period.'), + 'cache' => BLOCK_NO_CACHE // Too dynamic to cache. + ); + return $blocks; } +function _user_block_login_access() { + global $user; + // For usability's sake, avoid showing two login forms on one page. + return !$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1))); +} + +function _user_block_navigation_title() { + global $user; + return $user->uid ? check_plain($user->name) : t('Navigation'); +} + +function _user_block_new() { + // Retrieve a list of new users who have subsequently accessed the site successfully. + $items = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', array(), 0, variable_get('user_block_whois_new_count', 5))->fetchAll(); + return theme('user_list', $items); +} + +function _user_block_online() { + // Count users active within the defined period. + $interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900); + + // Perform database queries to gather online user lists. We use s.timestamp + // rather than u.access because it is much faster. + $anonymous_count = drupal_session_count($interval); + $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField(); + + // Format the output with proper grammar. + if ($anonymous_count == 1 && $authenticated_count == 1) { + $output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); + } + else { + $output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); + } + + // Display a list of currently online users. + $max_users = variable_get('user_block_max_list_count', 10); + if ($authenticated_count && $max_users) { + $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', array(':interval' => $interval), 0, $max_users)->fetchAll(); + $output .= theme('user_list', $items, t('Online users')); + } + return $output; +} + /** * Implementation of hook_block_configure(). + * + * @TODO: Remove this hook and instead add configuration options by altering the + * blocks configuration form. */ function user_block_configure($delta = '') { global $user; @@ -783,6 +844,9 @@ /** * Implementation of hook_block_save(). + * + * @TODO: Remove this hook and instead save configuration options by registering a submit + * handler in the blocks configuration form. */ function user_block_save($delta = '', $edit = array()) { global $user; @@ -800,74 +864,6 @@ } /** - * Implementation of hook_block_view(). - */ -function user_block_view($delta = '') { - global $user; - - $block = array(); - - switch ($delta) { - case 'login': - // For usability's sake, avoid showing two login forms on one page. - if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) { - - $block['subject'] = t('User login'); - $block['content'] = drupal_get_form('user_login_block'); - } - return $block; - - case 'navigation': - if ($menu = menu_tree()) { - $block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation'); - $block['content'] = $menu; - } - return $block; - - case 'new': - if (user_access('access content')) { - // Retrieve a list of new users who have subsequently accessed the site successfully. - $items = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', array(), 0, variable_get('user_block_whois_new_count', 5))->fetchAll(); - $output = theme('user_list', $items); - - $block['subject'] = t('Who\'s new'); - $block['content'] = $output; - } - return $block; - - case 'online': - if (user_access('access content')) { - // Count users active within the defined period. - $interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900); - - // Perform database queries to gather online user lists. We use s.timestamp - // rather than u.access because it is much faster. - $anonymous_count = drupal_session_count($interval); - $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField(); - - // Format the output with proper grammar. - if ($anonymous_count == 1 && $authenticated_count == 1) { - $output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); - } - else { - $output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests'))); - } - - // Display a list of currently online users. - $max_users = variable_get('user_block_max_list_count', 10); - if ($authenticated_count && $max_users) { - $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', array(':interval' => $interval), 0, $max_users)->fetchAll(); - $output .= theme('user_list', $items, t('Online users')); - } - - $block['subject'] = t('Who\'s online'); - $block['content'] = $output; - } - return $block; - } -} - -/** * Process variables for user-picture.tpl.php. * * The $variables array contains the following arguments: Index: modules/system/block.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/block.tpl.php,v retrieving revision 1.7 diff -u -r1.7 block.tpl.php --- modules/system/block.tpl.php 13 Oct 2008 12:31:43 -0000 1.7 +++ modules/system/block.tpl.php 27 Dec 2008 22:23:56 -0000 @@ -25,9 +25,9 @@ * @see template_preprocess_block() */ ?> -
-subject): ?> -

subject ?>

+
+title): ?> +

title?>

Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.294 diff -u -r1.294 system.install --- modules/system/system.install 26 Dec 2008 11:04:39 -0000 1.294 +++ modules/system/system.install 27 Dec 2008 22:24:30 -0000 @@ -367,10 +367,14 @@ db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", 'theme_default', 's:7:"garland";'); db_query("UPDATE {system} SET status = %d WHERE type = '%s' AND name = '%s'", 1, 'theme', 'garland'); - db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'user', 'login', 'garland', 1, 0, 'left', '', -1); - db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'user', 'navigation', 'garland', 1, 0, 'left', '', -1); - db_query("INSERT INTO {block} (module, delta, theme, status, weight, region, pages, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', '%s', %d)", 'system', 'powered-by', 'garland', 1, 10, 'footer', '', -1); - + + // Add a user login block instance to the left sidebar of the default theme. + db_query("INSERT INTO {block_instance} (block_id, theme, region, weight, pages) VALUES ('%s', '%s', '%s', %d, '%s')", 'user_login','garland', 'left', 0, ''); + // Add the main interactive navigation menu for the site to the left sidebar of the default theme. + db_query("INSERT INTO {block_instance} (block_id, theme, region, weight, pages) VALUES ('%s', '%s', '%s', %d, '%s')", 'user_navigation','garland', 'left', 1, ''); + // Add the powered-by block to the footer of the default theme. + db_query("INSERT INTO {block_instance} (block_id, theme, region, weight, pages) VALUES ('%s', '%s', '%s', %d, '%s')", 'system_powerd_by','garland', 'footer', 0, ''); + db_query("INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, '%s', %d, %d, %d)", 0, 0, 'all', 1, 0, 0); // Add input formats. Index: themes/garland/block.tpl.php =================================================================== RCS file: /cvs/drupal/drupal/themes/garland/block.tpl.php,v retrieving revision 1.4 diff -u -r1.4 block.tpl.php --- themes/garland/block.tpl.php 14 Apr 2008 17:48:46 -0000 1.4 +++ themes/garland/block.tpl.php 27 Dec 2008 22:24:48 -0000 @@ -1,10 +1,10 @@ -
+
-subject)): ?> -

subject ?>

+title)): ?> +

title ?>

content ?>
Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.316 diff -u -r1.316 block.module --- modules/block/block.module 16 Dec 2008 23:57:31 -0000 1.316 +++ modules/block/block.module 27 Dec 2008 22:23:56 -0000 @@ -184,7 +184,8 @@ */ function block_block_list() { $blocks = array(); - + + // @TODO: convert to callbacks structure. $result = db_query('SELECT bid, info FROM {box} ORDER BY info'); while ($block = db_fetch_object($result)) { $blocks[$block->bid]['info'] = $block->info; @@ -196,6 +197,9 @@ /** * Implementation of hook_block_configure(). + + * @TODO: Remove this hook and instead add configuration options by altering the + * blocks configuration form. */ function block_block_configure($delta = 0, $edit = array()) { $box = array('format' => FILTER_FORMAT_DEFAULT); @@ -209,6 +213,8 @@ /** * Implementation of hook_block_save(). + * @TODO: Remove this hook and instead save configuration options by registering a submit + * handler in the blocks configuration form. */ function block_block_save($delta = 0, $edit = array()) { block_box_save($edit, $delta); @@ -226,6 +232,95 @@ } /** + * Collect, alter and store the block definitions exported by enabled modules. + */ +function block_router_build($reset = FALSE) { + static $blocks; + + if (!isset($blocks) || $reset) { + if (!$reset && ($cache = cache_get('router:', 'cache_block')) && isset($cache->data)) { + $blocks = $cache->data; + } + else { + // We need to manually call each module so that we can know which module + // a given block came from. + $blocks = array(); + foreach (module_implements('block_list', TRUE) as $module) { + $module_blocks = call_user_func($module . '_block_list'); + if (isset($module_blocks) && is_array($module_blocks)) { + foreach (array_keys($module_blocks) as $block_id) { + $module_blocks[$block_id]['module'] = $module; + } + $blocks = array_merge($blocks, $module_blocks); + } + } + + // Alter the block callbacks. + drupal_alter('block', $callbacks); + + // Delete the existing block router since we have some data to replace it. + db_delete('block_router')->execute(); + + // Prepare insert object. + $insert = db_insert('block_router') + ->fields(array( + 'block_id', + 'module', + 'block_name', + 'description', + 'cache', + 'title', + 'title_callback', + 'title_arguments', + 'block_callback', + 'block_arguments', + 'access_callback', + 'access_arguments' + )); + + foreach ($blocks as $block_id => $v) { + $block = &$blocks[$block_id]; + + // Set defaults. + $block += array( + 'access arguments' => array(), + 'access callback' => 'user_access', + 'block arguments' => array(), + 'block callback' => '', + 'title' => '', + 'title arguments' => array(), + 'title callback' => 't', + 'description' => '', + 'cache' => BLOCK_CACHE_PER_ROLE, + ); + + // Fill in insert object values. + $insert->values(array( + 'block_id' => $block_id, + 'module' => $block['module'], + 'block_name' => $block['title'], + 'description' => $block['description'], + 'cache' => $block['cache'], + 'title' => $block['title'], + 'title_callback' => $block['title callback'], + 'title_arguments' => serialize($block['title arguments']), + 'block_callback' => $block['block callback'], + 'block_arguments' => serialize($block['block arguments']), + 'access_callback' => $block['access callback'], + 'access_arguments' => serialize($block['access arguments']), + )); + } + // Execute insert object. + $insert->execute(); + + // Sotore a copy in the block cache. + cache_set('router:', $blocks, 'cache_block'); + } + } + return $blocks; +} + +/** * Update the 'block' DB table with the blocks currently exported by modules. * * @return @@ -234,72 +329,25 @@ function _block_rehash() { global $theme_key; + $blocks = block_router_build(TRUE); + $blocks_ids = array_keys($blocks); + init_theme(); - - $result = db_query("SELECT * FROM {block} WHERE theme = '%s'", $theme_key); - $old_blocks = array(); - while ($old_block = db_fetch_array($result)) { - $old_blocks[$old_block['module']][$old_block['delta']] = $old_block; - } - - $blocks = array(); + // Valid region names for the theme. - $regions = system_region_list($theme_key); - - foreach (module_implements('block_list') as $module) { - $module_blocks = module_invoke($module, 'block_list'); - if ($module_blocks) { - foreach ($module_blocks as $delta => $block) { - if (empty($old_blocks[$module][$delta])) { - // If it's a new block, add identifiers. - $block['module'] = $module; - $block['delta'] = $delta; - $block['theme'] = $theme_key; - 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'] = ''; - } - // Add defaults and save it into the database. - drupal_write_record('block', $block); - // Set region to none if not enabled. - $block['region'] = $block['status'] ? $block['region'] : BLOCK_REGION_NONE; - // Add to the list of blocks we return. - $blocks[] = $block; - } - else { - // If it's an existing block, database settings should overwrite - // the code. But aside from 'info' everything that's definable in - // code is stored in the database and we do not store 'info', so we - // do not need to update the database here. - // Add 'info' to this block. - $old_blocks[$module][$delta]['info'] = $block['info']; - // If the region name does not exist, disable the block and assign it to none. - if (!empty($old_blocks[$module][$delta]['region']) && !isset($regions[$old_blocks[$module][$delta]['region']])) { - drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $old_blocks[$module][$delta]['info'], '%region' => $old_blocks[$module][$delta]['region'])), 'warning'); - $old_blocks[$module][$delta]['status'] = 0; - $old_blocks[$module][$delta]['region'] = BLOCK_REGION_NONE; - } - else { - $old_blocks[$module][$delta]['region'] = $old_blocks[$module][$delta]['status'] ? $old_blocks[$module][$delta]['region'] : BLOCK_REGION_NONE; - } - // Add this block to the list of blocks we return. - $blocks[] = $old_blocks[$module][$delta]; - // Remove this block from the list of blocks to be deleted. - unset($old_blocks[$module][$delta]); - } - } - } - } - - // Remove blocks that are no longer defined by the code from the database. - foreach ($old_blocks as $module => $old_module_blocks) { - foreach ($old_module_blocks as $delta => $block) { - db_query("DELETE FROM {block} WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $module, $delta, $theme_key); - } - } - return $blocks; + $regions = array_keys(system_region_list($theme_key)); + + // Remove all instances of blocks that are no longer defined, + // or that are assigned to an invalid region in the current theme. + db_delete('block_instance') + ->condition(db_or() + ->condition('block_id', $blocks_ids, 'NOT IN') + ->condition(db_and() + ->condition('region', $regions, 'NOT IN') + ->condition('theme' , $theme_key) + ) + ) + ->execute(); } function block_box_get($bid) { @@ -386,14 +434,10 @@ * The name of a region. * * @return - * An array of block objects, indexed with module_delta. + * An array of block objects, indexed with the block ID. * If you are displaying your blocks in one or two sidebars, you may check * whether this array is empty to see how many columns are going to be * displayed. - * - * @todo - * Now that the blocks table has a primary key, we should use that as the - * array key instead of module_delta. */ function block_list($region) { static $blocks = array(); @@ -417,18 +461,28 @@ */ function _block_load_blocks() { global $user, $theme_key; - + + $block_router = block_router_build(); + $blocks = array(); $rids = array_keys($user->roles); - $result = db_query(db_rewrite_sql("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.theme = '%s' AND b.status = 1 AND (r.rid IN (" . db_placeholders($rids) . ") OR r.rid IS NULL) ORDER BY b.region, b.weight, b.module", 'b', 'bid'), array_merge(array($theme_key), $rids)); + // @todo: join {block_instance_role} in this query + $result = db_query("SELECT * FROM {block_instance} WHERE theme = '%s' ORDER BY region, weight", $theme_key); + while ($block = db_fetch_object($result)) { + $block->router = $block_router[$block->block_id]; + $block->module = $block_router[$block->block_id]['module']; + if (!isset($blocks[$block->region])) { $blocks[$block->region] = array(); } + // Check access control. + // @todo: check access control + // Use the user's block visibility setting, if necessary. - if ($block->custom != 0) { - if ($user->uid && isset($user->block[$block->module][$block->delta])) { - $enabled = $user->block[$block->module][$block->delta]; + if (!empty($block->custom)) { + if ($user->uid && isset($user->block[$block->block_id])) { + $enabled = $user->block[$block->block_id]; } else { $enabled = ($block->custom == 1); @@ -461,7 +515,7 @@ } $block->enabled = $enabled; $block->page_match = $page_match; - $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block; + $blocks[$block->region][] = $block; } return $blocks; @@ -490,27 +544,30 @@ $array = $cache->data; } else { - $array = module_invoke($block->module, 'block_view', $block->delta); + // Render block content using block callback function. + $block->content = call_user_func_array($block->router['block callback'], $block->router['block arguments']); + // Render block title using block title callback function. + // t() is a special case. Since it is used very close to all the time, + // we handle it directly instead of using indirect, slower methods. + if ($block->router['title callback'] == 't') { + $block->title = t($block->router['title'], $block->router['title arguments']); + } + else { + $block->title = call_user_func_array($block->router['title callback'], array($block->router['title arguments'])); + } + if (isset($cid)) { - cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY); + cache_set($cid, $block, 'cache_block', CACHE_TEMPORARY); } } - if (isset($array) && is_array($array)) { - foreach ($array as $k => $v) { - $block->$k = $v; - } - } - if (isset($block->content) && $block->content) { + if (!empty($block->content)) { // Override default block title if a custom display title is present. - if ($block->title) { + if (!empty($block->custom_title)) { // Check plain here to allow module generated titles to keep any markup. - $block->subject = $block->title == '' ? '' : check_plain($block->title); - } - if (!isset($block->subject)) { - $block->subject = ''; + $block->title = $block->custom_title == '' ? '' : check_plain($block->custom_title); } - $region_blocks["{$block->module}_{$block->delta}"] = $block; + $region_blocks[$block->block_id] = $block; } } } Index: modules/block/block.install =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.install,v retrieving revision 1.17 diff -u -r1.17 block.install --- modules/block/block.install 16 Dec 2008 23:57:31 -0000 1.17 +++ modules/block/block.install 27 Dec 2008 22:23:53 -0000 @@ -5,64 +5,148 @@ * Implementation of hook_schema(). */ function block_schema() { - $schema['block'] = array( - 'description' => 'Stores block settings, such as region and visibility settings.', + $schema['block_router'] = array( + 'description' => 'Stores block\'s info and callbacks defined by enabled modules.', 'fields' => array( - 'bid' => array( - 'type' => 'serial', + 'block_id' => array( + 'description' => 'Primary Key: the block unique identifier', + 'type' => 'varchar', + 'length' => 255, 'not null' => TRUE, - 'description' => 'Primary Key: Unique block ID.', + 'default' => '', ), 'module' => array( 'type' => 'varchar', - 'length' => 64, + 'length' => 255, 'not null' => TRUE, 'default' => '', 'description' => "The module from which the block originates; for example, 'user' for the Who's Online block, and 'block' for any custom blocks.", ), - 'delta' => array( + 'block_name' => array( + 'description' => 'The human readable name of the block, as shown to the user in the block admin pages.', 'type' => 'varchar', - 'length' => 32, + 'length' => 255, 'not null' => TRUE, - 'default' => '0', - 'description' => 'Unique ID for block within a module.', + 'default' => '', ), - 'theme' => array( + 'description' => array( + 'description' => 'Provide a more descriptive information about the block.', 'type' => 'varchar', - 'length' => 64, + 'length' => 255, 'not null' => TRUE, 'default' => '', - 'description' => 'The theme under which the block settings apply.', ), - 'status' => array( + 'cache' => array( 'type' => 'int', 'not null' => TRUE, - 'default' => 0, + 'default' => 1, 'size' => 'tiny', - 'description' => 'Block enabled status. (1 = enabled, 0 = disabled)', + 'description' => 'Binary flag to indicate block cache mode. (-1: Do not cache, 1: Cache per role, 2: Cache per user, 4: Cache per page, 8: Block cache global) See BLOCK_CACHE_* constants in block.module for more detailed information.', + ), + 'title' => array( + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'default' => '', + 'description' => 'Title for the block provided by modules through hook_blocks.)', + ), + 'title_callback' => array( + 'description' => 'A function which will alter the title. Defaults to )', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'title_arguments' => array( + 'description' => 'A serialized array of arguments for the title callback. If empty, the title will be used as the sole argument for the title callback.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'block_callback' => array( + 'description' => 'Name of a function used to render the block on the system administration page for this item.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + 'default' => '', + ), + 'block_arguments' => array( + 'description' => 'A serialized array of arguments for the block callback.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'access_callback' => array( + 'description' => 'The callback which determines the access to this block. Defaults to user_access.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'access_arguments' => array( + 'description' => 'A serialized array of arguments for the access callback.', + 'type' => 'text', + 'not null' => FALSE, + ), + ), + + 'primary key' => array('block_id'), + ); + + $schema['block_instance'] = array( + 'description' => 'Stores blocks intances in themes and regions.', + 'fields' => array( + 'biid' => array( + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => 'Primary key: The block instance unique identifier.', + ), + 'block_id' => array( + 'description' => 'The block unique identifier.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', ), + 'theme' => array( + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'default' => '', + 'description' => 'Theme name in which the block instance is set.', + ), + 'region' => array( + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'default' => '', + 'description' => 'Theme region within which the block instance is set.', + ), 'weight' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny', - 'description' => 'Block weight within region.', + 'description' => 'Block instance weight within region.', ), - 'region' => array( + 'custom_title' => array( 'type' => 'varchar', - 'length' => 64, + 'length' => 255, 'not null' => TRUE, 'default' => '', - 'description' => 'Theme region within which the block is set.', - ), - 'custom' => array( + 'description' => 'Custom block title.', + ), + 'user_visibilty' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny', 'description' => 'Flag to indicate how users may control visibility of the block. (0 = Users cannot control, 1 = On by default, but can be hidden, 2 = Hidden by default, but can be shown)', ), - 'visibility' => array( + 'page_visibility' => array( 'type' => 'int', 'not null' => TRUE, 'default' => 0, @@ -73,45 +157,26 @@ 'type' => 'text', 'not null' => TRUE, 'description' => 'Contents of the "Pages" block; contains either a list of paths on which to include/exclude the block or PHP code, depending on "visibility" setting.', - ), - 'title' => array( - 'type' => 'varchar', - 'length' => 64, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Custom title for the block. (Empty string will use block default title, <none> will remove the title, text will cause block to use specified title.)', - ), - 'cache' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 1, - 'size' => 'tiny', - 'description' => 'Binary flag to indicate block cache mode. (-1: Do not cache, 1: Cache per role, 2: Cache per user, 4: Cache per page, 8: Block cache global) See BLOCK_CACHE_* constants in block.module for more detailed information.', - ), + ), ), - 'primary key' => array('bid'), + 'primary key' => array('biid'), 'unique keys' => array( - 'tmd' => array('theme', 'module', 'delta'), - ), + 'btr' => array('block_id', 'theme', 'region') + ), 'indexes' => array( - 'list' => array('theme', 'status', 'region', 'weight', 'module'), - ), - ); + 'list' => array('theme', 'region', 'weight') + ) + ); - $schema['block_role'] = array( - 'description' => 'Sets up access permissions for blocks based on user roles', + $schema['block_instance_role'] = array( + 'description' => 'Sets up access permissions for blocks instances based on user roles.', 'fields' => array( - 'module' => array( - 'type' => 'varchar', - 'length' => 64, - 'not null' => TRUE, - 'description' => "The block's origin module, from {block}.module.", - ), - 'delta' => array( + 'biid' => array( + 'description' => 'The block instance ID from {block_instance}.biid.', 'type' => 'varchar', - 'length' => 32, + 'length' => 255, 'not null' => TRUE, - 'description' => "The block's unique delta within module, from {block}.delta.", + 'default' => '', ), 'rid' => array( 'type' => 'int', @@ -120,10 +185,7 @@ 'description' => "The user's role ID from {users_roles}.rid.", ), ), - 'primary key' => array('module', 'delta', 'rid'), - 'indexes' => array( - 'rid' => array('rid'), - ), + 'primary key' => array('biid', 'rid'), ); $schema['box'] = array( @@ -133,7 +195,7 @@ 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, - 'description' => "The block's {block}.bid.", + 'description' => "Primary key: The box unique identifier.", ), 'body' => array( 'type' => 'text',