commit 83dc60b9d288d64fe69247a44814e50887f9dd8f
Author: Andreas Kohlbecker <a.kohlbecker@bgbm.org>
Date:   Mon Sep 3 18:44:48 2018 +0200

    ref #7658 adapting cdm_taxonRelationships() to new taxon relationship DTO webservice
     - test case
     - extending tagged text functions
     - adapting misapplied name redering

diff --git a/modules/cdm_dataportal/cdm_api/cdm_api.module b/modules/cdm_dataportal/cdm_api/cdm_api.module
index 2535554e..78e1e473 100644
--- a/modules/cdm_dataportal/cdm_api/cdm_api.module
+++ b/modules/cdm_dataportal/cdm_api/cdm_api.module
@@ -192,10 +192,17 @@ function cdm_api_cron() {
 
 // ===================== Tagged Text functions ================== //
 
+function tagged_text_new($tag_type, $text = null){
+  $tt = new stdClass();
+  $tt->type = $tag_type;
+  $tt->text = $text;
+  return $tt;
+}
+
 /**
  * Walks the passed TaggedText array to find all elements which have a
  * TaggedText->entityReference. For each of these the taggedTexts is loaded
- * from the webservice and the original enty in the TaggedText array will be
+ * from the webservice and the original entry in the TaggedText array will be
  * replaced by the newly loaded array.
  *
  * @param array $taggedtxt
@@ -234,13 +241,17 @@ function cdm_tagged_text_expand_entity_references(array $taggedtxt, $skiptags =
  * Each item is provided with a class attribute which is set to the key of the
  * TaggedText item.
  *
+ * Tagged text where the type starts with 'PLACEHOLDER_' will be added to the markup as plain text whereas the
+ * taggedText->type wrapped in curly brackets: '{'. $tt->text . '}' is used as text.
+ * see tagged_text_extract_secref()
+ *
  * @param array $taggedtxt
  *   Array with text items to convert.
  * @param array $skiptags
  *   Array of tag names to skip
  *
  * @return string
- *   A string with HTML.
+ *   The markup.
  */
 function cdm_tagged_text_to_markup(array $taggedtxt, $skiptags = array()) {
 
@@ -258,10 +269,46 @@ function cdm_tagged_text_to_markup(array $taggedtxt, $skiptags = array()) {
       $is_last = $i + 1 == count($taggedtxt);
       $is_separator = is_tagged_text_sepatator_type($tt->type);
       $glue = !$is_separator && !$was_separator && !$is_last ? ' ' : '';
-      $out .= '<' . $tag . ' class="' . $class_attr . '">'
-        . t('@text', array('@text' => $tt->text))
-        . '</' . $tag . '>'
-        . $glue;
+      if(str_beginsWith($tt->type, 'PLACEHOLDER_')){
+        $out .=  '{'. $tt->type . '}';
+      } else {
+        $out .= '<' . $tag . ' class="' . $class_attr . '">'
+          . t('@text', array('@text' => $tt->text))
+          . '</' . $tag . '>'
+          . $glue;
+        }
+      $was_separator = $is_separator;
+    }
+    $i++;
+  }
+  return $out;
+}
+
+/**
+ * Converts an array of TaggedText items into corresponding plain text string
+ *
+ * Each item is provided with a class attribute which is set to the key of the
+ * TaggedText item.
+ *
+ * @param array $taggedtxt
+ *   Array with text items to convert.
+ * @param array $skiptags
+ *   Array of tag names to skip
+ *
+ * @return string
+ *   The plain text
+ */
+function cdm_tagged_text_to_string(array $taggedtxt, $skiptags = array()) {
+
+  $out = '';
+  $was_separator = false;
+  $i = 0;
+  foreach ($taggedtxt as $tt) {
+    if (!in_array($tt->type, $skiptags) && $tt->text) {
+      $is_last = $i + 1 == count($taggedtxt);
+      $is_separator = is_tagged_text_sepatator_type($tt->type);
+      $glue = !$is_separator && !$was_separator && !$is_last ? ' ' : '';
+      $out .= t('@text', array('@text' => $tt->text)) . $glue;
       $was_separator = $is_separator;
     }
     $i++;
@@ -351,30 +398,50 @@ function normalize_tagged_text(&$taggedTextList) {
   }
 }
 
-function split_secref_from_tagged_text(&$tagged_text) {
+/**
+ * Extracts the tagged text for sec references with separator and citation detail from a tagged text array.
+ * @param $tagged_text
+ *    The tagged text to operate on
+ * @param string $ref_tag_type
+ *    The tagtype for a secreference is "secReference", but "relSecReference" is also used in case of relationships.
+ * @param bool $replace_with_placeholder
+ *    Indicates the method to add a empty placeholder tagged text alement as relpacement for the extrated tagged text
+ *    elements.
+ * @return array
+ */
+function tagged_text_extract_secref(&$tagged_text, $ref_tag_type = "secReference", $replace_with_placeholder = false) {
 
   $extracted_tt = array();
   if (is_array($tagged_text)) {
+    $extract_pos = null;
     for ($i = 0; $i < count($tagged_text) - 1; $i++) {
-      if ($tagged_text[$i + 1]->type == "secReference" && $tagged_text[$i]->type == "separator"){
+      if ($tagged_text[$i + 1]->type == $ref_tag_type && $tagged_text[$i]->type == "separator"){
         $extracted_tt[0] = $tagged_text[$i];
         $extracted_tt[1] = $tagged_text[$i + 1];
-        unset($tagged_text[$i]);
+
+        if($replace_with_placeholder){
+          // text must not be null, see cdm_tagged_text_to_markup()
+          $tagged_text[$i] = tagged_text_new("PLACEHOLDER_" . $ref_tag_type, "PLACEHOLDER_" . $ref_tag_type);
+        } else {
+          unset($tagged_text[$i]);
+        }
         unset($tagged_text[$i + 1]);
-        // also get the microfererence which could be in $tagged_text[$i + 3]
-        if(isset($tagged_text[$i + 3])  && $tagged_text[$i + 2]->type == "separator" && $tagged_text[$i + 3]->type == "secReference"){
+        // also get the microreference which could be in $tagged_text[$i + 3]
+        if(isset($tagged_text[$i + 3])  && $tagged_text[$i + 2]->type == "separator" && $tagged_text[$i + 3]->type == $ref_tag_type){
           $extracted_tt[2] = $tagged_text[$i + 2];
           $extracted_tt[3] = $tagged_text[$i + 3];
+          unset($tagged_text[$i + 2]);
+          unset($tagged_text[$i + 3]);
         }
         break;
       }
     }
   }
+  $tagged_text = array_values($tagged_text); // re-index array to make it continuous again
   return $extracted_tt;
 }
 
-
-function split_nomstatus_from_tagged_text(&$tagged_text) {
+function tagged_text_extract_nomstatus(&$tagged_text) {
 
   $extracted_tt = array();
   if (is_array($tagged_text)) {
