Project

General

Profile

Download (24.3 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
 * The render templates arrays contains one or more name render template to be used within the page elements identified the the
38
 * renderPath. The renderPath is the key of the subelements whereas the value is the name render template.
39
 * The following keys are curretly recogized:
40
 *
41
 *   - list_of_taxa:
42
 *   - acceptedFor:
43
 *   - taxon_page_synonymy
44
 *   - typedesignations
45
 *   - taxon_page_title
46
 *   - polytomousKey
47
 *   - na: name + authorship
48
 *   - nar:name + authorship + reference
49
 *   - #DEFAULT
50
 *
51
 * A single render template can be used for multiple render paths. In this case the according key of the render templates
52
 * array element should be the list of these render paths concatenated by ONLY a comma character without any whitespace.
53
 *
54
 * A render template is an associative array. The keys of this array are referring to the keys as defined in the part
55
 * definitions array.
56
 * @see get_partDefinition($taxonNameType) for more information
57
 *
58
 * The value of the render template element must be set to TRUE in order to let this part being rendered.
59
 * The namePart, nameAuthorPart and referencePart can also hold an associative array with a single
60
 * element: array('#uri' => TRUE). The value of the #uri element will be replaced by the according
61
 * links if the parameters $nameLink or $refenceLink are set.
62
 *
63
 * @param string $renderPath
64
 *   The render path can consist of multiple dot separated elements
65
 *   @see RenderHints::getRenderPath()
66
 * @param string $nameLink
67
 *   The link path ot URL to be used for name parts if a link is forseen in the template
68
 *   matching the given $renderPath.
69
 * @param string $referenceLink
70
 *   The link path ot URL to be used for nomenclatural reference parts if a link is forseen
71
 *   in the template matching the given $renderPath.
72
 * @return array
73
 *   An associative array, the render template
74
 */
75
function get_nameRenderTemplate($renderPath, $nameLink = NULL, $referenceLink = NULL) {
76
77
  static $default_render_templates = NULL;
78 03f4f6f7 Andreas Kohlbecker
  static $split_render_templates = NULL;
79
80
81 2fd6da0b Andreas Kohlbecker
  if (!isset($default_render_templates)) {
82
    $default_render_templates = unserialize(CDM_NAME_RENDER_TEMPLATES_DEFAULT);
83
  }
84 03f4f6f7 Andreas Kohlbecker
  if($split_render_templates == NULL) {
85 2fd6da0b Andreas Kohlbecker
    $render_templates = variable_get(CDM_NAME_RENDER_TEMPLATES, $default_render_templates);
86
    // needs to be converted to an array
87 03f4f6f7 Andreas Kohlbecker
    $render_templates = (convert_to_array($render_templates));
88
89
    // separate render templates which are combined with a comma
90
    $split_render_templates = array();
91
    foreach($render_templates as $key => $template){
92
      if(strpos($key, ',')){
93
        foreach(explode(',', $key) as $path){
94
          $split_render_templates[$path] = $template;
95
        }
96
      } else {
97
        $split_render_templates[$key] = $template;
98
      }
99
    }
100 2fd6da0b Andreas Kohlbecker
  }
101
102
  // get the base element of the renderPath
103
  if (($separatorPos = strpos($renderPath, '.')) > 0) {
104
    $renderPath_base = substr($renderPath, 0, $separatorPos);
105
  } else {
106
    $renderPath_base = $renderPath;
107
  }
108
109 03f4f6f7 Andreas Kohlbecker
  $template = NULL;
110 2fd6da0b Andreas Kohlbecker
  // 1. try to find a template using the render path base element
111 03f4f6f7 Andreas Kohlbecker
  if(array_key_exists($renderPath_base, $split_render_templates)){
112
    $template = (array)$split_render_templates[$renderPath_base];
113 2fd6da0b Andreas Kohlbecker
  }
114
115
  // 2. Find best matching default RenderTemplate in theme
116
  // by stripping the dot separated render path element by element
117
  // is no matching template is found the DEFAULT will be used.
118
  while (!is_array($template) && strlen($renderPath) > 0) {
119 03f4f6f7 Andreas Kohlbecker
    foreach ($split_render_templates as $path => $t) {
120
      if ($path == $renderPath) {
121 2fd6da0b Andreas Kohlbecker
        $template = $t;
122
        break;
123
      }
124
    }
125
    // shorten by one element
126 03f4f6f7 Andreas Kohlbecker
    $renderPath = substr($renderPath, strrpos($renderPath, '.') + 1, strlen($renderPath));
127 2fd6da0b Andreas Kohlbecker
  }
128
129 03f4f6f7 Andreas Kohlbecker
130 2fd6da0b Andreas Kohlbecker
  // 3. Otherwise get default RenderTemplate from theme.
131
  if (!is_array($template)) {
132 03f4f6f7 Andreas Kohlbecker
    $template = $split_render_templates['#DEFAULT'];
133 2fd6da0b Andreas Kohlbecker
  }
134
135
  // --- set the link uris to the according template fields if they exist
136
  if(isset($template['nameAuthorPart']) && isset($template['nameAuthorPart']['#uri'])) {
137
    if ($nameLink) {
138
      $template['nameAuthorPart']['#uri'] = $nameLink;
139
    }
140
    else {
141
      unset($template['nameAuthorPart']['#uri']);
142
    }
143
  }
144
145
  if ($nameLink && isset($template['namePart']['#uri'])) {
146
    $template['namePart']['#uri'] = $nameLink;
147
  }
148
  else {
149
    unset($template['namePart']['#uri']);
150
  }
151
152
  if ($referenceLink && isset($template['referencePart']['#uri'])) {
153
    $template['referencePart']['#uri'] = $referenceLink;
154
  }
155
  else {
156
    unset($template['referencePart']['#uri']);
157
  }
158
159
  return $template;
160
}
161
162
/**
163
 * The part definitions define the specific parts of which a rendered taxon name plus additional information will consist.
164
 *
165
 * A full taxon name plus additional information can consist of the following elements:
166
 *
167
 *   - name: the taxon name inclugin rank nbut without author
168
 *   - authorTeam:  The authors of a reference, also used in taxon names
169
 *   - authors:  The authors of a reference, also used in taxon names
170
 *   - reference: the nomenclatural reference,
171
 *   - microreference:  Volume, page number etc.
172
 *   - status:  The nomenclatural status of a name
173
 *   - description: name descriptions like protologues etc ...
174
 *
175
 * These elements are combined in the part definitions array to from the specific parts to be rendered.
176
 * Usually the following parts are formed:
177
 *
178
 * The name "Lapsana communis L., Sp. Pl.: 811. 1753" shall be an example here:
179
 *  - namePart: the name and rank (in example: "Lapsana communis")
180
 *  - authorshipPart: the author (in example: "L.")
181
 *  - nameAuthorPart: the combination of name and author part (in example: "Lapsana communis L.").
182
 *     This is useful for zoological names where the authorshipPart belongs to the name and both should
183
 *     be combined when a link to the taxon is rendered.
184
 *  - referencePart: the nomencaltural reference (in example: "Sp. Pl. 1753")
185
 *  - microreferencePart: usually the page number (in example ": 811.")
186
 *  - statusPart: the nomenclatorical status
187
 *  - descriptionPart:
188
 *
189
 * Each set of parts is dedicated to render a specific TaxonName type, the type names are used as keys for the
190
 * specific parts part definitions:
191
 *
192
 *  - BotanicalName
193
 *  - ZoologicalName
194
 *  - #DEFAULT:  covers ViralNames and general NonViralNames
195
 *
196
 * An example:
197
 * @code
198
 * array(
199
 *    'ZoologicalName' => array(
200
 *        'namePart' => array('name' => TRUE),
201
 *        'referencePart' => array('authorTeam' => TRUE),
202
 *        'microreferencePart' => array('microreference' => TRUE),
203
 *        'statusPart' => array('status' => TRUE),
204
 *        'descriptionPart' => array('description' => TRUE),
205
 *    ),
206
 *    'BotanicalName' => array(
207
 *        'namePart' => array(
208
 *            'name' => TRUE,
209
 *            'authors' => TRUE,
210
 *        ),
211
 *        'referencePart' => array(
212
 *            'reference' => TRUE,
213
 *            'microreference' => TRUE,
214
 *        ),
215
 *        'statusPart' => array('status' => TRUE),
216
 *        'descriptionPart' => array('description' => TRUE),
217
 *    ),
218
 *  );
219
 * @endcode
220
 *
221
 */
222
function get_partDefinition($taxonNameType) {
223
224
  static $default_part_definitions = null;
225
  if (!isset($default_part_definitions)) {
226
    $default_part_definitions= unserialize(CDM_PART_DEFINITIONS_DEFAULT);
227
  }
228
229
  static $part_definitions = null;
230
  if (!isset($part_definitions)) {
231
    $part_definitions = convert_to_array(variable_get(CDM_PART_DEFINITIONS, $default_part_definitions));
232
  }
233
234
  if (array_key_exists($taxonNameType, $part_definitions)) {
235
    return $part_definitions[$taxonNameType];
236
  } else {
237
    return $part_definitions['#DEFAULT']; // covers ViralNames and general NonViralNames
238
  }
239
240
}
241
242
243
/**
244
 * Renders the markup for a CDM TaxonName instance.
245
 *
246
 * The layout of the name representation is configured by the
247
 * part_definitions and render_templates (see get_partDefinition() and
248
 * get_nameRenderTemplate())
249
 *
250
 * @param $taxonName
251
 *    cdm TaxonNameBase instance
252
 * @param $sec
253
 *    the sec reference of a taxon having this name (optional)
254
 * @param $nameLink
255
 *    URI to the taxon, @see path_to_taxon(), must be processed by url() before passing to this method
256
 * @param $refenceLink
257
 *    URI to the reference, @see path_to_reference(), must be processed by url() before passing to this method
258
 * @param $show_annotations
259
 *    turns the display of annotations on
260
 * @param $is_type_designation
261
 *    To indicate that the supplied taxon name is a name type designation.
262
 * @param $skiptags
263
 *    an array of name elements tags like 'name', 'rank' to skip. The name part
264
 *          'authors' will not ber affected by this filter. This part is managed though the render template
265
 *          mechanism.
266 c35bab7f Andreas Kohlbecker
 * @param $is_invalid
267
 *   Indicates that this taxon is invalid. In this case the name part will be shown in double quotes.
268
 *   This is useful when rendering taxon relation ships.
269 2fd6da0b Andreas Kohlbecker
 *
270
 * @return string
271
 *  The markup for a taxon name.
272
 *
273
 */
274
function render_taxon_or_name($taxon_name_or_taxon_base, $nameLink = NULL, $refenceLink = NULL,
275 c35bab7f Andreas Kohlbecker
  $show_annotations = true, $is_type_designation = false, $skiptags = array(), $is_invalid = false) {
276 2fd6da0b Andreas Kohlbecker
277 ea3933d7 Andreas Kohlbecker
  $is_doubtful = false;
278
279 2fd6da0b Andreas Kohlbecker
  if($taxon_name_or_taxon_base->class == 'Taxon' || $taxon_name_or_taxon_base->class == 'Synonym'){
280
    $taxonName = $taxon_name_or_taxon_base->name;
281 ea3933d7 Andreas Kohlbecker
    $is_doubtful = $taxon_name_or_taxon_base->doubtful;
282 2fd6da0b Andreas Kohlbecker
    // use the TaxonBase.taggedTitle so we have the secRef
283
    $taggedTitle = $taxon_name_or_taxon_base->taggedTitle;
284
  } else {
285
    // assuming this is a TaxonNameBase
286
    $taxonName = $taxon_name_or_taxon_base;
287
    $taggedTitle = $taxon_name_or_taxon_base->taggedName;
288
  }
289
290
291
  $renderTemplate = get_nameRenderTemplate(RenderHints::getRenderPath(), $nameLink, $refenceLink);
292
  $partDefinition = get_partDefinition($taxonName->class);
293
294
  // Apply definitions to template.
295
  foreach ($renderTemplate as $part => $uri) {
296
297
    if (isset($partDefinition[$part])) {
298
      $renderTemplate[$part] = $partDefinition[$part];
299
    }
300
    if (is_array($uri) && isset($uri['#uri'])) {
301
      $renderTemplate[$part]['#uri'] = $uri['#uri'];
302
    }
303
  }
304
305 e90899ac Andreas Kohlbecker
  $secref_tagged_text = split_secref_from_tagged_text($taggedTitle);
306
  $nom_status_tagged_text = split_nomstatus_from_tagged_text($taggedTitle);
307 c35bab7f Andreas Kohlbecker
  $appended_phrase_tagged_text = array(); // this is filled later
308
309 e90899ac Andreas Kohlbecker
  normalize_tagged_text($taggedTitle);
310 2fd6da0b Andreas Kohlbecker
311
  $firstEntryIsValidNamePart =
312
    isset($taggedTitle)
313
    && is_array($taggedTitle)
314
    && isset($taggedTitle[0]->text)
315
    && is_string($taggedTitle[0]->text)
316
    && $taggedTitle[0]->text != ''
317
    && isset($taggedTitle[0]->type)
318
    && $taggedTitle[0]->type == 'name';
319
  $lastAuthorElementString = FALSE;
320
321 c35bab7f Andreas Kohlbecker
  $name_encasement = $is_invalid ? '"' : '';
322 ea3933d7 Andreas Kohlbecker
  $doubtful_marker = $is_doubtful ? '? ' : '';
323 c35bab7f Andreas Kohlbecker
324
  // split off all appendedPhrase item  from the end of the array (usually there only should  be one)
325
  while($taggedTitle[count($taggedTitle)-1]->type == "appendedPhrase"){
326
    $appended_phrase_tagged_text[] = array_pop($taggedTitle);
327
  }
328
329 2fd6da0b Andreas Kohlbecker
  // Got to use second entry as first one, see ToDo comment below ...
330
  if ($firstEntryIsValidNamePart) {
331
332
    $taggedName = $taggedTitle;
333
    $hasNamePart_with_Authors = isset($renderTemplate['namePart']) && isset($renderTemplate['namePart']['authors']);
334
    $hasNameAuthorPart_with_Authors = isset($renderTemplate['nameAuthorPart']) && isset($renderTemplate['nameAuthorPart']['authors']);
335
336 c35bab7f Andreas Kohlbecker
337 2fd6da0b Andreas Kohlbecker
    if (!(($hasNamePart_with_Authors) || ($hasNameAuthorPart_with_Authors))) {
338
      // Find author and split off from name.
339
      // TODO expecting to find the author as the last element.
340
      /*
341
      if($taggedName[count($taggedName)- 1]->type == 'authors'){
342
        $authorTeam = $taggedName[count($taggedName)- 1]->text;
343
        unset($taggedName[count($taggedName)- 1]);
344
      }
345
      */
346
347
      // Remove all authors.
348
      $taggedNameNew = array();
349
      foreach ($taggedName as $element) {
350
        if ($element->type != 'authors') {
351
          $taggedNameNew[] = $element;
352
        }
353
        else {
354
          $lastAuthorElementString = $element->text;
355
        }
356
      }
357
      $taggedName = $taggedNameNew;
358 e90899ac Andreas Kohlbecker
      unset($taggedNameNew);
359 2fd6da0b Andreas Kohlbecker
    }
360 ea3933d7 Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '">' . $doubtful_marker . $name_encasement . cdm_tagged_text_to_markup($taggedName, 'span', ' ', $skiptags) . $name_encasement . '</span>';
361 2fd6da0b Andreas Kohlbecker
  }
362
  else {
363 ea3933d7 Andreas Kohlbecker
    $name = '<span class="' . $taxonName->class . '_titleCache">' . $doubtful_marker . $name_encasement . $taxonName->titleCache . $name_encasement . '</span>';
364 c35bab7f Andreas Kohlbecker
  }
365
366
367
  if(isset($appended_phrase_tagged_text[0])){
368
    $name .= ' '. cdm_tagged_text_to_markup($appended_phrase_tagged_text);
369 2fd6da0b Andreas Kohlbecker
  }
370
371
  // Fill name into $renderTemplate.
372 c35bab7f Andreas Kohlbecker
  array_setr('name', $name , $renderTemplate);
373 2fd6da0b Andreas Kohlbecker
374
  // Fill with authorTeam.
375
  /*
376
  if($authorTeam){
377
    $authorTeamHtml = ' <span class="authorTeam">'.$authorTeam.'</span>';
378
    array_setr('authorTeam', $authorTeamHtml, $renderTemplate);
379
  }
380
  */
381
382
  // Fill with reference.
383
  if (isset($renderTemplate['referencePart']) && !$is_type_designation) {
384
385
    // default separator
386
    $separator = '';
387
388
    // [Eckhard]:"Komma nach dem Taxonnamen ist grunsätzlich falsch,
389
    // Komma nach dem Autornamen ist überall dort falsch, wo ein "in" folgt."
390
    if (isset($renderTemplate['referencePart']['reference']) && isset($taxonName->nomenclaturalReference)) {
391
      $microreference = NULL;
392
      if (isset($renderTemplate['referencePart']['microreference'])&& isset($taxonName->nomenclaturalMicroReference)) {
393
        $microreference = $taxonName->nomenclaturalMicroReference;
394
      }
395
      $citation = cdm_ws_getNomenclaturalReference($taxonName->nomenclaturalReference->uuid, $microreference);
396
397
      // Find preceding element of the reference.
398
      $precedingKey = get_preceding_contentElementKey('reference', $renderTemplate);
399
      if (str_beginsWith($citation, ", in")) {
400
        $citation = substr($citation, 2);
401
        $separator = ' ';
402
      }
403
      elseif (!str_beginsWith($citation, "in") && $precedingKey == 'authors') {
404
        $separator = ', ';
405
      } else {
406
        $separator = ' ';
407
      }
408
409
410
      $referenceArray['#separator'] = $separator;
411
      $referenceArray['#html'] = '<span class="reference">' . $citation . '</span>';
412
      array_setr('reference', $referenceArray, $renderTemplate);
413
    }
414
415
    // If authors have been removed from the name part the last named authorteam
416
    // should be added to the reference citation, otherwise, keep the separator
417
    // out of the reference.
418
    if (isset($renderTemplate['referencePart']['authors']) && $lastAuthorElementString) {
419
      // If the nomenclaturalReference citation is not included in the
420
      // reference part but diplay of the microreference
421
      // is wanted, append the microreference to the authorTeam.
422
      $citation = '';
423
      if (!isset($renderTemplate['referencePart']['reference']) && isset($renderTemplate['referencePart']['microreference'])) {
424
        $separator = ": ";
425
        $citation = $taxonName->nomenclaturalMicroReference;
426
      }
427
      $referenceArray['#html'] = ' <span class="reference">' . $lastAuthorElementString . $separator . $citation . '</span>';
428
      array_setr('authors', $referenceArray, $renderTemplate);
429
    }
430
  }
431
432
  $is_reference_year = false;
433
  if (isset($renderTemplate['referenceYearPart']['reference.year'])) {
434
    if(isset($taxonName->nomenclaturalReference->datePublished)){
435
      $referenceArray['#html'] = ' <span class="reference">' . timePeriodToString($taxonName->nomenclaturalReference->datePublished) . '</span>';
436
      array_setr('reference.year', $referenceArray, $renderTemplate);
437
      $is_reference_year = true;
438
    }
439
  }
440
441 e90899ac Andreas Kohlbecker
  // Fill with status.
442 1d0407b7 Andreas Kohlbecker
  if(isset($renderTemplate['statusPart'])){
443
    if (isset($nom_status_tagged_text[0])) {
444
      if (array_setr('status', TRUE, $renderTemplate)) {
445
        array_setr('status', '<span class="nomenclatural_status">' . cdm_tagged_text_to_markup($nom_status_tagged_text, 'span', '', array('postSeparator')) . '</span>', $renderTemplate);
446
      }
447 e90899ac Andreas Kohlbecker
    }
448
  }
449
450 2fd6da0b Andreas Kohlbecker
  if (isset($renderTemplate['secReferencePart'])){
451
    if(isset($secref_tagged_text[1])){
452 e90899ac Andreas Kohlbecker
      $post_separator_markup = $is_reference_year ? '.': '';
453 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')){
454 4a1ab871 Andreas Kohlbecker
        $post_separator_markup = cdm_tagged_text_to_markup(array($nom_status_tagged_text[count($nom_status_tagged_text) - 1 ]));
455 e90899ac Andreas Kohlbecker
      };
456 2fd6da0b Andreas Kohlbecker
      array_setr('secReference',
457 e90899ac Andreas Kohlbecker
        $post_separator_markup
458 2fd6da0b Andreas Kohlbecker
          . ' <span class="sec_reference">'
459 1d0407b7 Andreas Kohlbecker
          . join(' ', cdm_tagged_text_values($secref_tagged_text))
460 2fd6da0b Andreas Kohlbecker
          . '</span>', $renderTemplate);
461
    }
462
  }
463
464
  // Fill with protologues etc...
465
  $descriptionHtml = '';
466
  if (array_setr('description', TRUE, $renderTemplate)) {
467
    $descriptions = cdm_ws_get(CDM_WS_PORTAL_NAME_DESCRIPTIONS, $taxonName->uuid);
468
    foreach ($descriptions as $description) {
469
      if (!empty($description)) {
470
        foreach ($description->elements as $description_element) {
471
          $second_citation = '';
472
          if (isset($description_element->multilanguageText_L10n) && $description_element->multilanguageText_L10n->text) {
473
            $second_citation = '[& ' . $description_element->multilanguageText_L10n->text . '].';
474
          }
475
          $descriptionHtml .= $second_citation;
476
          $descriptionHtml .= theme("cdm_media", array(
477
              'descriptionElement' => $description_element,
478
              'mimeTypePreference' => array(
479
                'application/pdf',
480
                'image/png',
481
                'image/jpeg',
482
                'image/gif',
483
                'text/html',
484
              )
485
            )
486
          );
487
488
        }
489
      }
490
    }
491
    array_setr('description', $descriptionHtml, $renderTemplate);
492
  }
493
494
  // Render.
495 f695daf4 Andreas Kohlbecker
  $out = '';
496
  if(isset($_REQUEST['RENDER_PATH'])){
497
    // developer option to show the render path with each taxon name
498
    $out .= '<span class="render-path">' . RenderHints::getRenderPath() . '</span>';
499
  }
500
  $out .= '<span class="' . html_class_attribute_ref($taxon_name_or_taxon_base)
501
    . '" data-cdm-ref="/name/' . $taxonName->uuid . '" data-cdm-render-path="' . RenderHints::getRenderPath() .'">';
502 2fd6da0b Andreas Kohlbecker
503
  foreach ($renderTemplate as $partName => $part) {
504
    $separator = '';
505
    $partHtml = '';
506
    $uri = FALSE;
507
    if (!is_array($part)) {
508
      continue;
509
    }
510
    if (isset($part['#uri']) && is_string($part['#uri'])) {
511
      $uri = $part['#uri'];
512
      unset($part['#uri']);
513
    }
514
    foreach ($part as $key => $content) {
515
      $html = '';
516
      if (is_array($content)) {
517
        $html = $content['#html'];
518
        if(isset($content['#separator'])) {
519
          $separator = $content['#separator'];
520
        }
521
      }
522
      elseif (is_string($content)) {
523
        $html = $content;
524
      }
525
      $partHtml .= '<span class="' . $key . '">' . $html . '</span>';
526
    }
527
    if ($uri) {
528
      // cannot use l() here since the #uri aleady should have been processed through uri() at this point
529
      $out .= $separator . '<a href="' . $uri . '" class="' . $partName . '">' . $partHtml . '</a>';
530
531
    }
532
    else {
533
      $out .= $separator . $partHtml;
534
    }
535
  }
536
  $out .= '</span>';
537
  if ($show_annotations) {
538
    // $out .= theme('cdm_annotations_as_footnotekeys', $taxonName);
539
  }
540
  return $out;
541
}
542
543
/**
544 0b7bbf68 Andreas Kohlbecker
 * Renders the string of Homonyms for a given taxon.
545
 *
546
 * @param $taxon
547
 *    A CDM Taxon instance
548
 * @return String
549
 *    The string of homomyns
550
 *
551
 * @throws \Exception
552
 */
553
function cdm_name_relationships_of($taxon) {
554 f695daf4 Andreas Kohlbecker
555
  // =========== START OF HOMONYMS ========== //
556 0b7bbf68 Andreas Kohlbecker
  RenderHints::pushToRenderStack('homonym');
557
  // the render stack element homonyms is being used in the default render templates !!!, see CDM_NAME_RENDER_TEMPLATES_DEFAULT
558
559 f695daf4 Andreas Kohlbecker
  // Later homonym or treated as later homonym AND blocking names.
560 0b7bbf68 Andreas Kohlbecker
  // TODO apply filter ? $name_rels_to_show = variable_get('name_relationships_to_show', NULL);
561
  $from_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_FROM_NAMERELATIONS,
562
    $taxon->uuid);
563
  $to_name_relations = cdm_ws_get(CDM_WS_PORTAL_TAXON_TO_NAMERELATIONS,
564
    $taxon->uuid);
565
  $name_relations = array_merge($from_name_relations, $to_name_relations);
566
567
  $homonyms_array = array();
568
569
  if ($name_relations) {
570
    foreach ($name_relations as $element) {
571
      $taxon_html = NULL;
572
      switch ($element->type->uuid) {
573
        case UUID_LATER_HOMONYM :
574
          $elementTaxonBasesUuid = isset ($element->toName->taxonBases [0]->uuid) ? $element->toName->taxonBases [0]->uuid : '';
575
576
          //from relation ships -> only shown at fromName-synonym
577
          if ($taxon->name->uuid == $element->fromName->uuid) {
578
            $taxon_html =render_taxon_or_name($element->toName,
579
              url(path_to_name($element->toName->uuid, $taxon->uuid, $elementTaxonBasesUuid))
580
            );
581
          }
582
          break;
583
        case UUID_TREATED_AS_LATER_HOMONYM :
584
          $elementTaxonBasesUuid = isset ($element->toName->taxonBases [0]->uuid) ? $element->toName->taxonBases [0]->uuid : '';
585
586
          //from relation ships -> only shown at fromName-synonym
587
          if ($taxon->name->uuid == $element->fromName->uuid) {
588 f695daf4 Andreas Kohlbecker
            $taxon_html = render_taxon_or_name($element->toName,
589
              url(path_to_name($element->toName->uuid)));  // FIXME highlite in synonymy as in the other cases
590 0b7bbf68 Andreas Kohlbecker
          }
591
          break;
592
        case UUID_BLOCKING_NAME_FOR :
593
          $elementTaxonBasesUuid = isset ($element->fromName->taxonBases [0]->uuid) ? $element->fromName->taxonBases [0]->uuid : '';
594
595
          //to relation ships -> only shown at toName-synonym
596
          if ($taxon->name->uuid == $element->toName->uuid) {
597
            $taxon_html = render_taxon_or_name($element->fromName,
598
              url(path_to_name($element->fromName->uuid, $taxon->uuid, $elementTaxonBasesUuid))
599
            );
600
          }
601
          break;
602
        default:
603
          $taxon_html = NULL;
604
      }
605
      if (isset($taxon_html) && $taxon_html) {
606
        if (count($homonyms_array)) {
607 f695daf4 Andreas Kohlbecker
          // lat: "non nec" == german: "weder noch"
608 0b7bbf68 Andreas Kohlbecker
          $homonyms_array [] = 'nec ' . $taxon_html;
609 f695daf4 Andreas Kohlbecker
        } else {
610 0b7bbf68 Andreas Kohlbecker
          $homonyms_array [] = 'non ' . $taxon_html;
611
        }
612
      }
613
    }
614
  }
615
616
  RenderHints::popFromRenderStack();
617
  return (count($homonyms_array) ?'[' . trim(join(" ", $homonyms_array)) . ']' : '');
618
}
619
620
621
  /**
622 2fd6da0b Andreas Kohlbecker
 * Recursively searches the array for the $key and sets the given value.
623
 *
624
 * @param mixed $key
625
 *   Key to search for.
626
 * @param mixed $value
627
 *   Value to set.'
628
 * @param array $array
629
 *   Array to search in.
630
 *
631
 * @return bool
632
 *   True if the key has been found.
633
 */
634
function &array_setr($key, $value, array &$array) {
635
  $res = NULL;
636
  foreach ($array as $k => &$v) {
637
    if ($key == $k) {
638
      $v = $value;
639
      return $array;
640
    }
641
    elseif (is_array($v)) {
642
      $innerArray = array_setr($key, $value, $v);
643
      if ($innerArray) {
644
        return $array;
645
      }
646
    }
647
  }
648
  return $res;
649
}
650
651
/**
652
 * @todo Please document this function.
653
 * @see http://drupal.org/node/1354
654
 */
655
function &get_preceding_contentElement($contentElementKey, array &$renderTemplate) {
656
  $res = NULL;
657
  $precedingElement = NULL;
658
  foreach ($renderTemplate as &$part) {
659
    foreach ($part as $key => &$element) {
660
      if ($key == $contentElementKey) {
661
        return $precedingElement;
662
      }
663
      $precedingElement = $element;
664
    }
665
  }
666
  return $res;
667
}
668
669
/**
670
 * @todo Please document this function.
671
 * @see http://drupal.org/node/1354
672
 */
673
function &get_preceding_contentElementKey($contentElementKey, array &$renderTemplate) {
674
  $res = NULL;
675
  $precedingKey = NULL;
676
  foreach ($renderTemplate as &$part) {
677
    if (is_array($part)) {
678
      foreach ($part as $key => &$element) {
679
        if ($key == $contentElementKey) {
680
          return $precedingKey;
681
        }
682
        if (!str_beginsWith($key, '#')) {
683
          $precedingKey = $key;
684
        }
685
      }
686
    }
687
  }
688
  return $res;
689
}