Project

General

Profile

Download (75.6 KB) Statistics
| Branch: | Tag: | Revision:
1 2fd6da0b Andreas Kohlbecker
<?php
2
/**
3
 * @file
4
 * Functions for dealing with CDM entities from the package model.name
5
 *
6
 * @copyright
7
 *   (C) 2007-2015 EDIT
8
 *   European Distributed Institute of Taxonomy
9
 *   http://www.e-taxonomy.eu
10
 *
11
 *   The contents of this module are subject to the Mozilla
12
 *   Public License Version 1.1.
13
 * @see http://www.mozilla.org/MPL/MPL-1.1.html
14
 *
15
 * @author
16
 *   - Andreas Kohlbecker <a.kohlbecker@BGBM.org>
17
 */
18
19
/**
20
 * @defgroup compose Compose functions
21
 * @{
22
 * Functions which are composing Drupal render arays
23
 *
24
 * The cdm_dataportal module needs to compose rather complex render arrays from
25
 * the data returned by the CDM REST service. The compose functions are
26
 * responsible for creating the render arrays.
27
 *
28
 * All these functions are also implementations of the compose_hook()
29
 * which is used in the proxy_content() function.
30
 * @}
31
 */
32
33
34
/**
35
 * Provides the name render template to be used within the page elements identified the the $renderPath.
36
 *
37 a565e612 Andreas Kohlbecker
 * The render templates arrays contains one or more name render templates to be used within the page elements identified the the
38 2fd6da0b Andreas Kohlbecker
 * renderPath. The renderPath is the key of the subelements whereas the value is the name render template.
39
 *
40 a565e612 Andreas Kohlbecker
 * The render paths used for a cdm_dataportal page can be visualized by supplying the HTTP query parameter RENDER_PATH=1.
41
 *
42
 * It will be tried to find  the best matching default RenderTemplate by stripping the dot separated render path
43
 * element by element. If no matching template is found the DEFAULT will be used:
44
 *
45
 * - related_taxon.heterotypicSynonymyGroup.taxon_page_synonymy
46
 * - related_taxon.heterotypicSynonymyGroup.taxon_page_synonymy
47
 * - related_taxon.heterotypicSynonymyGroup.taxon_page_synonymy
48 2fd6da0b Andreas Kohlbecker
 *
49
 * A single render template can be used for multiple render paths. In this case the according key of the render templates
50
 * array element should be the list of these render paths concatenated by ONLY a comma character without any whitespace.
51
 *
52
 * A render template is an associative array. The keys of this array are referring to the keys as defined in the part
53
 * definitions array.
54
 * @see get_partDefinition($taxonNameType) for more information
55
 *
56
 * The value of the render template element must be set to TRUE in order to let this part being rendered.
57
 * The namePart, nameAuthorPart and referencePart can also hold an associative array with a single
58
 * element: array('#uri' => TRUE). The value of the #uri element will be replaced by the according
59
 * links if the parameters $nameLink or $refenceLink are set.
60
 *
61 a565e612 Andreas Kohlbecker
 * @param string $render_path
62 2fd6da0b Andreas Kohlbecker
 *   The render path can consist of multiple dot separated elements
63
 *   @see RenderHints::getRenderPath()
64
 * @param string $nameLink
65 87aa88d6 Andreas Kohlbecker
 *   The link path or URL to be used for name parts if a link is forseen in the template
66 2fd6da0b Andreas Kohlbecker
 *   matching the given $renderPath.
67
 * @param string $referenceLink
68
 *   The link path ot URL to be used for nomenclatural reference parts if a link is forseen
69
 *   in the template matching the given $renderPath.
70
 * @return array
71
 *   An associative array, the render template
72
 */
73 a565e612 Andreas Kohlbecker
function get_nameRenderTemplate($render_path, $nameLink = NULL, $referenceLink = NULL) {
74 2fd6da0b Andreas Kohlbecker
75
  static $default_render_templates = NULL;
76 03f4f6f7 Andreas Kohlbecker
  static $split_render_templates = NULL;
77
78
79 2fd6da0b Andreas Kohlbecker
  if (!isset($default_render_templates)) {
80
    $default_render_templates = unserialize(CDM_NAME_RENDER_TEMPLATES_DEFAULT);
81
  }
82 03f4f6f7 Andreas Kohlbecker
  if($split_render_templates == NULL) {
83 2fd6da0b Andreas Kohlbecker
    $render_templates = variable_get(CDM_NAME_RENDER_TEMPLATES, $default_render_templates);
84
    // needs to be converted to an array
85 db725031 Andreas Kohlbecker
    $render_templates = (object_to_array($render_templates));
86 03f4f6f7 Andreas Kohlbecker
87
    // separate render templates which are combined with a comma
88
    $split_render_templates = array();
89
    foreach($render_templates as $key => $template){
90
      if(strpos($key, ',')){
91
        foreach(explode(',', $key) as $path){
92
          $split_render_templates[$path] = $template;
93
        }
94
      } else {
95
        $split_render_templates[$key] = $template;
96
      }
97
    }
98 2fd6da0b Andreas Kohlbecker
  }
99
100
  // get the base element of the renderPath
101 a565e612 Andreas Kohlbecker
  if (($separatorPos = strpos($render_path, '.')) > 0) {
102
    $renderPath_base = substr($render_path, 0, $separatorPos);
103 2fd6da0b Andreas Kohlbecker
  } else {
104 a565e612 Andreas Kohlbecker
    $renderPath_base = $render_path;
105 2fd6da0b Andreas Kohlbecker
  }
106
107 03f4f6f7 Andreas Kohlbecker
  $template = NULL;
108 2fd6da0b Andreas Kohlbecker
  // 1. try to find a template using the render path base element
109 03f4f6f7 Andreas Kohlbecker
  if(array_key_exists($renderPath_base, $split_render_templates)){
110
    $template = (array)$split_render_templates[$renderPath_base];
111 2fd6da0b Andreas Kohlbecker
  }
112
113 a565e612 Andreas Kohlbecker
  // 2. Find best matching default RenderTemplate
114 2fd6da0b Andreas Kohlbecker
  // by stripping the dot separated render path element by element
115 a565e612 Andreas Kohlbecker
  // if no matching template is found the DEFAULT will be used.
116
  while (!is_array($template) && strlen($render_path) > 0) {
117 03f4f6f7 Andreas Kohlbecker
    foreach ($split_render_templates as $path => $t) {
118 a565e612 Andreas Kohlbecker
      if ($path == $render_path) {
119 2fd6da0b Andreas Kohlbecker
        $template = $t;
120
        break;
121
      }
122
    }
123
    // shorten by one element
124 a565e612 Andreas Kohlbecker
    $render_path = substr($render_path, strrpos($render_path, '.') + 1, strlen($render_path));
125 2fd6da0b Andreas Kohlbecker
  }
126
127 03f4f6f7 Andreas Kohlbecker
128 2fd6da0b Andreas Kohlbecker
  // 3. Otherwise get default RenderTemplate from theme.
129
  if (!is_array($template)) {
130 03f4f6f7 Andreas Kohlbecker
    $template = $split_render_templates['#DEFAULT'];
131 2fd6da0b Andreas Kohlbecker
  }
132
133
  // --- set the link uris to the according template fields if they exist
134
  if(isset($template['nameAuthorPart']) && isset($template['nameAuthorPart']['#uri'])) {
135
    if ($nameLink) {
136
      $template['nameAuthorPart']['#uri'] = $nameLink;
137
    }
138
    else {
139
      unset($template['nameAuthorPart']['#uri']);
140
    }
141
  }
142
143
  if ($nameLink && isset($template['namePart']['#uri'])) {
144
    $template['namePart']['#uri'] = $nameLink;
145
  }
146
  else {
147
    unset($template['namePart']['#uri']);
148
  }
149
150
  if ($referenceLink && isset($template['referencePart']['#uri'])) {
151
    $template['referencePart']['#uri'] = $referenceLink;
152
  }
153
  else {
154
    unset($template['referencePart']['#uri']);
155
  }
156
157
  return $template;
158
}
159
160
/**
161
 * The part definitions define the specific parts of which a rendered taxon name plus additional information will consist.
162
 *
163
 * A full taxon name plus additional information can consist of the following elements:
164
 *
165
 *   - name: the taxon name inclugin rank nbut without author
166
 *   - authorTeam:  The authors of a reference, also used in taxon names
167
 *   - authors:  The authors of a reference, also used in taxon names
168
 *   - reference: the nomenclatural reference,
169
 *   - microreference:  Volume, page number etc.
170
 *   - status:  The nomenclatural status of a name
171
 *   - description: name descriptions like protologues etc ...
172
 *
173
 * These elements are combined in the part definitions array to from the specific parts to be rendered.
174
 * Usually the following parts are formed:
175
 *
176
 * The name "Lapsana communis L., Sp. Pl.: 811. 1753" shall be an example here:
177
 *  - namePart: the name and rank (in example: "Lapsana communis")
178
 *  - authorshipPart: the author (in example: "L.")
179
 *  - nameAuthorPart: the combination of name and author part (in example: "Lapsana communis L.").
180
 *     This is useful for zoological names where the authorshipPart belongs to the name and both should
181
 *     be combined when a link to the taxon is rendered.
182
 *  - referencePart: the nomencaltural reference (in example: "Sp. Pl. 1753")
183
 *  - microreferencePart: usually the page number (in example ": 811.")
184
 *  - statusPart: the nomenclatorical status
185
 *  - descriptionPart:
186
 *
187
 * Each set of parts is dedicated to render a specific TaxonName type, the type names are used as keys for the
188
 * specific parts part definitions:
189
 *
190
 *  - BotanicalName
191
 *  - ZoologicalName
192
 *  - #DEFAULT:  covers ViralNames and general NonViralNames
193
 *
194
 * An example:
195
 * @code
196
 * array(
197
 *    'ZoologicalName' => array(
198
 *        'namePart' => array('name' => TRUE),
199
 *        'referencePart' => array('authorTeam' => TRUE),
200
 *        'microreferencePart' => array('microreference' => TRUE),
201
 *        'statusPart' => array('status' => TRUE),
202
 *        'descriptionPart' => array('description' => TRUE),
203
 *    ),
204
 *    'BotanicalName' => array(
205
 *        'namePart' => array(
206
 *            'name' => TRUE,
207
 *            'authors' => TRUE,
208
 *        ),
209
 *        'referencePart' => array(
210
 *            'reference' => TRUE,
211
 *            'microreference' => TRUE,
212
 *        ),
213
 *        'statusPart' => array('status' => TRUE),
214
 *        'descriptionPart' => array('description' => TRUE),
215
 *    ),
216
 *  );
217
 * @endcode
218
 *
219 828a0c8c Andreas Kohlbecker
 * @param object $taxonNameType
220
 *    A cdm TaxonNameType entity
221
 *
222 2fd6da0b Andreas Kohlbecker
 */
223
function get_partDefinition($taxonNameType) {
224
225
  static $default_part_definitions = null;
226
  if (!isset($default_part_definitions)) {
227
    $default_part_definitions= unserialize(CDM_PART_DEFINITIONS_DEFAULT);
228
  }
229
230
  static $part_definitions = null;
231
  if (!isset($part_definitions)) {
232 db725031 Andreas Kohlbecker
    $part_definitions = object_to_array(variable_get(CDM_PART_DEFINITIONS, $default_part_definitions));
233 2fd6da0b Andreas Kohlbecker
  }
234
235 c2545e1c Andreas Kohlbecker
  $dtype = nameTypeToDTYPE($taxonNameType);
236 2fd6da0b Andreas Kohlbecker
  if (array_key_exists($taxonNameType, $part_definitions)) {
237
    return $part_definitions[$taxonNameType];
238 c2545e1c Andreas Kohlbecker
  } else if (array_key_exists($dtype, $part_definitions)) {
239
    return $part_definitions[$dtype];
240 2fd6da0b Andreas Kohlbecker
  } else {
241
    return $part_definitions['#DEFAULT']; // covers ViralNames and general NonViralNames
242
  }
243
244
}
245
246
247
/**
248
 * Renders the markup for a CDM TaxonName instance.
249
 *
250
 * The layout of the name representation is configured by the
251
 * part_definitions and render_templates (see get_partDefinition() and
252
 * get_nameRenderTemplate())
253
 *
254
 * @param $taxonName
255 102f8c26 Andreas Kohlbecker
 *    cdm TaxonName instance
256 20bfe15b Andreas Kohlbecker
 * @param $name_link
257 2fd6da0b Andreas Kohlbecker
 *    URI to the taxon, @see path_to_taxon(), must be processed by url() before passing to this method
258 20bfe15b Andreas Kohlbecker
 * @param $reference_link
259 2fd6da0b Andreas Kohlbecker
 *    URI to the reference, @see path_to_reference(), must be processed by url() before passing to this method
260
 * @param $show_annotations
261
 *    turns the display of annotations on
262
 * @param $is_type_designation
263
 *    To indicate that the supplied taxon name is a name type designation.
264
 * @param $skiptags
265
 *    an array of name elements tags like 'name', 'rank' to skip. The name part
266
 *          'authors' will not ber affected by this filter. This part is managed though the render template
267
 *          mechanism.
268 c35bab7f Andreas Kohlbecker
 * @param $is_invalid
269
 *   Indicates that this taxon is invalid. In this case the name part will be shown in double quotes.
270
 *   This is useful when rendering taxon relation ships.
271 2fd6da0b Andreas Kohlbecker
 *
272
 * @return string
273
 *  The markup for a taxon name.
274
 *
275
 */
276 20bfe15b Andreas Kohlbecker
function render_taxon_or_name($taxon_name_or_taxon_base, $name_link = NULL, $reference_link = NULL,
277 c35bab7f Andreas Kohlbecker
  $show_annotations = true, $is_type_designation = false, $skiptags = array(), $is_invalid = false) {
278 2fd6da0b Andreas Kohlbecker
279 ea3933d7 Andreas Kohlbecker
  $is_doubtful = false;
280
281 2fd6da0b Andreas Kohlbecker
  if($taxon_name_or_taxon_base->class == 'Taxon' || $taxon_name_or_taxon_base->class == 'Synonym'){
282 e95b14dd Andreas Kohlbecker
    if(isset($taxon_name_or_taxon_base->name)){
283
      $taxonName = $taxon_name_or_taxon_base->name;
284
    } else {
285
      $taxonName = cdm_ws_get(CDM_WS_TAXON . '/$0/name', array($taxon_name_or_taxon_base->uuid));
286
    }
287 ea3933d7 Andreas Kohlbecker
    $is_doubtful = $taxon_name_or_taxon_base->doubtful;
288 de7bcbcc Andreas Kohlbecker
    // use the TaxonBase.tagged_title so we have the secRef
289
    $tagged_title = $taxon_name_or_taxon_base->taggedTitle;
290 2fd6da0b Andreas Kohlbecker
  } else {
291 102f8c26 Andreas Kohlbecker
    // assuming this is a TaxonName
292 2fd6da0b Andreas Kohlbecker
    $taxonName = $taxon_name_or_taxon_base;
293 de7bcbcc Andreas Kohlbecker
    if(isset($taxonName->taggedFullTitle)){
294
      $tagged_title = $taxon_name_or_taxon_base->taggedFullTitle;
295
    } else {
296
      $tagged_title = $taxon_name_or_taxon_base->taggedName;
297
    }
298 2fd6da0b Andreas Kohlbecker
  }
299
300
301 20bfe15b Andreas Kohlbecker
  $renderTemplate = get_nameRenderTemplate(RenderHints::getRenderPath(), $name_link, $reference_link);
302 c2545e1c Andreas Kohlbecker
  $partDefinition = get_partDefinition($taxonName->nameType);
303 2fd6da0b Andreas Kohlbecker
304
  // Apply definitions to template.
305
  foreach ($renderTemplate as $part => $uri) {
306
307
    if (isset($partDefinition[$part])) {
308
      $renderTemplate[$part] = $partDefinition[$part];
309
    }
310
    if (is_array($uri) && isset($uri['#uri'])) {
311
      $renderTemplate[$part]['#uri'] = $uri['#uri'];
312
    }
313
  }
314
315 de7bcbcc Andreas Kohlbecker
  $secref_tagged_text = tagged_text_extract_reference_and_detail($tagged_title);
316
  // taxon names will have the nomenclatural reference in the tagged full title:
317
  $nomref_tagged_text = tagged_text_extract_reference($tagged_title);
318
  $nom_status_tagged_text = tagged_text_extract_nomstatus($tagged_title);
319 c35bab7f Andreas Kohlbecker
  $appended_phrase_tagged_text = array(); // this is filled later
320
321 de7bcbcc Andreas Kohlbecker
  normalize_tagged_text($tagged_title);
322 2fd6da0b Andreas Kohlbecker
323 61fc6c93 Andreas Kohlbecker
  $is_valid_tagged_title =
324 de7bcbcc Andreas Kohlbecker
    isset($tagged_title)
325
    && is_array($tagged_title)
326
    && isset($tagged_title[0]->text)
327
    && is_string($tagged_title[0]->text)
328
    && $tagged_title[0]->text != ''
329 61fc6c93 Andreas Kohlbecker
    && isset($tagged_title[0]->type);
330 2fd6da0b Andreas Kohlbecker
  $lastAuthorElementString = FALSE;
331
332 c35bab7f Andreas Kohlbecker
  $name_encasement = $is_invalid ? '"' : '';
333 54a3c136 Andreas Kohlbecker
  $doubtful_marker = $is_doubtful ? '?&#8239;' : ''; // 	&#8239; =  NARROW NO-BREAK SPACE
334 2330b553 Andreas Kohlbecker
  $doubtful_marker_markup = '';
335
336
  if($doubtful_marker){
337
    $doubtful_marker_markup = '<span class="doubtful">' . $doubtful_marker . '</span>';
338 61fc6c93 Andreas Kohlbecker
    if($tagged_title[0]->text == '?' ){
339
      // remove the first tagged text element
340
      unset($tagged_title[0]);
341
    }
342 2330b553 Andreas Kohlbecker
  }
343 c35bab7f Andreas Kohlbecker
344
  // split off all appendedPhrase item  from the end of the array (usually there only should  be one)
345 de7bcbcc Andreas Kohlbecker
  while($tagged_title[count($tagged_title)-1]->type == "appendedPhrase"){
346
    $appended_phrase_tagged_text[] = array_pop($tagged_title);
347 c35bab7f Andreas Kohlbecker
  }
348
349 2fd6da0b Andreas Kohlbecker
  // Got to use second entry as first one, see ToDo comment below ...
350 61fc6c93 Andreas Kohlbecker
  if ($is_valid_tagged_title) {
351 2fd6da0b Andreas Kohlbecker
352 de7bcbcc Andreas Kohlbecker
    $taggedName = $tagged_title;
353 2fd6da0b Andreas Kohlbecker
    $hasNamePart_with_Authors = isset($renderTemplate['namePart']) && isset($renderTemplate['namePart']['authors']);
354
    $hasNameAuthorPart_with_Authors = isset($renderTemplate['nameAuthorPart']) && isset($renderTemplate['nameAuthorPart']['authors']);
355
356 c35bab7f Andreas Kohlbecker
357 2fd6da0b Andreas Kohlbecker
    if (!(($hasNamePart_with_Authors) || ($hasNameAuthorPart_with_Authors))) {
358
      // Find author and split off from name.
359
      // TODO expecting to find the author as the last element.
360
      /*
361
      if($taggedName[count($taggedName)- 1]->type == 'authors'){
362
        $authorTeam = $taggedName[count($taggedName)- 1]->text;
363
        unset($taggedName[count($taggedName)- 1]);
364
      }
365
      */
366
367
      // Remove all authors.
368
      $taggedNameNew = array();
369
      foreach ($taggedName as $element) {
370
        if ($element->type != 'authors') {
371
          $taggedNameNew[] = $element;
372
        }
373
        else {
374
          $lastAuthorElementString = $element->text;
375
        }
376
      }
377
      $taggedName = $taggedNameNew;
378 e90899ac Andreas Kohlbecker
      unset($taggedNameNew);
379 2fd6da0b Andreas Kohlbecker
    }
380 0f129a6f Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '">' . $doubtful_marker_markup . $name_encasement . cdm_tagged_text_to_markup($taggedName, $skiptags) . $name_encasement . '</span>';
381 2fd6da0b Andreas Kohlbecker
  }
382
  else {
383 61fc6c93 Andreas Kohlbecker
    // use titleCache instead
384 2330b553 Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '_titleCache">' . $doubtful_marker_markup . $name_encasement . $taxonName->titleCache . $name_encasement . '</span>';
385 c35bab7f Andreas Kohlbecker
  }
386
387
388
  if(isset($appended_phrase_tagged_text[0])){
389 54a3c136 Andreas Kohlbecker
    $name .= ' <span class="appended-phrase">'. cdm_tagged_text_to_markup($appended_phrase_tagged_text) . '</span>';
390 2fd6da0b Andreas Kohlbecker
  }
391
392
  // Fill name into $renderTemplate.
393 c35bab7f Andreas Kohlbecker
  array_setr('name', $name , $renderTemplate);
394 2fd6da0b Andreas Kohlbecker
395
  // Fill with authorTeam.
396
  /*
397
  if($authorTeam){
398
    $authorTeamHtml = ' <span class="authorTeam">'.$authorTeam.'</span>';
399
    array_setr('authorTeam', $authorTeamHtml, $renderTemplate);
400
  }
401
  */
402
403
  // Fill with reference.
404
  if (isset($renderTemplate['referencePart']) && !$is_type_designation) {
405
406 eaff53f7 Andreas Kohlbecker
    $registrations = cdm_ws_get(CDM_WS_NAME, array($taxonName->uuid, "registrations"));
407
    $registration_markup = render_registrations($registrations);
408
409 2fd6da0b Andreas Kohlbecker
    // default separator
410
    $separator = '';
411
412
    // [Eckhard]:"Komma nach dem Taxonnamen ist grunsätzlich falsch,
413
    // Komma nach dem Autornamen ist überall dort falsch, wo ein "in" folgt."
414 c21cfd4b Andreas Kohlbecker
    if (isset($renderTemplate['referencePart']['reference'])) {
415 2fd6da0b Andreas Kohlbecker
      $microreference = NULL;
416
      if (isset($renderTemplate['referencePart']['microreference'])&& isset($taxonName->nomenclaturalMicroReference)) {
417
        $microreference = $taxonName->nomenclaturalMicroReference;
418
      }
419 c21cfd4b Andreas Kohlbecker
      if(count($nomref_tagged_text) == 0 && isset($taxonName->nomenclaturalReference)){
420
        // TODO is this case still relevant? The tagged text should already contain all information!
421 de7bcbcc Andreas Kohlbecker
        $citation = cdm_ws_getNomenclaturalReference($taxonName->nomenclaturalReference->uuid, $microreference);
422
        // Find preceding element of the reference.
423
        $precedingKey = get_preceding_contentElementKey('reference', $renderTemplate);
424
        if (str_beginsWith($citation, ", in")) {
425
          $citation = substr($citation, 2);
426
          $separator = ' ';
427
        }
428
        elseif (!str_beginsWith($citation, "in") && $precedingKey == 'authors') {
429
          $separator = ', ';
430
        } else {
431
          $separator = ' ';
432
        }
433
        $referenceArray['#separator'] = $separator;
434
        $referenceArray['#html'] = '<span class="reference">' . $citation . '</span>' . $registration_markup;
435 2fd6da0b Andreas Kohlbecker
      } else {
436 de7bcbcc Andreas Kohlbecker
        // this ist the case for taxon names
437
        $referenceArray['#html'] = cdm_tagged_text_to_markup($nomref_tagged_text);
438 2fd6da0b Andreas Kohlbecker
      }
439
440
441
      array_setr('reference', $referenceArray, $renderTemplate);
442
    }
443
444
    // If authors have been removed from the name part the last named authorteam
445
    // should be added to the reference citation, otherwise, keep the separator
446
    // out of the reference.
447
    if (isset($renderTemplate['referencePart']['authors']) && $lastAuthorElementString) {
448
      // If the nomenclaturalReference citation is not included in the
449 eaff53f7 Andreas Kohlbecker
      // reference part but display of the microreference
450 2fd6da0b Andreas Kohlbecker
      // is wanted, append the microreference to the authorTeam.
451
      $citation = '';
452
      if (!isset($renderTemplate['referencePart']['reference']) && isset($renderTemplate['referencePart']['microreference'])) {
453
        $separator = ": ";
454
        $citation = $taxonName->nomenclaturalMicroReference;
455
      }
456
      $referenceArray['#html'] = ' <span class="reference">' . $lastAuthorElementString . $separator . $citation . '</span>';
457
      array_setr('authors', $referenceArray, $renderTemplate);
458
    }
459
  }
460
461
  $is_reference_year = false;
462
  if (isset($renderTemplate['referenceYearPart']['reference.year'])) {
463
    if(isset($taxonName->nomenclaturalReference->datePublished)){
464
      $referenceArray['#html'] = ' <span class="reference">' . timePeriodToString($taxonName->nomenclaturalReference->datePublished) . '</span>';
465
      array_setr('reference.year', $referenceArray, $renderTemplate);
466
      $is_reference_year = true;
467
    }
468
  }
469
470 e90899ac Andreas Kohlbecker
  // Fill with status.
471 dce1dacc Andreas Kohlbecker
  if(isset($renderTemplate['statusPart']['status'])){
472 1d0407b7 Andreas Kohlbecker
    if (isset($nom_status_tagged_text[0])) {
473 222784c5 Andreas Kohlbecker
        $tt_to_markup_options = array('html' => false);
474
        foreach ($nom_status_tagged_text as &$tt){
475
         if($tt->type == 'nomStatus'&& isset($tt->entityReference)) {
476
           $nom_status = cdm_ws_get(CDM_WS_NOMENCLATURALSTATUS, array($tt->entityReference->uuid));
477
           $nom_status_fkey = nomenclatural_status_footnote_markup($nom_status);
478
           $tt->text .= $nom_status_fkey;
479
           $tt_to_markup_options['html'] = true;
480
         }
481
        }
482
        array_setr(
483
          'status',
484 e9ac7c6f Andreas Kohlbecker
          '<span class="nomenclatural_status">' . cdm_tagged_text_to_markup($nom_status_tagged_text, array('postSeparator'), 'span', $tt_to_markup_options) . '</span>',
485
          $renderTemplate);
486 e90899ac Andreas Kohlbecker
    }
487
  }
488
489 2fd6da0b Andreas Kohlbecker
  if (isset($renderTemplate['secReferencePart'])){
490
    if(isset($secref_tagged_text[1])){
491 e90899ac Andreas Kohlbecker
      $post_separator_markup = $is_reference_year ? '.': '';
492 6aad9da8 Andreas Kohlbecker
      if(isset($nom_status_tagged_text[count($nom_status_tagged_text) - 1]) && ($nom_status_tagged_text[count($nom_status_tagged_text) - 1]->type ==  'postSeparator')){
493 4a1ab871 Andreas Kohlbecker
        $post_separator_markup = cdm_tagged_text_to_markup(array($nom_status_tagged_text[count($nom_status_tagged_text) - 1 ]));
494 e90899ac Andreas Kohlbecker
      };
495 2fd6da0b Andreas Kohlbecker
      array_setr('secReference',
496 e90899ac Andreas Kohlbecker
        $post_separator_markup
497 2fd6da0b Andreas Kohlbecker
          . ' <span class="sec_reference">'
498 4bfe18f9 Andreas Kohlbecker
          . join('', cdm_tagged_text_values($secref_tagged_text))
499 2fd6da0b Andreas Kohlbecker
          . '</span>', $renderTemplate);
500
    }
501
  }
502
503
  // Fill with protologues etc...
504
  $descriptionHtml = '';
505
  if (array_setr('description', TRUE, $renderTemplate)) {
506
    $descriptions = cdm_ws_get(CDM_WS_PORTAL_NAME_DESCRIPTIONS, $taxonName->uuid);
507 20bfe15b Andreas Kohlbecker
    if($descriptions){
508
      foreach ($descriptions as $description) {
509
        if (!empty($description)) {
510
          foreach ($description->elements as $description_element) {
511
            $second_citation = '';
512
            if (isset($description_element->multilanguageText_L10n) && $description_element->multilanguageText_L10n->text) {
513 1c7c424f Andreas Kohlbecker
              if(isset($description_element->feature) && $description_element->feature->uuid == UUID_ADDITIONAL_PUBLICATION){
514
                $prefix =  '& ';
515
              } else {
516
                $prefix = '';
517
              }
518
              $second_citation = ' [' . $prefix . $description_element->multilanguageText_L10n->text . '].';
519 20bfe15b Andreas Kohlbecker
            }
520
            $descriptionHtml .= $second_citation;
521
            $descriptionHtml .= cdm_description_element_media(
522
                $description_element,
523
                array(
524
                  'application/pdf',
525
                  'image/png',
526
                  'image/jpeg',
527
                  'image/gif',
528
                  'text/html',
529
                )
530
            );
531 2fd6da0b Andreas Kohlbecker
532 20bfe15b Andreas Kohlbecker
          }
533 2fd6da0b Andreas Kohlbecker
        }
534
      }
535
    }
536
    array_setr('description', $descriptionHtml, $renderTemplate);
537
  }
538
539
  // Render.
540 f695daf4 Andreas Kohlbecker
  $out = '';
541
  if(isset($_REQUEST['RENDER_PATH'])){
542
    // developer option to show the render path with each taxon name
543
    $out .= '<span class="render-path">' . RenderHints::getRenderPath() . '</span>';
544
  }
545
  $out .= '<span class="' . html_class_attribute_ref($taxon_name_or_taxon_base)
546
    . '" data-cdm-ref="/name/' . $taxonName->uuid . '" data-cdm-render-path="' . RenderHints::getRenderPath() .'">';
547 2fd6da0b Andreas Kohlbecker
548
  foreach ($renderTemplate as $partName => $part) {
549
    $separator = '';
550
    $partHtml = '';
551
    $uri = FALSE;
552
    if (!is_array($part)) {
553
      continue;
554
    }
555
    if (isset($part['#uri']) && is_string($part['#uri'])) {
556
      $uri = $part['#uri'];
557
      unset($part['#uri']);
558
    }
559
    foreach ($part as $key => $content) {
560
      $html = '';
561
      if (is_array($content)) {
562
        $html = $content['#html'];
563
        if(isset($content['#separator'])) {
564
          $separator = $content['#separator'];
565
        }
566
      }
567
      elseif (is_string($content)) {
568
        $html = $content;
569
      }
570
      $partHtml .= '<span class="' . $key . '">' . $html . '</span>';
571
    }
572
    if ($uri) {
573
      // cannot use l() here since the #uri aleady should have been processed through uri() at this point
574
      $out .= $separator . '<a href="' . $uri . '" class="' . $partName . '">' . $partHtml . '</a>';
575
576
    }
577
    else {
578
      $out .= $separator . $partHtml;
579
    }
580
  }
581
  $out .= '</span>';
582
  if ($show_annotations) {
583 2fc5c836 Andreas Kohlbecker
    // $out .= theme('cdm_entities_annotations_as_footnotekeys', $taxonName);
584 2fd6da0b Andreas Kohlbecker
  }
585
  return $out;
586
}
587
588 7212f0bc Andreas Kohlbecker
589
590
/**
591 26b8a1bc Andreas Kohlbecker
 * Composes information for a registration from a dto object.
592
 *
593
 * Registrations which are not yet published are suppressed.
594 7212f0bc Andreas Kohlbecker
 *
595
 * @param $registration_dto
596
 * @param $with_citation
597
 *   Whether to show the citation.
598
 *
599
 * @return array
600
 *    A drupal render array with the elements:
601 26b8a1bc Andreas Kohlbecker
 *    - 'name'
602
 *    - 'name-relations'
603
 *    - 'specimen_type_designations'
604
 *    - 'name_type_designations'
605 7212f0bc Andreas Kohlbecker
 *    - 'citation'
606 26b8a1bc Andreas Kohlbecker
 *    - 'registration_date_and_institute'
607 7212f0bc Andreas Kohlbecker
 * @ingroup compose
608
 */
609 26b8a1bc Andreas Kohlbecker
function compose_registration_dto_full($registration_dto, $with_citation = true)
610 7212f0bc Andreas Kohlbecker
{
611 54c10803 Andreas Kohlbecker
  $render_array = array(
612
    '#prefix' => '<div class="registration">',
613
    '#suffix' => '</div>'
614
  );
615 7212f0bc Andreas Kohlbecker
616 26b8a1bc Andreas Kohlbecker
  if(!(isset($registration_dto->identifier) && $registration_dto->status == 'PUBLISHED')){
617
    return $render_array;
618
  }
619
620 b7e96f18 Andreas Kohlbecker
  $render_array['sub_headline'] = markup_to_render_array(join(", ", registration_types($registration_dto)),-10, '<h3 class="registration_type">' . t('Event: '), '</h3>' );
621 c5abae79 Andreas Kohlbecker
  $render_array['nomenclatural_act'] = array(
622
    '#weight' => 0,
623
    '#prefix' => '<div class="nomenclatural_act">',
624 b7e96f18 Andreas Kohlbecker
625 c5abae79 Andreas Kohlbecker
    '#suffix' => '</div>'
626
  );
627 b90ef618 Andreas Kohlbecker
628 e69c4103 Andreas Kohlbecker
  // name
629 26b8a1bc Andreas Kohlbecker
  if($registration_dto->nameRef){
630
    $name = cdm_ws_get(CDM_WS_PORTAL_NAME, $registration_dto->nameRef->uuid);
631 a7560a18 Andreas Kohlbecker
    cdm_load_tagged_full_title($name);
632 c5abae79 Andreas Kohlbecker
    $render_array['nomenclatural_act']['published_name'] = markup_to_render_array('<div class="published-name">' . render_taxon_or_name($name, url(path_to_name($name->uuid))) . '</div>', 0);
633 26b8a1bc Andreas Kohlbecker
    $name_relations = cdm_ws_fetch_all(str_replace("$0", $registration_dto->nameRef->uuid, CDM_WS_PORTAL_NAME_NAME_RELATIONS));
634 c5abae79 Andreas Kohlbecker
    $render_array['nomenclatural_act']['name_relations'] = compose_name_relationships_list($name_relations, $registration_dto->nameRef->uuid, null);
635
    $render_array['nomenclatural_act']['name_relations']['#weight'] = 10;
636 2dce3b2a Andreas Kohlbecker
  } else {
637
    // in this case the registration must have a
638
    $name = cdm_ws_get(CDM_WS_PORTAL_NAME, $registration_dto->typifiedNameRef->uuid);
639 54c10803 Andreas Kohlbecker
    $render_array['typified_name'] = markup_to_render_array('<p class="typified-name">for ' . render_taxon_or_name($name, url(path_to_name($name->uuid))) . '</p>', 40);
640 26b8a1bc Andreas Kohlbecker
  }
641 e69c4103 Andreas Kohlbecker
  // typedesignation in detail
642 26b8a1bc Andreas Kohlbecker
  if(is_object($registration_dto->orderdTypeDesignationWorkingSets)) {
643
    $field_unit_uuids = array();
644
    $specimen_type_designation_refs = array();
645
    $name_type_designation_refs = array();
646 67f5eac2 Andreas Kohlbecker
    foreach ((array)$registration_dto->orderdTypeDesignationWorkingSets as $workingset_ref => $obj) {
647
      $tokens = explode("#", $workingset_ref);
648
      $types_in_fieldunit = get_object_vars($obj); // convert into associative array
649
650 26b8a1bc Andreas Kohlbecker
      if ($tokens[0] == 'NameTypeDesignation') {
651 67f5eac2 Andreas Kohlbecker
        foreach ($types_in_fieldunit as $type_status => $entity_reference_list) {
652
          if(!isset($name_type_designation_refs[$type_status])){
653
            $name_type_designation_refs[$type_status]  = $entity_reference_list;
654
          } else {
655
            array_push($name_type_designation_refs[$type_status] ,$entity_reference_list);
656
          }
657 7212f0bc Andreas Kohlbecker
        }
658 26b8a1bc Andreas Kohlbecker
      } else if ($tokens[0] == 'FieldUnit'){
659
        $field_unit_uuids[] = $tokens[1];
660 67f5eac2 Andreas Kohlbecker
        foreach ($types_in_fieldunit as $type_status => $entity_reference_list) {
661
          if(!isset($specimen_type_designation_refs[$type_status])){
662
            $specimen_type_designation_refs[$type_status] =  $entity_reference_list;
663
          } else {
664
            array_push($specimen_type_designation_refs[$type_status], $entity_reference_list);
665
          }
666
        }
667 26b8a1bc Andreas Kohlbecker
      } else {
668
        drupal_set_message("Unimplemented type: " . $tokens[0], 'error');
669 7212f0bc Andreas Kohlbecker
      }
670
    }
671 a9a04561 Andreas Kohlbecker
    // type designations wich are in this nomenclatural act.
672 26b8a1bc Andreas Kohlbecker
    if (count($name_type_designation_refs) > 0) {
673 c5abae79 Andreas Kohlbecker
      $render_array['nomenclatural_act']['name_type_designations'] = compose_name_type_designations($name_type_designation_refs);
674
      $render_array['nomenclatural_act']['name_type_designations']['#prefix'] = '<p class="name_type_designations">';
675
      $render_array['nomenclatural_act']['name_type_designations']['#suffix'] = '</p>';
676
      $render_array['nomenclatural_act']['name_type_designations']['#weight'] = 20;
677 26b8a1bc Andreas Kohlbecker
    }
678
    if (count($field_unit_uuids) > 0) {
679 e69c4103 Andreas Kohlbecker
      $specimen_type_designations_array = compose_specimen_type_designations($specimen_type_designation_refs, true);
680 c5abae79 Andreas Kohlbecker
      $render_array['nomenclatural_act']['specimen_type_designations'] = $specimen_type_designations_array['type_designations'];
681 41a348be Andreas Kohlbecker
      $render_array['map'] = $specimen_type_designations_array['map'];
682 c5abae79 Andreas Kohlbecker
      $render_array['map']['#weight'] = $render_array['nomenclatural_act']['#weight'] + 20;
683 26b8a1bc Andreas Kohlbecker
    }
684 7212f0bc Andreas Kohlbecker
  }
685
686
  // citation
687
  if ($with_citation) {
688
    $render_array['citation'] = markup_to_render_array(
689 c5abae79 Andreas Kohlbecker
      "<div class=\"citation nomenclatural_act_citation" . html_class_attribute_ref(new TypedEntityReference("Reference", $registration_dto->citationUuid)) . "\">"
690
      . "<span class=\"label\">published in: </span>"
691 2ffe4d59 Andreas Kohlbecker
      . $registration_dto->bibliographicInRefCitationString
692
      . l(custom_icon_font_markup('icon-interal-link-alt-solid', array('class' => array('superscript'))), path_to_reference($registration_dto->citationUuid), array('html' => true))
693 c5abae79 Andreas Kohlbecker
      . "</div>",
694
      $render_array['nomenclatural_act']['#weight'] + 10 );
695 7212f0bc Andreas Kohlbecker
  }
696
697 0e617798 Andreas Kohlbecker
  $render_array['footnotes'] = markup_to_render_array(
698
    theme('cdm_annotation_footnotes', ['footnoteListKey' => RenderHints::getFootnoteListKey() ]),
699
    12
700
  );
701
702 7212f0bc Andreas Kohlbecker
  // registration date and office
703 12466422 Andreas Kohlbecker
  $registration_date_insitute_markup = render_registration_date_and_institute($registration_dto);
704 26b8a1bc Andreas Kohlbecker
  if($registration_date_insitute_markup){
705
    $render_array['registration_date_and_institute'] = markup_to_render_array(
706
      $registration_date_insitute_markup . '</p>',
707
      100);
708
  }
709
710 0e617798 Andreas Kohlbecker
711 26b8a1bc Andreas Kohlbecker
  return $render_array;
712
}
713
714
715
/**
716
 * Composes a compact representation for a registrationDTO object
717
 *
718
 * Registrations which are not yet published are suppressed.
719
 *
720
 * @param $registration_dto
721
 * @param $style string
722
 *   The style of how to compose the 'identifier' and 'registration_date_and_institute' part with the summary
723
 *   - 'citation': Similar to the arrearance of nomenclatural acts in print media
724
 *   - 'list-item' : style suitable for result lists etc
725
 *
726
 * @return array
727
 *    A drupal render array with the elements:
728
 *    - 'registration-metadata' when $style == 'list-item'
729
 *    - 'summary'
730
 * @ingroup compose
731
 */
732
function compose_registration_dto_compact($registration_dto, $style = 'citation', $tag_enclosing_summary = 'p')
733
{
734
  $render_array = array();
735
  $media_link_map = array();
736
737
  if(!(isset($registration_dto->identifier) && $registration_dto->status == 'PUBLISHED')){
738
    return $render_array;
739
  }
740
741 12466422 Andreas Kohlbecker
  $registration_date_insitute_markup = render_registration_date_and_institute($registration_dto, 'span');
742 977bba78 Andreas Kohlbecker
  $itentifier_markup = l($registration_dto->identifier, path_to_registration($registration_dto->identifier), array('attributes' => array('class' => array('identifier'))));
743 26b8a1bc Andreas Kohlbecker
744 f461a488 Andreas Kohlbecker
  $tagged_text_options = array();
745
  if(isset($registration_dto->nameRef)){
746
    $tagged_text_options[] = array(
747
      'filter-type' => 'name',
748
      'prefix' => '<span class="registered_name">',
749
      'suffix' => '</span>',
750
    );
751
  } else {
752
    $tagged_text_options[] = array(
753
      'filter-type' => 'name',
754
      'prefix' => '<span class="referenced_typified_name">',
755
      'suffix' => '</span>',
756
    );
757
  }
758
  cdm_tagged_text_add_options($registration_dto->summaryTaggedText, $tagged_text_options);
759 26b8a1bc Andreas Kohlbecker
  $taggged_text_expanded = cdm_tagged_text_expand_entity_references($registration_dto->summaryTaggedText);
760
  foreach ($taggged_text_expanded  as $tagged_text){
761
    if(isset($tagged_text->entityReference->type) && $tagged_text->entityReference->type == 'SpecimenTypeDesignation') {
762
      $mediaDTOs = cdm_ws_get('typedesignation/$0/media', array($tagged_text->entityReference->uuid));
763
      if(isset($mediaDTOs[0]->uri)){
764
        $media_url_key = '{link-' . $mediaDTOs[0]->uuid . '}';
765
        $tagged_text->text = str_replace('[icon]', '[icon]' . $media_url_key, $tagged_text->text);
766
        $media_link_map[$media_url_key] =  cdm_external_uri($mediaDTOs[0]->uri, true);
767
      }
768
    }
769
  }
770
  $registation_markup = cdm_tagged_text_to_markup($taggged_text_expanded);
771
  foreach($media_link_map as $media_url_key => $link){
772
    $registation_markup = str_replace($media_url_key, $link, $registation_markup);
773
  }
774
  if($style == 'citation') {
775
    $registation_markup = $registation_markup . ' ' . $itentifier_markup . ' ' . $registration_date_insitute_markup;
776
  } else {
777
    $render_array['registration-metadata'] = markup_to_render_array('<div class="registration-metadata">' . $itentifier_markup . ' ' . $registration_date_insitute_markup. "</div>", -10);
778
  }
779 f461a488 Andreas Kohlbecker
  $render_array['summary'] = markup_to_render_array('<' . $tag_enclosing_summary . ' class="registration-summary">' . $registation_markup . '</' . $tag_enclosing_summary . '>', 0);
780 26b8a1bc Andreas Kohlbecker
781
  return $render_array;
782
}
783
784
785
/**
786
 * Renders the registrationDate and institutionTitleCache of the $registration_dto as markup.
787
 *
788
 * @param $registration_dto
789
 * @return string
790
 *    The markup or an empty string
791
 */
792 12466422 Andreas Kohlbecker
function render_registration_date_and_institute($registration_dto, $enclosing_tag = 'p') {
793
  $registration_date_institute_markup = '';
794 26b8a1bc Andreas Kohlbecker
  if ($registration_dto->registrationDate) {
795 7212f0bc Andreas Kohlbecker
    $date_string = format_datetime($registration_dto->registrationDate);
796 26b8a1bc Andreas Kohlbecker
    if (isset($registration_dto->institutionTitleCache) && $registration_dto->institutionTitleCache) {
797 12466422 Andreas Kohlbecker
      $registration_date_institute_markup =
798 7212f0bc Andreas Kohlbecker
        t("Registration on @date in @institution", array(
799
          '@date' => $date_string,
800
          '@institution' => $registration_dto->institutionTitleCache,
801
        ));
802
    } else {
803 12466422 Andreas Kohlbecker
      $registration_date_institute_markup =
804 7212f0bc Andreas Kohlbecker
        t("Registration on @date", array(
805
          '@date' => $date_string
806
        ));
807
    }
808 12466422 Andreas Kohlbecker
    $registration_date_institute_markup = '<' .$enclosing_tag . ' class="registration-date-and-institute">'. $registration_date_institute_markup . '</' .$enclosing_tag . '>';
809 7212f0bc Andreas Kohlbecker
  }
810 12466422 Andreas Kohlbecker
  return $registration_date_institute_markup;
811 7212f0bc Andreas Kohlbecker
}
812
813
814 eaff53f7 Andreas Kohlbecker
/**
815
 * @param $registrations
816
 * @return string
817
 */
818
function render_registrations($registrations)
819
{
820
  $registration_markup = '';
821
  $registration_markup_array = array();
822
  if ($registrations) {
823
    foreach ($registrations as $reg) {
824
      $registration_markup_array[] = render_registration($reg);
825
    }
826
    $registration_markup = " Registration" . (count($registration_markup_array) > 1 ? 's: ' : ': ')
827
      . join(', ', $registration_markup_array);
828
  }
829
  return $registration_markup;
830
}
831
832 471192e3 Andreas Kohlbecker
833 7212f0bc Andreas Kohlbecker
/**
834
 * Renders a registration
835
 *
836 26b8a1bc Andreas Kohlbecker
 * TODO replace by compose_registration_dto_compact
837 7212f0bc Andreas Kohlbecker
 * @param $registration
838
 */
839
function render_registration($registration){
840
  $markup = '';
841
842
  if(isset($registration->identifier) && $registration->status == 'PUBLISHED'){
843
    $office_class_attribute = '';
844
    if(isset($registration->institution->titleCache)){
845 26b8a1bc Andreas Kohlbecker
      $office_class_attribute = registration_intitute_class_attribute($registration);
846 7212f0bc Andreas Kohlbecker
    }
847 977bba78 Andreas Kohlbecker
    $markup = "<span class=\"registration $office_class_attribute\">" . l($registration->identifier, path_to_registration($registration->identifier)) . ', '
848 7212f0bc Andreas Kohlbecker
      .  preg_replace('/^([^T]*)(.*)$/', '${1}', $registration->registrationDate)
849
      . '</span>';
850
  }
851
  return $markup;
852
}
853
854 26b8a1bc Andreas Kohlbecker
/**
855
 * @param $registration
856
 * @return string
857
 */
858
function registration_intitute_class_attribute($registration_dto)
859
{
860
  if(isset($registration_dto->institutionTitleCache)){
861
    $institutionTitleCache = $registration_dto->institutionTitleCache;
862
  } else {
863
    // fall back option to also support cdm entities
864
    $institutionTitleCache = @$registration_dto->institution->titleCache;
865
  }
866
  return $institutionTitleCache ? 'registration-' . strtolower(preg_replace('/[^a-zA-Z0-9]/', '-', $institutionTitleCache)) : '';
867
}
868
869 7212f0bc Andreas Kohlbecker
870 79904336 Andreas Kohlbecker
/**
871
 * Renders and array of CDM TypeDesignations
872
 *
873 0e617798 Andreas Kohlbecker
 *  - NameTypeDesignation
874
 *  - SpecimenTypeDesignation
875
 *  - TextualTypeDesignation
876
 *
877 79904336 Andreas Kohlbecker
 * @param object $type_designations an array of cdm TypeDesignation entities
878
 *  to render
879
 * @param string $enclosing_tag the tag element type to enclose the whole list
880
 *  of type designation with. By default this DOM element is <ul>
881
 * @param string $element_tag the tag element type to be used for each
882
 *  type designation item.
883
 * @param bool $link_to_specimen_page whether a specimen in type designation element
884
 *  should be a link or not.
885
 *
886
 * @return string The markup.
887
 *
888
 * @InGroup Render
889
 */
890
function render_type_designations($type_designations, $enclosing_tag = 'ul', $element_tag =  'li', $link_to_specimen_page = true) {
891
892
  // need to add element to render path since type designations
893
  // need other name render template
894
  RenderHints::pushToRenderStack('typedesignations');
895
896
  $out = '<' . $enclosing_tag .' class="typeDesignations">';
897
  $specimen_type_designations = array();
898
  $name_type_designations = array();
899
  $textual_type_designations = array();
900
  $separator = ',';
901
902
  foreach ($type_designations as $type_designation) {
903
    switch ($type_designation->class) {
904
      case 'SpecimenTypeDesignation':
905
        $specimen_type_designations[] = $type_designation;
906
        break;
907
      case 'NameTypeDesignation':
908
        $name_type_designations[] = $type_designation;
909
        break;
910
      case 'TextualTypeDesignation':
911
        $textual_type_designations[] = $type_designation;
912
        break;
913
      default:  throw new Exception('Unknown type designation class: ' . $type_designation->class);
914
    }
915
  }
916
917
  // NameTypeDesignation ..................................
918
  if(!empty($name_type_designations)){
919 04d5812b Andreas Kohlbecker
    usort($name_type_designations, "compare_type_designations_by_status");
920 79904336 Andreas Kohlbecker
    foreach($name_type_designations as $name_type_designation){
921
      if ($name_type_designation->notDesignated) {
922
        $out .= '<'. $element_tag .' class="' . html_class_attribute_ref($name_type_designation) . '">' .  type_designation_status_label_markup($name_type_designation)  . ': '
923
          . t('not designated') . '</'. $element_tag .'>';
924
      }
925
      elseif (isset($name_type_designation->typeName)) {
926
        $link_to_name_page = url(path_to_name($name_type_designation->typeName->uuid));
927
        $out .= '<'. $element_tag .' class="' . html_class_attribute_ref($name_type_designation) . '">' .  type_designation_status_label_markup($name_type_designation) ;
928
929
        if (!empty($name_type_designation->citation)) {
930
          $out .= type_designation_citation_layout($name_type_designation, $separator); // TODO type_designation_citation_layout() needs most probably to be replaced
931
932
        }
933
        $referenceUri = '';
934
        if (isset($name_type_designation->typeName->nomenclaturalReference)) {
935
          $referenceUri = url(path_to_reference($name_type_designation->typeName->nomenclaturalReference->uuid));
936
        }
937
        $out .= ': ' . render_taxon_or_name($name_type_designation->typeName, $link_to_name_page, $referenceUri, TRUE, TRUE);
938
      }
939
    }
940
  } // END NameTypeDesignation
941
942
  // SpecimenTypeDesignation ...................................
943
  if (!empty($specimen_type_designations)) {
944
    usort($specimen_type_designations, "compare_specimen_type_designation");
945
    foreach ($specimen_type_designations as $specimen_type_designation) {
946
      $type_citation_markup = '';
947
948
      if (!empty($specimen_type_designation->citation)) {
949
950 e7f3789b Andreas Kohlbecker
        $citation_footnote_str = cdm_reference_markup($specimen_type_designation->citation, null, false, true);
951 79904336 Andreas Kohlbecker
        $author_team = cdm_ws_get(CDM_WS_REFERENCE_AUTHORTEAM, $specimen_type_designation->citation->uuid);
952
953
        if (!empty($author_team->titleCache)) {
954
          $year = @timePeriodToString($specimen_type_designation->citation->datePublished, true, 'YYYY');
955
          $authorteam_str = $author_team->titleCache . ($year ? ' ' : '') . $year;
956
          if ($authorteam_str == $specimen_type_designation->citation->titleCache) {
957
            $citation_footnote_str = '';
958
          }
959
        } else {
960
          $authorteam_str = $citation_footnote_str;
961
          // no need for a footnote in case in case it is used as replacement for missing author teams
962
          $citation_footnote_str = '';
963
        }
964
965
        // for being registered a typedesignation MUST HAVE a citation, so it is save to handle the
966
        // Registration output in if condition checking if the citation is present
967
        $registration_markup = render_registrations($specimen_type_designation->registrations);
968
        $citation_footnote_str .= ($citation_footnote_str ? ' ' : '') . $registration_markup;
969
970
        $footnote_key_markup = '';
971
        if ($citation_footnote_str) {
972
          // footnotes should be rendered in the parent element so we
973
          // are relying on the FootnoteListKey set there
974
          $_fkey2 = FootnoteManager::addNewFootnote(RenderHints::getFootnoteListKey(), $citation_footnote_str);
975
          $footnote_key_markup = theme('cdm_footnote_key', array(
976
            'footnoteKey' => $_fkey2,
977
            'separator' => $separator,
978
            'highlightable' => TRUE,
979
            'separator_off' => TRUE,
980
          ));
981
982
        }
983
984
        $type_citation_markup .= '&nbsp;(' . t('designated by') . '&nbsp;<span class="typeReference">' . $authorteam_str . '</span>';
985
        if (!empty($specimen_type_designation->citationMicroReference)) {
986
          $type_citation_markup .= ': ' . trim($specimen_type_designation->citationMicroReference);
987
        }
988
        $type_citation_markup .= $footnote_key_markup . ')';
989
990
      }
991
992
      $out .= '<'. $element_tag .' class="' . html_class_attribute_ref($specimen_type_designation) . '">';
993
      $out .= type_designation_status_label_markup($specimen_type_designation) . $type_citation_markup;
994
995
996
      $derivedUnitFacadeInstance = null;
997
      if (isset($specimen_type_designation->typeSpecimen)) {
998
        $derivedUnitFacadeInstance = cdm_ws_get(CDM_WS_DERIVEDUNIT_FACADE, $specimen_type_designation->typeSpecimen->uuid);
999
      }
1000
1001
      if (!empty($derivedUnitFacadeInstance->titleCache)) {
1002
        $specimen_markup = $derivedUnitFacadeInstance->titleCache;
1003
        if($link_to_specimen_page && isset($derivedUnitFacadeInstance->specimenLabel) && $derivedUnitFacadeInstance->specimenLabel){
1004
          $specimen_markup = str_replace($derivedUnitFacadeInstance->specimenLabel, l($derivedUnitFacadeInstance->specimenLabel, path_to_specimen($specimen_type_designation->typeSpecimen->uuid)), $specimen_markup);
1005
        }
1006
        $out .= ': <span class="' . html_class_attribute_ref($specimen_type_designation->typeSpecimen) . '">'
1007
          . $specimen_markup
1008
          . '</span>'; // . ': ' . theme('cdm_specimen', array('specimenTypeDesignation' => $derivedUnitFacadeInstance));
1009
        if(!empty($derivedUnitFacadeInstance->preferredStableUri)){
1010
          $out .= ' ' . l($derivedUnitFacadeInstance->preferredStableUri, $derivedUnitFacadeInstance->preferredStableUri, array('absolute' => true));
1011
        }
1012
      }
1013
1014
1015
      $out .= '</'. $element_tag .'>';
1016
1017
    }
1018
  } // END Specimen type designations
1019
1020
  // TextualTypeDesignation .........................
1021 04d5812b Andreas Kohlbecker
  usort($textual_type_designations, 'compare_textual_type_designation');
1022 79904336 Andreas Kohlbecker
  if(!empty($textual_type_designations)) {
1023
    foreach ($textual_type_designations as $textual_type_designation) {
1024
      $annotations_and_sources = handle_annotations_and_sources(
1025
        $textual_type_designation,
1026
        array(
1027
          'sources_as_content' => false, // as footnotes
1028
          'link_to_name_used_in_source' => false,
1029
          'link_to_reference' => true,
1030 a6c4c53c Andreas Kohlbecker
          'add_footnote_keys' => true,
1031
          'bibliography_aware' => false
1032
        ),
1033 79904336 Andreas Kohlbecker
        '',
1034
        RenderHints::getFootnoteListKey() // passing a defined key to avoid separate annotation footnote key see https://dev.e-taxonomy.eu/redmine/issues/8543
1035
      );
1036 a6c4c53c Andreas Kohlbecker
      $encasement =  $textual_type_designation->verbatim ? '"' : '';
1037
      $out .= '<' . $element_tag . ' class="' . html_class_attribute_ref($textual_type_designation) . '">' . type_designation_status_label_markup(null)
1038
        . ': ' .  $encasement . trim($textual_type_designation->text_L10n->text) . $encasement .  $annotations_and_sources['foot_note_keys'] .'</' . $element_tag . '>';
1039
//      if(is_array( $annotations_and_sources['source_references'])){
1040
//        $citation_markup = join(', ', $annotations_and_sources['source_references']);
1041
//      }
1042
//      $out .= $citation_markup;
1043 79904336 Andreas Kohlbecker
    }
1044
  }
1045
1046
  // Footnotes for citations, collection acronym?s.
1047
  // footnotes should be rendered in the parent element so we
1048
  // are relying on the FootnoteListKey set there
1049
  $_fkey = FootnoteManager::addNewFootnote(
1050
    RenderHints::getFootnoteListKey(),
1051
    (isset($derivedUnitFacadeInstance->collection->titleCache) ? $derivedUnitFacadeInstance->collection->titleCache : FALSE)
1052
  );
1053
  $out .= theme('cdm_footnote_key', array('footnoteKey' => $_fkey, 'separator' => $separator));
1054
  $out .= '</' . $enclosing_tag .'>';
1055
1056
  RenderHints::popFromRenderStack();
1057
1058
  return $out;
1059
}
1060
1061
1062 a9a04561 Andreas Kohlbecker
/**
1063
 * Composes the textual representation for the type designation of taxon name identified by the uuid in with a map for the location data.
1064 41a348be Andreas Kohlbecker
 *
1065 a9a04561 Andreas Kohlbecker
 * @param $taxon_name_uuid
1066 10858926 Andreas Kohlbecker
 * @param $show_specimen_details
1067 a9a04561 Andreas Kohlbecker
 * @return array
1068 ae177dac Andreas Kohlbecker
 *    A drupal render array with the following elements:
1069 a9a04561 Andreas Kohlbecker
 *    - 'type_designations'
1070
 *    - 'map'
1071 ae177dac Andreas Kohlbecker
 *    - 'specimens'
1072 a9a04561 Andreas Kohlbecker
 *
1073
 * @ingroup compose
1074
 */
1075 10858926 Andreas Kohlbecker
function compose_type_designations($taxon_name_uuid, $show_specimen_details = false)
1076 a9a04561 Andreas Kohlbecker
{
1077 41a348be Andreas Kohlbecker
  $render_array = array(
1078
    'type_designations' => array(),
1079
    'map' => array(),
1080
    );
1081 a9a04561 Andreas Kohlbecker
  $type_designations = cdm_ws_get(CDM_WS_PORTAL_NAME_TYPEDESIGNATIONS, $taxon_name_uuid);
1082
  if ($type_designations) {
1083 fb939fdc Andreas Kohlbecker
    usort($type_designations, 'compare_specimen_type_designation');
1084 a9a04561 Andreas Kohlbecker
    $render_array['type_designations'] = markup_to_render_array(
1085 0c720425 Andreas Kohlbecker
      render_type_designations($type_designations, 'div', 'div')
1086 a9a04561 Andreas Kohlbecker
    );
1087
1088
    $render_array['map'] = compose_type_designations_map($type_designations);
1089
  }
1090
  return $render_array;
1091
}
1092
1093
1094 471192e3 Andreas Kohlbecker
/**
1095
 * Composes the TypedEntityReference to name type designations passed as associatve array.
1096
 *
1097 0e617798 Andreas Kohlbecker
 * @param $type_entity_refs array
1098 471192e3 Andreas Kohlbecker
 *   an associative array of name type type => TypedEntityReference for name type designations as
1099
 *   produced by the eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager
1100
 *
1101
 * @ingroup compose
1102
 */
1103
function compose_name_type_designations($type_entity_refs){
1104
  $render_array = array();
1105 e1e2d593 Andreas Kohlbecker
  $preferredStableUri = '';
1106 f5396e17 Andreas Kohlbecker
  foreach($type_entity_refs as $type_status => $name_types){
1107
    foreach ($name_types as $name_type){
1108 2d95e99f Andreas Kohlbecker
      $type_designation = cdm_ws_get(CDM_WS_TYPEDESIGNATION, array($name_type->uuid, 'preferredUri'));
1109 f5396e17 Andreas Kohlbecker
      if(isset($type_designation->typeSpecimen->preferredStableUri) && $type_designation->typeSpecimen->preferredStableUri){
1110
        $preferredStableUri = $type_designation->typeSpecimen->preferredStableUri;
1111
      }
1112 9c12cb7f Andreas Kohlbecker
      $render_array[] = markup_to_render_array('<div class="name_type_designation ' . html_class_attribute_ref($name_type)  . '"><span class="type-status">'. ucfirst($type_status) . "</span>: "
1113 f5396e17 Andreas Kohlbecker
        . $name_type->label
1114
        . ($preferredStableUri ? " ". l($preferredStableUri,  $preferredStableUri) : '')
1115
        . '</div>');
1116
      }
1117 f5e7f68e Andreas Kohlbecker
  }
1118
  return $render_array;
1119
}
1120
1121
/**
1122 41a348be Andreas Kohlbecker
 * Composes the specimen type designations with map from the the $type_entity_refs
1123 f5e7f68e Andreas Kohlbecker
 *
1124
 * @param $type_entity_refs array
1125
 *   an associative array of specimen type type => TypedEntityReference for specimen type designations as
1126
 *   produced by the eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager
1127
 *
1128 e69c4103 Andreas Kohlbecker
 * @param $show_media_specimen
1129 41a348be Andreas Kohlbecker
 * @return array
1130 6abd581c Andreas Kohlbecker
 *    A drupal render array with the following elements:
1131 41a348be Andreas Kohlbecker
 *    - 'type_designations'
1132
 *    - 'map'
1133
 *
1134
 * @ingroup compose
1135
 *
1136 f5e7f68e Andreas Kohlbecker
 */
1137 e69c4103 Andreas Kohlbecker
function compose_specimen_type_designations($type_entity_refs, $show_media_specimen){
1138 204e8173 Andreas Kohlbecker
1139 f5e7f68e Andreas Kohlbecker
  $render_array = array();
1140 204e8173 Andreas Kohlbecker
1141 0e617798 Andreas Kohlbecker
  static $annotations_and_sources_config = [
1142
    'sources_as_content' => TRUE,
1143
    'link_to_name_used_in_source' => FALSE,
1144
    'link_to_reference' => TRUE,
1145
    'add_footnote_keys' => FALSE,
1146
    'bibliography_aware' => FALSE
1147
  ];
1148
1149 41a348be Andreas Kohlbecker
  $type_designation_list = array();
1150 d8de8d4d Andreas Kohlbecker
  uksort($type_entity_refs, "compare_type_designation_status_labels");
1151 0e617798 Andreas Kohlbecker
  foreach($type_entity_refs as $type_status => $type_designation_entity_refs){
1152
    foreach($type_designation_entity_refs as $type_designation_entity_ref){
1153 204e8173 Andreas Kohlbecker
1154 0e617798 Andreas Kohlbecker
      $type_designation = cdm_ws_get(CDM_WS_PORTAL_TYPEDESIGNATION, array($type_designation_entity_ref->uuid));
1155 e69c4103 Andreas Kohlbecker
      $type_designation_list[] = $type_designation; // collect for the map
1156
1157 0e617798 Andreas Kohlbecker
      $derived_unit_facade_dto = cdm_ws_get(CDM_WS_PORTAL_DERIVEDUNIT_FACADE, $type_designation->typeSpecimen->uuid);
1158 b8a0efb3 Andreas Kohlbecker
      // the media specimen is not contained in the $type_designation returned by CDM_PORTAL_TYPEDESIGNATION, so we need to fetch it separately
1159
      $mediaSpecimen = cdm_ws_get(CDM_WS_PORTAL_OCCURRENCE, array($type_designation->typeSpecimen->uuid, 'mediaSpecimen'));
1160
1161 204e8173 Andreas Kohlbecker
1162 67f5eac2 Andreas Kohlbecker
      $preferredStableUri = '';
1163
      $citation_markup = '';
1164
      $media = '';
1165 204e8173 Andreas Kohlbecker
1166 0e617798 Andreas Kohlbecker
      // annotations and sources for the $derived_unit_facade_dto
1167
      $annotations_and_sources = handle_annotations_and_sources(
1168
        $derived_unit_facade_dto,
1169
        $annotations_and_sources_config,
1170
        '',
1171
        null
1172
      );
1173
      $source_citations = $annotations_and_sources['source_references'];
1174
      $foot_note_keys = $annotations_and_sources['foot_note_keys'];
1175
1176 67f5eac2 Andreas Kohlbecker
      // preferredStableUri
1177
      if(isset($type_designation->typeSpecimen->preferredStableUri) && $type_designation->typeSpecimen->preferredStableUri){
1178
        $preferredStableUri = $type_designation->typeSpecimen->preferredStableUri;
1179 204e8173 Andreas Kohlbecker
      }
1180 67f5eac2 Andreas Kohlbecker
1181 e69c4103 Andreas Kohlbecker
      if($show_media_specimen && $mediaSpecimen){
1182 67f5eac2 Andreas Kohlbecker
        // compose output
1183
        // mediaURI
1184
        if(isset($mediaSpecimen->representations[0])) {
1185
          $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
1186
          $captionElements = array(
1187
            '#uri' => t('open media'),
1188
            'elements' => array('-none-'),
1189
            'sources_as_content' => true
1190
          );
1191
          $media = compose_cdm_media_gallerie(array(
1192
            'mediaList' => array($mediaSpecimen),
1193 0e617798 Andreas Kohlbecker
            'galleryName' => CDM_DATAPORTAL_TYPE_SPECIMEN_GALLERY_NAME . '_' . $type_designation_entity_ref->uuid,
1194 67f5eac2 Andreas Kohlbecker
            'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
1195
            'cols' => $gallery_settings['cdm_dataportal_media_cols'],
1196
            'captionElements' => $captionElements,
1197
          ));
1198
        }
1199 0e617798 Andreas Kohlbecker
        // citation and detail for the media specimen
1200 67f5eac2 Andreas Kohlbecker
        $annotations_and_sources = handle_annotations_and_sources(
1201 0e617798 Andreas Kohlbecker
          $mediaSpecimen,
1202
          $annotations_and_sources_config,
1203
          '',
1204
          null
1205 67f5eac2 Andreas Kohlbecker
        );
1206
        if(is_array( $annotations_and_sources['source_references'])){
1207 0e617798 Andreas Kohlbecker
          $source_citations = array_merge($source_citations, $annotations_and_sources['source_references']);
1208
        }
1209
        if($annotations_and_sources['foot_note_keys']){
1210
          $foot_note_keys .= ', ' . $annotations_and_sources['foot_note_keys'];
1211 67f5eac2 Andreas Kohlbecker
        }
1212 204e8173 Andreas Kohlbecker
      }
1213
1214 0e617798 Andreas Kohlbecker
      $citation_markup = join(', ', $source_citations);
1215
1216
      $specimen_markup = $derived_unit_facade_dto->titleCache;
1217
      if(isset($derived_unit_facade_dto->specimenLabel) && $derived_unit_facade_dto->specimenLabel){
1218
        $specimen_markup = str_replace(
1219
          $derived_unit_facade_dto->specimenLabel,
1220
          l($derived_unit_facade_dto->specimenLabel, path_to_specimen($type_designation->typeSpecimen->uuid)), $specimen_markup);
1221 e69c4103 Andreas Kohlbecker
      }
1222
1223 0e617798 Andreas Kohlbecker
      $type_designation_render_array = markup_to_render_array(
1224
        '<div class="type_designation_entity_ref ' . html_class_attribute_ref($type_designation_entity_ref)  . '">
1225 2154d631 Andreas Kohlbecker
          <span class="type-status">' . ucfirst($type_status) . "</span>: "
1226 0e617798 Andreas Kohlbecker
        . $specimen_markup . $foot_note_keys
1227 67f5eac2 Andreas Kohlbecker
        . ($citation_markup ? ' '. $citation_markup : '')
1228
        . ($preferredStableUri ? " ". l($preferredStableUri,  $preferredStableUri) : '')
1229
        . $media
1230
        . '</div>');
1231 e69c4103 Andreas Kohlbecker
1232
      $render_array['type_designations'][] = $type_designation_render_array;
1233 67f5eac2 Andreas Kohlbecker
    }
1234 471192e3 Andreas Kohlbecker
  }
1235 41a348be Andreas Kohlbecker
  if(count($type_designation_list) > 0 ){
1236
    $render_array['map'] = compose_type_designations_map($type_designation_list);
1237
  } else {
1238
    $render_array['map'] = array();
1239
  }
1240 471192e3 Andreas Kohlbecker
  return $render_array;
1241
}
1242
1243 2fd6da0b Andreas Kohlbecker
/**
1244 ef686dd8 Andreas Kohlbecker
 * @param $name_rel
1245
 * @param $current_name_uuid
1246
 * @param $current_taxon_uuid
1247
 * @param $suppress_if_current_name_is_source // FIXME UNUSED !!!!
1248
 * @param $show_name_cache_only
1249
 *    The nameCache will be shown instead of the titleCache if this parameter is true.
1250
 * @return null|string
1251
 */
1252 96614dfe Andreas Kohlbecker
function name_relationship_markup($name_rel, $current_name_uuid, $current_taxon_uuid, $show_name_cache_only = false){
1253 ef686dd8 Andreas Kohlbecker
1254
  $relationship_markup = null;
1255
1256
  $current_name_is_toName = $current_name_uuid == $name_rel->toName->uuid;
1257
1258
  if($current_name_is_toName){
1259
    $name = $name_rel->fromName;
1260
  } else {
1261
    $name = $name_rel->toName;
1262
  }
1263
1264 a7560a18 Andreas Kohlbecker
  cdm_load_tagged_full_title($name);
1265
1266 ef686dd8 Andreas Kohlbecker
  $highlited_synonym_uuid = isset ($name->taxonBases[0]->uuid) ? $name->taxonBases[0]->uuid : '';
1267
  if(!$show_name_cache_only){
1268
    $relationship_markup = render_taxon_or_name($name,
1269 2f65af04 Andreas Kohlbecker
      url(path_to_name($name->uuid, $current_taxon_uuid, $highlited_synonym_uuid, false))
1270 ef686dd8 Andreas Kohlbecker
    );
1271
  } else {
1272
    $relationship_markup = l(
1273
      '<span class="' . html_class_attribute_ref($name) . '"">' . $name->nameCache . '</span>',
1274 2f65af04 Andreas Kohlbecker
      path_to_name($name->uuid, $current_taxon_uuid, $highlited_synonym_uuid, false),
1275 ef686dd8 Andreas Kohlbecker
      array('html' => true)
1276
    );
1277
  }
1278
1279
  return $relationship_markup;
1280
}
1281
1282
1283
/**
1284 96614dfe Andreas Kohlbecker
 * Composes an inline representation of selected name relationships
1285 16592d77 Andreas Kohlbecker
 *
1286 23a017dd Andreas Kohlbecker
 * The output of this function will be usually appended to taxon name representations.
1287 ef686dd8 Andreas Kohlbecker
 * Only the following types are displayed: LATER_HOMONYM, TREATED_AS_LATER_HOMONYM, BLOCKING_NAME_FOR, ORTHOGRAPHIC_VARIANT
1288
 *
1289
 * LATER_HOMONYM, TREATED_AS_LATER_HOMONYM, BLOCKING_NAME_FOR are displayed as
1290
 * non {titleCache} nec {titleCache} nec {titleCache} whereas the related names
1291
 * are ordered alphabetically.
1292
 *
1293
 * ORTHOGRAPHIC_VARIANT is displayed as 'ort. var. {nameCache}'
1294 23a017dd Andreas Kohlbecker
 *
1295
 * Related issues:
1296
 *   - https://dev.e-taxonomy.eu/redmine/issues/5697 "Show name conserved against as [non xxx]"
1297
 *   - https://dev.e-taxonomy.eu/redmine/issues/6678 "How to correctly show name relationship "orth. var." in dataportal"
1298
 *   - https://dev.e-taxonomy.eu/redmine/issues/5857
1299 ef686dd8 Andreas Kohlbecker
 *   - https://dev.e-taxonomy.eu/redmine/issues/2001 "[Cichorieae Portal] Name Relationship -> blocking name are not shown"
1300 0b7bbf68 Andreas Kohlbecker
 *
1301 d4ea0dd9 Andreas Kohlbecker
 * @param $name_relations
1302
 *    The list of CDM NameRelationsips
1303
 * @param $current_name_uuid
1304 3c088da3 Andreas Kohlbecker
 *    The Uuid of the name for which the relations are to be rendered, the current name will be hidden when
1305
 *    rendering the relation an only the other name is shown. Parameter is REQUIRED.
1306
 * @param $suppress_if_current_name_is_source
1307
 *    The display of the relation will be
1308
 *    suppressed is the current name is on the source of the relation edge.
1309
 *    That is if it is on the from side of the relation. Except for 'blocking name for' which is
1310
 *    an inverse relation. For this relation type the toName is taken in to account.
1311 d4ea0dd9 Andreas Kohlbecker
 * @param $current_taxon_uuid
1312
 *    The taxon to be omitted from related taxa. This is only used to create links, see path_to_name()
1313 96614dfe Andreas Kohlbecker
 * @return array
1314
 *    A drupal render array
1315
 *
1316
 * @ingroup Compose
1317 0b7bbf68 Andreas Kohlbecker
 */
1318 96614dfe Andreas Kohlbecker
function compose_name_relationships_inline($name_relations, $current_name_uuid, $current_taxon_uuid, $suppress_if_current_name_is_source = true) {
1319 f695daf4 Andreas Kohlbecker
1320 0b7bbf68 Andreas Kohlbecker
  RenderHints::pushToRenderStack('homonym');
1321
  // the render stack element homonyms is being used in the default render templates !!!, see CDM_NAME_RENDER_TEMPLATES_DEFAULT
1322
1323 ef686dd8 Andreas Kohlbecker
  $selected_name_rel_uuids = variable_get(CDM_NAME_RELATIONSHIP_INLINE_TYPES, unserialize(CDM_NAME_RELATIONSHIP_INLINE_TYPES_DEFAULT));
1324 7efd13a9 Andreas Kohlbecker
  $name_rel_type_filter = array('direct' => array(), 'inverse' => array());
1325
  foreach ($selected_name_rel_uuids as $uuid){
1326
    $name_rel_type_filter['direct'][$uuid] = $uuid;
1327
    if($uuid != UUID_NAMERELATIONSHIPTYPE_MISSPELLING){
1328
      $name_rel_type_filter['inverse'][$uuid] = $uuid;
1329
    }
1330
  }
1331 6421984d Andreas Kohlbecker
1332 1636cc86 Andreas Kohlbecker
  $list_prefix = '<span class="name_relationships">[';
1333
  $list_suffix = ']</span>';
1334 96614dfe Andreas Kohlbecker
  $item_prefix = '<span class="item">';
1335
  $item_suffix = '</span> ';
1336 f8d5d6d9 Andreas Kohlbecker
  $render_array = compose_name_relationships($name_relations, $name_rel_type_filter, $current_name_uuid, $current_taxon_uuid, $list_prefix, $list_suffix, $item_prefix, $item_suffix);
1337 7efd13a9 Andreas Kohlbecker
1338
  // remove the glue space from the last item element which has been added by the $item_suffix = '</span> '
1339
  $items_ctn = count($render_array['list']['items']);
1340
  if($items_ctn){
1341
    $render_array['list']['items'][$items_ctn - 1]['#suffix'] = '</span>';
1342
  }
1343 0b7bbf68 Andreas Kohlbecker
1344
  RenderHints::popFromRenderStack();
1345 96614dfe Andreas Kohlbecker
  return $render_array;
1346 d4ea0dd9 Andreas Kohlbecker
}
1347
1348 ef686dd8 Andreas Kohlbecker
/**
1349
 * Composes an list representation of the name relationships.
1350
 *
1351
 * The output of this function will be usually appended to taxon name representations.
1352
 *
1353
 * Related issues:
1354
 *   - https://dev.e-taxonomy.eu/redmine/issues/5697 "Show name conserved against as [non xxx]"
1355
 *   - https://dev.e-taxonomy.eu/redmine/issues/6678 "How to correctly show name relationship "orth. var." in dataportal"
1356
 *   - https://dev.e-taxonomy.eu/redmine/issues/5857
1357
 *
1358
 * @param $name_relations
1359
 *    The list of CDM NameRelationsips
1360
 * @param $current_name_uuid
1361
 *    The Uuid of the name for which the relations are to be rendered, the current name will be hidden when
1362
 *    rendering the relation an only the other name is shown. Parameter is REQUIRED.
1363
 * @param $current_taxon_uuid
1364
 *    The taxon to be omitted from related taxa. This is only used to create links, see path_to_name()
1365
 * @return array
1366
 *    A drupal render array
1367
 *
1368
 * @ingroup Compose
1369
 */
1370 96614dfe Andreas Kohlbecker
function compose_name_relationships_list($name_relations, $current_name_uuid, $current_taxon_uuid) {
1371 ef686dd8 Andreas Kohlbecker
1372
  // $ordered_name_relation_type_uuids = array_keys(cdm_terms_by_type_as_option('NameRelationshipType', CDM_ORDER_BY_ORDER_INDEX_ASC));
1373
1374 222784c5 Andreas Kohlbecker
  $key = 'name_relationships';
1375
  RenderHints::pushToRenderStack($key);
1376
  if(!RenderHints::getFootnoteListKey()){
1377
    RenderHints::setFootnoteListKey($key);
1378
  }
1379 ef686dd8 Andreas Kohlbecker
  // the render stack element homonyms is being used in the default render templates !!!, see CDM_NAME_RENDER_TEMPLATES_DEFAULT
1380
1381 85669a85 Andreas Kohlbecker
  $selected_name_rel_uuids = variable_get(CDM_NAME_RELATIONSHIP_LIST_TYPES, cdm_vocabulary_as_defaults(UUID_NAME_RELATIONSHIP_TYPE));
1382 7efd13a9 Andreas Kohlbecker
  $name_rel_type_filter = array('direct' => array(), 'inverse' => array());
1383
  foreach ($selected_name_rel_uuids as $uuid){
1384
    $name_rel_type_filter['direct'][$uuid] = $uuid;
1385
    $name_rel_type_filter['inverse'][$uuid] = $uuid;
1386
  }
1387 ef686dd8 Andreas Kohlbecker
1388 96614dfe Andreas Kohlbecker
  $list_prefix = '<div class="relationships_list name_relationships">';
1389
  $list_suffix = '</div>';
1390
  $item_prefix = '<div class="item">';
1391
  $item_suffix = '</div>';
1392
1393 f8d5d6d9 Andreas Kohlbecker
  $render_array = compose_name_relationships($name_relations, $name_rel_type_filter, $current_name_uuid, $current_taxon_uuid, $list_prefix, $list_suffix, $item_prefix, $item_suffix);
1394 96614dfe Andreas Kohlbecker
1395
  RenderHints::popFromRenderStack();
1396
  $render_array['footnotes'] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => RenderHints::getFootnoteListKey())));
1397 222784c5 Andreas Kohlbecker
  if(RenderHints::getFootnoteListKey() == $key) {
1398
    RenderHints::clearFootnoteListKey();
1399
  }
1400 96614dfe Andreas Kohlbecker
  return $render_array;
1401
}
1402
1403
/**
1404
 * @param $name_relations
1405 7efd13a9 Andreas Kohlbecker
 * @param $name_rel_type_filter
1406
 *   Associative array with two keys:
1407
 *   - 'direct': the relationship type uuids for the direct direction of the relation edge to be included
1408
 *   - 'inverse': the relationship type uuids for the direct direction of the relation edge to be included
1409 96614dfe Andreas Kohlbecker
 * @param $current_name_uuid
1410
 * @param $current_taxon_uuid
1411
 * @param $list_prefix
1412
 * @param $list_suffix
1413
 * @param $item_prefix
1414
 * @param $item_suffix
1415
 * @return array
1416
 *
1417
 * @ingroup Compose
1418
 */
1419 7efd13a9 Andreas Kohlbecker
function compose_name_relationships($name_relations, $name_rel_type_filter, $current_name_uuid, $current_taxon_uuid,
1420 f8d5d6d9 Andreas Kohlbecker
                                    $list_prefix, $list_suffix, $item_prefix, $item_suffix)
1421 96614dfe Andreas Kohlbecker
{
1422
  $non_nec_name_reltype_uuids = array(UUID_NAMERELATIONSHIPTYPE_LATER_HOMONYM,
1423
    UUID_NAMERELATIONSHIPTYPE_TREATED_AS_LATER_HOMONYM,
1424 1636cc86 Andreas Kohlbecker
    UUID_NAMERELATIONSHIPTYPE_CONSERVED_AGAINST,
1425 7efd13a9 Andreas Kohlbecker
    UUID_NAMERELATIONSHIPTYPE_MISSPELLING,
1426 96614dfe Andreas Kohlbecker
    UUID_NAMERELATIONSHIPTYPE_BLOCKING_NAME_FOR);
1427
1428 ef686dd8 Andreas Kohlbecker
  $render_array = array(
1429
    'list' => array(
1430 96614dfe Andreas Kohlbecker
      '#prefix' => $list_prefix,
1431
      '#suffix' => $list_suffix,
1432 ef686dd8 Andreas Kohlbecker
      'items' => array()
1433
    ),
1434
    'footnotes' => array()
1435
  );
1436
1437 96614dfe Andreas Kohlbecker
  if ($name_relations) {
1438 ef686dd8 Andreas Kohlbecker
1439
    // remove all relations which are not selected in the settings and
1440 96614dfe Andreas Kohlbecker
    // separate all LATER_HOMONYM, TREATED_AS_LATER_HOMONYM, BLOCKING_NAME_FOR relations and ORTHOGRAPHIC_VARIANTs
1441 ef686dd8 Andreas Kohlbecker
    // for special handling
1442
    $filtered_name_rels = array();
1443
    $non_nec_name_rels = array();
1444
    $orthographic_variants = array();
1445 96614dfe Andreas Kohlbecker
    foreach ($name_relations as $name_rel) {
1446
      $rel_type_uuid = $name_rel->type->uuid;
1447 7efd13a9 Andreas Kohlbecker
      $is_inverse_relation = $current_name_uuid == $name_rel->toName->uuid;
1448
      if ((!$is_inverse_relation && isset($name_rel_type_filter['direct'][$rel_type_uuid]) && $name_rel_type_filter['direct'][$rel_type_uuid])
1449
        ||($is_inverse_relation && isset($name_rel_type_filter['inverse'][$rel_type_uuid]) && $name_rel_type_filter['inverse'][$rel_type_uuid])) {
1450
1451 96614dfe Andreas Kohlbecker
        if (array_search($rel_type_uuid, $non_nec_name_reltype_uuids) !== false && (
1452
            $current_name_uuid == $name_rel->fromName->uuid && $rel_type_uuid != UUID_NAMERELATIONSHIPTYPE_BLOCKING_NAME_FOR
1453
            || $current_name_uuid == $name_rel->toName->uuid && $rel_type_uuid == UUID_NAMERELATIONSHIPTYPE_BLOCKING_NAME_FOR
1454
          )
1455
        ){
1456 ef686dd8 Andreas Kohlbecker
          $non_nec_name_rels[] = $name_rel;
1457 96614dfe Andreas Kohlbecker
        } else if (UUID_NAMERELATIONSHIPTYPE_ORTHOGRAPHIC_VARIANT == $rel_type_uuid) {
1458 ef686dd8 Andreas Kohlbecker
          $orthographic_variants[] = $name_rel;
1459
        } else {
1460 96614dfe Andreas Kohlbecker
1461 ef686dd8 Andreas Kohlbecker
          $filtered_name_rels[] = $name_rel;
1462
        }
1463
      }
1464
    }
1465
    $name_relations = $filtered_name_rels;
1466
1467
    usort($name_relations, 'compare_name_relations_by_term_order_index');
1468
1469 7efd13a9 Andreas Kohlbecker
    // compose
1470 96614dfe Andreas Kohlbecker
    foreach ($name_relations as $name_rel) {
1471 ef686dd8 Andreas Kohlbecker
1472 96614dfe Andreas Kohlbecker
      $is_inverse_relation = $current_name_uuid == $name_rel->toName->uuid;
1473 ef686dd8 Andreas Kohlbecker
1474 f8d5d6d9 Andreas Kohlbecker
      $rel_footnote_key_markup = name_relationship_footnote_markup($name_rel);
1475 96614dfe Andreas Kohlbecker
      $relationship_markup = name_relationship_markup($name_rel, $current_name_uuid, $current_taxon_uuid);
1476 ef686dd8 Andreas Kohlbecker
1477
      $label = cdm_relationship_type_term_abbreviated_label($name_rel->type, $is_inverse_relation);
1478
      $symbol = cdm_relationship_type_term_symbol($name_rel->type, $is_inverse_relation);
1479 f8d5d6d9 Andreas Kohlbecker
      $symbol_markup = '<span class="symbol" title="' . $label . '">' . $symbol . '</span>' . $rel_footnote_key_markup . ' ';
1480
      $relationship_markup = $symbol_markup . $relationship_markup;
1481 96614dfe Andreas Kohlbecker
      if ($relationship_markup) {
1482 ef686dd8 Andreas Kohlbecker
        $render_array['list']['items'][] = markup_to_render_array($relationship_markup,
1483
          null,
1484 96614dfe Andreas Kohlbecker
          $item_prefix,
1485
          $item_suffix);
1486 ef686dd8 Andreas Kohlbecker
      }
1487
    }
1488
1489
    // name relationships to be displayed as non nec
1490 96614dfe Andreas Kohlbecker
    if (count($non_nec_name_rels) > 0) {
1491 ef686dd8 Andreas Kohlbecker
      $non_nec_markup = '';
1492 96614dfe Andreas Kohlbecker
      foreach ($non_nec_name_rels as $name_rel) {
1493
        $is_inverse_relation = $current_name_uuid == $name_rel->toName->uuid;
1494 f8d5d6d9 Andreas Kohlbecker
        $rel_footnote_key_markup = name_relationship_footnote_markup($name_rel);
1495 96614dfe Andreas Kohlbecker
        $relationship_markup = name_relationship_markup($name_rel, $current_name_uuid, $current_taxon_uuid);
1496
        $label = cdm_relationship_type_term_abbreviated_label($name_rel->type, $is_inverse_relation);
1497 ef686dd8 Andreas Kohlbecker
        $symbol = $non_nec_markup ? ' nec ' : 'non';
1498 f8d5d6d9 Andreas Kohlbecker
        $symbol_markup = '<span class="symbol" title="' . $label . '">' . $symbol . '</span>' . $rel_footnote_key_markup .  ' ';
1499
        $non_nec_markup .= $symbol_markup . $relationship_markup;
1500 96614dfe Andreas Kohlbecker
      }
1501
      if ($non_nec_markup) {
1502
        $render_array['list']['items'][] = markup_to_render_array($non_nec_markup,
1503
          null,
1504
          $item_prefix,
1505
          $item_suffix);
1506 ef686dd8 Andreas Kohlbecker
      }
1507
    }
1508
1509
    // orthographic variants
1510 96614dfe Andreas Kohlbecker
    if (count($orthographic_variants) > 0) {
1511
      foreach ($orthographic_variants as $name_rel) {
1512
1513
        $is_inverse_relation = $current_name_uuid == $name_rel->toName->uuid;
1514 f8d5d6d9 Andreas Kohlbecker
        $rel_footnote_key_markup = name_relationship_footnote_markup($name_rel);
1515 96614dfe Andreas Kohlbecker
        $relationship_markup = name_relationship_markup($name_rel, $current_name_uuid, $current_taxon_uuid, TRUE);
1516 222784c5 Andreas Kohlbecker
        $nomref_footnote_key_markup = nomenclatural_reference_footnote_key_markup($name_rel->toName);
1517 96614dfe Andreas Kohlbecker
        $label = cdm_relationship_type_term_abbreviated_label($name_rel->type, $is_inverse_relation);
1518 ef686dd8 Andreas Kohlbecker
        $symbol = cdm_relationship_type_term_symbol($name_rel->type, $is_inverse_relation);
1519 f8d5d6d9 Andreas Kohlbecker
        $symbol_markup = '<span class="symbol" title="' . $label . '">' . $symbol . '</span>' . $rel_footnote_key_markup .  ' ';
1520 222784c5 Andreas Kohlbecker
        $relationship_markup = $symbol_markup . $relationship_markup . $nomref_footnote_key_markup;
1521 ef686dd8 Andreas Kohlbecker
      }
1522 96614dfe Andreas Kohlbecker
      if ($relationship_markup) {
1523 ef686dd8 Andreas Kohlbecker
        $render_array['list']['items'][] = markup_to_render_array($relationship_markup,
1524
          null,
1525 96614dfe Andreas Kohlbecker
          $item_prefix,
1526
          $item_suffix);
1527 ef686dd8 Andreas Kohlbecker
      }
1528
    }
1529
  }
1530
  return $render_array;
1531
}
1532
1533
/**
1534
 * @param $name_rel
1535
 * @return string
1536
 */
1537
function name_relationship_footnote_markup($name_rel)
1538
{
1539
  $footnote_markup = '';
1540
  $footnote_key_markup = '';
1541 222784c5 Andreas Kohlbecker
  if (isset($name_rel->ruleConsidered) && $name_rel->ruleConsidered) {
1542 ef686dd8 Andreas Kohlbecker
    $footnote_markup = '<span class="rule_considered">' . $name_rel->ruleConsidered . '</span> ';
1543
  }
1544
  if (isset($name_rel->citation)) {
1545 040bf76f Andreas Kohlbecker
    $footnote_markup .= '<span class="reference">' . $name_rel->citation->titleCache . '</span>';
1546 ef686dd8 Andreas Kohlbecker
  }
1547 222784c5 Andreas Kohlbecker
  if (isset($name_rel->citationMicroReference) && $name_rel->citationMicroReference) {
1548 394d8d07 Andreas Kohlbecker
    $footnote_markup .= (isset($name_rel->citation) ? ':' : '') . ' <span class="reference_detail">' . $name_rel->citationMicroReference . '</span>';
1549 ef686dd8 Andreas Kohlbecker
  }
1550
  if ($footnote_markup) {
1551
    $fnkey = FootnoteManager::addNewFootnote(RenderHints::getFootnoteListKey(), $footnote_markup);
1552
    $footnote_key_markup = theme('cdm_footnote_key', array(
1553
      'footnoteKey' => $fnkey,
1554
      'separator' => ',',
1555
      'highlightable' => TRUE,
1556
      'separator_off' => TRUE,
1557
    ));
1558
  }
1559
  return $footnote_key_markup;
1560
}
1561
1562 222784c5 Andreas Kohlbecker
/**
1563
 * @param $nom_status
1564
 * @return string
1565
 */
1566
function nomenclatural_status_footnote_markup($nom_status)
1567
{
1568
  // NomenclaturalStatus is a subclass of ReferencedEntityBase
1569
  // and has the same structure as TaxonNameRelationship
1570
  return name_relationship_footnote_markup($nom_status);
1571
}
1572
1573 ef686dd8 Andreas Kohlbecker
/**
1574
 * @param $name
1575
 * @return string
1576
 */
1577 222784c5 Andreas Kohlbecker
function nomenclatural_reference_footnote_key_markup($name)
1578 ef686dd8 Andreas Kohlbecker
{
1579
  $footnote_markup = '';
1580
  $footnote_key_markup = '';
1581
  if (isset($name->nomenclaturalReference) && $name->nomenclaturalReference) {
1582
    $footnote_markup .= '<span class="reference">' . $name->nomenclaturalReference->titleCache . '</span>';
1583
  }
1584
  if (isset($name->nomenclaturalMicroReference)) {
1585
    $footnote_markup .= ($footnote_key_markup ? ':' : '') . '<span class="reference_detail">' . $name->nomenclaturalMicroReference . '</span>';
1586
  }
1587
  if ($footnote_markup) {
1588
    $fnkey = FootnoteManager::addNewFootnote(RenderHints::getFootnoteListKey(), $footnote_markup);
1589
    $footnote_key_markup = theme('cdm_footnote_key', array(
1590
      'footnoteKey' => $fnkey,
1591
      'separator' => ',',
1592
      'highlightable' => TRUE,
1593
      'separator_off' => TRUE,
1594
    ));
1595
  }
1596
  return $footnote_key_markup;
1597
}
1598
1599 222784c5 Andreas Kohlbecker
1600 d4ea0dd9 Andreas Kohlbecker
/**
1601
 * @param $taxon
1602
 * @return array
1603
 */
1604
function cdm_name_relationships_for_taxon($taxon)
1605
{
1606
  $from_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_FROM_NAMERELATIONS, $taxon->uuid);
1607
  $to_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_TO_NAMERELATIONS, $taxon->uuid);
1608
  $name_relations = array_merge($from_name_relations, $to_name_relations);
1609
  return $name_relations;
1610 0b7bbf68 Andreas Kohlbecker
}
1611
1612
1613 d4ea0dd9 Andreas Kohlbecker
/**
1614 2fd6da0b Andreas Kohlbecker
 * Recursively searches the array for the $key and sets the given value.
1615
 *
1616
 * @param mixed $key
1617
 *   Key to search for.
1618
 * @param mixed $value
1619
 *   Value to set.'
1620
 * @param array $array
1621
 *   Array to search in.
1622
 *
1623
 * @return bool
1624
 *   True if the key has been found.
1625
 */
1626
function &array_setr($key, $value, array &$array) {
1627
  $res = NULL;
1628
  foreach ($array as $k => &$v) {
1629
    if ($key == $k) {
1630
      $v = $value;
1631
      return $array;
1632
    }
1633
    elseif (is_array($v)) {
1634
      $innerArray = array_setr($key, $value, $v);
1635
      if ($innerArray) {
1636
        return $array;
1637
      }
1638
    }
1639
  }
1640
  return $res;
1641
}
1642
1643
/**
1644
 * @todo Please document this function.
1645
 * @see http://drupal.org/node/1354
1646
 */
1647
function &get_preceding_contentElement($contentElementKey, array &$renderTemplate) {
1648
  $res = NULL;
1649
  $precedingElement = NULL;
1650
  foreach ($renderTemplate as &$part) {
1651
    foreach ($part as $key => &$element) {
1652
      if ($key == $contentElementKey) {
1653
        return $precedingElement;
1654
      }
1655
      $precedingElement = $element;
1656
    }
1657
  }
1658
  return $res;
1659
}
1660
1661
/**
1662
 * @todo Please document this function.
1663
 * @see http://drupal.org/node/1354
1664
 */
1665
function &get_preceding_contentElementKey($contentElementKey, array &$renderTemplate) {
1666
  $res = NULL;
1667
  $precedingKey = NULL;
1668
  foreach ($renderTemplate as &$part) {
1669
    if (is_array($part)) {
1670
      foreach ($part as $key => &$element) {
1671
        if ($key == $contentElementKey) {
1672
          return $precedingKey;
1673
        }
1674
        if (!str_beginsWith($key, '#')) {
1675
          $precedingKey = $key;
1676
        }
1677
      }
1678
    }
1679
  }
1680
  return $res;
1681
}
1682 c2545e1c Andreas Kohlbecker
1683
function nameTypeToDTYPE($dtype){
1684
  static $nameTypeLabelMap = array(
1685
    "ICNB" => "BacterialName",
1686
    "ICNAFP" => "BotanicalName",
1687
    "ICNCP" => "CultivarPlantName",
1688
    "ICZN" => "ZoologicalName",
1689
    "ICVCN" => "ViralName",
1690
    "Any taxon name" => "TaxonName",
1691
    "NonViral" => "TaxonName",
1692
    "Fungus" => "BotanicalName",
1693
    "Plant" => "BotanicalName",
1694
    "Algae" => "BotanicalName",
1695
  );
1696
  return $nameTypeLabelMap[$dtype];
1697
1698
}
1699 ef686dd8 Andreas Kohlbecker
1700
1701
function compare_name_relations_by_term_order_index($name_rel1, $name_rel2){
1702
  return compare_terms_by_order_index($name_rel1->type, $name_rel2->type);
1703
}
1704 b90ef618 Andreas Kohlbecker
1705
/**
1706
 * Provides an array with the different registration types covered by the passed registration.
1707
 *
1708
 * The labels in the returned array are translatable.
1709
 *
1710
 * See also https://dev.e-taxonomy.eu/redmine/issues/8016
1711
 *
1712
 * @param $registration_dto
1713
 * @return array
1714
 *    An array of the labels describing the different registration types covered by the passed registration.
1715
 */
1716
function registration_types($registration_dto){
1717
  $reg_type_labels = array();
1718
  if(isset($registration_dto->nameRef)){
1719 0a02c62f Andreas Kohlbecker
    $reg_type_labels["name"] = t("new name");
1720
    $reg_type_labels["taxon"] = t("new taxon");
1721 b90ef618 Andreas Kohlbecker
    $name_relations = cdm_ws_fetch_all(str_replace("$0", $registration_dto->nameRef->uuid, CDM_WS_PORTAL_NAME_NAME_RELATIONS));
1722 0a02c62f Andreas Kohlbecker
    $is_new_combination = true;
1723 b90ef618 Andreas Kohlbecker
    foreach($name_relations as $name_rel){
1724
      if(isset($name_rel->type->uuid)){
1725
        $name_is_from_name = $registration_dto->nameRef->uuid == $name_rel->fromName->uuid;
1726
        switch($name_rel->type->uuid) {
1727
          case UUID_NAMERELATIONSHIPTYPE_BASIONYM:
1728
            if(!$name_is_from_name){
1729 0a02c62f Andreas Kohlbecker
              $reg_type_labels["basionym"] = t("new combination");
1730
              $is_new_combination = true;
1731 b90ef618 Andreas Kohlbecker
            }
1732
            break;
1733
          case UUID_NAMERELATIONSHIPTYPE_REPLACED_SYNONYM:
1734
            if(!$name_is_from_name) {
1735 0a02c62f Andreas Kohlbecker
              $is_new_combination = true;
1736 b90ef618 Andreas Kohlbecker
            }
1737
            break;
1738
          case UUID_NAMERELATIONSHIPTYPE_VALIDATED_BY_NAME:
1739
            if(!$name_is_from_name) {
1740 0a02c62f Andreas Kohlbecker
              $reg_type_labels["validation"] = t("validation");
1741 b90ef618 Andreas Kohlbecker
            }
1742
            break;
1743
          case UUID_NAMERELATIONSHIPTYPE_ORTHOGRAPHIC_VARIANT:
1744
            if(!$name_is_from_name) {
1745 0a02c62f Andreas Kohlbecker
              $reg_type_labels["orth_var"] = t("orthographical correction");
1746 b90ef618 Andreas Kohlbecker
            }break;
1747
          default:
1748
            // NOTHING
1749
        }
1750
      }
1751
    }
1752 0a02c62f Andreas Kohlbecker
    if($is_new_combination){
1753
      unset($reg_type_labels["taxon"]);
1754
    }
1755 b90ef618 Andreas Kohlbecker
  }
1756
  if(isset($registration_dto->orderdTypeDesignationWorkingSets)){
1757 0a02c62f Andreas Kohlbecker
    $reg_type_labels[] = t("new nomenclatural type");
1758 b90ef618 Andreas Kohlbecker
  }
1759
  return $reg_type_labels;
1760 b059b449 Andreas Kohlbecker
}
1761
1762
/**
1763
 * Collects and deduplicates the type designations associated with the passes synonyms.
1764
 *
1765
 * @param $synonymy_group
1766
 *    An array containing a homotypic or heterotypic group of names.
1767 5f188298 Andreas Kohlbecker
 * @param $accepted_taxon_name_uuid
1768 34852f2d Andreas Kohlbecker
 *    The uuid of the accepted taxon name. Optional parameter which is required when composing
1769
 *    the information for the homotypic group. In this case the accepted taxon is not included
1770
 *    in the $synonymy_group and must therefor passed in this second parameter.
1771
 *
1772 b059b449 Andreas Kohlbecker
 * @return array
1773
 *    The type designations
1774
 */
1775 dfbc27b0 Andreas Kohlbecker
function type_designations_for_synonymy_group($synonymy_group, $accepted_taxon_name_uuid = null)
1776
{
1777
  if (count($synonymy_group) > 0) {
1778 34852f2d Andreas Kohlbecker
    $name_uuid = array_pop($synonymy_group)->name->uuid;
1779
  } else {
1780
    $name_uuid = $accepted_taxon_name_uuid;
1781
  }
1782
  if ($name_uuid) {
1783
   $type_designations = cdm_ws_get(CDM_WS_PORTAL_NAME_TYPEDESIGNATIONS_IN_HOMOTYPICAL_GROUP, $name_uuid);
1784
    if ($type_designations) {
1785 3d14fdcf Andreas Kohlbecker
      return $type_designations;
1786
    }
1787 b059b449 Andreas Kohlbecker
  }
1788 34852f2d Andreas Kohlbecker
1789 dfbc27b0 Andreas Kohlbecker
  return array();
1790 fb939fdc Andreas Kohlbecker
}
1791
1792
1793
/**
1794 04d5812b Andreas Kohlbecker
 * Compares two SpecimenTypeDesignations
1795 fb939fdc Andreas Kohlbecker
 *
1796
 * @param object $a
1797
 *   A SpecimenTypeDesignation.
1798
 * @param object $b
1799
 *   SpecimenTypeDesignation.
1800
 */
1801
function compare_specimen_type_designation($a, $b) {
1802
1803 04d5812b Andreas Kohlbecker
  $cmp_by_status = compare_type_designations_by_status($a,$b);
1804
  if($cmp_by_status !== 0){
1805
    return $cmp_by_status;
1806
  }
1807 fb939fdc Andreas Kohlbecker
1808
  $aQuantifier = FALSE;
1809
  $bQuantifier = FALSE;
1810
  if ($aQuantifier == $bQuantifier) {
1811
    // Sort alphabetically.
1812
    $a_text =  isset($a->typeSpecimen->titleCache) ? preg_replace('/[\[\]\"]/', '', $a->typeSpecimen->titleCache) : '';
1813
    $b_text =  isset($b->typeSpecimen->titleCache) ? preg_replace('/[\[\]\"]/', '', $b->typeSpecimen->titleCache) : '';
1814
    return strcasecmp($a_text, $b_text);
1815
  }
1816 04d5812b Andreas Kohlbecker
  return ($aQuantifier < $bQuantifier) ? -1 : (($aQuantifier > $bQuantifier) ? 1 : 0);
1817
}
1818
1819
/**
1820
 * Compares the status of two TypeDesignations
1821
 *
1822
 * @param object $a
1823
 *   A TypeDesignation
1824
 * @param object $b
1825
 *   TypeDesignation
1826
 */
1827
function compare_type_designations_by_status($a, $b) {
1828 e5a89a58 Andreas Kohlbecker
  $status_a = isset($a->typeStatus) ? $a->typeStatus : null;
1829
  $status_b = isset($b->typeStatus) ? $b->typeStatus : null;
1830
  return compare_type_designation_status($status_a, $status_b);
1831 fb939fdc Andreas Kohlbecker
}
1832
1833
/**
1834 04d5812b Andreas Kohlbecker
 * Compares two TypeDesignationStatusBase
1835 fb939fdc Andreas Kohlbecker
 *
1836
 * @param object $a
1837
 *   A TypeDesignationStatusBase.
1838
 * @param object $b
1839
 *   TypeDesignationStatusBase.
1840
 */
1841
function compare_type_designation_status($a, $b) {
1842
  $type_status_order = type_status_order();
1843
  $aQuantifier = FALSE;
1844
  $bQuantifier = FALSE;
1845
  if (isset($a->label) && isset($b->label)) {
1846
    $aQuantifier = array_search($a->label, $type_status_order);
1847
    $bQuantifier = array_search($b->label, $type_status_order);
1848
  }
1849 04d5812b Andreas Kohlbecker
  return ($aQuantifier < $bQuantifier) ? -1 : (($aQuantifier > $bQuantifier) ? 1 : 0);
1850
}
1851
1852
/**
1853
 * Compares the two TextualTypeDesignations
1854
 *
1855
 * @param object $a
1856
 *   A TextualTypeDesignations.
1857
 * @param object $b
1858
 *   TextualTypeDesignations.
1859
 */
1860
function compare_textual_type_designation($a, $b) {
1861
1862
  $cmp_by_status = compare_type_designations_by_status($a,$b);
1863
  if($cmp_by_status !== 0){
1864
    return $cmp_by_status;
1865
  }
1866
1867
  $aQuantifier = FALSE;
1868
  $bQuantifier = FALSE;
1869
  if ($aQuantifier == $bQuantifier) {
1870
    // Sort alphabetically.
1871
    $a_text =  isset($a->text_L10n->text) ? $a->text_L10n->text : '';
1872
    $b_text =  isset($b->text_L10n->text) ? $b->text_L10n->text : '';
1873
    return strcasecmp($a_text, $b_text);
1874
  }
1875
  return ($aQuantifier < $bQuantifier) ? -1 : (($aQuantifier > $bQuantifier) ? 1 : 0);
1876 fb939fdc Andreas Kohlbecker
}
1877
1878 d8de8d4d Andreas Kohlbecker
1879
/**
1880
 * Compares two SpecimenTypeDesignation status labels
1881
 *
1882
 * @param string $a
1883
 *   A TypeDesignationStatus label.
1884
 * @param string $b
1885
 *   A TypeDesignationStatus label.
1886
 */
1887
function compare_type_designation_status_labels($a, $b) {
1888
1889
  $type_status_order = type_status_order();
1890
1891
  $aQuantifier = FALSE;
1892
  $bQuantifier = FALSE;
1893
  if (isset($a) && isset($b)) {
1894
    $aQuantifier = array_search($a, $type_status_order);
1895
    $bQuantifier = array_search($b, $type_status_order);
1896
  }
1897
  return ($aQuantifier < $bQuantifier) ? -1 : 1;
1898
}
1899
1900 fb939fdc Andreas Kohlbecker
/**
1901
 * @return array
1902
 */
1903
function type_status_order()
1904
{
1905
  /*
1906
    This is the desired sort order as of now: Holotype Isotype Lectotype
1907
    Isolectotype Syntype.
1908
    TODO Basically, what we are trying to do is, we define
1909
    an ordered array of TypeDesignation-states and use the index of this array
1910
    for comparison. This array has to be filled with the cdm- TypeDesignation
1911
    states and the order should be parameterisable inside the dataportal.
1912
    */
1913
  // Make that static for now.
1914
  $type_status_order = array(
1915
    'Epitype',
1916
    'Holotype',
1917
    'Isotype',
1918
    'Lectotype',
1919
    'Isolectotype',
1920
    'Syntype',
1921
    'Paratype'
1922
  );
1923
  return $type_status_order;
1924 4eab6eeb Andreas Kohlbecker
}
1925
1926
/**
1927
 * Return HTML for the lectotype citation with the correct layout.
1928
 *
1929
 * This function prints the lectotype citation with the correct layout.
1930
 * Lectotypes are renderized in the synonymy tab of a taxon if they exist.
1931
 *
1932
 * @param mixed $typeDesignation
1933
 *   Object containing the lectotype citation to print.
1934
 *
1935
 * @return string
1936
 *   Valid html string.
1937
 */
1938
function type_designation_citation_layout($typeDesignation, $footnote_separator = ',') {
1939
  $res = '';
1940
  $citation = $typeDesignation->citation;
1941
  $pages = $typeDesignation->citationMicroReference;
1942
  if(isset($typeDesignation->typeStatus->uuid) && isset($typeDesignation->typeStatus->representation_L10n)) {
1943
    if ( $typeDesignation->typeStatus->uuid == UUID_NTD_ORIGINAL_DESIGNATION || $typeDesignation->typeStatus->uuid == UUID_NTD_MONOTYPY) {
1944
      $res = ' (' . $typeDesignation->typeStatus->representation_L10n . ')';
1945
      return $res;
1946
    }
1947
  }
1948
1949
  if ($citation) {
1950
    // $type = $typeDesignation_citation->type;
1951
    $year = isset($citation->datePublished->start) ? substr($citation->datePublished->start, 0, 4) : '';
1952
    $author = isset($citation->authorship->titleCache) ? $citation->authorship->titleCache : '';
1953
    $res .= ' (designated by ';
1954
    $res .= $author;
1955
    $res .= ($year ? ' ' . $year : '');
1956
    $res .= ($pages ? ': ' . $pages : '');
1957
    // $res .= ')';
1958
1959
    // footnotes should be rendered in the parent element so we
1960
    // are relying on the FootnoteListKey set there
1961
    $fkey_typeDesignation = FootnoteManager::addNewFootnote(RenderHints::getFootnoteListKey(), $typeDesignation->citation->titleCache);
1962
    $res .= theme('cdm_footnote_key', array(
1963
        'footnoteKey' => $fkey_typeDesignation,
1964
        'separator' => $footnote_separator,
1965
        'highlightable' => TRUE,
1966
        'separator_off' => TRUE,
1967
      )) . ')';
1968
  }
1969
  return $res;
1970
}
1971
1972
/**
1973
 * Creates markup for the status of a type designation. In case the status or its representation is missing the label will be set to "Type"
1974
 *
1975
 * @param $type_designation
1976
 * @return string
1977
 */
1978
function type_designation_status_label_markup($type_designation)
1979
{
1980
  return '<span class="type-status">'
1981
    . ((isset($type_designation->typeStatus->representation_L10n)) ? ucfirst($type_designation->typeStatus->representation_L10n) : t('Type')) . '</span>'
1982
    ;
1983
}