You are here

render_cache_entity.module in Render cache 7.2

Hook implementations and frequently used functions for render cache entity module.

File

modules/controller/render_cache_entity/render_cache_entity.module
View source
<?php

/**
 * @file
 * Hook implementations and frequently used functions for render cache entity module.
 */

// -----------------------------------------------------------------------
// Core Hooks

/**
 * Implements hook_entity_info_alter().
 *
 * We hijack entity rendering, as performed through the Entity API module, to
 * provide full entity caching.
 *
 * @param array $entity_info
 */
function render_cache_entity_entity_info_alter(&$entity_info) {
  foreach ($entity_info as $type => $info) {

    // If this type is not render cacheable, continue.
    if (isset($info['render cache']) && $info['render cache'] == FALSE) {
      continue;
    }

    // Store that this entity type is render cached.
    $entity_info[$type]['render cache'] = TRUE;
    if (isset($info['view callback'])) {

      // Since we are overwriting the view callback we record the original
      // callback so that we know how to render.
      $entity_info[$type]['render cache storage']['callback'] = $info['view callback'];
      $entity_info[$type]['view callback'] = 'render_cache_entity_view_callback';
    }
    elseif (isset($info['controller class']) && in_array('EntityAPIControllerInterface', class_implements($info['controller class']))) {

      // We do not set the render cache callback, when it is missing we will
      // render using the controller class.
      $entity_info[$type]['view callback'] = 'render_cache_entity_view_callback';
    }
  }
}

/**
 * Implements hook_module_implements_alter().
 *
 * Moves our hook_entity_info_alter() implementation to occur last so that we
 * can consistently hijack the render function of the entity type.
 *
 * This also adjusts the weights for entity_view() and entity_view_alter().
 *
 * @param mixed[] $implementations
 *   Format: $[$module] = string|false
 * @param string $hook
 */
function render_cache_entity_module_implements_alter(&$implementations, $hook) {
  if (in_array($hook, array(
    'entity_info_alter',
    'entity_view',
    'entity_view_alter',
  ))) {

    // Move our hook implementations to the bottom.
    $group = $implementations['render_cache_entity'];
    unset($implementations['render_cache_entity']);
    $implementations['render_cache_entity'] = $group;
  }
}

// -----------------------------------------------------------------------
// Contrib Hooks

/**
 * Implements hook_ctools_plugin_directory().
 *
 * @param string $owner
 * @param string $plugin_type
 *
 * @return null|string
 */
function render_cache_entity_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'render_cache') {
    return 'src/RenderCache/' . $plugin_type;
  }
  return NULL;
}

/**
 * Implements hook_entity_view().
 *
 * @param object $entity
 * @param string $type
 * @param string $view_mode
 * @param string $langcode
 */
function render_cache_entity_entity_view($entity, $type, $view_mode, $langcode) {
  if (!empty($entity->render_cache_controller) && !empty($entity->content)) {

    // Store the entity we are processing in a special variable
    // as hook_entity_view_alter() does not give us the entity.
    $entity->content['#render_cache_entity'] = $entity;
  }
}

/**
 * Implements hook_entity_view_alter().
 *
 * @param array $build
 * @param string $type
 */
function render_cache_entity_entity_view_alter(&$build, $type) {

  // Ensure recursion works properly.
  if (!empty($build['#render_cache_entity'])) {
    $entity = $build['#render_cache_entity'];
    unset($build['#render_cache_entity']);
    $entity->render_cache_controller
      ->recursionStep($build);
  }
}

// -----------------------------------------------------------------------
// Public API

/**
 * Override entity API rendering callback to add a caching layer.
 *
 * @param object[] $entities
 * @param string $view_mode
 * @param string $langcode
 * @param string $entity_type
 *
 * @return array
 */
function render_cache_entity_view_callback($entities, $view_mode, $langcode, $entity_type) {

  // Remove any passed values that are not an object, this can happen with out
  // of date Apache Solr search when entities are deleted and probably other
  // situations.
  foreach ($entities as $key => $entity) {
    if (!is_object($entity)) {
      unset($entities[$key]);
    }
  }

  // @todo Unused variable $entity_info
  $entity_info = entity_get_info($entity_type);

  // Prepare context.
  $context = array(
    'entity_type' => $entity_type,
    'view_mode' => $view_mode,
    'langcode' => $langcode,
  );

  // Delegate to render cache controller.
  $rcc = render_cache_get_controller('entity');
  $rcc
    ->setContext($context);
  $build = $rcc
    ->view($entities);

  // Return $build, wrap with entity type key in array to match
  // entity_view()'s functionality.
  return array(
    $entity_type => $build,
  );
}

/**
 * Helper function to view a single entity.
 *
 * This can be used to replace node_view(), comment_view(), easier.
 *
 * @param string $entity_type
 *   The type of the entity.
 * @param object $entity
 *   The entity to render.
 * @param string $view_mode
 *   A view mode as used by this entity type, e.g. 'full', 'teaser'...
 *
 * @return array
 */
function render_cache_entity_view_single($entity_type, $entity, $view_mode) {
  list($entity_id) = entity_extract_ids($entity_type, $entity);
  $build = entity_view($entity_type, array(
    $entity_id => $entity,
  ), $view_mode);

  // The output needs to be compatible to what the single function would have
  // returned.
  if (isset($build[$entity_type][$entity_id])) {
    return $build[$entity_type][$entity_id];
  }
  return array();
}

/**
 * Implements hook_render_cache_entity_hash_alter().
 *
 * @param array $hash
 * @param object $entity
 * @param array $cache_info
 * @param array $context
 */
function node_render_cache_entity_hash_alter(&$hash, $entity, $cache_info, $context) {

  // We generally cache nodes based on comment count.
  if ($context['entity_type'] == 'node' && isset($entity->comment_count)) {

    // @todo This is very unreliable if comments can be edited, it would be better
    //       to directly save a list of entity_modified values but entity_modified
    //       needs to support multiple get and caching for that first.
    $hash['node_comment_count'] = $entity->comment_count;
  }
}