diff options
author | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-01-13 05:00:25 +0000 |
---|---|---|
committer | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-01-13 05:00:25 +0000 |
commit | 3a0f6b33720b1a939ec2f828bfefd31b6c51817f (patch) | |
tree | 89502c07e46b8eb5367aa880c74a15204c95c2cc | |
parent | 52f99dc071428a1490d0d367e95706a65f5b3d17 (diff) | |
download | brdo-3a0f6b33720b1a939ec2f828bfefd31b6c51817f.tar.gz brdo-3a0f6b33720b1a939ec2f828bfefd31b6c51817f.tar.bz2 |
#636992 by catch, yched: Fixed Entity loading needs protection from infinite recursion. Prevents unnecessary user_load()s from RDF.
-rw-r--r-- | includes/common.inc | 40 | ||||
-rw-r--r-- | modules/comment/comment.module | 2 | ||||
-rw-r--r-- | modules/node/node.module | 2 | ||||
-rw-r--r-- | modules/rdf/rdf.module | 19 | ||||
-rw-r--r-- | modules/system/system.api.php | 22 | ||||
-rw-r--r-- | modules/taxonomy/taxonomy.pages.inc | 1 | ||||
-rw-r--r-- | modules/user/user.module | 1 |
7 files changed, 87 insertions, 0 deletions
diff --git a/includes/common.inc b/includes/common.inc index 112b3bc5b..8d5f637d3 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -6485,6 +6485,46 @@ function entity_get_controller($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). * * @param $url diff --git a/modules/comment/comment.module b/modules/comment/comment.module index 1f24e44eb..3bbc3d991 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -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, diff --git a/modules/node/node.module b/modules/node/node.module index b56199455..32b107abe 100644 --- a/modules/node/node.module +++ b/modules/node/node.module @@ -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); diff --git a/modules/rdf/rdf.module b/modules/rdf/rdf.module index c25ae9323..31f3e2821 100644 --- a/modules/rdf/rdf.module +++ b/modules/rdf/rdf.module @@ -595,6 +595,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. * * This is called by rdf_process() shortly before the theme system renders diff --git a/modules/system/system.api.php b/modules/system/system.api.php index f78556c4c..f8f20b8cc 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -264,6 +264,28 @@ function hook_admin_paths_alter(&$paths) { } /** + * 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. * * This hook will only be called if cron.php is run (e.g. by crontab). diff --git a/modules/taxonomy/taxonomy.pages.inc b/modules/taxonomy/taxonomy.pages.inc index e4987e52b..712e8bc75 100644 --- a/modules/taxonomy/taxonomy.pages.inc +++ b/modules/taxonomy/taxonomy.pages.inc @@ -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( diff --git a/modules/user/user.module b/modules/user/user.module index 8db32ccd6..313ff34a4 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -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. |