Commit 3a0f6b33 authored by webchick's avatar webchick

#636992 by catch, yched: Fixed Entity loading needs protection from infinite...

#636992 by catch, yched: Fixed Entity loading needs protection from infinite recursion. Prevents unnecessary user_load()s from RDF.
parent 52f99dc0
......@@ -6484,6 +6484,46 @@ function entity_get_controller($entity_type) {
return $controllers[$entity_type];
}
/**
* Invoke hook_entity_prepare_view().
*
* If adding a new entity similar to nodes, comments or users, you should
* invoke this function during the ENTITY_build_content() or
* ENTITY_build_multiple() phases of rendering to allow other modules to alter
* the objects during this phase. This is needed for situations where
* information needs to be loaded outside of ENTITY_load() - particularly
* when loading entities into one another - i.e. a user object into a node, due
* to the potential for unwanted side-effects such as caching and infinite
* recursion. By convention, entity_prepare_view() is called after
* field_attach_prepare_view() to allow entity level hooks to act on content
* loaded by field API.
* @see hook_entity_prepare_view()
*
* @param $entity_type
* The type of entity, i.e. 'node', 'user'.
* @param $entities
* The entity objects which are being prepared for view, keyed by object ID.
*/
function entity_prepare_view($entity_type, $entities) {
// To ensure hooks are only run once per entity, check for an
// entity_view_prepared flag and only process items without it.
// @todo: resolve this more generally for both entity and field level hooks.
$prepare = array();
foreach ($entities as $id => $entity) {
if (empty($entity->entity_view_prepared)) {
// Add this entity to the items to be prepared.
$prepare[$id] = $entity;
// Mark this item as prepared.
$entity->entity_view_prepared = TRUE;
}
}
if (!empty($prepare)) {
module_invoke_all('entity_prepare_view', $prepare, $entity_type);
}
}
/**
* Performs one or more XML-RPC request(s).
*
......
......@@ -879,6 +879,7 @@ function comment_build_content($comment, $node, $view_mode = 'full') {
// Build fields content.
field_attach_prepare_view('comment', array($comment->cid => $comment), $view_mode);
entity_prepare_view('comment', array($comment->cid => $comment));
$comment->content += field_attach_view('comment', $comment, $view_mode);
// Prior to Drupal 7, the comment body was a simple text variable, but with
......@@ -997,6 +998,7 @@ function comment_links($comment, $node) {
*/
function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0) {
field_attach_prepare_view('comment', $comments, $view_mode);
entity_prepare_view('comment', $comments);
$build = array(
'#sorted' => TRUE,
......
......@@ -1209,6 +1209,7 @@ function node_build_content($node, $view_mode = 'full') {
// 'prepare_view' step. An internal flag prevents the operation from running
// twice.
field_attach_prepare_view('node', array($node->nid => $node), $view_mode);
entity_prepare_view('node', array($node->nid => $node));
$node->content += field_attach_view('node', $node, $view_mode);
// Always display a read more link on teasers because we have no way
......@@ -2254,6 +2255,7 @@ function node_feed($nids = FALSE, $channel = array()) {
*/
function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0) {
field_attach_prepare_view('node', $nodes, $view_mode);
entity_prepare_view('node', $nodes);
$build = array();
foreach ($nodes as $node) {
$build['nodes'][$node->nid] = node_view($node, $view_mode);
......
......@@ -594,6 +594,25 @@ function rdf_field_attach_view_alter(&$output, $context) {
}
}
/**
* Implements hook_entity_prepare_view().
*/
function rdf_entity_prepare_view($entities, $entity_type) {
$uids = array();
// In the case of both nodes and comments, the full $account object for the
// author is needed in rdf_preprocess_username(), however this is not
// available from node_load() or comment_load(). If the users are loaded
// for the first time in rdf_preprocess_username() this will issue an
// individual user_load() for each account, so pre-load the users needed
// here where we can take advantage of user_load_multiple().
if ($entity_type == 'node' || $entity_type == 'comment') {
foreach ($entities as $entity) {
$uids[$entity->uid] = $entity->uid;
}
user_load_multiple($uids);
}
}
/**
* Wraps a template variable in an HTML element with the desired attributes.
*
......
......@@ -263,6 +263,28 @@ function hook_admin_paths_alter(&$paths) {
$paths['node/add/forum'] = FALSE;
}
/**
* Act on entities as they are being prepared for view.
*
* Allows you to operate on multiple entities as they are being prepared for
* view. Only use this if attaching the data during the entity_load() phase
* is not appropriate, for example when attaching other 'entity' style objects.
*
* @param $entities
* The entities keyed by entity ID.
* @param $type
* The type of entities being loaded (i.e. node, user, comment).
*/
function hook_entity_prepare_view($entities, $type) {
// Load a specific node into the user object for later theming.
if ($type == 'user') {
$nodes = mymodule_get_user_nodes(array_keys($entities));
foreach ($entities as $uid => $entity) {
$entity->user_node = $nodes[$uid];
}
}
}
/**
* Perform periodic actions.
*
......
......@@ -31,6 +31,7 @@ function taxonomy_term_page($term) {
drupal_add_css(drupal_get_path('module', 'taxonomy') . '/taxonomy.css');
field_attach_prepare_view('taxonomy_term', array($term->tid => $term), 'full');
entity_prepare_view('taxonomy_term', array($term->tid => $term));
$build = array();
$build += field_attach_view('taxonomy_term', $term);
$build['term_description'] = array(
......
......@@ -2158,6 +2158,7 @@ function user_build_content($account, $view_mode = 'full') {
// Build fields content.
field_attach_prepare_view('user', array($account->uid => $account), $view_mode);
entity_prepare_view('user', array($account->uid => $account));
$account->content += field_attach_view('user', $account, $view_mode);
// Populate $account->content with a render() array.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment