summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Rothstein <drothstein@gmail.com>2014-11-01 17:31:26 -0400
committerDavid Rothstein <drothstein@gmail.com>2014-11-01 17:31:26 -0400
commitc312e5ee5589d060601f633deba3be26df494815 (patch)
tree0db9e745cdbefcec1cb9d6453669139901bf9546
parent5aede0dadeb785ca30f5e16c6d67281286a047ee (diff)
downloadbrdo-c312e5ee5589d060601f633deba3be26df494815.tar.gz
brdo-c312e5ee5589d060601f633deba3be26df494815.tar.bz2
Issue #1968348 by znerol, David_Rothstein, peximo, DuaelFr: Fixed hook_field_formatter_prepare_view does not make use of hook_entity_view_mode_alter causing major errors.
-rw-r--r--CHANGELOG.txt3
-rw-r--r--includes/common.inc50
-rw-r--r--modules/comment/comment.module28
-rw-r--r--modules/node/node.module24
-rw-r--r--modules/node/node.test43
-rw-r--r--modules/taxonomy/taxonomy.module24
-rw-r--r--modules/user/user.module7
7 files changed, 141 insertions, 38 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 97a04b3f6..47d51ced1 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,9 @@
Drupal 7.33, xxxx-xx-xx (development version)
-----------------------
+- Added an entity_view_mode_prepare() API function to allow entity-defining
+ modules to properly invoke hook_entity_view_mode_alter(), and used it
+ throughout Drupal core to fix bugs with the invocation of that hook.
- Security improvement: Made the database API's orderBy() method sanitize the
sort direction ("ASC" or "DESC") for queries built with db_select(), so that
calling code does not have to.
diff --git a/includes/common.inc b/includes/common.inc
index 63b691e48..84c5bfa89 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -7899,6 +7899,56 @@ function entity_prepare_view($entity_type, $entities, $langcode = NULL) {
}
/**
+ * Invoke hook_entity_view_mode_alter().
+ *
+ * If adding a new entity similar to nodes, comments or users, you should invoke
+ * this function during the ENTITY_build_content() or ENTITY_view_multiple()
+ * phases of rendering to allow other modules to alter the view mode during this
+ * phase. This function needs to be called before field_attach_prepare_view() to
+ * ensure that the correct content is loaded by field API.
+ *
+ * @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.
+ * @param $view_mode
+ * The original view mode e.g. 'full', 'teaser'...
+ * @param $langcode
+ * (optional) A language code to be used for rendering. Defaults to the global
+ * content language of the current request.
+ * @return
+ * An associative array with arrays of entities keyed by view mode.
+ *
+ * @see hook_entity_view_mode_alter()
+ */
+function entity_view_mode_prepare($entity_type, $entities, $view_mode, $langcode = NULL) {
+ if (!isset($langcode)) {
+ $langcode = $GLOBALS['language_content']->language;
+ }
+
+ // To ensure hooks are never run after field_attach_prepare_view() only
+ // process items without the entity_view_prepared flag.
+ $entities_by_view_mode = array();
+ foreach ($entities as $id => $entity) {
+ $entity_view_mode = $view_mode;
+ if (empty($entity->entity_view_prepared)) {
+
+ // Allow modules to change the view mode.
+ $context = array(
+ 'entity_type' => $entity_type,
+ 'entity' => $entity,
+ 'langcode' => $langcode,
+ );
+ drupal_alter('entity_view_mode', $entity_view_mode, $context);
+ }
+
+ $entities_by_view_mode[$entity_view_mode][$id] = $entity;
+ }
+
+ return $entities_by_view_mode;
+}
+
+/**
* Returns the URI elements of an entity.
*
* @param $entity_type
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 3c942002c..2972474c0 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -993,12 +993,7 @@ function comment_build_content($comment, $node, $view_mode = 'full', $langcode =
$comment->content = array();
// Allow modules to change the view mode.
- $context = array(
- 'entity_type' => 'comment',
- 'entity' => $comment,
- 'langcode' => $langcode,
- );
- drupal_alter('entity_view_mode', $view_mode, $context);
+ $view_mode = key(entity_view_mode_prepare('comment', array($comment->cid => $comment), $view_mode, $langcode));
// Build fields content.
field_attach_prepare_view('comment', array($comment->cid => $comment), $view_mode, $langcode);
@@ -1108,17 +1103,26 @@ function comment_links($comment, $node) {
* An array in the format expected by drupal_render().
*/
function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0, $langcode = NULL) {
- field_attach_prepare_view('comment', $comments, $view_mode, $langcode);
- entity_prepare_view('comment', $comments, $langcode);
+ $build = array();
+ $entities_by_view_mode = entity_view_mode_prepare('comment', $comments, $view_mode, $langcode);
+ foreach ($entities_by_view_mode as $entity_view_mode => $entities) {
+ field_attach_prepare_view('comment', $entities, $entity_view_mode, $langcode);
+ entity_prepare_view('comment', $entities, $langcode);
+
+ foreach ($entities as $entity) {
+ $build[$entity->cid] = comment_view($entity, $node, $entity_view_mode, $langcode);
+ }
+ }
- $build = array(
- '#sorted' => TRUE,
- );
foreach ($comments as $comment) {
- $build[$comment->cid] = comment_view($comment, $node, $view_mode, $langcode);
$build[$comment->cid]['#weight'] = $weight;
$weight++;
}
+ // Sort here, to preserve the input order of the entities that were passed to
+ // this function.
+ uasort($build, 'element_sort');
+ $build['#sorted'] = TRUE;
+
return $build;
}
diff --git a/modules/node/node.module b/modules/node/node.module
index acca83ecb..e5b716630 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1397,12 +1397,7 @@ function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
$node->content = array();
// Allow modules to change the view mode.
- $context = array(
- 'entity_type' => 'node',
- 'entity' => $node,
- 'langcode' => $langcode,
- );
- drupal_alter('entity_view_mode', $view_mode, $context);
+ $view_mode = key(entity_view_mode_prepare('node', array($node->nid => $node), $view_mode, $langcode));
// The 'view' hook can be implemented to overwrite the default function
// to display nodes.
@@ -2664,15 +2659,26 @@ function node_feed($nids = FALSE, $channel = array()) {
* An array in the format expected by drupal_render().
*/
function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
- field_attach_prepare_view('node', $nodes, $view_mode, $langcode);
- entity_prepare_view('node', $nodes, $langcode);
$build = array();
+ $entities_by_view_mode = entity_view_mode_prepare('node', $nodes, $view_mode, $langcode);
+ foreach ($entities_by_view_mode as $entity_view_mode => $entities) {
+ field_attach_prepare_view('node', $entities, $entity_view_mode, $langcode);
+ entity_prepare_view('node', $entities, $langcode);
+
+ foreach ($entities as $entity) {
+ $build['nodes'][$entity->nid] = node_view($entity, $entity_view_mode, $langcode);
+ }
+ }
+
foreach ($nodes as $node) {
- $build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
$build['nodes'][$node->nid]['#weight'] = $weight;
$weight++;
}
+ // Sort here, to preserve the input order of the entities that were passed to
+ // this function.
+ uasort($build['nodes'], 'element_sort');
$build['nodes']['#sorted'] = TRUE;
+
return $build;
}
diff --git a/modules/node/node.test b/modules/node/node.test
index 0777e1137..5c9118ebb 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -2782,8 +2782,8 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
$edit = array();
$langcode = LANGUAGE_NONE;
$edit["title"] = $this->randomName(8);
- $edit["body[$langcode][0][value]"] = t('Data that should appear only in the body for the node.');
- $edit["body[$langcode][0][summary]"] = t('Extra data that should appear only in the teaser for the node.');
+ $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
+ $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
$this->drupalPost('node/add/page', $edit, t('Save'));
$node = $this->drupalGetNodeByTitle($edit["title"]);
@@ -2801,6 +2801,45 @@ class NodeEntityViewModeAlterTest extends NodeWebTestCase {
$build = node_view($node);
$this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
}
+
+ /**
+ * Tests fields that were previously hidden when the view mode is changed.
+ */
+ function testNodeViewModeChangeHiddenField() {
+ // Hide the tags field on the default display
+ $instance = field_info_instance('node', 'field_tags', 'article');
+ $instance['display']['default']['type'] = 'hidden';
+ field_update_instance($instance);
+
+ $web_user = $this->drupalCreateUser(array('create article content', 'edit own article content'));
+ $this->drupalLogin($web_user);
+
+ // Create a node.
+ $edit = array();
+ $langcode = LANGUAGE_NONE;
+ $edit["title"] = $this->randomName(8);
+ $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
+ $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
+ $edit["field_tags[$langcode]"] = 'Extra tag';
+ $this->drupalPost('node/add/article', $edit, t('Save'));
+
+ $node = $this->drupalGetNodeByTitle($edit["title"]);
+
+ // Set the flag to alter the view mode and view the node.
+ variable_set('node_test_change_view_mode', 'teaser');
+ $this->drupalGet('node/' . $node->nid);
+
+ // Check that teaser mode is viewed.
+ $this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
+ // Make sure body text is not present.
+ $this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
+ // Make sure tags are present.
+ $this->assertText('Extra tag', 'Taxonomy term present');
+
+ // Test that the correct build mode has been set.
+ $build = node_view($node);
+ $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
+ }
}
/**
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 4191146a4..e147c1cab 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -776,15 +776,26 @@ function taxonomy_term_show($term) {
* An array in the format expected by drupal_render().
*/
function taxonomy_term_view_multiple($terms, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
- field_attach_prepare_view('taxonomy_term', $terms, $view_mode, $langcode);
- entity_prepare_view('taxonomy_term', $terms, $langcode);
$build = array();
+ $entities_by_view_mode = entity_view_mode_prepare('taxonomy_term', $terms, $view_mode, $langcode);
+ foreach ($entities_by_view_mode as $entity_view_mode => $entities) {
+ field_attach_prepare_view('taxonomy_term', $entities, $entity_view_mode, $langcode);
+ entity_prepare_view('taxonomy_term', $entities, $langcode);
+
+ foreach ($entities as $entity) {
+ $build['taxonomy_terms'][$entity->tid] = taxonomy_term_view($entity, $entity_view_mode, $langcode);
+ }
+ }
+
foreach ($terms as $term) {
- $build['taxonomy_terms'][$term->tid] = taxonomy_term_view($term, $view_mode, $langcode);
$build['taxonomy_terms'][$term->tid]['#weight'] = $weight;
$weight++;
}
+ // Sort here, to preserve the input order of the entities that were passed to
+ // this function.
+ uasort($build['taxonomy_terms'], 'element_sort');
$build['taxonomy_terms']['#sorted'] = TRUE;
+
return $build;
}
@@ -817,12 +828,7 @@ function taxonomy_term_build_content($term, $view_mode = 'full', $langcode = NUL
$term->content = array();
// Allow modules to change the view mode.
- $context = array(
- 'entity_type' => 'taxonomy_term',
- 'entity' => $term,
- 'langcode' => $langcode,
- );
- drupal_alter('entity_view_mode', $view_mode, $context);
+ $view_mode = key(entity_view_mode_prepare('taxonomy_term', array($term->tid => $term), $view_mode, $langcode));
// Add the term description if the term has one and it is visible.
$type = 'taxonomy_term';
diff --git a/modules/user/user.module b/modules/user/user.module
index b23979937..89d99da73 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -2633,12 +2633,7 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
$account->content = array();
// Allow modules to change the view mode.
- $context = array(
- 'entity_type' => 'user',
- 'entity' => $account,
- 'langcode' => $langcode,
- );
- drupal_alter('entity_view_mode', $view_mode, $context);
+ $view_mode = key(entity_view_mode_prepare('user', array($account->uid => $account), $view_mode, $langcode));
// Build fields content.
field_attach_prepare_view('user', array($account->uid => $account), $view_mode, $langcode);