Project

General

Profile

Download (36.8 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
 *   The link path ot URL to be used for name parts if a link is forseen in the template
66
 *   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 2fd6da0b Andreas Kohlbecker
 * @param $nameLink
257
 *    URI to the taxon, @see path_to_taxon(), must be processed by url() before passing to this method
258
 * @param $refenceLink
259
 *    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
function render_taxon_or_name($taxon_name_or_taxon_base, $nameLink = NULL, $refenceLink = 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
    $taxonName = $taxon_name_or_taxon_base->name;
283 ea3933d7 Andreas Kohlbecker
    $is_doubtful = $taxon_name_or_taxon_base->doubtful;
284 2fd6da0b Andreas Kohlbecker
    // use the TaxonBase.taggedTitle so we have the secRef
285
    $taggedTitle = $taxon_name_or_taxon_base->taggedTitle;
286
  } else {
287 102f8c26 Andreas Kohlbecker
    // assuming this is a TaxonName
288 2fd6da0b Andreas Kohlbecker
    $taxonName = $taxon_name_or_taxon_base;
289
    $taggedTitle = $taxon_name_or_taxon_base->taggedName;
290
  }
291
292
293
  $renderTemplate = get_nameRenderTemplate(RenderHints::getRenderPath(), $nameLink, $refenceLink);
294 c2545e1c Andreas Kohlbecker
  $partDefinition = get_partDefinition($taxonName->nameType);
295 2fd6da0b Andreas Kohlbecker
296
  // Apply definitions to template.
297
  foreach ($renderTemplate as $part => $uri) {
298
299
    if (isset($partDefinition[$part])) {
300
      $renderTemplate[$part] = $partDefinition[$part];
301
    }
302
    if (is_array($uri) && isset($uri['#uri'])) {
303
      $renderTemplate[$part]['#uri'] = $uri['#uri'];
304
    }
305
  }
306
307 83dc60b9 Andreas Kohlbecker
  $secref_tagged_text = tagged_text_extract_secref($taggedTitle);
308
  $nom_status_tagged_text = tagged_text_extract_nomstatus($taggedTitle);
309 c35bab7f Andreas Kohlbecker
  $appended_phrase_tagged_text = array(); // this is filled later
310
311 e90899ac Andreas Kohlbecker
  normalize_tagged_text($taggedTitle);
312 2fd6da0b Andreas Kohlbecker
313
  $firstEntryIsValidNamePart =
314
    isset($taggedTitle)
315
    && is_array($taggedTitle)
316
    && isset($taggedTitle[0]->text)
317
    && is_string($taggedTitle[0]->text)
318
    && $taggedTitle[0]->text != ''
319
    && isset($taggedTitle[0]->type)
320
    && $taggedTitle[0]->type == 'name';
321
  $lastAuthorElementString = FALSE;
322
323 c35bab7f Andreas Kohlbecker
  $name_encasement = $is_invalid ? '"' : '';
324 54a3c136 Andreas Kohlbecker
  $doubtful_marker = $is_doubtful ? '?&#8239;' : ''; // 	&#8239; =  NARROW NO-BREAK SPACE
325 2330b553 Andreas Kohlbecker
  $doubtful_marker_markup = '';
326
327
  if($doubtful_marker){
328
    $doubtful_marker_markup = '<span class="doubtful">' . $doubtful_marker . '</span>';
329
  }
330 c35bab7f Andreas Kohlbecker
331
  // split off all appendedPhrase item  from the end of the array (usually there only should  be one)
332
  while($taggedTitle[count($taggedTitle)-1]->type == "appendedPhrase"){
333
    $appended_phrase_tagged_text[] = array_pop($taggedTitle);
334
  }
335
336 2fd6da0b Andreas Kohlbecker
  // Got to use second entry as first one, see ToDo comment below ...
337
  if ($firstEntryIsValidNamePart) {
338
339
    $taggedName = $taggedTitle;
340
    $hasNamePart_with_Authors = isset($renderTemplate['namePart']) && isset($renderTemplate['namePart']['authors']);
341
    $hasNameAuthorPart_with_Authors = isset($renderTemplate['nameAuthorPart']) && isset($renderTemplate['nameAuthorPart']['authors']);
342
343 c35bab7f Andreas Kohlbecker
344 2fd6da0b Andreas Kohlbecker
    if (!(($hasNamePart_with_Authors) || ($hasNameAuthorPart_with_Authors))) {
345
      // Find author and split off from name.
346
      // TODO expecting to find the author as the last element.
347
      /*
348
      if($taggedName[count($taggedName)- 1]->type == 'authors'){
349
        $authorTeam = $taggedName[count($taggedName)- 1]->text;
350
        unset($taggedName[count($taggedName)- 1]);
351
      }
352
      */
353
354
      // Remove all authors.
355
      $taggedNameNew = array();
356
      foreach ($taggedName as $element) {
357
        if ($element->type != 'authors') {
358
          $taggedNameNew[] = $element;
359
        }
360
        else {
361
          $lastAuthorElementString = $element->text;
362
        }
363
      }
364
      $taggedName = $taggedNameNew;
365 e90899ac Andreas Kohlbecker
      unset($taggedNameNew);
366 2fd6da0b Andreas Kohlbecker
    }
367 0f129a6f Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '">' . $doubtful_marker_markup . $name_encasement . cdm_tagged_text_to_markup($taggedName, $skiptags) . $name_encasement . '</span>';
368 2fd6da0b Andreas Kohlbecker
  }
369
  else {
370 2330b553 Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '_titleCache">' . $doubtful_marker_markup . $name_encasement . $taxonName->titleCache . $name_encasement . '</span>';
371 c35bab7f Andreas Kohlbecker
  }
372
373
374
  if(isset($appended_phrase_tagged_text[0])){
375 54a3c136 Andreas Kohlbecker
    $name .= ' <span class="appended-phrase">'. cdm_tagged_text_to_markup($appended_phrase_tagged_text) . '</span>';
376 2fd6da0b Andreas Kohlbecker
  }
377
378
  // Fill name into $renderTemplate.
379 c35bab7f Andreas Kohlbecker
  array_setr('name', $name , $renderTemplate);
380 2fd6da0b Andreas Kohlbecker
381
  // Fill with authorTeam.
382
  /*
383
  if($authorTeam){
384
    $authorTeamHtml = ' <span class="authorTeam">'.$authorTeam.'</span>';
385
    array_setr('authorTeam', $authorTeamHtml, $renderTemplate);
386
  }
387
  */
388
389
  // Fill with reference.
390
  if (isset($renderTemplate['referencePart']) && !$is_type_designation) {
391
392 eaff53f7 Andreas Kohlbecker
    $registrations = cdm_ws_get(CDM_WS_NAME, array($taxonName->uuid, "registrations"));
393
    $registration_markup = render_registrations($registrations);
394
395 2fd6da0b Andreas Kohlbecker
    // default separator
396
    $separator = '';
397
398
    // [Eckhard]:"Komma nach dem Taxonnamen ist grunsätzlich falsch,
399
    // Komma nach dem Autornamen ist überall dort falsch, wo ein "in" folgt."
400
    if (isset($renderTemplate['referencePart']['reference']) && isset($taxonName->nomenclaturalReference)) {
401
      $microreference = NULL;
402
      if (isset($renderTemplate['referencePart']['microreference'])&& isset($taxonName->nomenclaturalMicroReference)) {
403
        $microreference = $taxonName->nomenclaturalMicroReference;
404
      }
405
      $citation = cdm_ws_getNomenclaturalReference($taxonName->nomenclaturalReference->uuid, $microreference);
406
407
      // Find preceding element of the reference.
408
      $precedingKey = get_preceding_contentElementKey('reference', $renderTemplate);
409
      if (str_beginsWith($citation, ", in")) {
410
        $citation = substr($citation, 2);
411
        $separator = ' ';
412
      }
413
      elseif (!str_beginsWith($citation, "in") && $precedingKey == 'authors') {
414
        $separator = ', ';
415
      } else {
416
        $separator = ' ';
417
      }
418
419
420
      $referenceArray['#separator'] = $separator;
421 eaff53f7 Andreas Kohlbecker
      $referenceArray['#html'] = '<span class="reference">' . $citation . '</span>' . $registration_markup;
422 2fd6da0b Andreas Kohlbecker
      array_setr('reference', $referenceArray, $renderTemplate);
423
    }
424
425
    // If authors have been removed from the name part the last named authorteam
426
    // should be added to the reference citation, otherwise, keep the separator
427
    // out of the reference.
428
    if (isset($renderTemplate['referencePart']['authors']) && $lastAuthorElementString) {
429
      // If the nomenclaturalReference citation is not included in the
430 eaff53f7 Andreas Kohlbecker
      // reference part but display of the microreference
431 2fd6da0b Andreas Kohlbecker
      // is wanted, append the microreference to the authorTeam.
432
      $citation = '';
433
      if (!isset($renderTemplate['referencePart']['reference']) && isset($renderTemplate['referencePart']['microreference'])) {
434
        $separator = ": ";
435
        $citation = $taxonName->nomenclaturalMicroReference;
436
      }
437
      $referenceArray['#html'] = ' <span class="reference">' . $lastAuthorElementString . $separator . $citation . '</span>';
438
      array_setr('authors', $referenceArray, $renderTemplate);
439
    }
440
  }
441
442
  $is_reference_year = false;
443
  if (isset($renderTemplate['referenceYearPart']['reference.year'])) {
444
    if(isset($taxonName->nomenclaturalReference->datePublished)){
445
      $referenceArray['#html'] = ' <span class="reference">' . timePeriodToString($taxonName->nomenclaturalReference->datePublished) . '</span>';
446
      array_setr('reference.year', $referenceArray, $renderTemplate);
447
      $is_reference_year = true;
448
    }
449
  }
450
451 e90899ac Andreas Kohlbecker
  // Fill with status.
452 dce1dacc Andreas Kohlbecker
  if(isset($renderTemplate['statusPart']['status'])){
453 1d0407b7 Andreas Kohlbecker
    if (isset($nom_status_tagged_text[0])) {
454 0f129a6f Andreas Kohlbecker
        array_setr('status', '<span class="nomenclatural_status">' . cdm_tagged_text_to_markup($nom_status_tagged_text, array('postSeparator')) . '</span>', $renderTemplate);
455 e90899ac Andreas Kohlbecker
    }
456
  }
457
458 2fd6da0b Andreas Kohlbecker
  if (isset($renderTemplate['secReferencePart'])){
459
    if(isset($secref_tagged_text[1])){
460 e90899ac Andreas Kohlbecker
      $post_separator_markup = $is_reference_year ? '.': '';
461 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')){
462 4a1ab871 Andreas Kohlbecker
        $post_separator_markup = cdm_tagged_text_to_markup(array($nom_status_tagged_text[count($nom_status_tagged_text) - 1 ]));
463 e90899ac Andreas Kohlbecker
      };
464 2fd6da0b Andreas Kohlbecker
      array_setr('secReference',
465 e90899ac Andreas Kohlbecker
        $post_separator_markup
466 2fd6da0b Andreas Kohlbecker
          . ' <span class="sec_reference">'
467 4bfe18f9 Andreas Kohlbecker
          . join('', cdm_tagged_text_values($secref_tagged_text))
468 2fd6da0b Andreas Kohlbecker
          . '</span>', $renderTemplate);
469
    }
470
  }
471
472
  // Fill with protologues etc...
473
  $descriptionHtml = '';
474
  if (array_setr('description', TRUE, $renderTemplate)) {
475
    $descriptions = cdm_ws_get(CDM_WS_PORTAL_NAME_DESCRIPTIONS, $taxonName->uuid);
476
    foreach ($descriptions as $description) {
477
      if (!empty($description)) {
478
        foreach ($description->elements as $description_element) {
479
          $second_citation = '';
480
          if (isset($description_element->multilanguageText_L10n) && $description_element->multilanguageText_L10n->text) {
481
            $second_citation = '[& ' . $description_element->multilanguageText_L10n->text . '].';
482
          }
483
          $descriptionHtml .= $second_citation;
484 275b2642 Andreas Kohlbecker
          $descriptionHtml .= cdm_description_element_media(
485
              $description_element,
486
              array(
487 2fd6da0b Andreas Kohlbecker
                'application/pdf',
488
                'image/png',
489
                'image/jpeg',
490
                'image/gif',
491
                'text/html',
492
              )
493
          );
494
495
        }
496
      }
497
    }
498
    array_setr('description', $descriptionHtml, $renderTemplate);
499
  }
500
501
  // Render.
502 f695daf4 Andreas Kohlbecker
  $out = '';
503
  if(isset($_REQUEST['RENDER_PATH'])){
504
    // developer option to show the render path with each taxon name
505
    $out .= '<span class="render-path">' . RenderHints::getRenderPath() . '</span>';
506
  }
507
  $out .= '<span class="' . html_class_attribute_ref($taxon_name_or_taxon_base)
508
    . '" data-cdm-ref="/name/' . $taxonName->uuid . '" data-cdm-render-path="' . RenderHints::getRenderPath() .'">';
509 2fd6da0b Andreas Kohlbecker
510
  foreach ($renderTemplate as $partName => $part) {
511
    $separator = '';
512
    $partHtml = '';
513
    $uri = FALSE;
514
    if (!is_array($part)) {
515
      continue;
516
    }
517
    if (isset($part['#uri']) && is_string($part['#uri'])) {
518
      $uri = $part['#uri'];
519
      unset($part['#uri']);
520
    }
521
    foreach ($part as $key => $content) {
522
      $html = '';
523
      if (is_array($content)) {
524
        $html = $content['#html'];
525
        if(isset($content['#separator'])) {
526
          $separator = $content['#separator'];
527
        }
528
      }
529
      elseif (is_string($content)) {
530
        $html = $content;
531
      }
532
      $partHtml .= '<span class="' . $key . '">' . $html . '</span>';
533
    }
534
    if ($uri) {
535
      // cannot use l() here since the #uri aleady should have been processed through uri() at this point
536
      $out .= $separator . '<a href="' . $uri . '" class="' . $partName . '">' . $partHtml . '</a>';
537
538
    }
539
    else {
540
      $out .= $separator . $partHtml;
541
    }
542
  }
543
  $out .= '</span>';
544
  if ($show_annotations) {
545
    // $out .= theme('cdm_annotations_as_footnotekeys', $taxonName);
546
  }
547
  return $out;
548
}
549
550 7212f0bc Andreas Kohlbecker
551
552
/**
553
 * Composes information for a registration from a dto object
554
 *
555
 * @param $registration_dto
556
 * @param $with_citation
557
 *   Whether to show the citation.
558
 * @param $with_identifier
559
 *   Whether to add the identifier to the summary (in enabled)
560
 * @param $with_compact_summary
561
 *   Whether to display the name and type designations as compact summary or in extended form.
562
 *
563
 * @return array
564
 *    A drupal render array with the elements:
565
 *    - 'publication_date_and_office'
566
 *    - 'citation'
567
 *    - 'summary' OR  'name', 'name-relations', 'name_type_designations', 'specimen_table' (depending on parameter $with_compact_summary)
568
 * @ingroup compose
569
 */
570
function compose_registration_dto($registration_dto, $with_citation = true, $with_identifier = false, $with_compact_summary = true)
571
{
572
  $render_array = array();
573
  $media_link_map = array();
574
575
  if($with_compact_summary){
576
    // summary
577
    $taggged_text_expanded = cdm_tagged_text_expand_entity_references($registration_dto->summaryTaggedText);
578
    foreach ($taggged_text_expanded  as $tagged_text){
579
      if(isset($tagged_text->entityReference->type) && $tagged_text->entityReference->type == 'SpecimenTypeDesignation') {
580
        $mediaDTOs = cdm_ws_get('typedesignation/$0/media', array($tagged_text->entityReference->uuid));
581
        if(isset($mediaDTOs[0]->uri)){
582
          $media_url_key = '{link-' . $mediaDTOs[0]->uuid . '}';
583
          $tagged_text->text = str_replace('[icon]', '[icon]' . $media_url_key, $tagged_text->text);
584
          $media_link_map[$media_url_key] =  cdm_external_uri($mediaDTOs[0]->uri, true);
585
        }
586
      }
587
    }
588
    $registation_markup = cdm_tagged_text_to_markup($taggged_text_expanded);
589
    foreach($media_link_map as $media_url_key => $link){
590
      $registation_markup = str_replace($media_url_key, $link, $registation_markup);
591
    }
592
    if($with_identifier){
593
      $registation_markup .= " " . l ($registration_dto->identifier, $registration_dto->identifier);
594
    }
595
    $render_array['summary'] = markup_to_render_array('<p class="registration-summary">' . $registation_markup . "</p>", 0);
596
  } else {
597
    // name and typedesignation in detail
598
    if($registration_dto->nameRef){
599
      $name = cdm_ws_get(CDM_WS_PORTAL_NAME, $registration_dto->nameRef->uuid);
600
      $render_array['name'] = markup_to_render_array('<p class="name">' . render_taxon_or_name($name) . '</p>', 0);
601
      $name_relations = cdm_ws_fetch_all(str_replace("$0", $registration_dto->nameRef->uuid, CDM_WS_PORTAL_NAME_NAME_RELATIONS));
602
      $render_array['name_relations'] = markup_to_render_array(render_name_relationships_of($name_relations, $registration_dto->nameRef->uuid, null, false));
603
      $render_array['name_relations']['#weight'] = 10;
604
    }
605
    if(is_object($registration_dto->orderdTypeDesignationWorkingSets)) {
606
      $field_unit_uuids = array();
607
      $specimen_type_designation_refs = array();
608
      $name_type_designation_refs = array();
609
      foreach ((array)$registration_dto->orderdTypeDesignationWorkingSets as $field_unit_ref => $obj) {
610
        $tokens = explode("#", $field_unit_ref);
611
        foreach ($obj as $type_status => $entity_reference_list) {
612
          // NOTE: there is always only one element, since we use the foreach to extract the objects field name and value
613
          $entity_reference = $entity_reference_list[0];
614
        }
615
        if ($tokens[0] == 'NameTypeDesignation') {
616
          foreach ($obj as $type_status => $entity_reference_list) {
617
            $name_type_designation_refs[$type_status] = $entity_reference;
618
          }
619
        } else if ($tokens[0] == 'FieldUnit'){
620
          $field_unit_uuids[] = $tokens[1];
621
          $specimen_type_designation_refs[$type_status] = $entity_reference;
622
        } else {
623
          drupal_set_message("Unimplemented type: " . $tokens[0], 'error');
624
        }
625
      }
626
      if (count($name_type_designation_refs) > 0) {
627
        $render_array['name_type_designations'] = compose_name_type_designations($name_type_designation_refs);
628
        $render_array['name_type_designations']['#prefix'] = '<p class="name_type_designations">';
629
        $render_array['name_type_designations']['#suffix'] = '</p>';
630
        $render_array['name_type_designations']['#weight'] = 20;
631
      }
632
      if (count($field_unit_uuids) > 0) {
633
        $render_array['specimen_type_designations'] = compose_specimen_type_designations($specimen_type_designation_refs);
634
        // $render_array['specimen_table'] = compose_specimen_table($field_unit_uuids);
635
        // below citation (weight=20)
636
        $render_array['specimen_table']['#weight'] = 21;
637
      }
638
    }
639
  }
640
641
  // citation
642
  if ($with_citation) {
643
    $render_array['citation'] = markup_to_render_array(
644
      "<p class=\"citation " . html_class_attribute_ref(new TypedEntityReference("Reference", $registration_dto->citationUuid)) . "\">"
645
      . l($registration_dto->bibliographicInRefCitationString, path_to_reference($registration_dto->citationUuid))
646
      . "</p>",
647
      50);
648
  }
649
650
  // registration date and office
651
  if($registration_dto->registrationDate){
652
    $date_string = format_datetime($registration_dto->registrationDate);
653
    if(isset($registration_dto->institutionTitleCache) && $registration_dto->institutionTitleCache){
654
      $registration_date_insitute_markup =
655
        t("Registration on @date in @institution", array(
656
          '@date' => $date_string,
657
          '@institution' => $registration_dto->institutionTitleCache,
658
        ));
659
    } else {
660
      $registration_date_insitute_markup =
661
        t("Registration on @date", array(
662
          '@date' => $date_string
663
        ));
664
    }
665
    $render_array['publication_date_and_office'] = markup_to_render_array(
666
      '<p class"date-and-institute">'.$registration_date_insitute_markup . '</p>',
667
      100);
668
  }
669
670
  return $render_array;
671
}
672
673
674 eaff53f7 Andreas Kohlbecker
/**
675
 * @param $registrations
676
 * @return string
677
 */
678
function render_registrations($registrations)
679
{
680
  $registration_markup = '';
681
  $registration_markup_array = array();
682
  if ($registrations) {
683
    foreach ($registrations as $reg) {
684
      $registration_markup_array[] = render_registration($reg);
685
    }
686
    $registration_markup = " Registration" . (count($registration_markup_array) > 1 ? 's: ' : ': ')
687
      . join(', ', $registration_markup_array);
688
  }
689
  return $registration_markup;
690
}
691
692 471192e3 Andreas Kohlbecker
693 7212f0bc Andreas Kohlbecker
/**
694
 * Renders a registration
695
 *
696
 * @param $registration
697
 */
698
function render_registration($registration){
699
  $markup = '';
700
701
  if(isset($registration->identifier) && $registration->status == 'PUBLISHED'){
702
    $office_class_attribute = '';
703
    if(isset($registration->institution->titleCache)){
704
      $office_class_attribute = 'registration-' . strtolower(preg_replace('/[^a-zA-Z0-9]/', '-', $registration->institution->titleCache));
705
    }
706
    $markup = "<span class=\"registration $office_class_attribute\">" . l($registration->identifier, $registration->identifier) . ', '
707
      .  preg_replace('/^([^T]*)(.*)$/', '${1}', $registration->registrationDate)
708
      . '</span>';
709
  }
710
  return $markup;
711
}
712
713
714 471192e3 Andreas Kohlbecker
/**
715
 * Composes the TypedEntityReference to name type designations passed as associatve array.
716
 *
717 f5e7f68e Andreas Kohlbecker
 * @param $$type_entity_refs array
718 471192e3 Andreas Kohlbecker
 *   an associative array of name type type => TypedEntityReference for name type designations as
719
 *   produced by the eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager
720
 *
721
 * @ingroup compose
722
 */
723
function compose_name_type_designations($type_entity_refs){
724
  $render_array = array();
725
  foreach($type_entity_refs as $type_status => $name_type){
726 f5e7f68e Andreas Kohlbecker
    $type_designation = cdm_ws_get(CDM_TYPEDESIGNATION, array($name_type->uuid, 'preferredUri'));
727
    if(isset($type_designation->typeSpecimen->preferredStableUri) && $type_designation->typeSpecimen->preferredStableUri){
728
      $preferredStableUri = $type_designation->typeSpecimen->preferredStableUri;
729
    }
730
    $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>: "
731
      . $name_type->label
732
      . ($preferredStableUri ? " ". l($preferredStableUri,  $preferredStableUri) : '')
733
      . '</div>');
734
  }
735
  return $render_array;
736
}
737
738
/**
739
 * Composes the TypedEntityReference to specimen type designations passed as associatve array.
740
 *
741
 * @param $type_entity_refs array
742
 *   an associative array of specimen type type => TypedEntityReference for specimen type designations as
743
 *   produced by the eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager
744
 *
745
 * @ingroup compose
746
 */
747
function compose_specimen_type_designations($type_entity_refs){
748 204e8173 Andreas Kohlbecker
749 f5e7f68e Andreas Kohlbecker
  $render_array = array();
750 204e8173 Andreas Kohlbecker
751 f5e7f68e Andreas Kohlbecker
  foreach($type_entity_refs as $type_status => $specimen_type){
752
    $type_designation = cdm_ws_get(CDM_TYPEDESIGNATION, array($specimen_type->uuid));
753 204e8173 Andreas Kohlbecker
754 f5e7f68e Andreas Kohlbecker
    $preferredStableUri = '';
755 204e8173 Andreas Kohlbecker
    $citation_markup = '';
756
    $media = '';
757
758
    // preferredStableUri
759 f5e7f68e Andreas Kohlbecker
    if(isset($type_designation->typeSpecimen->preferredStableUri) && $type_designation->typeSpecimen->preferredStableUri){
760
      $preferredStableUri = $type_designation->typeSpecimen->preferredStableUri;
761
    }
762 204e8173 Andreas Kohlbecker
763
    $mediaSpecimen = cdm_ws_get(CDM_WS_PORTAL_OCCURRENCE, array($type_designation->typeSpecimen->uuid, 'mediaSpecimen'));
764
    if($mediaSpecimen){
765
      // compose output
766
      // mediaURI
767
      if(isset($mediaSpecimen->representations[0])) {
768
        $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
769
        $captionElements = array(
770
          '#uri' => t('open media'),
771
          'elements' => array('-none-'),
772
          'sources_as_content' => true
773
        );
774
        $media = compose_cdm_media_gallerie(array(
775
          'mediaList' => array($mediaSpecimen),
776
          'galleryName' => CDM_DATAPORTAL_TYPE_SPECIMEN_GALLERY_NAME . '_' . $specimen_type->uuid,
777
          'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
778
          'cols' => $gallery_settings['cdm_dataportal_media_cols'],
779
          'captionElements' => $captionElements,
780
        ));
781
      }
782
      // citation and detail
783
      $annotations_and_sources = handle_annotations_and_sources(
784
          $mediaSpecimen,
785
          array(
786
              'sources_as_content' => true,
787
              'link_to_name_used_in_source' => false,
788
              'link_to_reference' => true,
789
              'add_footnote_keys' => false,
790
              'bibliography_aware' => false),
791
          '',
792
          null
793
      );
794
      if(is_array( $annotations_and_sources['source_references'])){
795
        $citation_markup = join(', ', $annotations_and_sources['source_references']);
796
      }
797
    }
798
799
    $render_array[] = markup_to_render_array('<div class="specimen_type_designation ' . html_class_attribute_ref($specimen_type)  . '">
800
        <span class="type_status">' . ucfirst($type_status) . "</span>: "
801 f5e7f68e Andreas Kohlbecker
      . $specimen_type->label
802 204e8173 Andreas Kohlbecker
      . ($citation_markup ? ' '. $citation_markup : '')
803 f5e7f68e Andreas Kohlbecker
      . ($preferredStableUri ? " ". l($preferredStableUri,  $preferredStableUri) : '')
804 204e8173 Andreas Kohlbecker
      . $media
805 f5e7f68e Andreas Kohlbecker
      . '</div>');
806 471192e3 Andreas Kohlbecker
  }
807
  return $render_array;
808
}
809
810 2fd6da0b Andreas Kohlbecker
/**
811 d4ea0dd9 Andreas Kohlbecker
 * Renders the name relationships.
812 0b7bbf68 Andreas Kohlbecker
 *
813 d4ea0dd9 Andreas Kohlbecker
 * @param $name_relations
814
 *    The list of CDM NameRelationsips
815
 * @param $current_name_uuid
816 3c088da3 Andreas Kohlbecker
 *    The Uuid of the name for which the relations are to be rendered, the current name will be hidden when
817
 *    rendering the relation an only the other name is shown. Parameter is REQUIRED.
818
 * @param $suppress_if_current_name_is_source
819
 *    The display of the relation will be
820
 *    suppressed is the current name is on the source of the relation edge.
821
 *    That is if it is on the from side of the relation. Except for 'blocking name for' which is
822
 *    an inverse relation. For this relation type the toName is taken in to account.
823 d4ea0dd9 Andreas Kohlbecker
 * @param $current_taxon_uuid
824
 *    The taxon to be omitted from related taxa. This is only used to create links, see path_to_name()
825 0b7bbf68 Andreas Kohlbecker
 * @return String
826 d4ea0dd9 Andreas Kohlbecker
 *    The markup for the name relationships
827 0b7bbf68 Andreas Kohlbecker
 */
828 3c088da3 Andreas Kohlbecker
function render_name_relationships_of($name_relations, $current_name_uuid, $current_taxon_uuid, $suppress_if_current_name_is_source = true) {
829 f695daf4 Andreas Kohlbecker
830 6421984d Andreas Kohlbecker
  static $inverse_name_rels_uuids = array(UUID_NAMERELATIONSHIPTYPE_BLOCKING_NAME_FOR);
831
832 0b7bbf68 Andreas Kohlbecker
  RenderHints::pushToRenderStack('homonym');
833
  // the render stack element homonyms is being used in the default render templates !!!, see CDM_NAME_RENDER_TEMPLATES_DEFAULT
834
835 6421984d Andreas Kohlbecker
  $selected_name_rel_uuids = variable_get(CDM_NAME_RELATIONSHIP_TYPES, unserialize(CDM_NAME_RELATIONSHIP_TYPES_DEFAULT));
836
837 d4ea0dd9 Andreas Kohlbecker
  $relations_array = array();
838 0b7bbf68 Andreas Kohlbecker
839
  if ($name_relations) {
840 d4ea0dd9 Andreas Kohlbecker
    foreach ($name_relations as $name_rel) {
841 3c088da3 Andreas Kohlbecker
      if (!(isset($selected_name_rel_uuids[$name_rel->type->uuid]) && $selected_name_rel_uuids[$name_rel->type->uuid])) {
842 6421984d Andreas Kohlbecker
        // skip if not selected in the settings
843
        continue;
844 0b7bbf68 Andreas Kohlbecker
      }
845 3c088da3 Andreas Kohlbecker
      $is_inverse_relation = array_search($name_rel->type->uuid, $inverse_name_rels_uuids) !== false;
846
      $is_current_name_to_name = $current_name_uuid == $name_rel->toName->uuid;
847
      $is_current_name_from_name = $current_name_uuid == $name_rel->fromName->uuid;
848 d4ea0dd9 Andreas Kohlbecker
      $relationship_markup = null;
849 f1c8d19a Andreas Kohlbecker
850 3c088da3 Andreas Kohlbecker
      if($is_current_name_to_name && ($suppress_if_current_name_is_source && $is_inverse_relation || !$suppress_if_current_name_is_source)){
851
        $highlited_synonym_uuid = isset ($name_rel->fromName->taxonBases[0]->uuid) ? $name_rel->fromName->taxonBases[0]->uuid : '';
852
        $relationship_markup = render_taxon_or_name($name_rel->fromName,
853
          url(path_to_name($name_rel->fromName->uuid, $current_taxon_uuid, $highlited_synonym_uuid))
854
        );
855
      } else if($is_current_name_from_name && ($suppress_if_current_name_is_source && !$is_inverse_relation || !$suppress_if_current_name_is_source)){
856 d4ea0dd9 Andreas Kohlbecker
        $highlited_synonym_uuid = isset ($name_rel->toName->taxonBases[0]->uuid) ? $name_rel->toName->taxonBases[0]->uuid : '';
857 3c088da3 Andreas Kohlbecker
        $relationship_markup = render_taxon_or_name($name_rel->toName,
858
          url(path_to_name($name_rel->toName->uuid, $current_taxon_uuid, $highlited_synonym_uuid))
859
        );
860 0b7bbf68 Andreas Kohlbecker
      }
861 3c088da3 Andreas Kohlbecker
        
862 d4ea0dd9 Andreas Kohlbecker
      if($relationship_markup){
863
        if (count($relations_array)) {
864 6aa5dc6a Andreas Kohlbecker
          // lat: "non nec" == german: "weder noch"
865 d4ea0dd9 Andreas Kohlbecker
          $relations_array [] = 'nec ' . $relationship_markup;
866 6aa5dc6a Andreas Kohlbecker
        } else {
867 d4ea0dd9 Andreas Kohlbecker
          $relations_array [] = 'non ' . $relationship_markup;
868 6aa5dc6a Andreas Kohlbecker
        }
869 6421984d Andreas Kohlbecker
      }
870
871 0b7bbf68 Andreas Kohlbecker
    }
872
  }
873
874
  RenderHints::popFromRenderStack();
875 bbeade6a Andreas Kohlbecker
  return (count($relations_array) ?'<div class="name-relationships">[' . trim(join(" ", $relations_array)) . ']</div>' : '');
876 d4ea0dd9 Andreas Kohlbecker
}
877
878
/**
879
 * @param $taxon
880
 * @return array
881
 */
882
function cdm_name_relationships_for_taxon($taxon)
883
{
884
  $from_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_FROM_NAMERELATIONS, $taxon->uuid);
885
  $to_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_TO_NAMERELATIONS, $taxon->uuid);
886
  $name_relations = array_merge($from_name_relations, $to_name_relations);
887
  return $name_relations;
888 0b7bbf68 Andreas Kohlbecker
}
889
890
891 d4ea0dd9 Andreas Kohlbecker
/**
892 2fd6da0b Andreas Kohlbecker
 * Recursively searches the array for the $key and sets the given value.
893
 *
894
 * @param mixed $key
895
 *   Key to search for.
896
 * @param mixed $value
897
 *   Value to set.'
898
 * @param array $array
899
 *   Array to search in.
900
 *
901
 * @return bool
902
 *   True if the key has been found.
903
 */
904
function &array_setr($key, $value, array &$array) {
905
  $res = NULL;
906
  foreach ($array as $k => &$v) {
907
    if ($key == $k) {
908
      $v = $value;
909
      return $array;
910
    }
911
    elseif (is_array($v)) {
912
      $innerArray = array_setr($key, $value, $v);
913
      if ($innerArray) {
914
        return $array;
915
      }
916
    }
917
  }
918
  return $res;
919
}
920
921
/**
922
 * @todo Please document this function.
923
 * @see http://drupal.org/node/1354
924
 */
925
function &get_preceding_contentElement($contentElementKey, array &$renderTemplate) {
926
  $res = NULL;
927
  $precedingElement = NULL;
928
  foreach ($renderTemplate as &$part) {
929
    foreach ($part as $key => &$element) {
930
      if ($key == $contentElementKey) {
931
        return $precedingElement;
932
      }
933
      $precedingElement = $element;
934
    }
935
  }
936
  return $res;
937
}
938
939
/**
940
 * @todo Please document this function.
941
 * @see http://drupal.org/node/1354
942
 */
943
function &get_preceding_contentElementKey($contentElementKey, array &$renderTemplate) {
944
  $res = NULL;
945
  $precedingKey = NULL;
946
  foreach ($renderTemplate as &$part) {
947
    if (is_array($part)) {
948
      foreach ($part as $key => &$element) {
949
        if ($key == $contentElementKey) {
950
          return $precedingKey;
951
        }
952
        if (!str_beginsWith($key, '#')) {
953
          $precedingKey = $key;
954
        }
955
      }
956
    }
957
  }
958
  return $res;
959
}
960 c2545e1c Andreas Kohlbecker
961
function nameTypeToDTYPE($dtype){
962
  static $nameTypeLabelMap = array(
963
    "ICNB" => "BacterialName",
964
    "ICNAFP" => "BotanicalName",
965
    "ICNCP" => "CultivarPlantName",
966
    "ICZN" => "ZoologicalName",
967
    "ICVCN" => "ViralName",
968
    "Any taxon name" => "TaxonName",
969
    "NonViral" => "TaxonName",
970
    "Fungus" => "BotanicalName",
971
    "Plant" => "BotanicalName",
972
    "Algae" => "BotanicalName",
973
  );
974
  return $nameTypeLabelMap[$dtype];
975
976
}