Issue #1067120 by BTMash, DamienMcKenna, corvus_ch, valthebald, mrfelton, fgm, Dave...
authorwebchick
Sat, 6 Oct 2012 17:26:39 +0000 (10:26 -0700)
committerwebchick
Sat, 6 Oct 2012 17:26:39 +0000 (10:26 -0700)
modules/simpletest/tests/taxonomy_test.module
modules/taxonomy/taxonomy.api.php
modules/taxonomy/taxonomy.module
modules/taxonomy/taxonomy.pages.inc
modules/taxonomy/taxonomy.test

index aae13a2..f82950c 100644 (file)
@@ -3,6 +3,8 @@
 /**
  * @file
  * Test module for Taxonomy hooks and functions not used in core.
+ *
+ * @see TaxonomyHooksTestCase::testTaxonomyTermHooks()
  */
 
 /**
@@ -55,6 +57,34 @@ function taxonomy_test_taxonomy_term_delete($term) {
 }
 
 /**
+ * Implements hook_taxonomy_term_view().
+ */
+function taxonomy_test_taxonomy_term_view($term, $view_mode, $langcode) {
+  if ($view_mode == 'full') {
+    $term->content['taxonomy_test_term_view_check'] = array(
+      '#prefix' => '<div>',
+      '#markup' => t('The antonym is %antonym', array('%antonym' => $term->antonym)),
+      '#suffix' => '</div>',
+      '#weight' => 10,
+    );
+  }
+}
+
+/**
+ * Implements hook_entity_view().
+ */
+function taxonomy_test_entity_view($entity, $type, $view_mode, $langcode) {
+  if ($type == 'taxonomy_term' && $view_mode == 'full') {
+    $entity->content['taxonomy_test_entity_view_check'] = array(
+      '#prefix' => '<div>',
+      '#markup' => t('The antonym is %antonym', array('%antonym' => $entity->antonym)),
+      '#suffix' => '</div>',
+      '#weight' => 20,
+    );
+  }
+}
+
+/**
  * Implements hook_form_alter().
  */
 function taxonomy_test_form_alter(&$form, $form_state, $form_id) {
index cb778c9..10575c5 100644 (file)
@@ -182,6 +182,30 @@ function hook_taxonomy_term_delete($term) {
 }
 
 /**
+ * Act on a taxonomy term that is being assembled before rendering.
+ *
+ * The module may add elements to $term->content prior to rendering. This hook
+ * will be called after hook_view(). The structure of $term->content is a
+ * renderable array as expected by drupal_render().
+ *
+ * @param $term
+ *   The term that is being assembled for rendering.
+ * @param $view_mode
+ *   The $view_mode parameter from taxonomy_term_view().
+ * @param $langcode
+ *   The language code used for rendering.
+ *
+ * @see hook_entity_view()
+ */
+function hook_taxonomy_term_view($term, $view_mode, $langcode) {
+  $term->content['my_additional_field'] = array(
+    '#markup' => $additional_field,
+    '#weight' => 10,
+    '#theme' => 'mymodule_my_additional_field',
+  );
+}
+
+/**
  * Alter the results of taxonomy_term_view().
  *
  * This hook is called after the content has been assembled in a structured
index 07d01d3..dc3cf44 100644 (file)
@@ -743,6 +743,102 @@ function taxonomy_term_delete($tid) {
 }
 
 /**
+ * Generates an array which displays a term detail page.
+ *
+ * @param term
+ *   A taxonomy term object.
+ * @return
+ *   A $page element suitable for use by drupal_page_render().
+ */
+function taxonomy_term_show($term) {
+  return taxonomy_term_view_multiple(array($term->tid => $term), 'full');
+}
+
+/**
+ * Constructs a drupal_render() style array from an array of loaded terms.
+ *
+ * @param $terms
+ *   An array of taxonomy terms as returned by taxonomy_term_load_multiple().
+ * @param $view_mode
+ *   View mode, e.g. 'full', 'teaser'...
+ * @param $weight
+ *   An integer representing the weight of the first node in the list.
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
+ *
+ * @return
+ *   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();
+  foreach ($terms as $term) {
+    $build['taxonomy_terms'][$term->tid] = taxonomy_term_view($term, $view_mode, $langcode);
+    $build['taxonomy_terms'][$term->tid]['#weight'] = $weight;
+    $weight++;
+  }
+  $build['taxonomy_terms']['#sorted'] = TRUE;
+  return $build;
+}
+
+/**
+ * Builds a structured array representing the term's content.
+ *
+ * The content built for the taxonomy term (field values, file attachments or
+ * other term components) will vary depending on the $view_mode parameter.
+ *
+ * Drupal core defines the following view modes for terms, with the following
+ * default use cases:
+ *   - full (default): term is displayed on its own page (taxonomy/term/123)
+ * Contributed modules might define additional view modes, or use existing
+ * view modes in additional contexts.
+ *
+ * @param $term
+ *   A taxonomy term object.
+ * @param $view_mode
+ *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
+ */
+function taxonomy_term_build_content($term, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
+  // Remove previously built content, if exists.
+  $term->content = array();
+
+  // Try to add in the core taxonomy pieces like description and nodes.
+  $type = 'taxonomy_term';
+  $entity_ids = entity_extract_ids($type, $term);
+  $settings = field_view_mode_settings($type, $entity_ids[2]);
+  $fields = field_extra_fields_get_display($type, $entity_ids[2], $view_mode);
+  if (!empty($term->description) && isset($fields['description']) && $fields['description']['visible']) {
+    $term->content['description'] = array(
+      '#markup' => check_markup($term->description, $term->format, '', TRUE),
+      '#weight' => $fields['description']['weight'],
+      '#prefix' => '<div class="taxonomy-term-description">',
+      '#suffix' => '</div>',
+    );
+  }
+
+  // Build fields content.
+  // In case of a multiple view, taxonomy_term_view_multiple() already ran the
+  // 'prepare_view' step. An internal flag prevents the operation from running
+  // twice.
+  field_attach_prepare_view('taxonomy_term', array($term->tid => $term), $view_mode, $langcode);
+  entity_prepare_view('taxonomy_term', array($term->tid => $term), $langcode);
+  $term->content += field_attach_view('taxonomy_term', $term, $view_mode, $langcode);
+
+  // Allow modules to make their own additions to the taxonomy term.
+  module_invoke_all('taxonomy_term_view', $term, $view_mode, $langcode);
+  module_invoke_all('entity_view', $term, 'taxonomy_term', $view_mode, $langcode);
+}
+
+/**
  * Generate an array for rendering the given term.
  *
  * @param $term
@@ -769,31 +865,23 @@ function taxonomy_term_view($term, $view_mode = 'full', $langcode = NULL) {
   );
   drupal_alter('entity_view_mode', $view_mode, $context);
 
-  field_attach_prepare_view('taxonomy_term', array($term->tid => $term), $view_mode, $langcode);
-  entity_prepare_view('taxonomy_term', array($term->tid => $term), $langcode);
+  // Populate $node->content with a render() array.
+  taxonomy_term_build_content($term, $view_mode, $langcode);
+  $build = $term->content;
+
+  // We don't need duplicate rendering info in $term->content.
+  unset($term->content);
 
-  $build = array(
+  $build += array(
     '#theme' => 'taxonomy_term',
     '#term' => $term,
     '#view_mode' => $view_mode,
     '#language' => $langcode,
   );
 
-  $build += field_attach_view('taxonomy_term', $term, $view_mode, $langcode);
-
-  // Add term description if the term has one.
-  if (!empty($term->description)) {
-    $build['description'] = array(
-      '#markup' => check_markup($term->description, $term->format, '', TRUE),
-      '#weight' => 0,
-      '#prefix' => '<div class="taxonomy-term-description">',
-      '#suffix' => '</div>',
-    );
-  }
-
   $build['#attached']['css'][] = drupal_get_path('module', 'taxonomy') . '/taxonomy.css';
 
-  // Allow modules to modify the structured term.
+  // Allow modules to modify the structured taxonomy term.
   $type = 'taxonomy_term';
   drupal_alter(array('taxonomy_term_view', 'entity_view'), $build, $type);
 
index 501ebbe..4d2c4e6 100644 (file)
@@ -33,21 +33,24 @@ function taxonomy_term_page($term) {
   drupal_set_breadcrumb($breadcrumb);
   drupal_add_feed('taxonomy/term/' . $term->tid . '/feed', 'RSS - ' . $term->name);
 
-  $build = array();
+  // If there is a menu link to this term, the link becomes the last part of
+  // the active trail, and the link name becomes the page title. Thus, we must
+  // explicitly set the page title to be the node title.
+  $uri = entity_uri('taxonomy_term', $term);
 
-  $build['term_heading'] = array(
-    '#prefix' => '<div class="term-listing-heading">',
-    '#suffix' => '</div>',
-    'term' => taxonomy_term_view($term, 'full'),
-  );
+  // Set the term path as the canonical URL to prevent duplicate content.
+  drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
+  // Set the non-aliased path as a default shortlink.
+  drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
 
+  $build = taxonomy_term_show($term);
   if ($nids = taxonomy_select_nodes($term->tid, TRUE, variable_get('default_nodes_main', 10))) {
     $nodes = node_load_multiple($nids);
     $build += node_view_multiple($nodes);
     $build['pager'] = array(
       '#theme' => 'pager',
       '#weight' => 5,
-     );
+    );
   }
   else {
     $build['no_content'] = array(
index 2a7f36b..4cfb81b 100644 (file)
@@ -1390,12 +1390,16 @@ class TaxonomyHooksTestCase extends TaxonomyWebTestCase {
 
   function setUp() {
     parent::setUp('taxonomy', 'taxonomy_test');
+    module_load_include('inc', 'taxonomy', 'taxonomy.pages');
     $taxonomy_admin = $this->drupalCreateUser(array('administer taxonomy'));
     $this->drupalLogin($taxonomy_admin);
   }
 
   /**
-   * Test that hooks are run correctly on creating, editing and deleting a term.
+   * Test that hooks are run correctly on creating, editing, viewing,
+   * and deleting a term.
+   *
+   * @see taxonomy_test.module
    */
   function testTaxonomyTermHooks() {
     $vocabulary = $this->createVocabulary();
@@ -1420,6 +1424,13 @@ class TaxonomyHooksTestCase extends TaxonomyWebTestCase {
     $term = taxonomy_term_load($term->tid);
     $this->assertEqual($edit['antonym'], $term->antonym, 'Antonym was successfully edited.');
 
+    // View the term and ensure that hook_taxonomy_term_view() and
+    // hook_entity_view() are invoked.
+    $term = taxonomy_term_load($term->tid);
+    $term_build = taxonomy_term_page($term);
+    $this->assertFalse(empty($term_build['taxonomy_terms'][$term->tid]['taxonomy_test_term_view_check']), 'hook_taxonomy_term_view() was invoked when viewing the term.');
+    $this->assertFalse(empty($term_build['taxonomy_terms'][$term->tid]['taxonomy_test_entity_view_check']), 'hook_entity_view() was invoked when viewing the term.');
+
     // Delete the term.
     taxonomy_term_delete($term->tid);
     $antonym = db_query('SELECT tid FROM {taxonomy_term_antonym} WHERE tid = :tid', array(':tid' => $term->tid))->fetchField();