Project

General

Profile

Download (32.8 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
3
 * @file
4
 * Name theming functions.
5
 *
6
 * @copyright
7
 *   (C) 2007-2012 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

    
16
/**
17
 * Return HTML for the lectotype citation with the correct layout.
18
 *
19
 * This function prints the lectotype citation with the correct layout.
20
 * Lectotypes are renderized in the synonymy tab of a taxon if they exist.
21
 *
22
 * @param mixed $typeDesignation
23
 *   Object containing the lectotype citation to print.
24
 *
25
 * @return string
26
 *   Valid html string.
27
 */
28
function type_designation_citation_layout($typeDesignation, $footnote_separator = ',') {
29
  $res = '';
30
  $citation = $typeDesignation->citation;
31
  $pages = $typeDesignation->citationMicroReference;
32
  if(isset($typeDesignation->typeStatus->uuid) && isset($typeDesignation->typeStatus->representation_L10n)) {
33
    if ( $typeDesignation->typeStatus->uuid == UUID_NTD_ORIGINAL_DESIGNATION || $typeDesignation->typeStatus->uuid == UUID_NTD_MONOTYPY) {
34
      $res = ' (' . $typeDesignation->typeStatus->representation_L10n . ')';
35
      return $res;
36
    }
37
  }
38

    
39
  if ($citation) {
40
    // $type = $typeDesignation_citation->type;
41
    $year = isset($citation->datePublished->start) ? substr($citation->datePublished->start, 0, 4) : '';
42
    $author = isset($citation->authorTeam->titleCache) ? $citation->authorTeam->titleCache : '';
43
    $res .= ' (designated by ';
44
    $res .= $author;
45
    $res .= ($year ? ' ' . $year : '');
46
    $res .= ($pages ? ': ' . $pages : '');
47
    // $res .= ')';
48
    $fkey_typeDesignation = FootnoteManager::addNewFootnote(RenderHints::getRenderPath(), $typeDesignation->citation->titleCache);
49
    $res .= theme('cdm_footnote_key', array(
50
      'footnoteKey' => $fkey_typeDesignation,
51
      'separator' => $footnote_separator,
52
      'highlightable' => TRUE,
53
      'separator_off' => TRUE,
54
    )) . ')';
55
  }
56
  return $res;
57
}
58

    
59
/**
60
 * @todo Please document this function.
61
 * @see http://drupal.org/node/1354
62
 */
63
function contains_type_designation($element, $collection) {
64
  $result = FALSE;
65
  foreach ($collection as $a) {
66
    if ($a->uuid == $element->uuid) {
67
      $result = TRUE;
68
    }
69
  }
70
  return $result;
71
}
72

    
73
/**
74
 * @todo Please document this function.
75
 * @see http://drupal.org/node/1354
76
 */
77
function cdm_add_type_designations($source, $extra) {
78
  if (is_array($source)) {
79
    $result = $source;
80
    if ($extra) {
81
      foreach ($extra as $element) {
82
        if (!contains_type_designation($element, $source)) {
83
          $result[] = $element;
84
        }
85
      }
86
    }
87
  }
88
  else {
89
    $result = $extra;
90
  }
91

    
92
  return $result;
93
}
94

    
95
/**
96
 * Renders and array of CDM TypeDesignations
97
 *
98
 * @param array $variables
99
 *   - typeDesignations: an array of cdm TypeDesignation entities to render
100
 */
101
function theme_cdm_typedesignations($variables) {
102
  $typeDesignations = $variables['typeDesignations'];
103

    
104
  // need to add element to render path since type designations
105
  // need other name render template
106
  RenderHints::pushToRenderStack('typedesignations');
107
  $out = '<ul class="typeDesignations">';
108
  $typeDesignation_footnotes = FALSE;
109
  $is_lectotype = FALSE;
110
  $specimenTypeDesignations = array();
111
  $separator = ',';
112
  foreach ($typeDesignations as $typeDesignation) {
113
    if ($typeDesignation->class == 'SpecimenTypeDesignation') {
114
      // SpecimenTypeDesignations should be ordered. Collect theme here only.
115
      $specimenTypeDesignations[] = $typeDesignation;
116
    }
117
    // It is a lectotype?
118
    else {
119
      if (isset($typeDesignation->typeStatus->uuid) && $typeDesignation->typeStatus->uuid == UUID_NTD_LECTOTYPE) {
120
        $is_lectotype = TRUE;
121
      }
122
      // It's a NameTypeDesignation.
123
      if ($typeDesignation->notDesignated) {
124
        $out .= '<li class="nameTypeDesignation"><span class="status">' . ($is_lectotype ? 'Lectotype' : 'Type') . '</span>: ' . t('not designated') . '</li>';
125
      }
126
      elseif ($typeDesignation->typeName) {
127
        $link_to_name_page = '?q=' . path_to_name($typeDesignation->typeName->uuid);
128
        $out .= '<li class="nameTypeDesignation"><span class="status">' . ($is_lectotype ? 'Lectotype' : 'Type') . '</span>';
129

    
130
        if ($typeDesignation->citation) {
131
          $out .= type_designation_citation_layout($typeDesignation, $separator);
132

    
133
        }
134
        $referenceUri = '';
135
        if (isset($typeDesignation->typeName->nomenclaturalReference)) {
136
          $referenceUri = url(path_to_reference($typeDesignation->typeName->nomenclaturalReference->uuid));
137
        }
138
        $out .= ': ' . theme('cdm_taxonName', array(
139
          'taxonName' => $typeDesignation->typeName,
140
          'nameLink' => $link_to_name_page,
141
          'refenceLink' => $referenceUri,
142
          'show_annotations' => TRUE,
143
          'is_type_designation' => TRUE,
144
          ));
145
      }
146
    }
147
  }
148

    
149
  if (!empty($specimenTypeDesignations)) {
150
    // Sorting might be different for dataportals so this has to be
151
    // parameterized.
152
    usort($specimenTypeDesignations, "compare_specimenTypeDesignationStatus");
153
    foreach ($specimenTypeDesignations as $std) {
154
      $typeReference = '';
155
      if (!empty($std->citation)) {
156
        $author_team = cdm_ws_get(CDM_WS_REFERENCE_AUTHORTEAM, $std->citation->uuid);
157
        $shortCitation = $author_team->titleCache;
158

    
159
        $shortCitation .= (strlen($shortCitation) > 0 ? ' ' : '') . partialToYear($std->citation->datePublished->start);
160
        $missingShortCitation = FALSE;
161
        if (strlen($shortCitation) == 0) {
162
          $shortCitation = theme('cdm_reference', array('reference' => $std->citation));
163
          $missingShortCitation = TRUE;
164
        }
165

    
166
        $typeReference .= '&nbsp;(' . t('designated by');
167
        $typeReference .= '&nbsp;<span class="typeReference ' . ($missingShortCitation ? '' : 'cluetip') . ' no-print" title="' . htmlspecialchars('|' . theme('cdm_reference', array('reference' => $std->citation)) . '|') . '">';
168
        $typeReference .= $shortCitation . '</span>';
169
        if (!empty($std->citationMicroReference)) {
170
          $typeReference .= ':' . $std->citationMicroReference;
171
        }
172
        $typeReference .= ')';
173

    
174
        $_fkey2 = FootnoteManager::addNewFootnote(RenderHints::getRenderPath(), $std->citation->titleCache);
175
        $typeReference .= theme('cdm_footnote_key', array(
176
          'footnoteKey' => $_fkey2,
177
          'separator' => $separator,
178
          'highlightable' => TRUE,
179
          'separator_off' => TRUE,
180
         ));
181
      }
182

    
183
      $derivedUnitFacadeInstance = null;
184

    
185
      $out .= '<li class="specimenTypeDesignation">';
186
      $out .= '<span class="status">'
187
        . ((isset($std->typeStatus->representation_L10n)) ? $std->typeStatus->representation_L10n : t('Type'))
188
        . $typeReference
189
        . '</span>: ';
190

    
191

    
192
      if (isset($std->typeSpecimen)) {
193
        $derivedUnitFacadeInstance = cdm_ws_get(CDM_WS_DERIVEDUNIT_FACADE, $std->typeSpecimen->uuid);
194
      }
195
      if ( isset($derivedUnitFacadeInstance ) ){
196
        $out .= $derivedUnitFacadeInstance->titleCache; // . ': ' . theme('cdm_specimen', array('specimenTypeDesignation' => $derivedUnitFacadeInstance));
197
      }
198

    
199
      // Footnotes for collection acronyms.
200
      $_fkey = FootnoteManager::addNewFootnote(
201
          RenderHints::getRenderPath(),
202
          (isset($derivedUnitFacadeInstance->collection->titleCache) ? $derivedUnitFacadeInstance->collection->titleCache : FALSE)
203
        );
204
      $out .= theme('cdm_footnote_key', array('footnoteKey' => $_fkey, 'separator' => $separator));
205
      $out .= '</li>';
206

    
207
    }
208
  }
209

    
210
  $out .= '</ul>';
211

    
212
  RenderHints::popFromRenderStack();
213

    
214
  return $out;
215
}
216

    
217
/**
218
 * FIXME this definitively has to be in another spot.
219
 * just didn't know where to put it right now.
220
 * Compares the status of two SpecimenTypeDesignations
221
 *
222
 * @param string $a
223
 *   A SpecimenTypeDesignations.
224
 * @param string $b
225
 *   SpecimenTypeDesignations.
226
 */
227
function compare_specimenTypeDesignationStatus($a, $b) {
228
  /*
229
  This is the desired sort order as of now: Holotype Isotype Lectotype
230
  Isolectotype Syntype.
231
  TODO Basically, what we are trying to do is, we define
232
  an ordered array of TypeDesignation-states and use the index of this array
233
  for comparison. This array has to be filled with the cdm- TypeDesignation
234
  states and the order should be parameterisable inside the dataportal.
235
  */
236
  // Make that static for now.
237
  $typeOrder = array(
238
    'Holotype',
239
    'Isotype',
240
    'Lectotype',
241
    'Isolectotype',
242
    'Syntype',
243
  );
244

    
245
  $aQuantifier = FALSE;
246
  $bQuantifier = FALSE;
247
  if (isset($a->typeStatus->label) && isset($b->typeStatus->label)) {
248
    $aQuantifier = array_search($a->typeStatus->label, $typeOrder);
249
    $bQuantifier = array_search($b->typeStatus->label, $typeOrder);
250
  }
251
  if ($aQuantifier == $bQuantifier) {
252
    // Sort alphabetically.
253
    return (isset($a->typeStatus->label) && isset($b->typeStatus->label) && $a->typeStatus->label < $b->typeStatus->label) ? -1 : 1;
254
  }
255
  return ($aQuantifier < $bQuantifier) ? -1 : 1;
256
}
257

    
258
/**
259
 * @todo Please document this function.
260
 * @see http://drupal.org/node/1354
261
 */
262
function theme_cdm_nameRelationships($variables) {
263
  $nameRelationships = $variables['nameRelationships'];
264
  $skipTypes = $variables['skipTypes'];
265
  if (!$nameRelationships) {
266
    return;
267
  }
268

    
269
  RenderHints::pushToRenderStack('nameRelationships');
270
  $footnoteListKey = 'nameRelationships';
271
  RenderHints::setFootnoteListKey($footnoteListKey);
272

    
273
  // Group by relationship type.
274
  $relationshipGroups = array();
275
  foreach ($nameRelationships as $nameRelationship) {
276
    if (!array_key_exists($nameRelationship->type->uuid, $relationshipGroups)) {
277
      $relationshipGroups[$nameRelationship->type->uuid] = array();
278
    }
279
    $relationshipGroups[$nameRelationship->type->uuid][] = $nameRelationship;
280
  }
281

    
282
  // Generate output.
283
  $out = '';
284
  $block = new stdclass(); // Empty object.
285
  foreach ($relationshipGroups as $group) {
286
    $type = $group[0]->type;
287

    
288
    if (is_array($skipTypes) && in_array($type->uuid, $skipTypes)) {
289
      continue;
290
    }
291

    
292
    $block->module = 'cdm_dataportal';
293
    $block->subject = t(ucfirst($type->inverseRepresentation_L10n));
294
    $block->delta = generalizeString(strtolower($type->inverseRepresentation_L10n));
295

    
296
    foreach ($group as $relationship) {
297
      $relatedNames[] = cdm_taggedtext2html($relationship->fromName->taggedName);
298
    }
299

    
300
    $block->content .= implode('; ', $relatedNames);
301
    $out .= theme('block', $block);
302
  }
303
  $out .= theme('cdm_footnotes', array('footnoteListKey' => $footnoteListKey, 'enclosingTag' => 'li'));
304

    
305
  RenderHints::popFromRenderStack();
306
  return $out;
307
}
308

    
309
/**
310
 * @todo Please document this function.
311
 * @see http://drupal.org/node/1354
312
 */
313
function theme_cdm_homotypicSynonymLine($variables) {
314
  $taxon = $variables['taxon'];
315
  $out = '';
316
  $out .= '<li class="synonym">' . cdm_related_taxon($taxon, UUID_HOMOTYPIC_SYNONYM_OF) . '</li>';
317

    
318
  return $out;
319
}
320

    
321
/**
322
 * @todo Please document this function.
323
 * @see http://drupal.org/node/1354
324
 */
325
function theme_cdm_heterotypicSynonymyGroup($variables) {
326
  $homotypicalGroup = $variables['homotypicalGroup'];
327
  RenderHints::pushToRenderStack('heterotypicSynonymyGroup');
328

    
329
  $out = '';
330
  $out = '<div class="heterotypic-synonymy-group"><ul class="heterotypicSynonymyGroup">';
331
  $footnoteListKey = (isset($homotypicalGroup[0]) ? $homotypicalGroup[0]->uuid : 'NULL');
332
  RenderHints::setFootnoteListKey($footnoteListKey);
333

    
334
  $is_first_entry = TRUE;
335
  $typeDesignations = NULL;
336
  foreach ($homotypicalGroup as $synonym) {
337
    if ($is_first_entry) {
338
      $is_first_entry = FALSE;
339
      $typeDesignations = cdm_ws_get(CDM_WS_PORTAL_NAME_TYPEDESIGNATIONS, $synonym->name->uuid);
340
      // Is first list entry.
341
      $out .= '<li class="firstentry synonym">' . cdm_related_taxon($synonym, UUID_HETEROTYPIC_SYNONYM_OF) . '</li>';
342
    }
343
    else {
344
      $out .= '<li class="synonym">' . cdm_related_taxon($synonym, UUID_HOMOTYPIC_SYNONYM_OF) . '</li>';
345
    }
346
  }
347

    
348
  if ($typeDesignations) {
349
    $out .= theme('cdm_typedesignations', array('typeDesignations' => $typeDesignations));
350
  }
351
  $out .= '</ul>';
352

    
353
  // ------- footnotes ------- //
354
  $out .= '<ul class="footnotes">';
355
  $out .= theme('cdm_annotation_footnotes', array('footnoteListKey' => $footnoteListKey, 'enclosingTag' => 'li'));
356
  $out .= '</ul>';
357

    
358
  $out .= '</div>';
359

    
360
  RenderHints::popFromRenderStack();
361
  return $out;
362
}
363

    
364
/**
365
 * @todo Please document this function.
366
 * @see http://drupal.org/node/1354
367
 */
368
function theme_cdm_homotypicSynonymyGroup($variables) {
369
  $synonymList = $variables['synonymList'];
370
  $accepted_taxon_uuid = $variables['accepted_taxon_uuid'];
371
  $prependedSynonyms = $variables['prependedSynonyms'];
372
  RenderHints::pushToRenderStack('homotypicSynonymyGroup');
373

    
374
  $footnoteListKey = isset($prependedSynonyms[0]) ? $prependedSynonyms[0]->uuid : (isset($synonymList[0]) ? $synonymList[0]->uuid : 'NULL');
375
  $accepted_taxon_footnoteListKey = RenderHints::getFootnoteListKey();
376
  RenderHints::setFootnoteListKey($footnoteListKey);
377

    
378
  if (!is_array($synonymList) || count($synonymList) == 0) {
379
    return;
380
  }
381

    
382
  $out = '<div class="homotypic-synonymy-group"><ul class="homotypicSynonyms">';
383

    
384
  if (!empty($prependedSynonyms)) {
385
    foreach ($prependedSynonyms as $taxon) {
386
      $out .= '<li class="synonym">' . cdm_related_taxon($taxon, UUID_HOMOTYPIC_SYNONYM_OF) . '</li>';
387
    }
388
  }
389

    
390
  foreach ($synonymList as $synonym) {
391
    $out .= '<li class="synonym">' . cdm_related_taxon($synonym, UUID_HOMOTYPIC_SYNONYM_OF) . '</li>';
392
  }
393

    
394
  $homonym_typeDesignations = cdm_ws_get(CDM_WS_PORTAL_NAME_TYPEDESIGNATIONS, $synonymList[0]->name->uuid);
395
  $accepted_typeDesignations = cdm_ws_get(CDM_WS_PORTAL_TAXON_NAMETYPEDESIGNATIONS, $accepted_taxon_uuid);
396
  if ($accepted_typeDesignations) {
397
    $typeDesignations = cdm_add_type_designations($homonym_typeDesignations, $accepted_typeDesignations);
398
  }
399
  else {
400
    $typeDesignations = $homonym_typeDesignations;
401
  }
402
  if ($typeDesignations) {
403
    $out .= theme('cdm_typedesignations', array('typeDesignations' => $typeDesignations));
404
  }
405
  $out .= '</ul>';
406

    
407
  // ------- footnotes ------- //
408
  $out .= '<ul class="footnotes">';
409
  // To avoiding drupal warnings (#1830).
410
  if ($accepted_taxon_footnoteListKey) {
411
    // Why FALSE???
412
    $out .= theme('cdm_footnotes', array('footnoteListKey' => $accepted_taxon_footnoteListKey, 'enclosingTag' => 'li'));
413
  }
414
  $out .= theme('cdm_annotation_footnotes', array('footnoteListKey' => $footnoteListKey, 'enclosingTag' => 'li'));
415
  $out .= theme('cdm_footnotes', array('footnoteListKey' => RenderHints::getRenderPath(), 'enclosingTag' => 'li'));
416
  $out .= '</ul>';
417

    
418
  $out .= '</div>';
419

    
420

    
421
  RenderHints::popFromRenderStack();
422
  return $out;
423
}
424

    
425
/**
426
 * Provides the name render template to be used within the page elements identified the the $renderPath.
427
 *
428
 * The render templates arrays contains one or more name render template to be used within the page elements identified the the
429
 * renderPath. The renderPath is the key of the subelements whereas the value is the name render template.
430
 * The following keys are curretly recogized:
431
 *
432
 *   - list_of_taxa:
433
 *   - acceptedFor:
434
 *   - taxon_page_synonymy
435
 *   - typedesignations
436
 *   - taxon_page_title
437
 *   - polytomousKey
438
 *   - na: name + authorship
439
 *   - nar:name + authorship + reference
440
 *   - #DEFAULT
441
 *
442
 * A single render template can be used for multiple render paths. In this case the according key of the render templates
443
 * array element should be the list of these render paths concatenated by ONLY a comma character without any whitespace.
444
 *
445
 * A render template is an associative array. The keys of this array are referring to the keys as defined in the part
446
 * definitions array.
447
 * @see get_partDefinition($taxonNameType) for more information
448
 *
449
 * The value of the render template element must be set to TRUE in order to let this part being rendered.
450
 * The namePart, nameAuthorPart and referencePart can also hold an associative array with a single
451
 * element: array('#uri' => TRUE). The value of the #uri element will be replaced by the according
452
 * links if the paramters $nameLink or $refenceLink are set.
453
 *
454
 * @param string $renderPath
455
 *   The render path can consist of multiple dot separated elements
456
 *   @see RenderHints::getRenderPath()
457
 * @param string $nameLink
458
 *   The link path ot URL to be used for name parts if a link is forseen in the template
459
 *   matching the given $renderPath.
460
 * @param string $referenceLink
461
 *   The link path ot URL to be used for nomencaltural reference parts if a link is forseen
462
 *   in the template matching the given $renderPath.
463
 * @return array
464
 *   An assciative array, the render template
465
 */
466
function get_nameRenderTemplate($renderPath, $nameLink = NULL, $refenceLink = NULL) {
467

    
468
  $template = NULL;
469

    
470
  static $default_render_templates = NULL;
471
  if (!isset($default_render_templates)) {
472
    $default_render_templates = unserialize(CDM_NAME_RENDER_TEMPLATES_DEFAULT);
473
  }
474

    
475
  // get the base element of the renderPath
476
  if (($separatorPos = strpos($renderPath, '.')) > 0) {
477
    $renderPath_base = substr($renderPath, 0, $separatorPos);
478
  } else {
479
    $renderPath_base = $renderPath;
480
  }
481

    
482
  // --- preliminar solution: using themes.
483
  $render_templates = theme('get_nameRenderTemplate', array());
484
  if (!isset($render_templates)) {
485
    // from the variables
486
    $render_templates = variable_get(CDM_NAME_RENDER_TEMPLATES, $default_render_templates);
487
  }
488

    
489
  // 1. try to find a template using the render path base element
490
  if(array_key_exists($renderPath_base, $render_templates)){
491
    $template = $render_templates[$renderPath_base];
492
  }
493

    
494
  // 2. Find best matching default RenderTemplate in theme
495
  // by stripping the dot separated render path element by element
496
  // is no matching template is found the DEFAULT will be used.
497
  while (!is_array($template) && strlen($renderPath) > 0) {
498

    
499
    foreach ($render_templates as $k => $t) {
500
      if (strpos(',' . $k . ',', $renderPath ) !== FALSE) {
501
        $template = $t;
502
        break;
503
      }
504
    }
505

    
506
    // shorten by one element
507
    $renderPath = substr($renderPath, 0, strrpos($renderPath, '.'));
508
    /*
509
    if(!is_array($template)){
510
      echo "<br/>->".$renderPath;
511
    }
512
    */
513
  }
514

    
515
  // 3. Otherwise get default RenderTemplate from theme.
516
  if (!is_array($template)) {
517
      $template = $render_templates['#DEFAULT'];
518
  }
519

    
520
  // --- set the link uris to the according template fields if they exist
521
  if ($nameLink && isset($template['nameAuthorPart']['#uri'])) {
522
    $template['nameAuthorPart']['#uri'] = $nameLink;
523
  }
524
  else {
525
    unset($template['nameAuthorPart']['#uri']);
526
  }
527

    
528
  if ($nameLink && isset($template['namePart']['#uri'])) {
529
    $template['namePart']['#uri'] = $nameLink;
530
  }
531
  else {
532
    unset($template['namePart']['#uri']);
533
  }
534

    
535
  if ($refenceLink && isset($template['referencePart']['#uri'])) {
536
    $template['referencePart']['#uri'] = $refenceLink;
537
  }
538
  else {
539
    unset($template['referencePart']['#uri']);
540
  }
541

    
542
  return $template;
543
}
544

    
545
/**
546
 * The part definitions define the specific parts of which a rendered taxon name plus additional information will consist.
547
 *
548
 * A full taxon name plus additional information can consist of the following elements:
549
 *
550
 *   - name: the taxon name inclugin rank nbut without author
551
 *   - authorTeam:  The authors of a reference, also used in taxon names
552
 *   - authors:  The authors of a reference, also used in taxon names
553
 *   - reference: the nomenclatural reference,
554
 *   - microreference:  Volume, page number etc.
555
 *   - status:  The nomenclatural status of a name
556
 *   - description: name descriptions like protologues etc ...
557
 *
558
 * These elements are combined in the part definitions array to from the specific parts to be rendered.
559
 * Usually the following parts are formed:
560
 *
561
 * The name "Lapsana communis L., Sp. Pl.: 811. 1753" shall be an example here:
562
 *  - namePart: the name and rank (in example: "Lapsana communis")
563
 *  - authorshipPart: the author (in example: "L.")
564
 *  - nameAuthorPart: the combination of name and author part (in example: "Lapsana communis L.").
565
 *     This is useful for zoological names where the authorshipPart belongs to the name and both should
566
 *     be combined when a link to the taxon is rendered.
567
 *  - referencePart: the nomencaltural reference (in example: "Sp. Pl. 1753")
568
 *  - microreferencePart: usually the page number (in example ": 811.")
569
 *  - statusPart: the nomenclatorical status
570
 *  - descriptionPart:
571
 *
572
 * Each set of parts is dedicated to render a specific TaxonName type, the type names are used as keys for the
573
 * specific parts part definitions:
574
 *
575
 *  - BotanicalName
576
 *  - ZoologicalName
577
 *  - #DEFAULT:  covers ViralNames and general NonViralNames
578
 *
579
 * An example:
580
 * @code
581
 * array(
582
 *    'ZoologicalName' => array(
583
 *        'namePart' => array('name' => TRUE),
584
 *        'referencePart' => array('authorTeam' => TRUE),
585
 *        'microreferencePart' => array('microreference' => TRUE),
586
 *        'statusPart' => array('status' => TRUE),
587
 *        'descriptionPart' => array('description' => TRUE),
588
 *    ),
589
 *    'BotanicalName' => array(
590
 *        'namePart' => array(
591
 *            'name' => TRUE,
592
 *            'authors' => TRUE,
593
 *        ),
594
 *        'referencePart' => array(
595
 *            'reference' => TRUE,
596
 *            'microreference' => TRUE,
597
 *        ),
598
 *        'statusPart' => array('status' => TRUE),
599
 *        'descriptionPart' => array('description' => TRUE),
600
 *    ),
601
 *  );
602
 * @endcode
603
 *
604
 * @todo document this function.
605
 */
606
function get_partDefinition($taxonNameType) {
607

    
608
  static $default_part_definitions = null;
609
  if (!isset($default_part_definitions)) {
610
    $default_part_definitions= unserialize(CDM_PART_DEFINITIONS_DEFAULT);
611
  }
612

    
613
  // Preliminar solution: using themes.
614
  // TODO remove this once all themes are using the newly introcuded part_definition settings
615
  $part_definitions = theme('get_partDefinition', array());
616

    
617
  // try to get get part definitions from variables
618
  if(!is_array($part_definitions)) {
619
    $part_definitions = variable_get(CDM_PART_DEFINITIONS, $default_part_definitions);
620
  }
621

    
622
  if (array_key_exists($taxonNameType, $part_definitions)) {
623
    return $part_definitions[$taxonNameType];
624
  } else {
625
    return $part_definitions['#DEFAULT']; // covers ViralNames and general NonViralNames
626
  }
627

    
628
}
629

    
630
/**
631
 * @param $variables
632
 *    - taxonName : cdm TaxonNameBase instance
633
 *    - nameLink: URI to the taxon, @see path_to_taxon()
634
 *    - refenceLink: URI to the reference, @see path_to_reference()
635
 *    - show_annotations: ...
636
 *    - is_type_designation: ...
637
 *    - skiptags: an array of tags to skip ....
638
 *
639
 * @todo Please document this function.
640
 * @see http://drupal.org/node/1354
641
 */
642
function theme_cdm_taxonName($variables) {
643

    
644
  $taxonName = $variables['taxonName'];
645
  $nameLink = $variables['nameLink'];
646
  $refenceLink = $variables['refenceLink'];
647
  $show_annotations = $variables['show_annotations'];
648
  $is_type_designation = $variables['is_type_designation'];
649
  $skiptags = $variables['skiptags'];
650

    
651
  $renderTemplate = get_nameRenderTemplate(RenderHints::getRenderPath(), $nameLink, $refenceLink);
652
  $partDefinition = get_partDefinition($taxonName->class);
653

    
654
  // Apply definitions to template.
655
  foreach ($renderTemplate as $part => $uri) {
656

    
657
    if (isset($partDefinition[$part])) {
658
      $renderTemplate[$part] = $partDefinition[$part];
659
    }
660
    if (is_array($uri) && isset($uri['#uri'])) {
661
      $renderTemplate[$part]['#uri'] = $uri['#uri'];
662
    }
663
  }
664

    
665
  normalize_TaggedName($taxonName->taggedName);
666

    
667
  $firstEntryIsValidNamePart = isset($taxonName->taggedName) && is_array($taxonName->taggedName) && isset($taxonName->taggedName[0]->text) && is_string($taxonName->taggedName[0]->text) && $taxonName->taggedName[0]->text != '' && isset($taxonName->taggedName[0]->type) && $taxonName->taggedName[0]->type == 'name';
668

    
669
  // Got to use second entry as first one, see ToDo comment below ...
670
  if ($firstEntryIsValidNamePart) {
671

    
672
    $taggedName = $taxonName->taggedName;
673
    $lastAuthorElementString = FALSE;
674
    $hasNamePart_with_Authors = isset($renderTemplate['namePart']) && isset($renderTemplate['namePart']['authors']);
675
    $hasNameAuthorPart_with_Authors = isset($renderTemplate['nameAuthorPart']) && isset($renderTemplate['nameAuthorPart']['authors']);
676

    
677
    if (!(($hasNamePart_with_Authors) || ($hasNameAuthorPart_with_Authors))) {
678
      // Find author and split off from name.
679
      // TODO expecting to find the author as the last element.
680
      /*
681
      if($taggedName[count($taggedName)- 1]->type == 'authors'){
682
        $authorTeam = $taggedName[count($taggedName)- 1]->text;
683
        unset($taggedName[count($taggedName)- 1]);
684
      }
685
      */
686

    
687
      // Remove all authors.
688
      $taggedNameNew = array();
689
      foreach ($taggedName as $element) {
690
        if ($element->type != 'authors') {
691
          $taggedNameNew[] = $element;
692
        }
693
        else {
694
          $lastAuthorElementString = $element->text;
695
        }
696
      }
697
      $taggedName = $taggedNameNew;
698
    }
699
    $name = '<span class="' . $taxonName->class . '">' . theme('cdm_taggedtext2html', array(
700
      'taggedtxt' => $taggedName,
701
      'tag' => 'span',
702
      'glue' => ' ',
703
      'skiptags' => $skiptags,
704
      )) . '</span>';
705
  }
706
  else {
707
    $name = '<span class="' . $taxonName->class . '_titleCache">' . $taxonName->titleCache . '</span>';
708
  }
709

    
710
  // Fill name into $renderTemplate.
711
  array_setr('name', $name, $renderTemplate);
712

    
713
  // Fill with authorTeam.
714
  /*
715
  if($authorTeam){
716
    $authorTeamHtml = ' <span class="authorTeam">'.$authorTeam.'</span>';
717
    array_setr('authorTeam', $authorTeamHtml, $renderTemplate);
718
  }
719
  */
720

    
721
  // Fill with reference.
722
  if (isset($renderTemplate['referencePart']) && !$is_type_designation) {
723

    
724
    // [Eckhard]:"Komma nach dem Taxonnamen ist grunsätzlich falsch,
725
    // Komma nach dem Autornamen ist überall dort falsch, wo ein "in" folgt."
726
    if (isset($renderTemplate['referencePart']['reference']) && isset($taxonName->nomenclaturalReference)) {
727
      $microreference = NULL;
728
      if (isset($renderTemplate['referencePart']['microreference'])&& isset($taxonName->nomenclaturalMicroReference)) {
729
        $microreference = $taxonName->nomenclaturalMicroReference;
730
      }
731
      $citation = cdm_ws_getNomenclaturalReference($taxonName->nomenclaturalReference->uuid, $microreference);
732

    
733
      // Find preceding element of the reference.
734
      $precedingKey = get_preceding_contentElementKey('reference', $renderTemplate);
735
      if (str_beginsWith($citation, ", in")) {
736
        $citation = substr($citation, 2);
737
        $separator = ' ';
738
      }
739
      elseif (!str_beginsWith($citation, "in") && $precedingKey == 'authors') {
740
        $separator = ', ';
741
      }
742
      else {
743
        $separator = ' ';
744
      }
745

    
746
      $referenceArray['#separator'] = $separator;
747
      $referenceArray['#html'] = '<span class="reference">' . $citation . '</span>';
748
      array_setr('reference', $referenceArray, $renderTemplate);
749
    }
750

    
751
    // If authors have been removed from the name part the last named authorteam
752
    // should be added to the reference citation, otherwise, keep the separator
753
    // out of the reference.
754
    if (isset($renderTemplate['referencePart']['authors']) && $lastAuthorElementString) {
755
      // If the nomenclaturalReference citation is not included in the
756
      // reference part but diplay of the microreference
757
      // is wanted, append the microreference to the authorTeam.
758
      if (!isset($renderTemplate['referencePart']['reference']) && isset($renderTemplate['referencePart']['microreference'])) {
759
        $separator = ": ";
760
        $citation = $taxonName->nomenclaturalMicroReference;
761
      }
762
      $referenceArray['#html'] = ' <span class="reference">' . $lastAuthorElementString . $separator . $citation . '</span>';
763
      array_setr('authors', $referenceArray, $renderTemplate);
764
    }
765
  }
766

    
767
  // Fill with status.
768
  $statusHtml = '';
769
  if (isset($taxonName->status) && is_array($taxonName->status)) {
770
    if (array_setr('status', TRUE, $renderTemplate)) {
771
      if (isset($taxonName->status[0])) {
772
        foreach ($taxonName->status as $status) {
773
          $statusHtml .= ', ' . $status->type->representation_L10n_abbreviatedLabel;
774
        }
775
      }
776
      array_setr('status', '<span class="nomenclatural_status">' . $statusHtml . '</span>', $renderTemplate);
777
    }
778
  }
779

    
780
  // Fill with protologues etc...
781
  $descriptionHtml = '';
782
  if (array_setr('description', TRUE, $renderTemplate)) {
783
    $descriptions = cdm_ws_get(CDM_WS_PORTAL_NAME_DESCRIPTIONS, $taxonName->uuid);
784
    foreach ($descriptions as $description) {
785
      if (!empty($description)) {
786
        foreach ($description->elements as $description_element) {
787
          $second_citation = '';
788
          if (isset($description_element->multilanguageText_L10n) && $description_element->multilanguageText_L10n->text) {
789
            $second_citation = '[& ' . $description_element->multilanguageText_L10n->text . '].';
790
          }
791
          $descriptionHtml .= $second_citation;
792
          $descriptionHtml .= theme("cdm_media", array(
793
              'descriptionElement' => $description_element,
794
              'mimeTypePreference' => array(
795
                  'application/pdf',
796
                  'image/png',
797
                  'image/jpeg',
798
                  'image/gif',
799
                  'text/html',
800
                )
801
              )
802
            );
803

    
804
        }
805
      }
806
    }
807
    array_setr('description', $descriptionHtml, $renderTemplate);
808
  }
809

    
810
  // Render.
811
  $out = '<span ref="/name/' . $taxonName->uuid . '">';
812

    
813
  foreach ($renderTemplate as $partName => $part) {
814
    $separator = '';
815
    $partHtml = '';
816
    $uri = FALSE;
817
    if (!is_array($part)) {
818
      continue;
819
    }
820
    if (isset($part['#uri']) && is_string($part['#uri'])) {
821
      $uri = $part['#uri'];
822
      unset($part['#uri']);
823
    }
824
    foreach ($part as $key => $content) {
825
      $html = '';
826
      if (is_array($content)) {
827
        $html = $content['#html'];
828
        $separator = $content['#separator'];
829
      }
830
      elseif (is_string($content)) {
831
        $html = $content;
832
      }
833
      $partHtml .= '<span class="' . $key . '">' . $html . '</span>';
834
    }
835
    if ($uri) {
836
      $out .= $separator . '<a href="' . $uri . '" class="' . $partName . '">' . $partHtml . '</a>';
837
    }
838
    else {
839
      $out .= $separator . $partHtml;
840
    }
841
  }
842
  $out .= '</span>';
843
  if ($show_annotations) {
844
    // $out .= theme('cdm_annotations_as_footnotekeys', $taxonName);
845
  }
846
  return $out;
847
}
848

    
849
/**
850
 * Recursively searches the array for the $key and sets the given value.
851
 *
852
 * @param mixed $key
853
 *   Key to search for.
854
 * @param mixed $value
855
 *   Value to set.
856
 * @param array $array
857
 *   Array to search in.
858
 *
859
 * @return bool
860
 *   True if the key has been found.
861
 */
862
function &array_setr($key, $value, array &$array) {
863
  $res = NULL;
864
  foreach ($array as $k => &$v) {
865
    if ($key == $k) {
866
      $v = $value;
867
      return $array;
868
    }
869
    elseif (is_array($v)) {
870
      $innerArray = array_setr($key, $value, $v);
871
      if ($innerArray) {
872
        return $array;
873
      }
874
    }
875
  }
876
  return $res;
877
}
878

    
879
/**
880
 * @todo Please document this function.
881
 * @see http://drupal.org/node/1354
882
 */
883
function &get_preceding_contentElement($contentElementKey, array &$renderTemplate) {
884
  $res = NULL;
885
  $precedingElement = NULL;
886
  foreach ($renderTemplate as &$part) {
887
    foreach ($part as $key => &$element) {
888
      if ($key == $contentElementKey) {
889
        return $precedingElement;
890
      }
891
      $precedingElement = $element;
892
    }
893
  }
894
  return $res;
895
}
896

    
897
/**
898
 * @todo Please document this function.
899
 * @see http://drupal.org/node/1354
900
 */
901
function &get_preceding_contentElementKey($contentElementKey, array &$renderTemplate) {
902
  $res = NULL;
903
  $precedingKey = NULL;
904
  foreach ($renderTemplate as &$part) {
905
    if (is_array($part)) {
906
      foreach ($part as $key => &$element) {
907
        if ($key == $contentElementKey) {
908
          return $precedingKey;
909
        }
910
        if (!str_beginsWith($key, '#')) {
911
          $precedingKey = $key;
912
        }
913
      }
914
    }
915
  }
916
  return $res;
917
}
918

    
919
/**
920
 * Returns HTML for a name in your theme, when implemented.
921
 *
922
 * This function returns currently nothing, but can be used to override
923
 * how names are rendered in your theme. See the code that is commented out
924
 * for an example usage. it is used in the function get_nameRenderTemplate.
925
 * See that function to find out how the create template is used.
926
 *
927
 * @see get_nameRenderTemplate()
928
 *
929
 * @deprecated define name render templates via the layout settings
930
 *
931
 * @ingroup: themeable
932
 */
933
function theme_get_nameRenderTemplate() {
934
  /*
935
  // Example usage:
936
//   $render_path = $variables['renderPath'];
937

    
938
  $templates = array(
939
    'taxon_page_title,polytomousKey' => array(
940
        'namePart' => array(
941
          '#uri' => TRUE
942
        )
943
      ),
944
    'taxon_page_synonymy,related_taxon' => array(
945
        'nameAuthorPart' => array(
946
          '#uri' => TRUE
947
        ),
948
        'referencePart' => TRUE,
949
        'statusPart' => TRUE,
950
        'descriptionPart' => TRUE
951
      ),
952
     'acceptedFor' => array(
953
        'nameAuthorPart' => array(
954
          '#uri' => TRUE
955
        ),
956
        'referencePart' => TRUE
957
      ),
958
     'typedesignations,list_of_taxa' => array(
959
        'nameAuthorPart' => array(
960
           '#uri' => TRUE
961
        ), 'referencePart' => TRUE
962
      ),
963
    '#DEFAULT'=> array(
964
        'nameAuthorPart' => array(
965
           '#uri' => TRUE
966
        ), 'referencePart' => TRUE
967
      )
968
  );
969
  return $templates;
970
  */
971

    
972
}
(5-5/10)