Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.224 diff -u -p -r1.224 block.module --- modules/block/block.module 27 Aug 2006 12:43:18 -0000 1.224 +++ modules/block/block.module 30 Aug 2006 22:41:34 -0000 @@ -7,6 +7,14 @@ */ /** + * Constants to define the caching modes for blocks + */ +define('BLOCK_NOT_CACHABLE', 0); +define('BLOCK_ALWAYS_CACHED', 1); +define('BLOCK_CACHED_PER_USER', 2); +define('BLOCK_CACHED_PER_ROLE', 3); + +/** * Implementation of hook_help(). */ function block_help($section) { @@ -112,6 +120,16 @@ function block_menu($may_cache) { return $items; } + +/** + * Implementation of hook_cron(). + * + * Expire outdated block cache entries + */ +function block_cron() { + cache_clear_all(NULL, 'cache_block'); +} + /** * Implementation of hook_block(). * @@ -164,12 +182,17 @@ function _block_rehash() { $blocks = array(); + // We test for node_acess usage + $node_access = node_access_view_all_nodes(); + foreach (module_list() as $module) { $module_blocks = module_invoke($module, 'block', 'list'); if ($module_blocks) { foreach ($module_blocks as $delta => $block) { $block['module'] = $module; $block['delta'] = $delta; + $block['cache_mode'] = isset($block['cache_mode']) ? (($block['cache_mode'] == BLOCK_CACHED_PER_ROLE && $node_access) ? BLOCK_CACHED_PER_USER : $block['cache_mode']) : BLOCK_NOT_CACHABLE; + $block['cache_ttl'] = isset($block['cache_ttl']) ? $block['cache_ttl'] : 0; // If previously written to database, load values. if ($old_blocks[$module][$delta]) { $block['status'] = $old_blocks[$module][$delta]->status; @@ -202,7 +225,7 @@ function _block_rehash() { // Reinsert new set of blocks into table. foreach ($blocks as $block) { - 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, cache_mode, cache_ttl, weight, region, visibility, pages, custom, throttle, title) VALUES ('%s', '%s', '%s', %d, %d, %d, %d, '%s', %d, '%s', %d, %d, '%s')", $block['module'], $block['delta'], $theme_key, $block['status'], $block['cache_mode'], $block['cache_ttl'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['title']); } db_unlock_tables(); @@ -682,9 +705,38 @@ function block_list($region) { // 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); - if (isset($array) && is_array($array)) { - foreach ($array as $k => $v) { + switch ($block->cache_mode) { + case BLOCK_NOT_CACHABLE: + $cid = NULL; + break; + case BLOCK_ALWAYS_CACHED: + $cid = "$block->module:$block->delta"; + break; + case BLOCK_CACHED_PER_USER: + $cid = "$block->module:$block->delta:$user->uid"; + break; + case BLOCK_CACHED_PER_ROLE: + $cid = "$block->module:$block->delta:". implode(',', array_keys($user->roles)); + break; + } + if ($cid) { + global $locale; + $cid .= ":$locale"; + $cache = cache_get($cid, 'cache_block'); + } + + if ($cache->data) { + $block_view = unserialize($cache->data); + } + else { + $block_view = module_invoke($block->module, 'block', 'view', $block->delta); + if ($cid) { + cache_set($cid, 'cache_block', serialize($block_view), $block['cache_ttl'] ? (time() + $block['cache_ttl']) : CACHE_PERMANENT); + } + } + + if (isset($block_view) && is_array($block_view)) { + foreach ($block_view as $k => $v) { $block->$k = $v; } } Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.264 diff -u -p -r1.264 blog.module --- modules/blog/blog.module 27 Aug 2006 12:43:18 -0000 1.264 +++ modules/blog/blog.module 30 Aug 2006 22:41:34 -0000 @@ -288,6 +288,13 @@ function blog_block($op = 'list', $delta global $user; if ($op == 'list') { $block[0]['info'] = t('Recent blog posts'); + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + } return $block; } else if ($op == 'view') { Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.387 diff -u -p -r1.387 book.module --- modules/book/book.module 29 Aug 2006 18:43:25 -0000 1.387 +++ modules/book/book.module 30 Aug 2006 22:41:34 -0000 @@ -154,6 +154,14 @@ function book_block($op = 'list', $delta $block = array(); if ($op == 'list') { $block[0]['info'] = t('Book navigation'); + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + } + return $block; } else if ($op == 'view') { Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.481 diff -u -p -r1.481 comment.module --- modules/comment/comment.module 29 Aug 2006 18:43:25 -0000 1.481 +++ modules/comment/comment.module 30 Aug 2006 22:41:35 -0000 @@ -172,6 +172,13 @@ function comment_perm() { function comment_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Recent comments'); + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + } return $blocks; } else if ($op == 'view' && user_access('access comments')) { Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.356 diff -u -p -r1.356 forum.module --- modules/forum/forum.module 29 Aug 2006 18:43:25 -0000 1.356 +++ modules/forum/forum.module 30 Aug 2006 22:41:36 -0000 @@ -280,6 +280,18 @@ function forum_block($op = 'list', $delt case 'list': $blocks[0]['info'] = t('Active forum topics'); $blocks[1]['info'] = t('New forum topics'); + + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + $blocks[1]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[1]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + $blocks[1]['cache_mode'] = BLOCK_NOT_CACHABLE; + } + return $blocks; case 'configure': Index: modules/menu/menu.module =================================================================== RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v retrieving revision 1.85 diff -u -p -r1.85 menu.module --- modules/menu/menu.module 30 Aug 2006 15:17:49 -0000 1.85 +++ modules/menu/menu.module 30 Aug 2006 22:41:36 -0000 @@ -136,6 +136,8 @@ function menu_block($op = 'list', $delta // Default "Navigation" block is handled by user.module. if ($mid != 1) { $blocks[$mid]['info'] = check_plain($title); + // menu blocks might be different on every page + $blocks[$mid]['cache_mode'] = BLOCK_NOT_CACHABLE; } } return $blocks; Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.691 diff -u -p -r1.691 node.module --- modules/node/node.module 30 Aug 2006 18:50:35 -0000 1.691 +++ modules/node/node.module 30 Aug 2006 22:41:37 -0000 @@ -1673,6 +1673,7 @@ function node_admin_search() { function node_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Syndicate'); + $blocks[0]['cache_mode'] = BLOCK_ALWAYS_CACHED; return $blocks; } else if ($op == 'view') { Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.214 diff -u -p -r1.214 poll.module --- modules/poll/poll.module 30 Aug 2006 18:50:35 -0000 1.214 +++ modules/poll/poll.module 30 Aug 2006 22:41:38 -0000 @@ -46,6 +46,13 @@ function poll_block($op = 'list', $delta if (user_access('access content')) { if ($op == 'list') { $blocks[0]['info'] = t('Most recent poll'); + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + } return $blocks; } else if ($op == 'view') { Index: modules/profile/profile.module =================================================================== RCS file: /cvs/drupal/drupal/modules/profile/profile.module,v retrieving revision 1.167 diff -u -p -r1.167 profile.module --- modules/profile/profile.module 20 Aug 2006 07:07:17 -0000 1.167 +++ modules/profile/profile.module 30 Aug 2006 22:41:38 -0000 @@ -104,6 +104,8 @@ function profile_block($op = 'list', $de if ($op == 'list') { $blocks[0]['info'] = t('Author information'); + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = 900; return $blocks; } Index: modules/search/search.module =================================================================== RCS file: /cvs/drupal/drupal/modules/search/search.module,v retrieving revision 1.195 diff -u -p -r1.195 search.module --- modules/search/search.module 29 Aug 2006 09:51:50 -0000 1.195 +++ modules/search/search.module 30 Aug 2006 22:41:39 -0000 @@ -135,6 +135,7 @@ function search_perm() { function search_block($op = 'list', $delta = 0) { if ($op == 'list') { $blocks[0]['info'] = t('Search form'); + $blocks[0]['cache_mode'] = BLOCK_ALWAYS_CACHED; return $blocks; } else if ($op == 'view' && user_access('search content')) { Index: modules/statistics/statistics.module =================================================================== RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v retrieving revision 1.239 diff -u -p -r1.239 statistics.module --- modules/statistics/statistics.module 29 Aug 2006 18:43:25 -0000 1.239 +++ modules/statistics/statistics.module 30 Aug 2006 22:41:39 -0000 @@ -471,6 +471,13 @@ function statistics_block($op = 'list', case 'list': if (variable_get('statistics_count_content_views', 0)) { $blocks[0]['info'] = t('Popular content'); + if ($ttl = variable_get('cache_lifetime', 0)) { + $blocks[0]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[0]['cache_ttl'] = $ttl; + } + else { + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; + } } return $blocks; Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.14 diff -u -p -r1.14 system.install --- modules/system/system.install 30 Aug 2006 08:46:16 -0000 1.14 +++ modules/system/system.install 30 Aug 2006 22:41:40 -0000 @@ -54,6 +54,15 @@ function system_install() { PRIMARY KEY (cid), INDEX expire (expire) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + db_query("CREATE TABLE {cache_block} ( + cid varchar(255) NOT NULL default '', + data longblob, + expire int NOT NULL default '0', + created int NOT NULL default '0', + headers text, + PRIMARY KEY (cid), + INDEX expire (expire) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); db_query("CREATE TABLE {cache_filter} ( cid varchar(255) NOT NULL default '', data longblob, @@ -482,6 +491,14 @@ function system_install() { headers text, PRIMARY KEY (cid) )"); + db_query("CREATE TABLE {cache_block} ( + cid varchar(255) NOT NULL default '', + data bytea, + expire int NOT NULL default '0', + created int NOT NULL default '0', + headers text, + PRIMARY KEY (cid) + )"); db_query("CREATE TABLE {cache_filter} ( cid varchar(255) NOT NULL default '', data bytea, @@ -507,6 +524,7 @@ function system_install() { PRIMARY KEY (cid) )"); db_query("CREATE INDEX {cache}_expire_idx ON {cache} (expire)"); + db_query("CREATE INDEX {cache}_expire_idx ON {cache_block} (expire)"); db_query("CREATE INDEX {cache}_expire_idx ON {cache_filter} (expire)"); db_query("CREATE INDEX {cache}_expire_idx ON {cache_menu} (expire)"); db_query("CREATE INDEX {cache}_expire_idx ON {cache_page} (expire)"); @@ -3227,6 +3245,35 @@ function system_update_1009() { return $ret; } +function system_update_1010() { + $ret = array(); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql("CREATE TABLE {cache_block} ( + cid varchar(255) NOT NULL default '', + data longblob, + expire int NOT NULL default '0', + created int NOT NULL default '0', + headers text, + PRIMARY KEY (cid), + INDEX expire (expire) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + case 'pgsql': + $ret[] = update_sql("CREATE TABLE {cache_block} ( + cid varchar(255) NOT NULL default '', + data bytea, + expire int NOT NULL default '0', + created int NOT NULL default '0', + headers text, + PRIMARY KEY (cid) + )"); + $ret[] = update_sql("CREATE INDEX {cache_block}_expire_idx ON {cache_block} (expire)"); + break; + } + return $ret; +} + /** * @} End of "defgroup updates-4.7-to-x.x" * The next series of updates should start at 2000. Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.665 diff -u -p -r1.665 user.module --- modules/user/user.module 30 Aug 2006 08:46:17 -0000 1.665 +++ modules/user/user.module 30 Aug 2006 22:41:41 -0000 @@ -506,9 +506,18 @@ function user_block($op = 'list', $delta if ($op == 'list') { $blocks[0]['info'] = t('User login'); + // Contains a redirect url which changes each page view. + $blocks[0]['cache_mode'] = BLOCK_NOT_CACHABLE; $blocks[1]['info'] = t('Navigation'); + // The navigation block isn't cachable as it also depends on the + // page where it appears + $blocks[1]['cache_mode'] = BLOCK_NOT_CACHABLE; $blocks[2]['info'] = t('Who\'s new'); + $blocks[2]['cache_mode'] = BLOCK_CACHED_PER_ROLE; + $blocks[2]['cache_ttl'] = 900; $blocks[3]['info'] = t('Who\'s online'); + // too dynamic to cache + $blocks[3]['cache_mode'] = BLOCK_NOT_CACHABLE; return $blocks; }