[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/blockcache_alter/ -> blockcache_alter.module (source)

   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('&nbsp;', $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  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7