### Eclipse Workspace Patch 1.0 #P Test Drupal 6 Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.266 diff -u -r1.266 block.module --- modules/block/block.module 22 Jun 2007 08:32:26 -0000 1.266 +++ modules/block/block.module 23 Jun 2007 15:08:42 -0000 @@ -13,6 +13,19 @@ define('BLOCK_REGION_NONE', -1); /** + * Flags defining cache granularity for cached blocks. + * + * BLOCK_CACHE_CUSTOM lets modules define their own critrions + * using hook_block('cache_id'). + */ +define('BLOCK_NO_CACHE', -1); +define('BLOCK_CACHE_GLOBAL', 0x0001); +define('BLOCK_CACHE_PER_PAGE', 0x0002); +define('BLOCK_CACHE_PER_USER', 0x0004); +define('BLOCK_CACHE_PER_ROLE', 0x0008); +define('BLOCK_CACHE_CUSTOM', 0x0010); + +/** * Implementation of hook_help(). */ function block_help($section) { @@ -171,6 +184,7 @@ foreach ($module_blocks as $delta => $block) { $block['module'] = $module; $block['delta'] = $delta; + $block['cache_mode'] = isset($block['cache_mode']) ? $block['cache_mode'] : BLOCK_CACHE_PER_ROLE; // If previously written to database, load values. if (!empty($old_blocks[$module][$delta])) { $block['status'] = $old_blocks[$module][$delta]->status; @@ -207,7 +221,7 @@ 'visibility' => NULL, 'throttle' => NULL, ); - db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s')", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title']); + db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, title, cache_mode) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, '%s', %d)", $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title'], $block['cache_mode']); } db_unlock_tables(); @@ -217,7 +231,7 @@ /** * Generate main block administration form. */ -function block_admin_display($theme = NULL) { +function block_admin_display(&$form_state, $theme = NULL) { global $theme_key, $custom_theme; // Add CSS @@ -379,7 +393,7 @@ /** * Menu callback; displays the block configuration form. */ -function block_admin_configure($module = NULL, $delta = 0) { +function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { $form['module'] = array('#type' => 'value', '#value' => $module); $form['delta'] = array('#type' => 'value', '#value' => $delta); @@ -524,8 +538,8 @@ /** * Menu callback: display the custom block addition form. */ -function block_add_block_form() { - return block_admin_configure('block', NULL); +function block_add_block_form(&$form_state) { + return block_admin_configure($form_state, 'block', NULL); } function block_add_block_form_validate($form, &$form_state) { @@ -728,7 +742,17 @@ // Check the current throttle status and see if block should be displayed // based on server load. if (!($block->throttle && (module_invoke('throttle', 'status') > 0))) { - $array = module_invoke($block->module, 'block', 'view', $block->delta); + // Try fetching block from cache. + if (($cid = _block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) { + $array = unserialize($cache->data); + } + else { + $array = module_invoke($block->module, 'block', 'view', $block->delta); + if ($cid) { + cache_set($cid, serialize($array), 'cache_block', variable_get('cache_lifetime', CACHE_TEMPORARY)); + } + } + if (isset($array) && is_array($array)) { foreach ($array as $k => $v) { $block->$k = $v; @@ -752,3 +776,59 @@ } return $blocks[$region]; } + +/** + * Determine the block caching granularity. + * + * @param $block + * @return + * The string used as cid for the block + */ +function _block_get_cache_id($block) { + global $theme, $base_root, $user; + + if (variable_get('block_cache', 0) && $block->cache_mode != BLOCK_NO_CACHE && $user->uid != 1) { + + $base_cid = "$block->module:$block->delta:$theme"; + if (module_exists('locale')) { + global $language; + $base_cid .= ":$language->language"; + } + + $cid_parts = array(); + + // If node access modules are enabled, we force 'per user' caching + if (module_implements('node_grants')) { + $block->cache_mode |= BLOCK_CACHE_PER_USER & ~BLOCK_CACHE_PER_ROLE; + } + + // Let the module define specific cache granularity. + if ($block->cache_mode & BLOCK_CACHE_CUSTOM) { + $cid_parts[] = module_invoke($block->module, 'block', 'cache_id', $block->delta); + } + + // 'per role' and 'per user' are mutually exclusive : + // we favor the less expensive 'per role'. + if ($block->cache_mode & BLOCK_CACHE_PER_ROLE) { + $cid_parts[] = 'r_'. implode(',', array_keys($user->roles)); + } + elseif ($block->cache_mode & BLOCK_CACHE_PER_USER) { + $cid_parts[] = "u_$user->uid"; + } + + if ($block->cache_mode & BLOCK_CACHE_PER_PAGE) { + $cid_parts[] = $base_root . request_uri(); + } + + return "$base_cid:". implode(':', $cid_parts); + } +} + +/** + * Implementation of hook_cron(). + * + * Expire outdated block cache entries + */ +function block_cron() { + cache_clear_all(NULL, 'cache_block'); +} Index: modules/block/block.schema =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.schema,v retrieving revision 1.1 diff -u -r1.1 block.schema --- modules/block/block.schema 25 May 2007 12:46:43 -0000 1.1 +++ modules/block/block.schema 23 Jun 2007 13:23:45 -0000 @@ -4,18 +4,19 @@ function block_schema() { $schema['blocks'] = array( 'fields' => array( - 'bid' => array('type' => 'serial', 'not null' => TRUE), - 'module' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''), - 'delta' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '0'), - 'theme' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), - 'status' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), - 'weight' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), - 'region' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => 'left'), - 'custom' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), - 'throttle' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), - 'visibility' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), - 'pages' => array('type' => 'text', 'not null' => TRUE), - 'title' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => '') + 'bid' => array('type' => 'serial', 'not null' => TRUE), + 'module' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''), + 'delta' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => '0'), + 'theme' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'status' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), + 'weight' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), + 'region' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => 'left'), + 'custom' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), + 'throttle' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), + 'visibility' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), + 'pages' => array('type' => 'text', 'not null' => TRUE), + 'title' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''), + 'cache_mode' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny'), ), 'primary key' => array('bid'), ); @@ -44,6 +45,8 @@ 'primary key' => array('bid'), ); + $schema['cache_block'] = drupal_get_schema_unprocessed('system', 'cache'); + return $schema; } Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.117 diff -u -r1.117 menu.module --- modules/menu/menu.module 22 Jun 2007 08:32:27 -0000 1.117 +++ modules/menu/menu.module 23 Jun 2007 13:23:46 -0000 @@ -520,6 +520,8 @@ foreach ($custom_menus as $name => $title) { // Default "Navigation" block is handled by user.module. $blocks[$name]['info'] = check_plain($title); + // menu blocks might be different on every page + $blocks[$name]['cache_mode'] = BLOCK_NO_CACHE; } return $blocks; } Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.226 diff -u -r1.226 search.module --- modules/search/search.module 22 Jun 2007 08:32:28 -0000 1.226 +++ modules/search/search.module 23 Jun 2007 13:30:44 -0000 @@ -144,6 +144,8 @@ function search_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Search form'); + // Can't be cached because it contains a form. + $blocks[0]['cache_mode'] = BLOCK_NO_CACHE; return $blocks; } else if ($op == 'view' && user_access('search content')) { Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.803 diff -u -r1.803 user.module --- modules/user/user.module 23 Jun 2007 08:58:31 -0000 1.803 +++ modules/user/user.module 23 Jun 2007 13:30:46 -0000 @@ -605,10 +605,16 @@ if ($op == 'list') { $blocks[0]['info'] = t('User login'); + // Can't be cached because it contains a form. + $blocks[1]['cache_mode'] = BLOCK_NO_CACHE; + // Contains a redirect url which changes each page view. + $blocks[0]['cache_mode'] = BLOCK_CACHE_PER_PAGE; $blocks[1]['info'] = t('Navigation'); + $blocks[1]['cache_mode'] = BLOCK_CACHE_PER_PAGE & BLOCK_CACHE_PER_USER; $blocks[2]['info'] = t('Who\'s new'); + // too dynamic to cache $blocks[3]['info'] = t('Who\'s online'); - + $blocks[3]['cache_mode'] = BLOCK_NO_CACHE; return $blocks; } else if ($op == 'configure' && $delta == 2) { Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.123 diff -u -r1.123 system.install --- modules/system/system.install 23 Jun 2007 11:15:15 -0000 1.123 +++ modules/system/system.install 23 Jun 2007 13:23:50 -0000 @@ -3362,6 +3362,29 @@ } /** + * Add cache_block table. + */ +function system_update_6025() { + $ret = array(); + db_add_field($ret, 'blocks', 'cache_mode', array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny')); + $schema['cache_block'] = array( + 'fields' => array( + 'cid' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''), + 'data' => array('type' => 'blob', 'not null' => FALSE, 'size' => 'big'), + 'expire' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), + 'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), + 'headers' => array('type' => 'text', 'not null' => FALSE), + 'serialized' => array('type' => 'int', 'size' => 'small', 'not null' => TRUE, 'default' => 0) + ), + 'indexes' => array('expire' => array('expire')), + 'primary key' => array('cid'), + ); + _drupal_initialize_schema('block', $schema); + db_create_table($ret, $schema['cache_block']); + return $ret; +} + +/** * @} End of "defgroup updates-5.x-to-6.x" * The next series of updates should start at 7000. */ Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.495 diff -u -r1.495 system.module --- modules/system/system.module 22 Jun 2007 08:32:28 -0000 1.495 +++ modules/system/system.module 23 Jun 2007 13:23:51 -0000 @@ -704,6 +704,22 @@ '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.') ); + $form['block_cache'] = array( + '#type' => 'fieldset', + '#title' => t('Block cache'), + // TODO + '#description' => t(''), + ); + + $form['block_cache']['block_cache'] = array( + '#type' => 'radios', + '#title' => t('Block cache'), + '#default_value' => variable_get('block_cache', CACHE_DISABLED), + '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Enabled (recommended)')), + // TODO + '#description' => t(''), + ); + $form['bandwidth_optimizations'] = array( '#type' => 'fieldset', '#title' => t('Bandwidth optimizations'), Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.835 diff -u -r1.835 node.module --- modules/node/node.module 22 Jun 2007 08:32:27 -0000 1.835 +++ modules/node/node.module 23 Jun 2007 13:23:47 -0000 @@ -1896,6 +1896,7 @@ function node_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Syndicate'); + $blocks[0]['cache_mode'] = BLOCK_CACHE_GLOBAL; return $blocks; } else if ($op == 'view') {