| 1 |
<?php
|
| 2 |
// $Id$
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* The Bock Cache module creates a duplicate cached version of each of available blocks.
|
| 7 |
* written by Jeff Robbins | Lullabot | www.lullabot.com
|
| 8 |
*/
|
| 9 |
|
| 10 |
/**
|
| 11 |
* Implementation of hook_block().
|
| 12 |
*/
|
| 13 |
function blockcache_block($op = 'list', $delta = 0, $edit = array()) {
|
| 14 |
if ($op == 'list') {
|
| 15 |
return blockcache_get_blocks();
|
| 16 |
}
|
| 17 |
else if ($op == 'configure') {
|
| 18 |
$form['bc_type'] = array(
|
| 19 |
'#type' => 'radios',
|
| 20 |
'#title' => t('Cache type'),
|
| 21 |
'#options' => array('site' => t('site-wide'), 'page' => t('per page')),
|
| 22 |
'#default_value' => variable_get('bc_type_'. $delta, 'site'),
|
| 23 |
'#description' => t('Should this block be cached for each page or for the entire site? If the block content changes from page to page, you will want to select <em>per page</em>. Otherwise, select <em>site-wide</em>.'),
|
| 24 |
);
|
| 25 |
// should research this some more to see if this is really true
|
| 26 |
$form['bc_life'] = array(
|
| 27 |
'#type' => 'textfield',
|
| 28 |
'#title' => t('Cache lifetime'),
|
| 29 |
'#size' => 10,
|
| 30 |
'#default_value' => variable_get('bc_life_'. $delta, ''),
|
| 31 |
'#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 (recommended).'),
|
| 32 |
);
|
| 33 |
$r = db_fetch_object(db_query('SELECT * FROM {bc_blocks} WHERE my_delta = %d', $delta));
|
| 34 |
$form['bc_origlink'] = array(
|
| 35 |
'#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))),
|
| 36 |
|
| 37 |
);
|
| 38 |
return $form;
|
| 39 |
}
|
| 40 |
else if ($op == 'save') {
|
| 41 |
variable_set('bc_type_'. $delta, $edit['bc_type']);
|
| 42 |
variable_set('bc_life_'. $delta, trim($edit['bc_life']));
|
| 43 |
}
|
| 44 |
else if ($op == 'view') {
|
| 45 |
return blockcache_block_view($delta);
|
| 46 |
}
|
| 47 |
}
|
| 48 |
|
| 49 |
|
| 50 |
/**
|
| 51 |
* Implementation of hook_help().
|
| 52 |
*/
|
| 53 |
function blockcache_help($section) {
|
| 54 |
switch ($section) {
|
| 55 |
case 'admin/help#blockcache':
|
| 56 |
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>
|
| 57 |
|
| 58 |
<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>
|
| 59 |
|
| 60 |
<p>Click the \'configure\' link for each cached block to modify the parameters determining when the cache gets refreshed.</p>
|
| 61 |
|
| 62 |
<h3>Cached block configuration options:</h3>
|
| 63 |
<dl>
|
| 64 |
<dt>site-wide</dt>
|
| 65 |
<dd>Each cached block is cached on a per site basis. The block is saved into the cache on the first page that it is hit and then the cached version is loaded for all subsequent page views until the cache is refreshed.</dd>
|
| 66 |
</dl>
|
| 67 |
<dt>per page</dt>
|
| 68 |
<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.</dd>
|
| 69 |
|
| 70 |
<h3>Cache lifetime:</h3>
|
| 71 |
<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>
|
| 72 |
|
| 73 |
<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>
|
| 74 |
|
| 75 |
<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>
|
| 76 |
|
| 77 |
<h3>BlockCache setting:</h3>
|
| 78 |
<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>
|
| 79 |
|
| 80 |
', array('%settings' => url('admin/settings/blockcache')));
|
| 81 |
case 'admin/modules#description':
|
| 82 |
return t('Block Cache module. Allows caching of blocks.');
|
| 83 |
// OPTIONAL: Add additional cases for other paths that should display help text.
|
| 84 |
}
|
| 85 |
}
|
| 86 |
|
| 87 |
/**
|
| 88 |
* Implementation of hook_settings().
|
| 89 |
*/
|
| 90 |
function blockcache_settings() {
|
| 91 |
$form['bc_debug'] = array(
|
| 92 |
'#type' => 'radios',
|
| 93 |
'#title' => t('Display cache refresh'),
|
| 94 |
'#description' => t('For testing and debugging. If enabled, a message will be shown to users with "administer nodes" privileges when cached blocks are refreshed.'),
|
| 95 |
'#options' => array(t('disabled'), t('enabled')),
|
| 96 |
'#default_value' => variable_get('bc_debug', 0),
|
| 97 |
);
|
| 98 |
return $form;
|
| 99 |
}
|
| 100 |
|
| 101 |
/**
|
| 102 |
* Return a list of block objects
|
| 103 |
*
|
| 104 |
* @todo
|
| 105 |
* - Yank out all of the "active" code... it's not needed
|
| 106 |
*/
|
| 107 |
function blockcache_get_blocks() {
|
| 108 |
static $css;
|
| 109 |
if (!isset($css)) {
|
| 110 |
$path = drupal_get_path('module', 'blockcache');
|
| 111 |
theme('add_style', $path .'/blockcache.css');
|
| 112 |
$css = TRUE;
|
| 113 |
}
|
| 114 |
|
| 115 |
$blocks = array();
|
| 116 |
$result = db_query('SELECT * FROM {bc_blocks}');
|
| 117 |
// make an array to cross reference the modules' blocks with our delta for them
|
| 118 |
while($r = db_fetch_object($result)){
|
| 119 |
// $blocks_lookup is ALL of the blocks that have ever been seen
|
| 120 |
// this may include blocks from modules that are no longer enabled
|
| 121 |
$blocks_lookup[$r->module][$r->mod_delta] = $r->my_delta;
|
| 122 |
}
|
| 123 |
|
| 124 |
foreach (module_implements('block') as $module) {
|
| 125 |
if ($module != 'blockcache') { // endless loop alert!
|
| 126 |
$mod_blocks = module_invoke($module, 'block', 'list');
|
| 127 |
if (is_array($mod_blocks)) {
|
| 128 |
foreach($mod_blocks as $mod_delta => $info) {
|
| 129 |
// do we have this one saved?
|
| 130 |
if ($delta = $blocks_lookup[$module][$mod_delta]) {
|
| 131 |
//yes...
|
| 132 |
|
| 133 |
}
|
| 134 |
else {
|
| 135 |
$delta = db_next_id('{bc_blocks}');
|
| 136 |
db_query('INSERT INTO {bc_blocks} (my_delta, module, mod_delta) VALUES (%d, "%s", "%s")', $delta, $module, $mod_delta);
|
| 137 |
}
|
| 138 |
$blocks[$delta]['info'] = $info['info'] . ' <em class="bc_cached">'. t('cached') .'</em>';
|
| 139 |
|
| 140 |
}
|
| 141 |
}
|
| 142 |
}
|
| 143 |
}
|
| 144 |
return $blocks;
|
| 145 |
|
| 146 |
}
|
| 147 |
|
| 148 |
function blockcache_block_view($delta) {
|
| 149 |
global $base_root;
|
| 150 |
$cache_name = variable_get('bc_type_'. $delta, 'site') == 'page' ? 'bc_'. $delta .'_'. $base_root . request_uri() : 'bc_'. $delta .'_'. $base_root;
|
| 151 |
$cached = cache_get($cache_name);
|
| 152 |
if ($cached && ($cached->expire == CACHE_TEMPORARY || $cached->expire > time())) {
|
| 153 |
$block = unserialize($cached->data);
|
| 154 |
}
|
| 155 |
else {
|
| 156 |
// it's not cached. let's cache it
|
| 157 |
$r = db_fetch_object(db_query('SELECT * FROM {bc_blocks} WHERE my_delta = %d', $delta));
|
| 158 |
$block = module_invoke($r->module, 'block', 'view', $r->mod_delta);
|
| 159 |
$cache = serialize($block);
|
| 160 |
$expire = is_numeric(variable_get('bc_life_'.$delta, '')) ? time() + variable_get('bc_life_'.$delta, '') : CACHE_TEMPORARY;
|
| 161 |
cache_set($cache_name, $cache, $expire);
|
| 162 |
|
| 163 |
// for testing:
|
| 164 |
if (variable_get('bc_debug', 0) && user_access('administer nodes')) {
|
| 165 |
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");
|
| 166 |
}
|
| 167 |
|
| 168 |
}
|
| 169 |
return $block;
|
| 170 |
}
|