| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: blockcache_alter.module,v 1.2.2.18 2009/06/06 11:36:40 swentel Exp $ 3 4 /** 5 * @file 6 * Block Cache alter. 7 */ 8 9 /** 10 * Implementation of hook_menu(). 11 */ 12 function blockcache_alter_menu() { 13 $items['admin/settings/blockcache_alter'] = array( 14 'title' => 'Block cache alter', 15 'description' => 'Debug settings for Blockcache Alter', 16 'page callback' => 'drupal_get_form', 17 'page arguments' => array('blockcache_alter_admin_settings'), 18 'access arguments' => array('administer site configuration'), 19 ); 20 return $items; 21 } 22 23 /** 24 * Menu callback, settings page for blockcache alter 25 */ 26 function blockcache_alter_admin_settings() { 27 28 $status = _blockcache_alter_core_patch(); 29 30 $form['bca_corepatch'] = array( 31 '#type' => 'checkbox', 32 '#title' => t('Core patch ?'), 33 '#description' => t('Check this box if you applied one of the 2 core patches that comes with this module. This will extend the caching settings fieldset on the block configuration page. Note: if you did not apply the patch but check the box, the additional functionality simply won\'t work at all.<br /><strong>Current status: you have @status applied a blockcache alter patch.</strong>', array('@status' => $status)), 34 '#default_value' => variable_get('bca_corepatch', 0), 35 ); 36 $form['bca_debug'] = array( 37 '#type' => 'checkbox', 38 '#title' => t('Show debug information ?'), 39 '#description' => t('Debug info: shows messages when each block is refreshed.'), 40 '#default_value' => variable_get('bca_debug', 0), 41 ); 42 return system_settings_form($form); 43 } 44 45 /** 46 * Implementation of hook_form_alter(). 47 */ 48 function blockcache_alter_form_alter(&$form, $form_state, $form_id) { 49 // Add caching fieldset to the block configure page. 50 if ($form_id == 'block_admin_configure') { 51 52 // Add some funky hide and show javascript. 53 drupal_add_js(drupal_get_path('module', 'blockcache_alter') .'/blockcache_alter.js', 'module'); 54 55 // Core patch applied or not. 56 $core_patch = variable_get('bca_corepatch', 0); 57 58 // Blockcache options. 59 $block_cache_options = array( 60 BLOCK_NO_CACHE => t('Do not cache'), 61 BLOCK_CACHE_GLOBAL => t('Cache once for everything (global)'), 62 BLOCK_CACHE_PER_PAGE => t('Per page'), 63 BLOCK_CACHE_PER_ROLE => t('Per role'), 64 BLOCK_CACHE_PER_ROLE | BLOCK_CACHE_PER_PAGE => t('Per role per page'), 65 BLOCK_CACHE_PER_USER => t('Per user'), 66 BLOCK_CACHE_PER_USER | BLOCK_CACHE_PER_PAGE => t('Per user per page'), 67 ); 68 69 // Cache clear actions. 70 $cache_clear_actions = array( 71 '1' => t('Clear caching for this block only'), 72 '2' => t('Clear all cache (block and page)'), 73 ); 74 75 // Retrieve current cache setting for this block. 76 $default_value = db_result(db_query("SELECT cache FROM {blocks} WHERE module = '%s' AND delta = '%s'", $form['module']['#value'], $form['delta']['#value'])); 77 78 // Blockcache fieldset. 79 $form['cache'] = array( 80 '#type' => 'fieldset', 81 '#title' => t('Cache settings'), 82 '#weight' => 1, 83 '#collapsible' => TRUE, 84 ); 85 86 // Cache setting. 87 $form['cache']['cache_block'] = array( 88 '#type' => 'select', 89 '#title' => t('Cache setting'), 90 '#description' => t('Select the appropriate cache setting for this block.'), 91 '#options' => $block_cache_options, 92 '#default_value' => $default_value, 93 '#attributes' => array('onChange' => 'javascript:BlockCacheAlterCheck(); return false;'), 94 ); 95 96 // Cache clearing option after saving this block. 97 $display = ($default_value == BLOCK_NO_CACHE) ? 'none' : 'block'; 98 $form['cache']['cache_block_clear'] = array( 99 '#type' => 'radios', 100 '#title' => t('Clear cache'), 101 '#prefix' => '<div id="blockcache_alter_wrapper" style="display: '. $display .';">', 102 '#description' => t('Select the appropriate cache clearing action after saving this block.'), 103 '#options' => $cache_clear_actions, 104 '#default_value' => 1, 105 ); 106 if ($core_patch != TRUE) { 107 $form['cache']['cache_block_clear']['#suffix'] = '</div>'; 108 } 109 110 // Show options underneath onl if core patch is applied. 111 if ($core_patch == TRUE) { 112 113 // Blockcache fieldset. 114 $form['cache']['option_1'] = array( 115 '#type' => 'fieldset', 116 '#title' => t('Cache refresh option 1: Cache lifetime'), 117 '#description' => t('Set a minimum cache lifetime (in seconds). Leave 0 or empty to use the second option.') 118 ); 119 120 // Blockcache lifetime. 121 $form['cache']['option_1']['bc_life'] = array( 122 '#type' => 'textfield', 123 '#title' => t('Cache lifetime'), 124 '#size' => 10, 125 '#default_value' => variable_get('bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value'], ''), 126 ); 127 128 // Blockcache fieldset. 129 $form['cache']['option_2'] = array( 130 '#type' => 'fieldset', 131 '#title' => t('Cache refresh option 2: Drupal actions'), 132 '#description' => t('Refresh on certain actions in the Drupal system. When choosing node or comment action, you also need to specify on which node types it should refresh. Note that clicking any of these checkboxes will not have any effect if a minimum lifetime is set in option 1.'), 133 ); 134 135 // Blockcache refresh. 136 $form['cache']['option_2']['bc_refresh'] = array( 137 '#prefix' => '<div style="float: left;">', 138 '#suffix' => '</div>', 139 '#type' => 'checkboxes', 140 '#title' => t('Refresh when'), 141 '#options' => array( 142 'node' => t('A node is added/updated/deleted'), 143 'comment' => t('A comment is added/updated/deleted'), 144 'user' => t('A user is added/updated/deleted'), 145 'login' => t('A user logs in our out'), 146 ), 147 '#default_value' => variable_get('bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value'], array()), 148 ); 149 150 // Associate with node types. 151 $node_types = array(); 152 $types = node_get_types('types'); 153 foreach ($types as $type) { 154 $node_types[$type->type] = $type->name; 155 } 156 157 $form['cache']['option_2']['bc_relate'] = array( 158 '#prefix' => '<div style="float: left; margin-left: 15px;">', 159 '#suffix' => '</div><div style="clear: both;"></div>', 160 '#type' => 'checkboxes', 161 '#title' => t('Relation'), 162 '#options' => $node_types, 163 '#default_value' => variable_get('bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value'], array()), 164 ); 165 166 // End div. 167 $form['cache']['enddiv'] = array( 168 '#type' => 'hidden', 169 '#suffix' => '</div>', 170 ); 171 172 } 173 174 // Add our own submit handler and remove the default submit handler. 175 unset($form['#submit'][0]); 176 $form['submit']['#weight'] = 2; 177 $form['#submit'][] = 'blockcache_alter_save_settings'; 178 179 } 180 181 // Alter the performance settings page: remove the #disabled key from the block_cache form completely 182 // and add a warning message instead to warn the user that block caching won't work when one 183 // at least on module implements node_grants and blockcache_alter_no_node_grants is not applied. 184 // Note, again, we don't check which patch is applied, that's up to the developer. 185 if ($form_id == 'system_performance_settings') { 186 $node_grants = $form['block_cache']['block_cache']['#disabled']; 187 $form['block_cache']['block_cache']['#disabled'] = FALSE; 188 if ($node_grants == TRUE) { 189 $form['block_cache']['block_cache']['#description'] = t('There are modules implementing node grants. If you want block caching to work, you need to apply the "blockcache_alter_no_node_grants.patch"'); 190 } 191 else { 192 $form['block_cache']['block_cache']['#description'] = ''; 193 } 194 } 195 } 196 197 /** 198 * Submit callback. Saves block configuration and cache settings per block. 199 * This module takes over from block_admin_configure_submit() so we can 200 * decide what to clear from cache. 201 */ 202 function blockcache_alter_save_settings($form, &$form_state) { 203 if (!form_get_errors()) { 204 db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d, title = '%s' WHERE module = '%s' AND delta = '%s'", $form_state['values']['visibility'], trim($form_state['values']['pages']), $form_state['values']['custom'], $form_state['values']['title'], $form_state['values']['module'], $form_state['values']['delta']); 205 db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $form_state['values']['module'], $form_state['values']['delta']); 206 foreach (array_filter($form_state['values']['roles']) as $rid) { 207 db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_state['values']['module'], $form_state['values']['delta']); 208 } 209 module_invoke($form_state['values']['module'], 'block', 'save', $form_state['values']['delta'], $form_state['values']); 210 drupal_set_message(t('The block configuration has been saved.')); 211 212 // Update block cache settings. 213 db_query("UPDATE {blocks} set cache = %d WHERE module = '%s' AND delta = '%s'", $form_state['values']['cache_block'], $form_state['values']['module'], $form_state['values']['delta']); 214 215 // Core patch applied or not. 216 $core_patch = variable_get('bca_corepatch', 0); 217 218 // Cache clearing 219 switch ($form_state['values']['cache_block_clear']) { 220 case '1': 221 cache_clear_all($form_state['values']['module'] .':'. $form_state['values']['delta'], 'cache_block', TRUE); 222 break; 223 224 case '2': 225 cache_clear_all(); 226 break; 227 } 228 229 // Store extra variables if core patch is applied. 230 if ($core_patch == TRUE) { 231 // Remove old variables to avoid clutter in the variable table. 232 db_query("DELETE FROM {variable} WHERE name IN ('%s', '%s', '%s')", 233 'bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value'], 234 'bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value'], 235 'bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value'] 236 ); 237 // Remember block expire time or refresh actions for the future. 238 if (!empty($form_state['values']['bc_life'])) { 239 variable_set('bc_life_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_life']); 240 } 241 else { 242 variable_set('bc_refresh_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_refresh']); 243 variable_set('bc_relate_'. $form['module']['#value'] .'_'. $form['delta']['#value'], $form_state['values']['bc_relate']); 244 } 245 } 246 247 // Redirect. 248 $form_state['redirect'] = 'admin/build/block'; 249 return; 250 } 251 } 252 253 /** 254 * Helper function to check if a blockcache alter patch is found. 255 * Note: it doesn't check which patch is applied. 256 */ 257 function _blockcache_alter_core_patch() { 258 $status = 'not'; 259 $block_file = drupal_get_filename('module', 'block'); 260 $block_contents = file_get_contents($block_file); 261 if (strpos($block_contents, 'bca_debug') !== FALSE) { 262 $status = ''; 263 } 264 return $status; 265 } 266 267 /** 268 * Helper function to check if this block should be refreshed or not. 269 * 270 * @param stdClass $cache A complete cache object. 271 * @param int $time The current timestamp. 272 * @return FALSE or TRUE 273 */ 274 function _blockcache_alter_check_expire($cache, $time) { 275 if ($cache->expire == CACHE_PERMANENT) { 276 return TRUE; 277 } 278 if ($cache->expire > $time) { 279 return TRUE; 280 } 281 return FALSE; 282 } 283 284 /** 285 * Implementation of hook_nodeapi(). 286 */ 287 function blockcache_alter_nodeapi($node, $op) { 288 switch ($op) { 289 case 'insert': 290 case 'update': 291 case 'delete': 292 _blockcache_alter_cleanup('node', $node->type); 293 break; 294 } 295 } 296 297 /** 298 * Implementation of hook_comment(). 299 */ 300 function blockcache_alter_comment($comment, $op) { 301 switch ($op) { 302 case 'insert': 303 $thiscnode = node_load($comment['nid']); 304 $nodetype = $thiscnode->type; 305 _blockcache_alter_cleanup('comment', $nodetype); 306 break; 307 case 'update': 308 $thiscnode = node_load($comment['nid']); 309 $aabb = $thiscnode->type; 310 _blockcache_alter_cleanup('comment', $nodetype); 311 break; 312 case 'delete': 313 $thiscnode = node_load($comment->nid); 314 $nodetype = $thiscnode->type; 315 _blockcache_alter_cleanup('comment', $nodetype); 316 break; 317 318 } 319 } 320 321 /** 322 * Implementation of hook_user(). 323 */ 324 function blockcache_alter_user($op) { 325 switch ($op) { 326 case 'insert': 327 case 'update': 328 case 'delete': 329 _blockcache_alter_cleanup('user', 'user_actions'); 330 break; 331 case 'login': 332 case 'logout': 333 _blockcache_alter_cleanup('login', 'user_actions'); 334 break; 335 } 336 } 337 338 /** 339 * Cleanup cached blocks if necessary. 340 * 341 * @param string $type operation type. 342 * @param string $relatednodetype Related node type (if available) 343 */ 344 function _blockcache_alter_cleanup($type, $relatednodetype = FALSE) { 345 $info = array(); 346 $time = time(); 347 $debug = variable_get('bca_debug', FALSE) && user_access('administer site configuration'); 348 $result = db_query("SELECT module, delta FROM {blocks} WHERE status = '1' AND cache <> '-1'"); 349 while ($r = db_fetch_object($result)) { 350 if (module_exists($r->module)) { 351 $refresh = variable_get('bc_refresh_'. $r->module .'_'. $r->delta, array()); 352 if ($refresh[$type] === $type) { 353 $relate = variable_get('bc_relate_'. $r->module .'_'. $r->delta, array()); 354 if ($relatednodetype == 'user_actions' || (is_array($relate) && $relate[$relatednodetype] === $relatednodetype)) { 355 db_query("DELETE FROM {cache_block} WHERE cid like '%s'", $r->module .':'. $r->delta .'%'); 356 if ($debug) { 357 $info[] = t('<br /> - module: %mod, delta: %delta', array('%mod' => $r->module, '%delta' => $r->delta)); 358 } 359 } 360 } 361 } 362 } 363 // Implode and put together a LIKE query. 364 if ($debug && !empty($info)) { 365 drupal_set_message(t("Block re-cached: ". implode(' ', $info))); 366 } 367 } 368 369 /** 370 * Implementation of hook_block(). 371 * Functions underneath will only be called when someone programmaticaly 372 * calls a block in code with module_invoke, eg: 373 * 374 * $block = module_invoke('blockcache_alter', 'block', 'view', 'block,14'); 375 * print $block['content']; 376 * 377 * The last parameter should consist of the name of original block and its 378 * original delta seperated by comma. All blocks can be cached this way. 379 */ 380 function blockcache_alter_block($op, $delta = 0, $edit = array()) { 381 switch ($op) { 382 case 'view': 383 return blockcache_alter_block_view($delta); 384 } 385 } 386 387 /** 388 * View a cached block using hook_block(). 389 * If the block is not cached or the cache is stale, get the info and stick it back into the cache. 390 */ 391 function blockcache_alter_block_view($delta) { 392 $d = explode(",", $delta); 393 $module = $d[0]; 394 $delta = $d[1]; 395 $cid = _blockcache_alter_get_cache_id($module, $delta); 396 397 if (($cid) && ($cache = cache_get($cid, 'cache_block'))) { 398 $array = $cache->data; 399 } 400 else { 401 $array = module_invoke($module, 'block', 'view', $delta); 402 if (isset($cid)) { 403 $blocklife = variable_get('bc_life_'. $module .'_'. $delta, ''); 404 $blocklife = (int) $blocklife + time(); 405 cache_set($cid, $array, 'cache_block', $blocklife); 406 if ($debug = variable_get('bca_debug', FALSE) && user_access('administer site configuration')) { 407 drupal_set_message('block re-cached: '. $block->title .'_'. $module .'_'. $delta .'_'. $blocklife .'_'. time()); 408 } 409 } 410 } 411 return $array; 412 } 413 414 /** 415 * Get cid for a block. 416 */ 417 function _blockcache_alter_get_cache_id($module, $delta) { 418 global $theme, $base_root, $user; 419 420 $block->cache = db_result(db_query("SELECT cache FROM {blocks} WHERE module = '%s' AND delta = %d AND theme = '%s'", $module, $delta, $theme)); 421 422 // User 1 being out of the regular 'roles define permissions' schema, 423 // it brings too many chances of having unwanted output get in the cache 424 // and later be served to other users. We therefore exclude user 1 from 425 // block caching. 426 if (variable_get('block_cache', 0) && $block->cache != BLOCK_NO_CACHE && $user->uid != 1) { 427 $cid_parts = array(); 428 429 // Start with common sub-patterns: block identification, theme, language. 430 $cid_parts[] = $module; 431 $cid_parts[] = $delta; 432 $cid_parts[] = $theme; 433 if (module_exists('locale')) { 434 global $language; 435 $cid_parts[] = $language->language; 436 } 437 438 // 'PER_ROLE' and 'PER_USER' are mutually exclusive. 'PER_USER' can be a 439 // resource drag for sites with many users, so when a module is being 440 // equivocal, we favor the less expensive 'PER_ROLE' pattern. 441 if ($block->cache & BLOCK_CACHE_PER_ROLE) { 442 $cid_parts[] = 'r.'. implode(',', array_keys($user->roles)); 443 } 444 elseif ($block->cache & BLOCK_CACHE_PER_USER) { 445 $cid_parts[] = "u.$user->uid"; 446 } 447 448 if ($block->cache & BLOCK_CACHE_PER_PAGE) { 449 $cid_parts[] = $base_root . request_uri(); 450 } 451 452 return implode(':', $cid_parts); 453 } 454 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |