display_cache.module in Display Cache 7
Module file for Display Cache.
File
display_cache.moduleView source
<?php
/**
* @file
* Module file for Display Cache.
*/
define('DISPLAY_CACHE_DISABLED', '0');
define('DISPLAY_CACHE_ENABLED', '1');
define('DISPLAY_CACHE_FIELDS', '2');
/**
* Name of the display cache cache bin.
*
* @var string
*/
define('DISPLAY_CACHE_CACHE_BIN', 'cache_display_cache');
/**
* Suffix to a view mode that triggers on-the-fly re-rendering of the view mode.
*
* @var string
*/
define('DISPLAY_CACHE_VIEW_MODE_CACHE_IGNORE_SUFFIX', ':display_cache_no_cache');
/**
* Implements hook_form_FORM_ID_alter().
*/
function display_cache_form_field_ui_display_overview_form_alter(&$form, &$form_state) {
if (user_access('administer display cache')) {
form_load_include($form_state, 'inc', 'display_cache', 'display_cache.admin');
display_cache_field_ui_form($form, $form_state);
}
}
/**
* Implements hook_flush_caches().
*/
function display_cache_flush_caches() {
return array(
DISPLAY_CACHE_CACHE_BIN,
);
}
/**
* Implements hook_menu().
*/
function display_cache_menu() {
$menu_items = array();
// Menu item for configurations.
$menu_items['admin/config/development/display-cache'] = array(
'title' => 'Display Cache',
'description' => 'Form to submit cache flush for display cache.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'display_cache_flush_caches_form',
),
'access arguments' => array(
'administer display cache',
),
'file' => 'display_cache.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
return $menu_items;
}
/**
* Implements hook_admin_menu_cache_info().
*/
function display_cache_admin_menu_cache_info() {
$links['display_cache'] = array(
'title' => 'Display Caches',
'callback' => '_display_cache_clear_cache',
);
return $links;
}
/**
* Implements hook_permission().
*/
function display_cache_permission() {
return array(
'administer display cache' => array(
'title' => t('Administer Display Cache'),
'description' => t('Permission to administer display cache settings and clear display cache caches from the ui.'),
),
);
}
/**
* Implements hook_form_FORM_ID_alter().
*
* FORM ID: node_type
*/
function display_cache_form_node_type_form_alter(&$form, &$form_state) {
if (user_access('administer display cache')) {
form_load_include($form_state, 'inc', 'display_cache', 'display_cache.admin');
display_cache_node_type_form($form, $form_state);
}
}
/**
* Implements hook_comment_publish().
*/
function display_cache_comment_publish($comment) {
display_cache_clear_comment_host_entity_cache($comment);
}
/**
* Implements hook_comment_update().
*
* This basically implements hook_comment_unpublished() which is not implemented
* by the comment module.
*/
function display_cache_comment_update($comment) {
if ($comment->original && $comment->original->status != $comment->status && $comment->status == COMMENT_NOT_PUBLISHED) {
display_cache_clear_comment_host_entity_cache($comment);
}
}
/**
* Implements hook_comment_delete().
*/
function display_cache_comment_delete($comment) {
if ($comment->status == COMMENT_PUBLISHED) {
display_cache_clear_comment_host_entity_cache($comment);
}
}
/**
* Implemenets hook_node_type_delete().
*/
function display_cache_node_type_delete($info) {
variable_del('display_cache_comment_publication_clears_host_entity_cache_' . $info->type);
variable_del('display_cache_comment_publication_clears_host_entity_cache_node_' . $info->type);
}
/**
* Clears the given comments' host entity if needed.
*
* @param Object $comment
* The comment.
*/
function display_cache_clear_comment_host_entity_cache($comment) {
if ($comment->nid) {
$node = node_load($comment->nid);
$should_clear_host_entity_cache_globally = variable_get('display_cache_comment_publication_clears_host_entity_cache_' . $node->type, FALSE);
$view_modes_to_clear = display_cache_get_comment_publication_clears_host_entity_cache_settings('node', $node->type);
if ($should_clear_host_entity_cache_globally) {
display_cache_flush_cache('node', $node);
}
elseif (!empty($view_modes_to_clear) && array_sum($view_modes_to_clear) > 0) {
foreach ($view_modes_to_clear as $view_mode => $clear) {
if ($clear) {
display_cache_flush_cache('node', $node, $view_mode);
}
}
}
}
}
/**
* Flushes the display cache of a given element.
*
* If one argument is missing, all following arguments will be replaced with a
* wildcard.
*
* @param string $entity_type
* Type like 'node' or 'comment'.
*
* @param int|object $entity
* (optional) Entity object or entity id.
* Leave empty to flush all entities of given type.
*
* @param string $view_mode
* (optional) View mode like 'full' or 'teaser'.
* Leave empty to flush all view modes of given entity.
*
* @param string $element
* (optional) Element like 'entity', 'field' or 'render_array'.
*/
function display_cache_flush_cache($entity_type, $entity = NULL, $view_mode = NULL, $element = NULL) {
if (is_object($entity)) {
$entity = entity_id($entity_type, $entity);
}
$keys = display_cache_get_cache_keys($entity_type, $entity, $view_mode, $element);
$cache_id = implode(':', $keys) . ':';
cache_clear_all($cache_id, DISPLAY_CACHE_CACHE_BIN, TRUE);
}
/**
* Implements hook_entity_delete().
*/
function display_cache_entity_delete($entity, $entity_type) {
display_cache_flush_cache($entity_type, $entity);
}
/**
* Implements hook_entity_update().
*/
function display_cache_entity_update($entity, $entity_type) {
display_cache_flush_cache($entity_type, $entity);
}
/**
* Returns display cache settings for given entity type, bundle and view mode.
*
* @param string $entity_type
* The entity type like 'node' or 'comment'.
*
* @param string $bundle
* Bundle within the entity type like 'page' or 'article' for nodes.
*
* @param string $view_mode
* View mode like 'full' or 'teaser'.
*
* @return array
* Array with settings.
*/
function display_cache_get_settings($entity_type, $bundle, $view_mode) {
$settings = variable_get('display_cache_' . $entity_type . '_' . $bundle . '_' . $view_mode, FALSE);
// Get default settings.
if (!$settings && $view_mode !== 'default') {
$settings = display_cache_get_settings($entity_type, $bundle, 'default');
if (!$settings) {
return array(
'default' => array(
'use' => DISPLAY_CACHE_DISABLED,
'page_granularity' => DISPLAY_CACHE_DISABLED,
'user_granularity' => DISPLAY_CACHE_DISABLED,
'granularity' => DISPLAY_CACHE_DISABLED,
),
);
}
}
return $settings;
}
/**
* Collects the comment publication host entity cache clearing settings.
*
* @param string $entity_type
* This is almost all the type 'node'. It is just here for completeness.
* @param string $bundle
* The bundle to check.
* @param string $view_mode
* If given, the settings obtained will be searched for this specific view
* mode.
*
* @return mixed(array|bool)
* Returns a setting array or a bool if $view_mode has been given.
*/
function display_cache_get_comment_publication_clears_host_entity_cache_settings($entity_type, $bundle, $view_mode = NULL) {
$variable_name = display_cache_get_comment_publication_clears_host_entity_cache_setting_name($entity_type, $bundle);
$result = variable_get($variable_name, array());
if (!is_null($view_mode)) {
$result = isset($result[$view_mode]) ? $result[$view_mode] : FALSE;
}
return $result;
}
/**
* Implements hook_entity_view_alter().
*/
function display_cache_entity_view_alter(&$build, $entity_type) {
// Disable display_cache by global setting.
if (variable_get('display_cache_disable', FALSE) === TRUE) {
return;
}
$view_mode = $build['#view_mode'];
$bundle = isset($build['#bundle']) ? $build['#bundle'] : NULL;
$settings = display_cache_get_settings($entity_type, $bundle, $view_mode);
$display_settings = $settings['default'];
// Cache if enabled.
if ($display_settings['use'] === DISPLAY_CACHE_ENABLED) {
if (!empty($build['#' . $entity_type])) {
$entity_id = entity_id($entity_type, $build['#' . $entity_type]);
}
elseif (!empty($build['#entity'])) {
$entity_id = entity_id($entity_type, $build['#entity']);
}
elseif ($entity_type === 'taxonomy_term') {
$entity_id = entity_id($entity_type, $build['#term']);
}
elseif ($entity_type === 'user') {
$entity_id = entity_id($entity_type, $build['#account']);
}
else {
// Create watchdog entry for unsupported entities.
watchdog('display cache', 'The entity type %entity_type seems to be unsupported until now. Please report this to the issue cue of Display Cache so we can fix this.', array(
'%entity_type' => $entity_type,
), WATCHDOG_WARNING);
return;
}
$keys = display_cache_get_cache_keys($entity_type, $entity_id, $view_mode, 'entity');
$build['#cache'] = array(
'keys' => $keys,
'bin' => DISPLAY_CACHE_CACHE_BIN,
'granularity' => $display_settings['granularity'],
);
}
}
/**
* Implements hook_field_attach_view_alter().
*/
function display_cache_field_attach_view_alter(&$output, $context) {
// Disable display_cache by global setting.
if (variable_get('display_cache_disable', FALSE) === TRUE) {
return;
}
$entity_type = $context['entity_type'];
$entity_id = entity_id($entity_type, $context['entity']);
$view_mode = $context['view_mode'];
// Get bundle.
if (isset($output['#bundle'])) {
$bundle = $output['#bundle'];
}
else {
$first_field = reset($output);
$bundle = $first_field['#bundle'];
}
$settings = display_cache_get_settings($entity_type, $bundle, $view_mode);
// Cache if enabled.
if (!empty($settings['default']['use']) && $settings['default']['use'] == DISPLAY_CACHE_FIELDS) {
foreach (element_children($output) as $field_name) {
if (array_key_exists($field_name, $settings) && $settings[$field_name]['override'] != DISPLAY_CACHE_DISABLED) {
$element =& $output[$field_name];
$keys = display_cache_get_cache_keys($entity_type, $entity_id, $view_mode, $field_name);
$element['#cache'] = array(
'keys' => $keys,
'bin' => DISPLAY_CACHE_CACHE_BIN,
'granularity' => $settings[$field_name]['granularity'],
);
}
}
}
}
/**
* Implements hook_entity_info_alter().
*/
function display_cache_entity_info_alter(&$entity_info) {
foreach ($entity_info as &$entity) {
// Replace view callback with own callback display_cache_view_entity().
if (isset($entity['view callback'])) {
$entity['entity view callback'] = $entity['view callback'];
}
$entity['view callback'] = 'display_cache_view_entity';
}
}
/**
* Alternative entity view callback.
*
* This callback replacing all view callbacks provided by the Entity module. The
* original callback will be called within this callback. In this way it is
* possible to return the cached html before a renderable array is build.
*
* @see entity_view()
* @see display_cache_entity_info_alter()
*/
function display_cache_view_entity($entities, $view_mode, $langcode, $entity_type) {
$info = entity_get_info($entity_type);
$return = array();
$ignore_cache = strpos($view_mode, DISPLAY_CACHE_VIEW_MODE_CACHE_IGNORE_SUFFIX) !== FALSE;
if ($ignore_cache) {
$view_mode = str_replace(':display_cache_no_cache', '', $view_mode);
}
foreach ($entities as $entity_id => $entity) {
$render_array = array();
// Disable display_cache by global setting.
if (!$ignore_cache && variable_get('display_cache_disable', FALSE) === FALSE) {
if (!empty($info['entity keys']['bundle'])) {
$bundle_key = $info['entity keys']['bundle'];
}
elseif (!empty($entity_info['bundle keys']['bundle'])) {
$bundle_key = $info['bundle keys']['bundle'];
}
// This entity may not have a bundle key, fallback to the entity type.
if (isset($bundle_key) && !empty($entity->{$bundle_key})) {
$bundle = $entity->{$bundle_key};
}
else {
$bundle = $entity_type;
}
$render_array = display_cache_get_cached_display($entity_type, $bundle, $entity_id, $view_mode, 'entity');
}
// No cached result was found. Render entity.
if (empty($render_array)) {
// Get renderable array.
if (isset($info['entity view callback'])) {
$entity = entity_key_array_by_property(array(
$entity,
), $info['entity keys']['id']);
$render_array = $info['entity view callback']($entity, $view_mode, $langcode, $entity_type);
$render_array = $render_array[$entity_type][$entity_id];
}
elseif (in_array('EntityAPIControllerInterface', class_implements($info['controller class']))) {
$render_array = entity_get_controller($entity_type)
->view(array(
$entity,
), $view_mode, $langcode);
$render_array = $render_array[$entity_type][$entity_id];
}
}
$return[$entity_type][$entity_id] = $render_array;
}
return $return;
}
/**
* Check for cached display.
*
* @param string $entity_type
* The entity type.
* @param string $bundle
* The bundle.
* @param int $entity_id
* The entity id.
* @param string $view_mode
* The view mode.
* @param string $element
* Element which is cached like 'entity', 'field' or 'render_array'.
*
* @return array
* A render array containing only a #markup index.
*/
function display_cache_get_cached_display($entity_type, $bundle = NULL, $entity_id = NULL, $view_mode = NULL, $element = 'entity') {
// Initiate result.
$result = array();
// Get settings.
$settings = display_cache_get_settings($entity_type, $bundle, $view_mode);
if ($settings['default']['use'] == DISPLAY_CACHE_ENABLED) {
// Get rendered HTML from cache.
$keys = display_cache_get_cache_keys($entity_type, $entity_id, $view_mode, $element);
$cid_parts = array(
'#cache' => array(
'keys' => $keys,
'granularity' => $settings['default']['granularity'],
),
);
$cid = drupal_render_cid_create($cid_parts);
$data = cache_get($cid, DISPLAY_CACHE_CACHE_BIN);
if (!empty($data->data)) {
$result = $data->data;
}
}
return $result;
}
/**
* Implements hook_module_implements_alter().
*
* Move the hook implementation of hook_entity_info_alter() to the bottom to be
* able to alter the view callback added by Entity API during this hook.
*
* @see entity_entity_info_alter()
* @see display_cache_install()
*/
function display_cache_module_implements_alter(&$implementations, $hook) {
if ($hook == 'entity_info_alter') {
// Move our hook implementation to the bottom.
$group = $implementations['display_cache'];
unset($implementations['display_cache']);
$implementations['display_cache'] = $group;
}
}
/**
* Returns array of given keys for caching.
*
* @param string $entity_type
* Entity type like 'node'.
*
* @param int $entity_id
* Entity ID.
*
* @param string $view_mode
* View mode like 'full' or 'teaser'.
*
* @param null $element
* Element which is cached like 'entity', 'field' or 'render_array'.
*
* @return array
* Array with keys to build the cache id.
*/
function display_cache_get_cache_keys($entity_type, $entity_id = NULL, $view_mode = NULL, $element = NULL) {
$keys = array(
'entity_type' => $entity_type,
);
if (!empty($entity_id)) {
$keys['entity_id'] = $entity_id;
if (!empty($view_mode)) {
$keys['view_mode'] = $view_mode;
if (!empty($element)) {
$keys['element'] = $element;
}
}
}
drupal_alter('display_cache_cache_keys', $keys);
return $keys;
}
/**
* Clears cache of display_cache module.
*/
function _display_cache_clear_cache() {
cache_clear_all('*', DISPLAY_CACHE_CACHE_BIN, TRUE);
}
/**
* Returns setting name for comment publication host entity clearing.
*/
function display_cache_get_comment_publication_clears_host_entity_cache_setting_name($entity_type, $bundle) {
$variable_name_parts = array(
'display_cache_comment_publication_clears_host_entity_cache',
$entity_type,
$bundle,
);
return implode('_', $variable_name_parts);
}
Functions
Constants
Name | Description |
---|---|
DISPLAY_CACHE_CACHE_BIN | Name of the display cache cache bin. |
DISPLAY_CACHE_DISABLED | @file Module file for Display Cache. |
DISPLAY_CACHE_ENABLED | |
DISPLAY_CACHE_FIELDS | |
DISPLAY_CACHE_VIEW_MODE_CACHE_IGNORE_SUFFIX | Suffix to a view mode that triggers on-the-fly re-rendering of the view mode. |