You are here

panels_content_cache.module in Panels Content Cache 6

Same filename and directory in other branches
  1. 7 panels_content_cache.module

File

panels_content_cache.module
View source
<?php

/**
 * Implements hook_ctools_plugin_directory().
 */
function panels_content_cache_ctools_plugin_directory($module, $plugin) {
  if ($module == 'page_manager' || $module == 'panels' || $module == 'ctools') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Implementation of hook_nodeapi().
 */
function panels_content_cache_nodeapi(&$node, $op, $teaser, $page) {
  switch ($op) {
    case 'insert':
    case 'update':
    case 'delete':
    case 'delete revision':
      panels_content_cache_node_clear_cache($node);
      break;
  }
}

/**
 * Implements hook_panels_display_save().
 */
function panels_content_cache_panels_display_save($display) {
  $content_cache = array();

  // First clear down any rows in panels_content_cache associated with this display.
  // We do this incase content caching was previously enabled for a display/pane and it
  // was subsequenty turned off before the panel was saved again, therefore we want
  // to clear out those records from panels_content_cache. The table will be updated again
  // with any panes that have content caching enabled.
  db_query("DELETE FROM {panels_content_cache} WHERE did = %d", $display->did);

  // First check if we have set content caching on the entire display.
  // If the entire display has content caching on then we dont even need
  if (isset($display->cache['method']) && $display->cache['method'] == 'content') {
    $content_cache[] = $display;
  }

  // Next we check any panes on the display to see if any of those have content caching enabled.
  if (!empty($display->content)) {
    foreach ($display->content as $pane) {
      if (isset($pane->cache['method']) && $pane->cache['method'] == 'content') {
        $content_cache[] = $pane;
      }
    }
  }

  // Save the cached items to panels_content_cache table.
  if (!empty($content_cache)) {
    panels_content_cache_save($content_cache);

    // Cache the content types in the lookup table. We do this to potentially save a database query on the hook_nodeapi() lookup.
    panels_content_cache_variable_set('types');
    panels_content_cache_variable_set('menu_names');
  }
}

/**
 * Helper function to set a variable to store the list of content_types (types)
 * in panels_content_cache table and the list of menu_names.
 *
 * These variables are used to save queries against the table in other hooks
 * @see panels_content_cache_nodeapi()
 * @see panels_content_cache_menu_link_alter()
 *
 * @param $name
 * The name of the variable to set.
 */
function panels_content_cache_variable_set($name = 'types') {
  $fields = array(
    'menu_names' => 'menu_name',
    'types' => 'type',
  );
  $field = isset($fields[$name]) ? $fields[$name] : NULL;

  // Check if we have a valid field to retrieve.
  if (!empty($field)) {
    $values = array();
    $sql = "SELECT DISTINCT {$field} FROM {panels_content_cache} WHERE {$field} IS NOT NULL";
    $result = db_query($sql);
    while ($value = db_fetch_object($result)) {
      $values[] = $value->{$field};
    }
    variable_set("panels_content_cache_{$name}", $values);
  }
}

/**
 * Implements hook_menu_link_alter().
 */
function panels_content_cache_menu_link_alter(&$item, $menu) {
  static $cache_cleared = array();
  $menu_name = $item['menu_name'];

  // We keep a static cache of the caches cleared by menu_name.
  // We do this because hook_menu_link_alter() may be called multiple times in a single request
  // cycle (for example if one is re-arranging a whole bunch of menu items).
  // In this scenario we want to avoid clearing any panel display caches over and over again.
  // To achieve this, we clear any associated panel display caches first time round
  // (in the scenario they could be re-arranging / editing just a single menu link).
  // If we come here again (in the same request cycle and for the same menu name)
  // we register a shutdown function so that any panels can be cleared at the end of the request cycle.
  // This ensures those displays will be cleared again only once more, instead of X amount of times.
  if (!isset($cache_cleared[$menu_name])) {
    $menus = variable_get('panels_content_cache_menu_names', array());
    if (!empty($menus) && in_array($menu_name, $menus)) {
      panels_content_cache_menu_clear_cache($menu_name);
      $cache_cleared[$menu_name] = 1;
    }
  }
  else {
    if ($cache_cleared[$menu_name] == 1) {
      register_shutdown_function('panels_content_cache_menu_clear_cache', $menu_name);
      $cache_cleared[$menu_name] = 2;
    }
  }
}

/**
 * Helper function to save items into the panels_content_cache table
 *
 * @param array $content_cache
 * An array of panels display or pane objects to save to panels_content_cache table.
 */
function panels_content_cache_save($content_cache = array()) {
  if (!empty($content_cache)) {
    foreach ($content_cache as $display) {

      // Handle menu selections in admin pane.
      $menus = isset($display->cache['settings']['menus']) ? array_filter($display->cache['settings']['menus']) : array();
      if (!empty($menus)) {
        foreach ($menus as $menu) {
          panels_content_cache_save_row($display, NULL, $menu);
        }
      }

      // Handle content type selections in admin pane.
      $types = isset($display->cache['settings']['content_types']) ? array_filter($display->cache['settings']['content_types']) : array();
      if (!empty($types)) {
        foreach ($types as $type) {
          panels_content_cache_save_row($display, $type);
        }
      }
    }
  }
}

/*
 * Save a row to the panels_content_cache table.
 *
 * @param $display
 * The panels display / pane
 *
 * @param $type
 * optional The content type to save
 *
 * @param $menu
 * optional The menu name to save.
 */
function panels_content_cache_save_row($display, $type = NULL, $menu = NULL) {
  if (!empty($display)) {
    $row = new stdClass();
    $row->did = $display->did;
    $row->type = isset($type) ? $type : NULL;
    $row->menu_name = isset($menu) ? $menu : NULL;
    $row->pid = isset($display->pid) ? $display->pid : NULL;
    drupal_write_record('panels_content_cache', $row);
  }
}

/**
 * This function is called from hook_nodeapi() and invalidates the panel cache
 * when a node is updated and it matches the criteria chosen in the caching of any
 * panels.
 *
 * @param $node
 * The node object for the current node being saved.
 */
function panels_content_cache_node_clear_cache($node) {

  // Check if the $node->type is in panels_content_cache table. If it exists
  // then we want to try and lookup the display ID from panels_content_cache
  // to see if we need to clear the cache on any panels.
  $types = variable_get('panels_content_cache_types', array());
  if (!empty($types) && in_array($node->type, $types)) {
    module_load_include('inc', 'panels_content_cache', 'plugins/cache/content');
    $result = db_query("SELECT DISTINCT did FROM {panels_content_cache} WHERE type = '%s'", $node->type);
    while ($row = db_fetch_object($result)) {
      $display = panels_load_display($row->did);
      panels_content_cache_clear_cache($display);
    }
  }
}

/**
 * Clear any panels displays that are associated with a menu.
 * This function looks up any panel displays by menu_name that are
 * in the panels_content_cache table, and clears the cache on those displays.
 *
 * @param $menu_name
 * The menu_name to look up any panels associated with this menu.
 */
function panels_content_cache_menu_clear_cache($menu_name) {
  if (!empty($menu_name)) {
    module_load_include('inc', 'panels_content_cache', 'plugins/cache/content');
    $result = db_query("SELECT DISTINCT did FROM {panels_content_cache} WHERE menu_name = '%s'", $menu_name);
    while ($row = db_fetch_object($result)) {
      $display = panels_load_display($row->did);
      panels_content_cache_clear_cache($display);
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Add additional submit form to menu_delete_form.
 * @see menu_delete_form().
 */
function panels_content_cache_form_menu_item_delete_form_alter(&$form, &$form_state) {
  $form['#submit'][] = 'panels_content_cache_menu_delete_form_submit';
}

/**
 * Additional submit handler for menu_delete_form.
 *
 * @see menu_delete_form().
 */
function panels_content_cache_menu_delete_form_submit($form, &$form_state) {
  $item = $form['#item'];
  $menus = variable_get('panels_content_cache_menu_names', array());
  if (!empty($menus) && in_array($item['menu_name'], $menus)) {

    // Clear any panel which contains a reference to the menu of the menu item being deleted.
    panels_content_cache_menu_clear_cache($item['menu_name']);
  }
}

Functions

Namesort descending Description
panels_content_cache_ctools_plugin_directory Implements hook_ctools_plugin_directory().
panels_content_cache_form_menu_item_delete_form_alter Implements hook_form_FORM_ID_alter().
panels_content_cache_menu_clear_cache Clear any panels displays that are associated with a menu. This function looks up any panel displays by menu_name that are in the panels_content_cache table, and clears the cache on those displays.
panels_content_cache_menu_delete_form_submit Additional submit handler for menu_delete_form.
panels_content_cache_menu_link_alter Implements hook_menu_link_alter().
panels_content_cache_nodeapi Implementation of hook_nodeapi().
panels_content_cache_node_clear_cache This function is called from hook_nodeapi() and invalidates the panel cache when a node is updated and it matches the criteria chosen in the caching of any panels.
panels_content_cache_panels_display_save Implements hook_panels_display_save().
panels_content_cache_save Helper function to save items into the panels_content_cache table
panels_content_cache_save_row
panels_content_cache_variable_set Helper function to set a variable to store the list of content_types (types) in panels_content_cache table and the list of menu_names.