views_plugin_cache.inc
Same filename in other branches
File
-
plugins/
views_plugin_cache.inc
View source
<?php
/**
* The base plugin to handle caching.
*
* @ingroup views_cache_plugins
*/
class views_plugin_cache extends views_plugin {
/**
* Contains all data that should be written/read from cache.
*/
var $storage = array();
/**
* What table to store data in.
*/
var $table = 'cache_views_data';
/**
* Initialize the plugin.
*
* @param $view
* The view object.
* @param $display
* The display handler.
*/
function init(&$view, &$display) {
$this->view =& $view;
$this->display =& $display;
if (is_object($display->handler)) {
$options = $display->handler
->get_option('cache');
// Overlay incoming options on top of defaults
$this->unpack_options($this->options, $options);
}
}
/**
* Return a string to display as the clickable title for the
* access control.
*/
function summary_title() {
return t('Unknown');
}
/**
* Determine the expiration time of the cache type, or NULL if no expire.
*
* Plugins must override this to implement expiration.
*
* @param $type
* The cache type, either 'query', 'result' or 'output'.
*/
function cache_expire($type) {
}
/**
* Determine expiration time in the cache table of the cache type
* or CACHE_PERMANENT if item shouldn't be removed automatically from cache.
*
* Plugins must override this to implement expiration in the cache table.
*
* @param $type
* The cache type, either 'query', 'result' or 'output'.
*/
function cache_set_expire($type) {
return CACHE_PERMANENT;
}
/**
* Save data to the cache.
*
* A plugin should override this to provide specialized caching behavior.
*/
function cache_set($type) {
switch ($type) {
case 'query':
// Not supported currently, but this is certainly where we'd put it.
break;
case 'results':
if ($this->get_results_key() !== FALSE) {
$data = array(
'result' => $this->view->result,
'total_rows' => $this->view->total_rows,
'current_page' => $this->view
->get_current_page(),
);
cache_set($this->get_results_key(), $data, $this->table, $this->cache_set_expire($type));
}
break;
case 'output':
$this->gather_headers();
$this->storage['output'] = $this->view->display_handler->output;
cache_set($this->get_output_key(), $this->storage, $this->table, $this->cache_set_expire($type));
break;
}
}
/**
* Retrieve data from the cache.
*
* A plugin should override this to provide specialized caching behavior.
*/
function cache_get($type) {
$cutoff = $this->cache_expire($type);
switch ($type) {
case 'query':
// Not supported currently, but this is certainly where we'd put it.
return FALSE;
case 'results':
// Values to set: $view->result, $view->total_rows, $view->execute_time,
// $view->current_page.
$results_key = $this->get_results_key();
if ($results_key === FALSE) {
return FALSE;
}
else {
if ($cache = cache_get($results_key, $this->table)) {
if (!$cutoff || $cache->created > $cutoff) {
$this->view->result = $cache->data['result'];
$this->view->total_rows = $cache->data['total_rows'];
$this->view
->set_current_page($cache->data['current_page']);
$this->view->execute_time = 0;
return TRUE;
}
}
}
return FALSE;
case 'output':
if ($cache = cache_get($this->get_output_key(), $this->table)) {
if (!$cutoff || $cache->created > $cutoff) {
$this->storage = $cache->data;
$this->view->display_handler->output = $cache->data['output'];
$this->restore_headers();
return TRUE;
}
}
return FALSE;
}
}
/**
* Clear out cached data for a view.
*
* We're just going to nuke anything related to the view, regardless of display,
* to be sure that we catch everything. Maybe that's a bad idea.
*/
function cache_flush() {
cache_clear_all($this->view->name . ':', $this->table, TRUE);
}
/**
* Post process any rendered data.
*
* This can be valuable to be able to cache a view and still have some level of
* dynamic output. In an ideal world, the actual output will include HTML
* comment based tokens, and then the post process can replace those tokens.
*
* Example usage. If it is known that the view is a node view and that the
* primary field will be a nid, you can do something like this:
*
* <!--post-FIELD-NID-->
*
* And then in the post render, create an array with the text that should
* go there:
*
* strtr($output, array('<!--post-FIELD-1-->', 'output for FIELD of nid 1');
*
* All of the cached result data will be available in $view->result, as well,
* so all ids used in the query should be discoverable.
*/
function post_render(&$output) {
}
/**
* Start caching javascript, css and other out of band info.
*
* This takes a snapshot of the current system state so that we don't
* duplicate it. Later on, when gather_headers() is run, this information
* will be removed so that we don't hold onto it.
*/
function cache_start() {
$this->storage['head'] = drupal_set_html_head();
$this->storage['css'] = drupal_add_css();
foreach (array(
'header',
'footer',
) as $scope) {
$this->storage['js'][$scope] = drupal_add_js(NULL, NULL, $scope);
}
}
/**
* Gather out of band data, compare it to what we started with and store the difference.
*/
function gather_headers() {
// Simple replacement for head
$this->storage['head'] = str_replace($this->storage['head'], '', drupal_set_html_head());
// Slightly less simple for CSS:
$css = drupal_add_css();
$start = $this->storage['css'];
$this->storage['css'] = array();
foreach ($css as $media => $medias) {
foreach ($medias as $type => $types) {
foreach ($types as $path => $preprocess) {
if (!isset($start[$media][$type][$path])) {
$this->storage['css'][] = array(
$path,
$type,
$media,
$preprocess,
);
}
}
}
}
$js = array();
// A little less simple for js
foreach (array(
'header',
'footer',
) as $scope) {
$js[$scope] = drupal_add_js(NULL, NULL, $scope);
}
$start = $this->storage['js'];
$this->storage['js'] = array();
foreach ($js as $scope => $scopes) {
foreach ($scopes as $type => $types) {
foreach ($types as $id => $info) {
if (!isset($start[$scope][$type][$id])) {
switch ($type) {
case 'setting':
$this->storage['js'][] = array(
$info,
$type,
$scope,
);
break;
case 'inline':
$this->storage['js'][] = array(
$info['code'],
$type,
$scope,
$info['defer'],
);
break;
default:
$this->storage['js'][] = array(
$id,
$type,
$scope,
$info['defer'],
$info['cache'],
);
}
}
}
}
}
}
/**
* Restore out of band data saved to cache. Copied from Panels.
*/
function restore_headers() {
if (!empty($this->storage['head'])) {
drupal_set_html_head($this->storage['head']);
}
if (!empty($this->storage['css'])) {
foreach ($this->storage['css'] as $args) {
call_user_func_array('drupal_add_css', $args);
}
}
if (!empty($this->storage['js'])) {
foreach ($this->storage['js'] as $args) {
call_user_func_array('drupal_add_js', $args);
}
}
}
function get_results_key() {
global $user;
if (!isset($this->_results_key)) {
$cache_info = $this->view->query
->get_cache_info();
if ($cache_info === FALSE) {
$this->_results_key = FALSE;
}
else {
$key_data = array(
'build_info' => $this->view->build_info,
'cache_info' => $this->view->query
->get_cache_info(),
'roles' => array_keys($user->roles),
'super-user' => $user->uid == 1,
// special caching for super user.
'language' => $GLOBALS['language'],
);
foreach (array(
'exposed_info',
'page',
'sort',
'order',
) as $key) {
if (isset($_GET[$key])) {
$key_data[$key] = $_GET[$key];
}
}
$this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data));
}
}
return $this->_results_key;
}
function get_output_key() {
global $user;
if (!isset($this->_output_key)) {
$key_data = array(
'result' => $this->view->result,
'roles' => array_keys($user->roles),
'super-user' => $user->uid == 1,
// special caching for super user.
'theme' => $GLOBALS['theme'],
'language' => $GLOBALS['language'],
);
$this->_output_key = $this->view->name . ':' . $this->display->id . ':output:' . md5(serialize($key_data));
}
return $this->_output_key;
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
views_plugin_cache | The base plugin to handle caching. |