| 1 |
<?php
|
| 2 |
// $Id: blockcache.module,v 1.6 2006/09/26 11:43:49 jjeff Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* The Bock Cache module creates a duplicate cached version of each of available blocks.
|
| 7 |
*
|
| 8 |
* @author Jeff Robbins | Lullabot | www.lullabot.com
|
| 9 |
*
|
| 10 |
* @todo Reorganize so that there aren't block duplicates.
|
| 11 |
* Approach: Do form_alter() to add cache stuff to block/configure pages.
|
| 12 |
* Figure out how to disable 'normal' blocks and enable cached version on submit.
|
| 13 |
* I'm not sure this is even possible.
|
| 14 |
* @todo 5.0 version
|
| 15 |
*/
|
| 16 |
|
| 17 |
/**
|
| 18 |
* Implementation of hook_block().
|
| 19 |
*
|
| 20 |
* @todo research / QA if bc_life really works
|
| 21 |
*/
|
| 22 |
function blockcache_block($op = 'list', $delta = 0, $edit = array()) {
|
| 23 |
switch ($op) {
|
| 24 |
case 'list':
|
| 25 |
return blockcache_get_blocks();
|
| 26 |
case 'configure':
|
| 27 |
$form['bc_type'] = array(
|
| 28 |
'#type' => 'checkboxes',
|
| 29 |
'#title' => t('Cache type'),
|
| 30 |
'#options' => array('page' => t('Page specific'), 'user' => t('User specific')),
|
| 31 |
'#default_value' => variable_get('bc_type_'. $delta, 'site'),
|
| 32 |
'#description' => t('If the block content changes from page to page, select <em>page spefic</em>. If the content changes based on user permissions, access, or has user-specific information, select <em>user specific</em>.'),
|
| 33 |
);
|
| 34 |
$form['bc_life'] = array(
|
| 35 |
'#type' => 'textfield',
|
| 36 |
'#title' => t('Cache lifetime'),
|
| 37 |
'#size' => 10,
|
| 38 |
'#default_value' => variable_get('bc_life_'. $delta, ''),
|
| 39 |
'#description' => t('Lifetime (in seconds) of this item in the cache. How often is the content of this block refreshed? Leave blank to refresh automatically when new content is created.'),
|
| 40 |
);
|
| 41 |
$r = db_fetch_object(db_query('SELECT * FROM {bc_blocks} WHERE my_delta = %d', $delta));
|
| 42 |
$form['bc_origlink'] = array(
|
| 43 |
'#value' => t("<div class=\"form-item\"><label>Further configuration:</label><p>The Block Cache module acts as a wrapper around the original block. Please visit <a href=\"%url\">the original block's configuration page</a> to change its configurations.</p></div>", array('%url' => url('admin/block/configure/'. $r->module .'/'. $r->mod_delta))),
|
| 44 |
);
|
| 45 |
$form['bc_refresh'] = array(
|
| 46 |
'#type' => 'checkbox',
|
| 47 |
'#title' => t('Refresh now'),
|
| 48 |
'#prefix' => '<div class="form-item"><label>'. t('Cache refresh:') .'</label>',
|
| 49 |
'#description' => t('Refresh the content of this block now.'),
|
| 50 |
'#suffix' => '</div>',
|
| 51 |
);
|
| 52 |
if (module_exist('help')) {
|
| 53 |
$form['bc_help'] = array(
|
| 54 |
'#value' => t('<div class="form-item"><label>Help:</label><p>Find more help for the Block Cache module <a href="%help">here</a>.</p></div>', array('%help' => url('admin/help/blockcache'))),
|
| 55 |
);
|
| 56 |
}
|
| 57 |
return $form;
|
| 58 |
case 'save':
|
| 59 |
variable_set('bc_type_'. $delta, $edit['bc_type']);
|
| 60 |
variable_set('bc_life_'. $delta, trim($edit['bc_life']));
|
| 61 |
if ($edit['bc_refresh']) {
|
| 62 |
blockcache_refresh($delta);
|
| 63 |
}
|
| 64 |
break;
|
| 65 |
case 'view':
|
| 66 |
return blockcache_block_view($delta);
|
| 67 |
}
|
| 68 |
}
|
| 69 |
|
| 70 |
/**
|
| 71 |
* Implementation of hook_help().
|
| 72 |
*/
|
| 73 |
|
| 74 |
function blockcache_help($section) {
|
| 75 |
switch ($section) {
|
| 76 |
case 'admin/help#blockcache':
|
| 77 |
return t('<p>This module creates a cached version of each block. Block caching happens separately from page caching and so it will work for logged-in users whether or not page caching is enabled for the site. Cached blocks make just one call to the database and can therefore reduce the overhead required to render blocks that require complex queries and/or calculations such as some Views or Taxonomy-related blocks.</p>
|
| 78 |
|
| 79 |
<p>When this BlockCache is enabled, administrators will see a duplicate "cached" version of each of the site\'s blocks. By enabling the cached version (and disabling the original version), you can display a block that is physically identical to the original, but is loaded from the cache rather than calculated for each page. There are several options for how and when the cache is refreshed.</p>
|
| 80 |
|
| 81 |
<p>Click the \'configure\' link for each cached block to modify the parameters determining the criteria by which the cache gets displayed and refreshed.</p>
|
| 82 |
|
| 83 |
<h3>Cached block configuration options:</h3>
|
| 84 |
<dl>
|
| 85 |
<dt>Page specific</dt>
|
| 86 |
<dd>Each block is cached on a per page basis. A separate version of the block is saved into the cache for every page that it appears on. This is most appropriate for node-specific blocks such as "Author Information" which change (or don\'t appear) from page to page. Leave unchecked and all pages will display the same block content.</dd>
|
| 87 |
|
| 88 |
<dt>User specific</dt>
|
| 89 |
<dd>If the information in this block changes on a per-user basis enable this checkbox. Leave unchecked and all users will see the same block content.</dd>
|
| 90 |
</dl>
|
| 91 |
|
| 92 |
<h3>Cache lifetime:</h3>
|
| 93 |
<p>For most blocks, you will want to leave this field blank. When the field is blank, cached blocks are only refreshed when new content (nodes or comments) are added to the site. This should be fine for most Views lists, taxonomy, or node-based blocks. However you will probably want to set a lifetime for things like "Who\'s Online", frequently updated RSS feeds from the aggregator.module, or other regularly updating non-node-based block content. The lifetime is entered in seconds and represents how often the block will be refreshed. For instance, setting this to 300 could update the "Who\'s Online" block every 5 minutes. Users that log in during that 5 minutes won\'t be displayed until the cache is refreshed and the block updates.</p>
|
| 94 |
|
| 95 |
<p>Note that many modules already include their own caching system and therefore using the cached version of these blocks may not speed things up.</p>
|
| 96 |
|
| 97 |
<p>Also note that the cached versions of blocks are essentially "wrappers" around the original block. You should visit the original block\'s configuration screen to change any of the original parameters for that block.</p>
|
| 98 |
|
| 99 |
<h3>BlockCache setting:</h3>
|
| 100 |
<p>On the module\'s <a href="%settings">settings page</a>, you can choose to display a message to administrators when a block is refreshed. This is useful when setting things up to get some feedback as to what is happening "behind the scenes" and make sure that the blocks are refreshing on a regular basis.</p>
|
| 101 |
|
| 102 |
'. blockcache_version(), array('%settings' => url('admin/settings/blockcache')));
|
| 103 |
case 'admin/modules#description':
|
| 104 |
return t('Block Cache module. Allows caching of blocks.');
|
| 105 |
}
|
| 106 |
}
|
| 107 |
|
| 108 |
/**
|
| 109 |
* Implementation of hook_settings().
|
| 110 |
*/
|
| 111 |
function blockcache_settings() {
|
| 112 |
$form['bc_debug'] = array(
|
| 113 |
'#type' => 'radios',
|
| 114 |
'#title' => t('Display cache refresh'),
|
| 115 |
'#description' => t('For testing and debugging. If enabled, a message will be shown to users with "administer nodes" privileges when cached blocks are refreshed.'),
|
| 116 |
'#options' => array(t('disabled'), t('enabled')),
|
| 117 |
'#default_value' => variable_get('bc_debug', 0),
|
| 118 |
);
|
| 119 |
return $form;
|
| 120 |
}
|
| 121 |
|
| 122 |
/**
|
| 123 |
* Return a list of block objects
|
| 124 |
*/
|
| 125 |
function blockcache_get_blocks() {
|
| 126 |
static $blockcache_css;
|
| 127 |
if (!isset($blockcache_css)) {
|
| 128 |
$path = drupal_get_path('module', 'blockcache');
|
| 129 |
theme('add_style', $path .'/blockcache.css');
|
| 130 |
$blockcache_css = TRUE;
|
| 131 |
}
|
| 132 |
|
| 133 |
$blocks = array();
|
| 134 |
$result = db_query('SELECT * FROM {bc_blocks}');
|
| 135 |
// make an array to cross reference the modules' blocks with our delta for them
|
| 136 |
while($r = db_fetch_object($result)){
|
| 137 |
// $blocks_lookup is ALL of the blocks that have ever been seen
|
| 138 |
// this may include blocks from modules that are no longer enabled
|
| 139 |
// we want to save the preferences and delta for these blocks
|
| 140 |
$blocks_lookup[$r->module][$r->mod_delta] = $r->my_delta;
|
| 141 |
}
|
| 142 |
|
| 143 |
foreach (module_implements('block') as $module) {
|
| 144 |
if ($module != 'blockcache') { // endless loop alert!
|
| 145 |
$mod_blocks = module_invoke($module, 'block', 'list');
|
| 146 |
if (is_array($mod_blocks)) {
|
| 147 |
foreach($mod_blocks as $mod_delta => $info) {
|
| 148 |
$delta = $blocks_lookup[$module][$mod_delta];
|
| 149 |
if (!$delta) {
|
| 150 |
// store new block reference
|
| 151 |
$delta = db_next_id('{bc_blocks}');
|
| 152 |
db_query('INSERT INTO {bc_blocks} (my_delta, module, mod_delta) VALUES (%d, "%s", "%s")', $delta, $module, $mod_delta);
|
| 153 |
}
|
| 154 |
$blocks[$delta]['info'] = $info['info'] . ' <em class="bc_cached">'. t('cached') .'</em>';
|
| 155 |
$blocks[$delta]['orig_info'] = $info['info'];
|
| 156 |
}
|
| 157 |
}
|
| 158 |
}
|
| 159 |
}
|
| 160 |
return $blocks;
|
| 161 |
}
|
| 162 |
|
| 163 |
/**
|
| 164 |
* View a cached block using hook_block().
|
| 165 |
*
|
| 166 |
* If the block is not cached or the cache is stale, get the info and stick it back into the cache.
|
| 167 |
*/
|
| 168 |
function blockcache_block_view($delta) {
|
| 169 |
$cache_name = _blockcache_get_name($delta);
|
| 170 |
$cached = cache_get($cache_name);
|
| 171 |
if ($cached && ($cached->expire == CACHE_TEMPORARY || $cached->expire > time())) {
|
| 172 |
// fetch block from cache
|
| 173 |
$block = unserialize($cached->data);
|
| 174 |
}
|
| 175 |
else {
|
| 176 |
// cache block
|
| 177 |
$r = db_fetch_object(db_query('SELECT * FROM {bc_blocks} WHERE my_delta = %d', $delta));
|
| 178 |
$block = module_invoke($r->module, 'block', 'view', $r->mod_delta);
|
| 179 |
$cache = serialize($block);
|
| 180 |
$expire = is_numeric(variable_get('bc_life_'.$delta, '')) ? time() + variable_get('bc_life_'.$delta, '') : CACHE_TEMPORARY;
|
| 181 |
cache_set($cache_name, $cache, $expire);
|
| 182 |
|
| 183 |
// display debug message
|
| 184 |
if (variable_get('bc_debug', 0) && user_access('administer nodes')) {
|
| 185 |
drupal_set_message("Refreshed cache for module: <strong>$r->module</strong> delta: <strong>$r->mod_delta</strong> subject: <strong>{$block[subject]}</strong> as $cache_name");
|
| 186 |
}
|
| 187 |
}
|
| 188 |
return $block;
|
| 189 |
}
|
| 190 |
|
| 191 |
function blockcache_refresh($delta){
|
| 192 |
$blocks = blockcache_get_blocks();
|
| 193 |
$name = $blocks[$delta]['orig_info'];
|
| 194 |
$cache_name = 'bc_'. $delta;
|
| 195 |
cache_clear_all($cache_name, TRUE);
|
| 196 |
drupal_set_message(t('Block cache refreshed for <strong>%info</strong>.', array('%info' => $name)));
|
| 197 |
}
|
| 198 |
|
| 199 |
function _blockcache_get_name($delta) {
|
| 200 |
global $base_root;
|
| 201 |
$vars = variable_get('bc_type_'. $delta, array());
|
| 202 |
$cache_name = 'bc_'. $delta;
|
| 203 |
if (module_exist('locale')) {
|
| 204 |
global $locale;
|
| 205 |
$cache_name .= '_'. $locale;
|
| 206 |
}
|
| 207 |
if ($vars['user']) {
|
| 208 |
global $user;
|
| 209 |
$cache_name .= '_u'. $user->uid;
|
| 210 |
}
|
| 211 |
$cache_name .= '_'. $base_root;
|
| 212 |
if ($vars['page']) {
|
| 213 |
$cache_name .= request_uri();
|
| 214 |
}
|
| 215 |
return $cache_name;
|
| 216 |
}
|
| 217 |
|
| 218 |
/**
|
| 219 |
* Display BlockCache version.
|
| 220 |
*/
|
| 221 |
function blockcache_version(){
|
| 222 |
return str_replace(array('$RCSf'.'ile:', ',v', '$Re'.'vision: ', '$Da'.'te: ', '$'), '', '<p style="font-size:x-small">$RCSfile: blockcache.module,v $ version: <b>$Revision: 1.6 $</b>, $Date: 2006/09/26 11:43:49 $</p>');
|
| 223 |
}
|