Project

General

Profile

Download (61.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
3
 * @file
4
 * Description 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
/**
18
 * Theme function to alter the feature representation.
19
 *
20
 * It is highly qeutionalbe if this function should be completely removed.
21
 * If a feature needs a different representation this should be edited directly
22
 * in the cdm data but it shoud not be tweeked like this in the portal.
23
 *
24
 * Used in:
25
 *  - theme_cdm_feature_nodesTOC()
26
 *  - theme_cdm_feature_nodes()
27
 *  - theme_cdm_media_mime_application()
28
 *  - theme_cdm_media_mime_text()
29
 *
30
 * TODO delete this function? (a.kohlbecker feb 2013)
31
 *
32
 */
33
function theme_cdm_feature_name($variables) {
34
  $feature_name = $variables['feature_name'];
35
  return t($feature_name);
36
}
37

    
38
/**
39
 * Returns a set of feature blocks for a taxon profile from the $mergedFeatureNodes of a given $taxon.
40
 *
41
 * The taxon profile consists of drupal block elements, one for the description elements
42
 * of a specific feature. The structure is defined by specific FeatureTree.
43
 * The chosen FeatureTree is merged with the list of description elements prior to using this method.
44
 *
45
 * The merged nodes can be obtained by making use of the
46
 * function cdm_ws_descriptions_by_featuretree().
47
 *
48
 * @see cdm_ws_descriptions_by_featuretree()
49
 *
50
 * @param $mergedFeatureNodes
51
 *
52
 * @param $taxon
53
 *
54
 * @return array
55
 *  A Drupal render array containing feature blocks and the table of content
56
 *
57
 * @ingroup compose
58
 */
59
function compose_cdm_feature_nodes($mergedFeatureNodes, $taxon) {
60

    
61
  $block_list = array();
62

    
63
  RenderHints::pushToRenderStack('feature_nodes');
64

    
65
  $gallery_settings = getGallerySettings(CDM_DATAPORTAL_DESCRIPTION_GALLERY_NAME);
66

    
67
  // Create a drupal block for each feature
68
  foreach ($mergedFeatureNodes as $node) {
69

    
70
    if ((isset($node->descriptionElements['#type']) ||
71
        has_feature_node_description_elements($node)) && $node->feature->uuid != UUID_IMAGE) { // skip empty or supressed features
72

    
73
      $feature_name = cdm_term_representation($node->feature, 'Unnamed Feature');
74

    
75
      $block = feature_block($feature_name, $node->feature);
76
      $block->content = array();
77
      $block_content_is_empty = TRUE;
78
      $block_content_weight = 0;
79

    
80
      /*
81
       * Content/DISTRIBUTION.
82
       */
83

    
84
      if ($node->feature->uuid == UUID_DISTRIBUTION) {
85
        $block = compose_feature_block_distribution($taxon, $node->descriptionElements, $node->feature);
86
        $block_content_is_empty = FALSE;
87
      }
88
      /*
89
       * Content/COMMON_NAME.
90
       */
91
      else if ($node->feature->uuid == UUID_COMMON_NAME) {
92
        $common_names_render_array = compose_cdm_common_names($node->descriptionElements, $node->feature);
93
        $block->content[] = $common_names_render_array;
94
        $block_content_is_empty = FALSE;
95
      }
96

    
97
      else if ($node->feature->uuid == UUID_USE_RECORD) {
98
        $block_uses_content_html = theme('cdm_block_Uses', array('taxonUuid' => $taxon->uuid));
99
        $block->content[] = markup_to_render_array($block_uses_content_html);
100
        $block_content_is_empty = FALSE;
101
      }
102

    
103
      /*
104
       * Content/ALL OTHER FEATURES.
105
       */
106
      else {
107

    
108
        $media_list = array();
109
        $out_child_elements = '';
110

    
111
        if (isset($node->descriptionElements)) {
112
          $taxon_uuid = NULL;
113
          if(isset($taxon) ) {
114
            $taxon_uuid = $taxon->uuid;
115
          }
116
          $elements_render_array = compose_cdm_descriptionElements($node->descriptionElements, $node->feature, $taxon_uuid);
117
          $block_content_is_empty = empty($elements_render_array);
118
          $block->content[] = $elements_render_array;
119
        }
120

    
121
          // Content/ALL OTHER FEATURES/Subordinate Features
122
          // subordinate features are printed inline in one floating text,
123
          // it is expected hat subordinate features can "contain" TextData,
124
          // Qualitative- and Qualitative- DescriptioneElements
125
          if (isset($node->childNodes[0])) {
126

    
127
          // TODO support more than one level of children.
128
          // can this be solved by recursively calling this function?
129
          // @see http://dev.e-taxonomy.eu/trac/ticket/2393
130
          $text = '';
131
          foreach ($node->childNodes as $child) {
132

    
133
            if (isset($child->descriptionElements) && is_array($child->descriptionElements)) {
134
              foreach ($child->descriptionElements as $element) {
135

    
136
                //TODO it woud be better if we could use compose_cdm_descriptionElements() directly instead of the below stuff
137

    
138
                if (is_array($element->media)) {
139
                  // Append media of supordinate elements to list of main
140
                  // feature.
141
                  $media_list = array_merge($media_list, $element->media);
142
                }
143

    
144
                switch ($element->class) {
145
                  case 'TextData':
146
                    // FIXME use theme_cdm_descriptionElementTextData()
147
                    $out_child_elements = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
148
                    $out_child_elements = str_replace($child->feature->titleCache, '<em>' . $child->feature->representation_L10n . '</em>', $out_child_elements);
149
                    break;
150
                  case 'CategoricalData':
151
                    $out_child_elements  = '<em>' . $child->feature->representation_L10n . '</em> '
152
                      . theme('cdm_descriptionElement_CategoricalData', array('element' => $element));
153
                    break;
154
                  case 'QuantitativeData':
155
                    $out_child_elements = '<em>' . $child->feature->representation_L10n . '</em> '
156
                      . theme('cdm_descriptionElement_QuantitativeData', array('element' => $element));
157

    
158
                }
159

    
160
              }
161
              $text .= " " . $out_child_elements;
162
              $out_child_elements = '';
163
            }
164
          }
165
          $block_content_is_empty = $block_content_is_empty && empty($text);
166
          $block->content[] = markup_to_render_array($text);
167
          $block_content_is_empty = $block_content_is_empty && empty($media_list);
168
          $block->content[] = compose_feature_media_gallery($node, $media_list, $gallery_settings);
169

    
170

    
171
          }
172
        /*
173
         * Footnotes for the feature block
174
         */
175
        $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => $node->feature->uuid)));
176
        $block->content[] = markup_to_render_array(theme('cdm_annotation_footnotes', array('footnoteListKey' => $node->feature->uuid)));
177
      } // END all other features
178

    
179
      if(!$block_content_is_empty){ // skip empty block content
180
        $block_list[] = $block;
181
        cdm_toc_list_add_item(cdm_term_representation($node->feature), $node->feature->uuid);
182
      } // END: skip empty block content
183
    } // END: skip empty or supressed features
184
  } // END: creating a block per feature
185

    
186
  drupal_alter('cdm_feature_node_blocks', $block_list, $taxon);
187

    
188
  RenderHints::popFromRenderStack();
189

    
190
  return _block_get_renderable_array($block_list);
191
}
192

    
193
  /**
194
   * @param $node
195
   * @param $media_list
196
   * @param $gallery_settings
197
   * @return array
198
   */
199
  function compose_feature_media_gallery($node, $media_list, $gallery_settings) {
200
    if (isset($node->descriptionElements)) {
201
      $media_list = array_merge($media_list, cdm_dataportal_media_from_descriptionElements($node->descriptionElements));
202
    }
203
    $captionElements = array('title', 'rights');
204
    $gallery = '';
205
    if (isset($gallery_settings['cdm_dataportal_media_maxextend']) && isset($gallery_settings['cdm_dataportal_media_cols'])) {
206
      $gallery = theme('cdm_media_gallerie', array(
207
        'mediaList' => $media_list,
208
        'galleryName' => CDM_DATAPORTAL_DESCRIPTION_GALLERY_NAME . '_' . $node->feature->uuid,
209
        'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
210
        'cols' => $gallery_settings['cdm_dataportal_media_cols'],
211
        'captionElements' => $captionElements,
212
      ));
213
      return array($media_list, $gallery);
214
    }
215
    return array($media_list, $gallery);
216
  }
217

    
218
  /**
219
   * @param $taxon
220
   * @param $descriptionElements
221
   *   an associative array with two elements:
222
   *   - '#type': must be 'DTO'
223
   *   - 'DistributionInfoDTO': a CDM DistributionInfoDTO object as returned by the DistributionInfo web service
224
   * @param $feature
225
   *
226
   * @ingroup compose
227
   */
228
  function compose_feature_block_distribution($taxon, $descriptionElements, $feature) {
229
    $text_data_glue = '';
230
    $text_data_sortOutArray = FALSE;
231
    $text_data_enclosingTag = 'ul';
232
    $text_data_out_array = array();
233

    
234
    $distributionElements = NULL;
235
    $distribution_info_dto = NULL;
236
    $distribution_sortOutArray = FALSE;
237

    
238
    if (variable_get('distribution_sort', 'NO_SORT') != 'NO_SORT') {
239
      $distribution_glue = '';
240
      $distribution_enclosingTag = 'dl';
241
    } else {
242
      $distribution_glue = '';
243
      $distribution_enclosingTag = 'ul';
244
    }
245

    
246
    if (!isset($descriptionElements['#type']) || !$descriptionElements['#type'] == 'DTO') {
247
      // skip the DISTRIBUTION section if there is no DTO type element
248
      return array(); // FIXME is it ok to return an empty array?
249
    }
250

    
251
    $block = feature_block(
252
      cdm_term_representation($feature, 'Unnamed Feature'),
253
      $feature
254
    );
255

    
256
    // $$descriptionElements['TextData'] is added to to the feature node in merged_taxon_feature_tree()
257
    if (isset($descriptionElements['TextData'])) {
258
      // --- TextData
259
      foreach ($descriptionElements['TextData'] as $text_data_element) {
260
        $asListElement = FALSE;
261
        $text_data_render_array = compose_cdm_descriptionElementTextData($text_data_element, $asListElement, $text_data_element->feature->uuid);
262
        $repr = drupal_render($text_data_render_array);
263

    
264
        if (!array_search($repr, $text_data_out_array)) { // de-duplication !!
265
          $text_data_out_array[] = $repr;
266
          // TODO HINT: sorting in compose_cdm_feature_block_elements will
267
          // not work since this array contains html attributes with uuids
268
          // and what is about cases like the bibliography where
269
          // any content can be prefixed with some foot-note anchors?
270
          $text_data_sortOutArray = TRUE;
271
          $text_data_glue = '<br/> ';
272
          $text_data_enclosingTag = 'p';
273
        }
274
      }
275
    }
276

    
277

    
278
    if ($text_data_out_array && variable_get(DISTRIBUTION_TEXTDATA_DISPLAY_ON_TOP, 0)) {
279
      $block->content[] = compose_cdm_feature_block_elements(
280
        $text_data_out_array,
281
        $feature,
282
        $text_data_glue,
283
        $text_data_sortOutArray,
284
        $text_data_enclosingTag
285
      );
286
    }
287

    
288
    // --- Distribution map
289
    $distribution_map_query_parameters = NULL;
290
    if (isset($descriptionElements['DistributionInfoDTO'])) {
291
      $distribution_map_query_parameters = $descriptionElements['DistributionInfoDTO']->mapUriParams;
292
    }
293
    $map_render_element = compose_distribution_map($taxon, $distribution_map_query_parameters);
294
    $block->content[] = $map_render_element;
295

    
296
    // --- tree or list
297
    $dto_out_array = array();
298
    if (isset($descriptionElements['DistributionInfoDTO'])) {
299
      $distribution_info_dto = $descriptionElements['DistributionInfoDTO'];
300

    
301
      // --- tree
302
      if (is_object($distribution_info_dto->tree)) {
303
        $dto_out_array[] = theme('cdm_description_ordered_distributions', array('distribution_tree' => $distribution_info_dto->tree));
304
      }
305

    
306
      // --- sorted element list
307
      if (is_array($distribution_info_dto->elements) && count($distribution_info_dto->elements) > 0) {
308
        foreach ($distribution_info_dto->elements as $descriptionElement) {
309
          if (is_object($descriptionElement->area)) {
310
            $sortKey = $descriptionElement->area->representation_L10n;
311
            $distributionElements[$sortKey] = $descriptionElement;
312
          }
313
        }
314
        ksort($distributionElements);
315
        $dto_out_array[] = theme('cdm_descriptionElement_Distribution', array(
316
          'descriptionElements' => $distributionElements,
317
        ));
318

    
319
      }
320
      //
321
      $block->content[] = compose_cdm_feature_block_elements(
322
        $dto_out_array,
323
        $feature,
324
        $distribution_glue,
325
        $distribution_sortOutArray,
326
        $distribution_enclosingTag
327
      );
328
    }
329

    
330
    // --- TextData at the bottom
331
    if ($text_data_out_array && !variable_get(DISTRIBUTION_TEXTDATA_DISPLAY_ON_TOP, 0)) {
332
      $block->content[] = compose_cdm_feature_block_elements(
333
        $text_data_out_array,
334
        $feature,
335
        $text_data_glue,
336
        $text_data_sortOutArray,
337
        $text_data_enclosingTag
338
      );
339
    }
340

    
341
    $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => UUID_DISTRIBUTION)));
342
    $block->content[] = markup_to_render_array(theme('cdm_annotation_footnotes', array('footnoteListKey' => UUID_DISTRIBUTION)));
343

    
344
    return $block;
345
  }
346

    
347

    
348
  /**
349
 * @todo Please document this function.
350
 * @see http://drupal.org/node/1354
351
 */
352
function theme_FeatureTree_hierarchy($variables) {
353

    
354
  $FeatureTreeUuid = $variables['FeatureTreeUuid'];
355
  if (!is_uuid($FeatureTreeUuid)) {
356
    return;
357
  }
358

    
359
  $out = '';
360
  $featureTree = cdm_ws_get(CDM_WS_FEATURETREE, array(
361
    $FeatureTreeUuid,
362
  ));
363

    
364
  if (isset($featureTree) && isset($featureTree->root)) {
365
    $out = '<ul class="' . $featureTree->class . '">';
366
    $out .= theme('FeatureTree_hierarchy_children', array('node' => $featureTree->root));
367
    $out .= '</ul>';
368
  }
369
  return $out;
370
}
371

    
372
/**
373
 * @todo Please document this function.
374
 * @see http://drupal.org/node/1354
375
 */
376
function theme_FeatureTree_hierarchy_children($variables) {
377

    
378
  $node = $variables['node'];
379
  $out = '';
380
  if (isset($node->childNodes)) {
381

    
382
    foreach ($node->childNodes as $childNode) {
383
      $out .= '<li>' . check_plain($childNode->feature->representation_L10n);
384
      if (isset($childNode->childNodes) && count($childNode->childNodes) > 0) {
385
        $out .= '<ul>' . theme('FeatureTree_hierarchy_children', array('node' => $childNode)) . '</ul>';
386
      }
387
      $out .= '</li>';
388
    }
389
  }
390
  return $out;
391
}
392

    
393
/**
394
 * Returns HTML for the texts in a description $elements.
395
 *
396
 * Joins the texts in $elements and encloses with a HTML tag.
397
 *
398
 * @param  $elements
399
 * @param  feature:
400
 *  The feature to which the elements given in $elements are belonging to.
401
 * @param  glue:
402
 *  Defaults to empty string.
403
 * @param $sort
404
 *   Boolean Whether to sort the $elements alphabetically, default is FALSE
405
 * @param  $enclosing_tag
406
 *
407
 * @ingroup compose
408
 */
409
function compose_cdm_feature_block_elements($elements, $feature, $glue = '', $sort = FALSE, $enclosing_tag = 'ul') {
410

    
411
  $feature_block_settings = get_feature_block_settings($feature->uuid);
412
  if($feature_block_settings['as_list']){
413
    $enclosing_tag = $feature_block_settings['as_list'];
414
  }
415

    
416
  $out = '<' . $enclosing_tag . ' class="feature-block-elements" id="' . $feature->representation_L10n . '">';
417

    
418
  if ($sort) {
419
    sort($elements);
420
  }
421

    
422
  //TODO it would be nice if any element would get "feature-block-element" as additional class attribute
423
  //     this will become possible once all $elemets are real Drupal render arrays
424
  $out .= join($elements, $glue) ;
425

    
426
  $out .= '</' . $enclosing_tag . '>';
427
  return markup_to_render_array($out);
428
}
429

    
430

    
431
/**
432
 * Theme function to render CDM DescriptionElements of the type CategoricalData.
433
 *
434
 * @param array $variables
435
 *   An associative array containing:
436
 *  - element: the CategoricalData element
437
 * @return a html representation of the given CategoricalData element
438
 *
439
 * @ingroup themeable
440
 */
441
function theme_cdm_descriptionElement_CategoricalData($variables) {
442
  $element = $variables['element'];
443

    
444
  $state_data_strings = array();
445
  if (isset($element->stateData)) {
446
    foreach ($element->stateData as $stateData) {
447

    
448
      $state  = NULL;
449

    
450
      if(isset($stateData->state)){
451
        $state = cdm_term_representation($stateData->state);
452
      }
453

    
454
      if (isset($stateData->modifyingText_L10n)) {
455
        $state = ' ' . $stateData->modifyingText_L10n;
456
      }
457

    
458
      $modifiers_strings = cdm_modifers_representations($stateData);
459

    
460
      $state_data_strings[] = $state . ($modifiers_strings ? ' ' . $modifiers_strings : '');
461

    
462
    }
463
  }
464

    
465
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
466

    
467
  $out = '<span class="' . html_class_attribute_ref($element) . '">' . implode(', ', $state_data_strings) . '</span>';
468
  return $out . $footnote_key_list_str;
469
}
470

    
471
/**
472
 * Theme function to render CDM DescriptionElements of the type QuantitativeData.
473
 *
474
 * @param array $variables
475
 *   An associative array containing:
476
 *  - element: the QuantitativeData element
477
 * @return a html representation of the given QuantitativeData element
478
 *
479
 * @ingroup themeable
480
 */
481
function theme_cdm_descriptionElement_QuantitativeData($variables) {
482
  /*
483
   * - statisticalValues
484
   *   - value
485
   *   - modifiers
486
   *   - type
487
   * - unit->representation_L10n
488
   * - modifyingText
489
   * - modifiers
490
   * - sources
491
   */
492
  $element = $variables['element'];
493

    
494
  $out = '';
495

    
496
  $type_representation = NULL;
497
  $modifiers_strings = array();
498

    
499

    
500
  if (isset($element->statisticalValues)) {
501
    $value_array = array();
502
    foreach ($element->statisticalValues as $val) {
503
      if (isset($val->value)) {
504
        $value_array[] = $val->value;
505
      }
506
    }
507

    
508
    $out .= implode($value_array, ', ');
509
  }
510

    
511
  if (isset($element->unit)) {
512
    $out .= ' '. cdm_term_representation($element->unit);
513
  }
514

    
515
  if (isset($element->statisticalValues->modifyingText_L10n)) {
516
    $out .=  ' ' . $element->statisticalValues->modifyingText_L10n;
517
  }
518
  $modifiers_strings = cdm_modifers_representations($element->statisticalValues);
519
  $out .= ($modifiers_strings ? ' ' . cdm_modifers_representations($element->statisticalValues) : '');
520

    
521
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
522

    
523
  return $out . $footnote_key_list_str;
524

    
525
}
526

    
527
/**
528
 * Theme function to render CDM DescriptionElements of the type IndividualsAssociations.
529
 *
530
 * @param array $variables
531
 *   An associative array containing:
532
 *  - element: the IndividualsAssociations element
533
 * @return html representation of the given IndividualsAssociations element
534
 *
535
 * @ingroup themeable
536
 */
537
function theme_cdm_descriptionElement_IndividualsAssociation($variables) {
538

    
539
  $element = $variables['element'];
540

    
541
  $out = '';
542

    
543
  $render_array = compose_cdm_specimenOrObservation($element->associatedSpecimenOrObservation);
544

    
545
  if (isset($element->description_L10n)) {
546
    $out .=  ' ' . $element->description_L10n;
547
  }
548

    
549
  $out .= drupal_render($render_array);
550

    
551
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
552

    
553
  return $out . $footnote_key_list_str;
554

    
555

    
556
}
557

    
558
/**
559
 * Theme function to render CDM DescriptionElements of the type TaxonInteraction.
560
 *
561
 * @param array $variables
562
 *   An associative array containing:
563
 *  - element: the TaxonInteraction element
564
 * @return html representation of the given TaxonInteraction element
565
 *
566
 * @ingroup themeable
567
 */
568
function theme_cdm_descriptionElement_TaxonInteraction($variables) {
569

    
570
  $element = $variables['element'];
571

    
572
  $out = '';
573

    
574
  if (isset($element->description_L10n)) {
575
    $out .=  ' ' . $element->description_L10n;
576
  }
577

    
578
  if(isset($element->taxon2)){
579
    $out = theme('cdm_taxonName',
580
        array(
581
            'taxonName' => $element->taxon2->name,
582
            'nameLink' => url(path_to_taxon($element->taxon2->uuid))
583
        )
584
      );
585
  }
586

    
587
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
588

    
589
  return $out . $footnote_key_list_str;
590

    
591

    
592
}
593

    
594
/**
595
 * Returns HTML for citations textdata elements.
596
 *
597
 * TODO: assign a new name to the function? Because it is used for the citations
598
 * Textdata elements and not for all text data description elements.
599
 *
600
 * @param $element
601
 *    The CDM TextData description element which contains the textual  information.
602
 * @param $asListElement
603
 *    A boolean which determines whether the citations should
604
 *     be rendered as a list or not.
605
 *    TODO remove and replace $asListElement by $feature_block_settings['as_list']
606
 *  @param $feature_uuid
607
 *
608
 * @return array
609
 *   A drupal render array with the following elements being used:
610
 *    - #tag: either 'div', 'li', ...
611
 *    ⁻ #attributes: class attributes
612
 *    - #value_prefix: (optionally) contains footnote anchors
613
 *    - #value: contains the textual content
614
 *    - #value_suffix: (optionally) contains footnote keys
615
 *
616
 * @ingroup compose
617
 */
618
function compose_cdm_descriptionElementTextData($element, $asListElement, $feature_uuid) {
619

    
620
  $footnote_list_key_suggestion = $feature_uuid;
621

    
622
  $sourceRefs = '';
623
  $name_used_in_source = '';
624

    
625
  // FIXME $feature_block_settings should be passed as parameter!!!!!
626
  $feature_block_settings = get_feature_block_settings($feature_uuid);
627
  $do_references_inline = $feature_block_settings['sources_as_content'];
628

    
629
  // FIXME remove this hack ---------------------------
630
  $default_theme = variable_get('theme_default', NULL);
631
  if($default_theme == 'garland_cichorieae' || $default_theme == 'cyprus'
632
    || $default_theme == 'flore_afrique_centrale' || $default_theme == 'flora_malesiana' || $default_theme == 'flore_gabon' ){
633
    $asListElement = $feature_block_settings['as_list'] == 'ul';
634
  }
635
  // --------------------------------------------------
636

    
637
  $render_array = array(
638
    '#type' => 'html_tag',
639
    '#tag' => $asListElement ? 'li' : 'span',
640
    '#attributes' => array(
641
      'class' => 'DescriptionElement DescriptionElement-' . $element->class . '
642
      ' .  html_class_attribute_ref($element)
643
    ),
644
    '#value' => '',
645
    '#value_suffix' => NULL
646
  );
647

    
648
  // TODO this should be configurable
649
  $description = '';
650
  if (isset($element->multilanguageText_L10n->text)) {
651
    $description = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
652
  }
653

    
654
  // original sources
655
  if($do_references_inline) {
656
    foreach ($element->sources as $source) {
657
      // ---------------------------------------------------------------------------
658
      // CUSTOM CODE (2) from cichorieae theme,
659
      // use nomref web service to combine reference with microreference, other way to combine these?
660
      // is this a general case for all features?
661
      // compare with theme_cdm_reference() where it is only appended
662
      // FIXME the CDM_WS_NOMENCLATURAL_REFERENCE_CITATION service should onyl be used for nomenclatural references
663
      // needs however further discussion with the users!!!
664
      // SKIPPING THIS FOR NOW:
665
      if (FALSE && $feature_uuid == UUID_CITATION) {
666

    
667
        $referenceCitation = cdm_ws_get(
668
          CDM_WS_NOMENCLATURAL_REFERENCE_CITATION,
669
          array($source->citation->uuid),
670
          "microReference=" . urlencode($source->citationMicroReference
671
          ));
672
        $referenceCitation = $referenceCitation->String;
673

    
674
        // END CUSTOM CODE (2)
675
        // ---------------------------------------------------------------------------
676
      } else {
677
        $referenceCitation = theme('cdm_OriginalSource',
678
          array(
679
            'source' => $source,
680
            'doLink' => $feature_block_settings['link_to_reference']
681
          )
682
        );
683
      }
684

    
685
      if ($description && strlen($description) > 0 && $referenceCitation) {
686
        $sourceRefs .= ' (' . $referenceCitation . ')';
687
      }
688
      elseif ($referenceCitation) {
689
        $sourceRefs = $referenceCitation;
690
      }
691

    
692
      if (strlen($sourceRefs) > 0) {
693
        $sourceRefs = '<span class="sources">' . $sourceRefs . '</span>';
694
      }
695

    
696
      // link the nameUsedInSource to the according name page
697
      // Do a link to name page.
698
      if (isset($source->nameUsedInSource->uuid) && isset($source->nameUsedInSource->titleCache)) {
699
        // it is a DescriptionElementSource
700
        if($feature_block_settings['link_to_name_used_in_source']){
701
          $name_used_in_source = l(
702
            $source->nameUsedInSource->titleCache,
703
            path_to_name($source->nameUsedInSource->uuid),
704
            array(
705
              'attributes' => array(),
706
              'absolute' => TRUE,
707
              'html' => TRUE,
708
            ));
709

    
710
        } else {
711
          $name_used_in_source = $source->nameUsedInSource->titleCache;
712
        }
713
      }
714
      else if (isset($source->nameUsedInSource->originalNameString) && strlen($source->nameUsedInSource->originalNameString) > 0) {
715
        // TODO does this make sense? is $source->nameUsedInSource->originalNameString different from $source->nameUsedInSource->titleCache ?
716
        // it is NOT a DescriptionElementSource
717
        // Show a text without link.
718
        $name_used_in_source = $source->nameUsedInSource->originalNameString;
719
      }
720
    } // END of loop over sources
721

    
722
    // annotations footnotes separate.
723
    $render_array['#value-suffix'] = theme('cdm_annotations_as_footnotekeys',
724
      array(
725
        'cdmBase_list' => $element,
726
        'footnote_list_key' => $footnote_list_key_suggestion,
727
      )
728
    );
729

    
730
  } // END of references inline
731

    
732
  if(!$do_references_inline || $feature_block_settings['sources_as_content_to_bibliography']) {
733
    $render_array['#value-suffix'] = cdm_create_description_element_footnotes($element, ',', $footnote_list_key_suggestion);
734
  }
735

    
736

    
737
  // FIXME the only distinction between $asListElement = TRUE and FLASE is the different display of the
738
  // nameInSource which is prepended with "name in source:" in case of the 'not as list' case:
739
  if ($asListElement) {
740
    // Adding ":" if necessary.
741
    if (!empty($name_used_in_source)) {
742
      if ( (!empty($description)|| !empty($sourceRefs)) && $feature_uuid != UUID_CHROMOSOMES_NUMBERS) {
743
        $render_array['#value'] = $name_used_in_source . ': ';
744
      } else {
745
        $render_array['#value'] .= $name_used_in_source . ' ';
746
      }
747
    }
748
    $render_array['#value'] .= $description . $sourceRefs;
749
  }
750
  else {
751
    if ($name_used_in_source) {
752
      $name_used_in_source = ' (name in source: ' . $name_used_in_source . ')';
753
    }
754
    $render_array['#value'] = $description . $sourceRefs . $name_used_in_source;
755
  }
756

    
757
  return $render_array;
758
}
759

    
760
/**
761
 * Composes block of common names for the given DescriptionElements $elements which must be of the feature CommonName
762
 *
763
 * @parameter $elements
764
 *  an array of CDM DescriptionElements either of type CommonName or TextData
765
 * @parameter $feature
766
 *  the common feature of all $elements, must be CommonName
767
 *
768
 * @return
769
 *   A drupal render array
770
 *
771
 * @ingroup compose
772
 */
773
function compose_cdm_common_names($elements, $feature, $weight = FALSE) {
774

    
775
  $common_name_out = '';
776
  $common_name_feature_elements = array();
777
  $textData_commonNames = array();
778

    
779
  $footnote_key_suggestion = 'common-names-feature-block';
780

    
781
  if (is_array($elements)) {
782
    foreach ($elements as $element) {
783

    
784
      if ($element->class == 'CommonTaxonName') {
785

    
786
        // common name without a language or area, should not happen but is possible
787
        $language_area_key = '';
788
        if (isset($element->language->representation_L10n)) {
789
          $language_area_key .= '<b>' . $element->language->representation_L10n . '</b>';
790
        }
791
        if(isset($element->area->titleCache) && strlen($element->area->titleCache) > 0){
792
          $language_area_key .= ($language_area_key ? ' '  : '') . '(' . $element->area->titleCache . ')';
793
        }
794

    
795
        if(isset($common_names[$language_area_key][$element->name])) {
796
          // same name already exists for language and areae combination, se we merge the description elements
797
          cdm_merge_description_elements($common_names[$language_area_key][$element->name], $element);
798
        } else{
799
          // otherwise add as new entry
800
          $common_names[$language_area_key][$element->name] = $element;
801
        }
802

    
803
      }
804
      elseif ($element->class == 'TextData') {
805
        $textData_commonNames[] = $element;
806
      }
807
    }
808
  }
809
  // Handling common names.
810
  if (isset($common_names) && count($common_names) > 0) {
811
    // Sorting the array based on the key (language, + area if set).
812
    // Comment @WA there are common names without a language, so this sorting
813
    // can give strange results.
814
    ksort($common_names);
815

    
816
    // loop over set of elements per language area
817
    foreach ($common_names as $language_area_key => $elements) {
818
      ksort($elements); // sort names alphabetically
819
      $per_language_area_out = array();
820
      // loop over set of individual elements
821
      foreach ($elements as $element) {
822
        if ($element->name) {
823
          $per_language_area_out[] = '<span class="' . html_class_attribute_ref($element) . '">'
824
          . $element->name . cdm_create_description_element_footnotes($element, ',', $footnote_key_suggestion) . '</span>';
825
        }
826
      } // End of loop over set of individual elements
827
      $common_name_feature_elements[] = ($language_area_key ? $language_area_key . ': ' : '' ) . join(', ', $per_language_area_out);
828
    } // End of loop over set of elements per language area
829

    
830

    
831
    $common_name_feature_elements_render_array = compose_cdm_feature_block_elements(
832
      $common_name_feature_elements,
833
      $feature,
834
      '; ',
835
      FALSE,
836
      'div'
837
      );
838
    $common_name_out .= $common_name_feature_elements_render_array['#markup'];
839

    
840
  }
841

    
842
  // Handling commons names as text data.
843
  $text_data_out = array();
844

    
845
  foreach ($textData_commonNames as $text_data_element) {
846
    /* footnotes are not handled correctly in theme_cdm_descriptionElementTextData,
847
       need to set 'common-names-feature-block' as $footnote_key_suggestion */
848
    RenderHints::setFootnoteListKey($footnote_key_suggestion);
849
    $text_data_render_array = compose_cdm_descriptionElementTextData($text_data_element, TRUE, $text_data_element->feature->uuid);
850
    $text_data_out[] = drupal_render($text_data_render_array);
851
  }
852

    
853
  $common_name_out_text_data = compose_cdm_feature_block_elements(
854
        $text_data_out,
855
        $feature
856
      );
857

    
858

    
859
  $footnotes = theme('cdm_footnotes', array('footnoteListKey' => $footnote_key_suggestion)); // FIXME is this needed at all?
860
  $footnotes .= theme('cdm_annotation_footnotes', array('footnoteListKey' => $footnote_key_suggestion));
861

    
862
  return  markup_to_render_array(
863
    '<div class="common_names_as_common_names">' . $common_name_out . '</div>'
864
    .'<div class="common_names_as_text_data">' . $common_name_out_text_data['#markup'] . '</div>'
865
    .$footnotes,
866
    $weight
867
  );
868
}
869

    
870
/**
871
 * Return HTML for a list of description elements.
872
 *
873
 * Usually these are of a specific feature type.
874
 *
875
 * @param $descriptionElements
876
 *   array of descriptionElements which belong to the same feature.
877
 *   These descriptions elements of a Description must be ordered by the chosen feature tree by
878
 *   calling the function _mergeFeatureTreeDescriptions().
879
 *   @see _mergeFeatureTreeDescriptions()
880
 *
881
 * @param  $feature_uuid
882
 *
883
 * @return
884
 *    A drupal render array for the $descriptionElements, may be an empty array if the textual content was empty.
885
 *    Footnote key or anchors are not considered to be textual content.
886
 *
887
 * @ingroup compose
888
 */
889
function compose_cdm_descriptionElements($descriptionElements, $feature) {
890

    
891
  $render_array = array();
892
  $elements_out_array = array();
893
  $distribution_tree = null;
894

    
895
  /*
896
   * $feature_block_has_content will be set true if at least one of the
897
   * $descriptionElements contains some text which makes up some content
898
   * for the feature block. Footnote keys are not considered
899
   * to be content in this sense.
900
   */
901
  $feature_block_has_content = false;
902

    
903
  /*
904
  $userDefined = mixed_variable_get(LAYOUT_SETTING_PREFIX . $feature_uuid, FEATURE_TREE_LAYOUT_DEFAULTS);
905
  if(variable_get('distribution_sort',
906
      'NO_SORT') != 'NO_SORT'){
907
      $glue = '';
908
      $enclosingTag = 'dl';
909
      $entryEnclosingTag = NULL;
910
  } else if($userDefined &&
911
      $userDefined['enabled']){
912
    $glue = $userDefined['glue'];
913
    $enclosingTag =  $userDefined['enclosingTag'];
914
    $entryEnclosingTag = $userDefined['entryEnclosingTag'];
915
  } else { // TODO remove once  LAYOUT_SETTING_PREFIX-{uuid} setting are configured to work for all portals(selenium test still missing!!!)
916
    $glue = ''; $enclosingTag = 'ul';
917
    $entryEnclosingTag = NULL ;
918
  }
919
  */
920

    
921
  RenderHints::pushToRenderStack('cdm_descriptionElements');
922

    
923
  if (is_array($descriptionElements)) {
924
    // --- normal description element arrays
925
    foreach ($descriptionElements as $descriptionElement) {
926

    
927
      // --- IMAGE_SOURCES --- //
928
      if ($descriptionElement->feature->uuid == UUID_IMAGE_SOURCES) {
929
        $image_sources[] = $descriptionElement;
930
      }
931
      // --- USE TEXTDATA --- //
932
      elseif ($descriptionElement->feature->uuid == UUID_USE) {
933
        // Do nothing to avoid rendering.
934
      } else {
935
        /* decide based on the description element class
936
         *
937
         * Features handled here:
938
         * all except DISTRIBUTION, COMMON_NAME, USES, IMAGES,
939
         *
940
         *
941
         * TODO provide api_hook as extension point for this?
942
         */
943
        $feature_block_settings = get_feature_block_settings($descriptionElement->feature->uuid);
944
        $asListElement  = $feature_block_settings['as_list'] == 'ul';
945
        switch ($descriptionElement->class) {
946
          case 'TextData':
947
              $text_data_render_array = compose_cdm_descriptionElementTextData($descriptionElement, $asListElement, $descriptionElement->feature->uuid);
948
              $feature_block_has_content = $feature_block_has_content || !empty($text_data_render_array['#value']);
949
              $elements_out_array[] = drupal_render($text_data_render_array);
950
            break;
951
          case 'CategoricalData':
952
            $feature_block_has_content = true;
953
            $elements_out_array[] = theme('cdm_descriptionElement_CategoricalData', array('element' => $descriptionElement));
954
            break;
955
          case 'QuantitativeData':
956
            $feature_block_has_content = true;
957
            $elements_out_array[] = theme('cdm_descriptionElement_QuantitativeData', array('element' => $descriptionElement));
958
            break;
959
          case 'IndividualsAssociation':
960
            $feature_block_has_content = true;
961
            $elements_out_array[] = theme('cdm_descriptionElement_IndividualsAssociation', array('element' => $descriptionElement));
962
            break;
963
          case 'TaxonInteraction':
964
            $feature_block_has_content = true;
965
            $elements_out_array[] = theme('cdm_descriptionElement_TaxonInteraction', array('element' => $descriptionElement));
966
            break;
967
          case 'Uses':
968
          /* IGNORE Uses classes, these are handled completely in theme_cdm_UseDescription */
969
          break;
970
        default:
971
          $feature_block_has_content = true;
972
          $elements_out_array[] = '<li>No method for rendering unknown description class: ' . $descriptionElement->class . '</li>';
973
      }
974
    }
975
    } // --- END loop over normal description element arrays
976

    
977
    // If feature = CITATION sort the list of sources.
978
    // This is ONLY for FLORA MALESIANA and FLORE d'AFRIQUE CENTRALE.
979
    if ($descriptionElement->feature->uuid == UUID_CITATION) {
980
      sort($elements_out_array);
981
    }
982

    
983
    if (isset($image_sources)) {
984
      $elements_out_array[] = theme('cdm_description_element_image_source', array('image_sources' => $image_sources, 'asListElement' => TRUE));
985
    }
986
  } // END normal description element arrays
987

    
988
  if($feature_block_has_content){
989
    $render_array = compose_cdm_feature_block_elements(
990
      $elements_out_array,
991
      $feature
992
    );
993
  }
994

    
995
  RenderHints::popFromRenderStack();
996
  return $render_array;
997
}
998

    
999
/**
1000
 * @todo Please document this function.
1001
 * @see http://drupal.org/node/1354
1002
 */
1003
function compare_image_sources($a, $b) {
1004
  if ($a->multilanguageText_L10n->text == $b->multilanguageText_L10n->text) {
1005
    return 0;
1006
  }
1007
  return ($a->multilanguageText_L10n->text < $b->multilanguageText_L10n->text) ? -1 : 1;
1008
}
1009

    
1010
/**
1011
 * @todo Please document this function.
1012
 * @see http://drupal.org/node/1354
1013
 */
1014
function theme_cdm_description_element_image_source($variables) {
1015
  $image_sources = $variables['image_sources'];
1016
  $asListElement = $variables['asListElement'];
1017
  $out = '';
1018
  $separator = ',';
1019
  RenderHints::pushToRenderStack('descriptionElementImageSource');
1020
  RenderHints::setFootnoteListKey(UUID_IMAGE_SOURCES);
1021

    
1022
  // Sorting the image sources.
1023
  usort($image_sources, "compare_image_sources");
1024
  // Generate the footnotes.
1025
  foreach ($image_sources as $image_source) {
1026
    $footNoteKeys = cdm_annotations_as_footnotekeys($image_source);
1027
    foreach ($image_source->sources as $source) {
1028
      if (_is_original_source_type($source)) {
1029
        $fn_key = FootnoteManager::addNewFootnote(original_source_footnote_list_key(), theme('cdm_OriginalSource', array(
1030
          'source' => $source,
1031
          'doLink' => FALSE,
1032
        )));
1033
        // Ensure uniqueness of the footnote keys.
1034
        cdm_add_footnote_to_array($footNoteKeys, $fn_key);
1035
      }
1036
    }
1037
    // Sort and render footnote keys.
1038
    $footnote_key_list_str = '';
1039
    asort($footNoteKeys);
1040
    foreach ($footNoteKeys as $footNoteKey) {
1041
      $footnote_key_list_str .= theme('cdm_footnote_key', array('footnoteKey' => $footNoteKey, 'separator' => ($footnote_key_list_str ? $separator : '')));
1042
    }
1043
    // Return value!
1044
    $out .= '<span class="descriptionElement descriptionElement-' . $image_source->uuid . '">' . $image_source->multilanguageText_L10n->text . $footnote_key_list_str . '; </span>';
1045
  }
1046

    
1047
  RenderHints::popFromRenderStack();
1048
  return $out;
1049
}
1050

    
1051
/**
1052
 * @todo Please document this function.
1053
 * @see http://drupal.org/node/1354
1054
 */
1055
function theme_cdm_descriptionElement_Distribution($variables) {
1056
  $descriptionElements = $variables['descriptionElements'];
1057
  $enclosingTag = $variables['enclosingTag'];
1058
  if (!$enclosingTag) {
1059
    $enclosingTag = "span";
1060
  }
1061

    
1062
  $out = '';
1063
  RenderHints::pushToRenderStack('descriptionElementDistribution');
1064
  RenderHints::setFootnoteListKey(UUID_DISTRIBUTION);
1065

    
1066
  foreach ($descriptionElements as $descriptionElement) {
1067

    
1068
    $footnote_key_list_str = cdm_create_description_element_footnotes($descriptionElement);
1069

    
1070
    $out .= '<' . $enclosingTag . ' class="descriptionElement descriptionElement-' . $descriptionElement->uuid . '">'
1071
        . $descriptionElement->area->representation_L10n . $footnote_key_list_str
1072
        . ' </' . $enclosingTag . '>';
1073
  }
1074

    
1075
  RenderHints::popFromRenderStack();
1076
  return $out;
1077
}
1078

    
1079

    
1080
/**
1081
 * Compare two different footnotes objects.
1082
 *
1083
 * The comparison is based on the footnote key. The one which is
1084
 * displayed as footnote number.
1085
 *
1086
 * @param mixed $a
1087
 *   Footnote object $a.
1088
 * @param mixed $b
1089
 *   Footnote object $b.
1090
 */
1091
function footnotes_key_compare($a, $b) {
1092
  $res = 0;
1093
  if (empty($a) || empty($b)) {
1094
    return $res;
1095
  }
1096
  if ($a->keyStr < $b->keyStr) {
1097
    $res = -1;
1098
  }
1099
  elseif ($a->keyStr > $b->keyStr) {
1100
    $res = 1;
1101
  }
1102
  return $res;
1103
}
1104

    
1105
/**
1106
 * @todo Please document this function.
1107
 * @see http://drupal.org/node/1354
1108
 */
1109
function theme_cdm_description_ordered_distributions($variables) {
1110

    
1111
  $distribution_tree = $variables['distribution_tree'];
1112

    
1113
  // Returning NULL if there are no description elements.
1114
  if ($distribution_tree == null) {
1115
    return NULL;
1116
  }
1117

    
1118
  // Initialization of some variables.
1119
  $out = '';
1120
  $separator = ',';
1121
  RenderHints::pushToRenderStack('descriptionElementDistribution');
1122
  RenderHints::setFootnoteListKey(UUID_DISTRIBUTION);
1123

    
1124
  $ordered_areas = $distribution_tree;
1125
  if (isset($ordered_areas->rootElement->children)) {
1126
    $ordered_areas = $ordered_areas->rootElement->children;
1127
  }
1128

    
1129
  // Printing the distributions.
1130
  if (is_array($ordered_areas) && count($ordered_areas) > 0) {
1131
    foreach ($ordered_areas as $element_level1) {
1132
      // Level1.
1133
      $out .= '<dt>' . $element_level1->nodeId->representation_L10n . ':</dt> ';
1134
      $out .= '<dd>';
1135

    
1136
      // Level3.
1137
      foreach ($element_level1->children as $element_level3) {
1138
        $text_l3 = $element_level3->nodeId->representation_L10n;
1139
        $fnKeysLevel3Str = '';
1140
        $fnKeysLevel3 = cdm_annotations_as_footnotekeys($element_level3->data);
1141
        if (isset($element_level3->data[0])) {
1142
          foreach ($element_level3->data as $description_level3){
1143
            foreach ($description_level3->sources as $source) {
1144
              if (_is_original_source_type($source)) {
1145
                $fn_key3 = FootnoteManager::addNewFootnote(
1146
                  original_source_footnote_list_key(),
1147
                  theme('cdm_OriginalSource', array('source' => $source, 'doLink' => FALSE)
1148
                ));
1149
                cdm_add_footnote_to_array($fnKeysLevel3, $fn_key3);
1150
              }
1151
            }
1152
          }
1153
        }
1154
        // Level4.
1155
        $l4_regions = array();
1156
        foreach ($element_level3->children as $element_level4) {
1157
          if (isset($element_level4->data[0])) {
1158
            $text_l4 = $element_level4->nodeId->representation_L10n;
1159
            $l4_regions[$element_level3->nodeId->representation_L10n] = array();
1160
            $fnKeysLevel4Str = '';
1161
            foreach($element_level4->data as $description_level4) {
1162
              $fnKeysLevel4 = cdm_annotations_as_footnotekeys($description_level4);
1163
              foreach ($description_level4->sources as $source) {
1164
                if (_is_original_source_type($source)) {
1165
                  $fn_key4 = FootnoteManager::addNewFootnote(
1166
                      original_source_footnote_list_key(),
1167
                      theme('cdm_OriginalSource', array('source' => $source, 'doLink' => FALSE)));
1168
                  cdm_add_footnote_to_array($fnKeysLevel4, $fn_key4);
1169
                }
1170
              }
1171
              usort($fnKeysLevel4, "footnotes_key_compare");
1172
              if(!isset( $l4_regions[$text_l4])){
1173
                $l4_regions[$text_l4] = $fnKeysLevel4;
1174
              } else {
1175
                $l4_regions[$text_l4] = array_merge($l4_regions[$text_l4], $fnKeysLevel4);
1176
              }
1177
            }
1178
          }
1179
        }// Level4.
1180
        // Managing level3 and level4 for generating the right output.
1181
        usort($fnKeysLevel3, "footnotes_key_compare");
1182
        foreach ($fnKeysLevel3 as $key3) {
1183
          foreach ($l4_regions as $key4 => $value4) {
1184
            cdm_add_footnote_to_array($l4_regions[$key4], $key3);
1185
          }
1186
        }
1187
        if ($element_level3->numberOfChildren == 1 && $text_l3 == $element_level3->children[0]->nodeId->representation_L10n) {
1188
          // var_dump($element_level3->children[0]->data->area->representation_L10n);
1189
          $fnStr = '';
1190
          $region = array_pop($l4_regions);
1191
          foreach ($region as $key) {
1192
            $fnStr .= theme('cdm_footnote_key', array('footnoteKey' => $key, 'separator' => ($fnStr ? $separator : '')));
1193
          }
1194
          $out .= "$text_l3 $fnStr; ";
1195
          // Removing whitespaces when &fnStr is empty.
1196
          if (substr($out, -3) == ' ; ') {
1197
            $out = substr($out, 0, -3) . '; ';
1198
          }
1199
        } else {
1200
          $fnKeysLevel3Str = '';
1201
          foreach ($fnKeysLevel3 as $key) {
1202
            $fnKeysLevel3Str .= theme('cdm_footnote_key', array('footnoteKey' => $key, 'separator' => ($fnKeysLevel3Str ? $separator : '')));
1203
          }
1204
          $text_l4_aux = '';
1205
          foreach ($l4_regions as $key => $value) {
1206
            $fnKeysLevel4Str = '';
1207
            if (is_array($l4_regions[$key])) {
1208
              foreach ($l4_regions[$key] as $fnkey) {
1209
                $fnKeysLevel4Str .= theme('cdm_footnote_key', array('footnoteKey' => $fnkey, 'separator' => ($fnKeysLevel4Str ? $separator : '')));
1210
              }
1211
            }
1212
            // if ($key != $text_l3 || sizeof($l4_regions > 1)){
1213
            if ($key != $text_l3) {
1214
              $text_l4_aux .= "$key $fnKeysLevel4Str, ";
1215
            }
1216
          }
1217
          $text_l4_aux = substr($text_l4_aux, 0, -2);
1218

    
1219
          if (strlen($text_l4_aux) > 0) {
1220
            $out .= "$text_l3 $fnKeysLevel3Str ($text_l4_aux); ";
1221
          }
1222
          else {
1223
            $out .= "$text_l3 $fnKeysLevel3Str; ";
1224
          }
1225
        }
1226
      }// Level3.
1227
      $out = substr($out, 0, -2);
1228
      $out .= '.</dd>';
1229
    }// Level1.
1230
  }
1231
  RenderHints::popFromRenderStack();
1232
  return $out;
1233
}
1234

    
1235

    
1236
/*
1237
function theme_cdm_descriptionElement_Distribution($descriptionElements){ $out
1238
  = ''; $separator = ',';
1239
  RenderHints::pushToRenderStack('descriptionElementDistribution');
1240
  RenderHints::setFootnoteListKey(UUID_DISTRIBUTION);
1241
  foreach($descriptionElements as $descriptionElement){ // annotations as
1242
  footnotes $annotationFootnoteKeys = theme('cdm_annotations_as_footnotekeys',
1243
  $descriptionElement); // source references as footnotes
1244
  $sourcesFootnoteKeyList = ''; foreach($descriptionElement->sources as
1245
  $source){ if(_is_original_source_type($source)){ $_fkey =
1246
  FootnoteManager::addNewFootnote(UUID_DISTRIBUTION,
1247
  theme('cdm_OriginalSource', $source, FALSE));
1248
  $sourcesFootnoteKeyList .= theme('cdm_footnote_key', $_fkey,
1249
  UUID_DISTRIBUTION, ($sourcesFootnoteKeyList ? $separator : '')); } }
1250
  if($annotationFootnoteKeys && $sourcesFootnoteKeyList){
1251
  $annotationFootnoteKeys .= $separator; } $out .=
1252
  $descriptionElement->area->representation_L10n . $annotationFootnoteKeys .
1253
  $sourcesFootnoteKeyList . ' '; } $out = substr($out, 0,
1254
  strlen($out)-strlen($separator) ); RenderHints::popFromRenderStack(); return
1255
  $out; }
1256
*/
1257

    
1258
/**
1259
 * Returns a list of a specific type of IdentificationKeys.
1260
 *
1261
 * The list can be restricteded by a taxon.
1262
 *
1263
 * @param string $type
1264
 *   The simple name of the cdm class implementing the interface
1265
 *   IdentificationKey, valid values are:
1266
 *   PolytomousKey, MediaKey, MultiAccessKey.
1267
 * @param string $taxonUuid
1268
 *   If given this parameter restrict the listed keys to those which have
1269
 *   the taxon identified be this uuid in scope.
1270
 *
1271
 * @return array
1272
 *   List with identification keys.
1273
 */
1274
function _list_IdentificationKeys($type, $taxonUuid = NULL, $pageSize = NULL, $pageNumber = NULL) {
1275
  if (!$type) {
1276
    drupal_set_message(t('Type parameter is missing'), 'error');
1277
    return;
1278
  }
1279
  $cdm_ws_pasepath = NULL;
1280
  switch ($type) {
1281
    case "PolytomousKey":
1282
      $cdm_ws_pasepath = CDM_WS_POLYTOMOUSKEY;
1283
      break;
1284

    
1285
    case "MediaKey":
1286
      $cdm_ws_pasepath = CDM_WS_MEDIAKEY;
1287
      break;
1288

    
1289
    case "MultiAccessKey":
1290
      $cdm_ws_pasepath = CDM_WS_MULTIACCESSKEY;
1291
      break;
1292

    
1293
  }
1294

    
1295
  if (!$cdm_ws_pasepath) {
1296
    drupal_set_message(t('Type parameter is not valid: ') . $type, 'error');
1297
  }
1298

    
1299
  $queryParameters = '';
1300
  if (is_numeric($pageSize)) {
1301
    $queryParameters = "pageSize=" . $pageSize;
1302
  }
1303
  else {
1304
    $queryParameters = "pageSize=0";
1305
  }
1306

    
1307
  if (is_numeric($pageNumber)) {
1308
    $queryParameters = "pageNumber=" . $pageNumber;
1309
  }
1310
  else {
1311
    $queryParameters = "pageNumber=0";
1312
  }
1313
  $queryParameters = NULL;
1314
  if ($taxonUuid) {
1315
    $queryParameters = "findByTaxonomicScope=$taxonUuid";
1316
  }
1317
  $pager = cdm_ws_get($cdm_ws_pasepath, NULL, $queryParameters);
1318

    
1319
  if (!$pager || $pager->count == 0) {
1320
    return array();
1321
  }
1322
  return $pager->records;
1323
}
1324

    
1325
/**
1326
 * @todo Please document this function.
1327
 * @see http://drupal.org/node/1354
1328
 */
1329
function theme_cdm_IdentificationKey($variables) {
1330
  $out = '';
1331
  $identificationKey = $variables['identificationKey'];
1332
  $doLinkToKeyPage = $variables['doLinkToKeyPage'];
1333
  $showIdentificationKeyTitle = $variables['showIdentificationKeyTitle'];
1334
  $parentRenderPath = RenderHints::getRenderPath();
1335
  RenderHints::pushToRenderStack("IdentificationKey");
1336

    
1337
  if ($showIdentificationKeyTitle) {
1338
    if ($doLinkToKeyPage) {
1339
      $out = l($identificationKey->titleCache, path_to_key($identificationKey->class, $identificationKey->uuid));
1340
    }
1341
    else {
1342
      $out = $identificationKey->titleCache;
1343
    }
1344
  }
1345
  if (isset($identificationKey->sources) && is_array($identificationKey->sources)) {
1346
    // order and display sources.
1347
    $sources = oder_sources($identificationKey->sources, TRUE);
1348
    $out .= '<div class="sources">';
1349
    $out .=  implode('', $sources);
1350
    $out .= '</div>';
1351
  }
1352
  // Display annotations.
1353
  $out .= theme('cdm_annotations', array('annotations' => cdm_ws_getAnnotationsFor($identificationKey), 'enclosingTag' => 'div'));
1354
  RenderHints::popFromRenderStack();
1355
  return $out;
1356
}
1357

    
1358
/**
1359
 * @todo Please document this function.
1360
 * @see http://drupal.org/node/1354
1361
 */
1362
function theme_cdm_polytomousKey($variables) {
1363
  $polytomousKey = $variables['polytomousKey'];
1364

    
1365
  // TODO settings needed.
1366
  // @see http://en.wikipedia.org/wiki/Single_access_key#Presentation_styles
1367
  // @see http://dev.e-taxonomy.eu/trac/ticket/2152
1368
  $keyStyle = "linkedStyle";
1369

    
1370
  RenderHints::pushToRenderStack("polytomousKey");
1371
  // Key nodes in linked style.
1372
  $out = '<table class="polytomousKey polytomousKey_' . $keyStyle . '">';
1373
  $out .= theme('cdm_polytomousKey_' . $keyStyle . '_subgraph', array('polytomousKeyNode' => $polytomousKey->root));
1374
  $out .= '</table>';
1375
  RenderHints::popFromRenderStack();
1376
  return $out;
1377
}
1378

    
1379
/**
1380
 * @todo Please document this function.
1381
 * @see http://drupal.org/node/1354
1382
 */
1383
function theme_cdm_polytomousKey_linkedStyle_subgraph($variables) {
1384
  $polytomousKeyNode = $variables['polytomousKeyNode'];
1385
  static $statementCountCharacter = '\'';
1386
  $out = "";
1387

    
1388
  if (is_array($polytomousKeyNode->children)) {
1389
    $childIndex = 0;
1390

    
1391
    // Render edges of the current node.
1392
    foreach ($polytomousKeyNode->children as &$child) {
1393

    
1394
      if (!isset($child->statement) && isset($child->taxon->uuid)) {
1395
        // Skip node with empty statements (see below for explanation: "Special
1396
        // case").
1397
        // this skipping here happens always in the next deeper level of iteration
1398
        // the check below is node on the level above
1399
        continue;
1400
      }
1401

    
1402
      /*
1403
       * Special case: Child nodes with empty statements but taxa as leaf are to
1404
       * treated as if all those taxa where direct children of the source node.
1405
       */
1406
      $islinkToManyTaxa = !isset($child->children[0]->statement) && isset($child->children[0]->taxon->uuid);
1407
      $islinkToTaxon = isset($child->taxon->uuid);
1408
      $islinkToSubKey = isset($child->subkey->uuid);
1409
      $islinkToOtherNode = isset($child->otherNode);
1410
      // Either NULL or 0.
1411
      $islinkToNode = $child->nodeNumber && !$islinkToManyTaxa && !$islinkToOtherNode;
1412
      $hasQuestion = !empty($polytomousKeyNode->question->label_l10n);
1413
      $hasFeature = isset($polytomousKeyNode->feature);
1414

    
1415
      // $indentEdge = $hasQuestion && $childIndex > 0;
1416
      // Question.
1417
      if ($hasQuestion && $childIndex == 0) {
1418
        // Place question, as extra table row.
1419
        $out .= '<tr class="question new_section">';
1420
        $out .= '<td class="nodeNumber">' . uuid_anchor($polytomousKeyNode->uuid, $polytomousKeyNode->nodeNumber) . "</td>";
1421
        $out .= '<td class="question">' . $polytomousKeyNode->question->label_l10n . '</td>';
1422
        $out .= '</tr>';
1423
      }
1424

    
1425
      $out .= '<tr class="childCount_' . $childIndex . (!$hasQuestion && $childIndex == 0 ? ' new_section' : '') . '">';
1426

    
1427
      if ($hasQuestion) {
1428
        $out .= '<td class="nodeNumber"></td>';
1429
      }
1430
      else {
1431
        $out .= '<td class="nodeNumber">' . uuid_anchor($polytomousKeyNode->uuid, $polytomousKeyNode->nodeNumber . str_pad("", $childIndex, $statementCountCharacter)) . "</td>";
1432
      }
1433

    
1434
      $out .= '<td ' . RenderHints::getHtmlElementID($child) . '  class="edge' . ($hasQuestion ? ' edge-indent' : '') . '">';
1435

    
1436
      // Feature.
1437
      if ($hasFeature) {
1438
        $out .= $polytomousKeyNode->feature->representation_L10n . ": ";
1439
      }
1440

    
1441
      // Statement.
1442
      $out .= $child->statement->label_l10n;
1443

    
1444
      // --- Links to nodes taxa and subkeys.
1445
      $out .= '<div class="nodeLink">';
1446

    
1447
      // Link to a PolytomousKeyNode.
1448
      if ($islinkToNode) {
1449
        $out .= '<div class="nodeLinkToNode">';
1450
        if (isset($child->modifyingText)) {
1451
          $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $child->modifyingText));
1452
        }
1453
        $out .= l($child->nodeNumber, request_path(), array(
1454
          'attributes' => NULL,
1455
          'query' => NULL,
1456
          'fragment' => $child->uuid,
1457
        )) . '</div>';
1458
      }
1459

    
1460
      // Link to a PolytomousKeyNode.
1461
      if ($islinkToOtherNode) {
1462
        $out .= '<div class="nodeLinkToOtherNode">';
1463
        if (isset($child->modifyingText)) {
1464
          $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $child->modifyingText));
1465
        }
1466
        $out .= l($child->otherNode->nodeNumber, $_REQUEST["q"], array(
1467
          'attributes' => NULL,
1468
          'query' => NULL,
1469
          'fragment' => $child->otherNode->uuid,
1470
        )) . '</div>';
1471
      }
1472

    
1473
      // Link to one or many taxa.
1474
      if ($islinkToTaxon || $islinkToManyTaxa) {
1475

    
1476
        if ($islinkToManyTaxa) {
1477
          $taxonChildren = $child->children;
1478
        }
1479
        else {
1480
          $taxonChildren = array(
1481
            $child,
1482
          );
1483
        }
1484

    
1485
        foreach ($taxonChildren as $taxonChild) {
1486
          // TODO many taxa $child->children->taxon.
1487
          $out .= '<div class="nodeLinkToTaxon">';
1488
          if (isset($taxonChild->modifyingText)) {
1489
            $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $taxonChild->modifyingText));
1490
          }
1491
          $out .= theme("cdm_taxonName", array('taxonName' => $taxonChild->taxon->name, 'nameLink' => url(path_to_taxon($taxonChild->taxon->uuid))));
1492
          $out .= '</div>';
1493
        }
1494

    
1495
        // Link to a subkey.
1496
        if ($islinkToSubKey) {
1497
          $out .= '<div class="nodeLinkToSubkey">' . theme('cdm_IdentificationKey', array('identificationKey' => $child->subkey)) . '</div>';
1498
        }
1499
      }
1500

    
1501
      $out .= '</div>'; // End node link.
1502
      $out .= '</td>'; // End edge.
1503
      $out .= '</tr>';
1504

    
1505
      $childIndex++;
1506
    }
1507

    
1508
    // Recurse into child nodes.
1509
    foreach ($polytomousKeyNode->children as &$child) {
1510
      $out .= theme('cdm_polytomousKey_linkedStyle_subgraph', array('polytomousKeyNode' => $child));
1511
    }
1512
  }
1513

    
1514
  return $out;
1515
}
1516

    
1517
/**
1518
 * @todo Please document this function.
1519
 * @see http://drupal.org/node/1354
1520
 */
1521
function theme_cdm_poytomousKeyNode_modifyingText($variables) {
1522
  $out = '';
1523
  $modifyingText = $variables['modifyingText'];
1524
  if (is_object($modifyingText)) {
1525
    $i = 0;
1526
    foreach (get_object_vars($modifyingText) as $lang => $languageString) {
1527
      $out .= ($i++ > 0 ? ', ' : '') . '<span class="modifyingText">' . $languageString->text . '</span> ';
1528
    }
1529
  }
1530
  return $out;
1531
}
1532

    
1533
/**
1534
 * Returns HTML for a list of a specific type of IdentificationKeys.
1535
 *
1536
 * The list can be restricteded by a taxon.
1537
 *
1538
 * @param array $variables
1539
 *   An associative array containing:
1540
 *   - type: The simple name of the cdm class implementing the interface
1541
 *     IdentificationKey, valid values are:
1542
 *     PolytomousKey, MediaKey, MultiAccessKey
1543
 *   - taxonUuid: If given, this parameter restrict the listed keys to those
1544
 *     which have the taxon identified be this uuid in scope.
1545
 *
1546
 * @ingroup themeable
1547
 */
1548
function theme_cdm_list_IdentificationKeys($variables) {
1549
  $type = $variables['type'];
1550
  $taxonUuid = $variables['taxonUuid'];
1551
  $keyList = _list_IdentificationKeys($type, $taxonUuid);
1552
  if (!$keyList || count($keyList) == 0) {
1553
    return;
1554
  }
1555

    
1556
  RenderHints::pushToRenderStack('list_IdentificationKeys');
1557
  $out = '<ul>';
1558
  foreach ($keyList as $key) {
1559
    $out .= '<li>';
1560
    $out .= theme('cdm_IdentificationKey', array('identificationKey' => $key));
1561
    $out .= '</li>';
1562
  }
1563
  $out .= '</ul>';
1564
  $out .= theme("cdm_annotation_footnotes", array('footnoteListKey' => RenderHints::getRenderPath()));
1565
  RenderHints::popFromRenderStack();
1566

    
1567
  return $out;
1568
}
1569

    
1570
/**
1571
 * @todo Please document this function.
1572
 * @see http://drupal.org/node/1354
1573
 */
1574
function theme_cdm_block_IdentificationKeys($variables) {
1575
  $taxonUuid = $variables['taxonUuid'];
1576
  static $types = array(
1577
    "PolytomousKey" => "Polytomous",
1578
    "MediaKey" => "Media",
1579
    "MultiAccessKey" => "Multiaccess",
1580
  );
1581
  RenderHints::pushToRenderStack('block_IdentificationKeys');
1582
  $out = '';
1583
  foreach ($types as $type => $label) {
1584
    $keylist = theme('cdm_list_IdentificationKeys', array('type' => $type, 'taxonUuid' => $taxonUuid));
1585
    if (!$keylist) {
1586
      continue;
1587
    }
1588
    $out .= '<div class="' . $type . '">';
1589
    $out .= '<h3>' . t($label) . "</h3>";
1590
    $out .= $keylist;
1591
    $out .= '</div>';
1592
  }
1593
  RenderHints::popFromRenderStack();
1594
  return $out;
1595
}
1596

    
1597
/**
1598
 * This theming function formats the use description and use record list for
1599
 * these descriptions.
1600
 *
1601
 * @see http://drupal.org/node/1354
1602
 */
1603
function theme_cdm_UseDescription($variables) {
1604
  $descriptions = $variables['description'];
1605
  $taxonUuid = $variables['taxonUuid'];
1606
  $out = '<div id="content"><ul id="Description" class ="description">';
1607
  if ($descriptions == NULL) {
1608
    return;
1609
  }
1610
  $descriptionSynonyms = '';
1611
  $descriptionOut = '';
1612
  $synonymOut = '';
1613
  $currentTaxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $taxonUuid);
1614

    
1615
  foreach ($descriptions as $description) {
1616
    $useSummary = '';
1617
    foreach ($description->elements as $element) {
1618

    
1619
      if ($element->feature->uuid == UUID_USE && !(strlen($useSummary) > 0) && isset($element->multilanguageText_L10n)) {
1620
        $useSummary = $element->multilanguageText_L10n->text;
1621
      }
1622
    }
1623
    // uses will be ordered by source
1624
    foreach ($description->sources as $source) {
1625
      $is_about_current_taxon = FALSE;
1626
      $originalTaxonUsedInSource = NULL;
1627
      $originalTaxonPager = NULL;
1628
      if ($source->originalNameString) {
1629
        $request_params = array();
1630
        $request_params['query'] = $source->originalNameString;
1631
        $request_params['matchMode'] = "EXACT";
1632
        $originalTaxonPager = cdm_ws_get(CDM_WS_PORTAL_NAME_FINDBYNAME, NULL, queryString($request_params));
1633
        if ($originalTaxonPager->count > 0) {
1634
          $originalTaxonUsedInSource = $originalTaxonPager->records[0];
1635
        }
1636
        else {
1637
          $originalTaxonUsedInSource = $currentTaxon->name;
1638
        }
1639
      }
1640
      else {
1641
        $originalTaxonUsedInSource = $currentTaxon->name;
1642
      }
1643

    
1644
      $is_about_current_taxon = $currentTaxon->name->uuid == $originalTaxonUsedInSource->uuid;
1645

    
1646
      if (!$is_about_current_taxon) {
1647
        $descriptionOut .= '<li class="descriptionText DescriptionElement">';
1648
        $name_used_in_source_link_to_show_use = l($source->originalNameString, path_to_name($originalTaxonUsedInSource->uuid), array(
1649
          'absolute' => TRUE,
1650
          'html' => TRUE,
1651
        ));
1652
        $descriptionOut .= $name_used_in_source_link_to_show_use . ': ';
1653
        $descriptionOut .= $useSummary;
1654
        foreach ($description->sources as $source) {
1655
          $descriptionOut .= " (" . theme('cdm_OriginalSource', array('source' => $source, 'doLink' => TRUE)) . ")";
1656
        }
1657
        $hasUseRecords = FALSE;
1658
        $descriptionUseRecordOut = '<div id=useRecords><table><th>Use Category</th><th>Use Sub Category</th><th>Plant Part</th><th>Human Group</th><th>Ethnic Group</th><th>Country</th>';
1659
        foreach ($description->elements as $descriptionElement) {
1660
          if ($descriptionElement->feature->uuid == UUID_USE_RECORD) {
1661
            $hasUseRecords = TRUE;
1662
            // FIXME localization hardcoded to English
1663
            $useRecordTags = explode(';', $descriptionElement->modifyingText_l10n);
1664
            $descriptionUseRecordOut .= '<tr>';
1665
            $descriptionUseRecordOut .= '<td>' . $useRecordTags[0] . '</td>' . '<td>' . $useRecordTags[1] . '</td>' . '<td>' . $useRecordTags[3] . '</td>' . '<td>' . $useRecordTags[4] . '</td>' . '<td>' . $useRecordTags[5] . '</td>' . '<td>' . $useRecordTags[2] . '</td>';
1666
            $descriptionUseRecordOut .= '</tr>';
1667
          }
1668
        }
1669
        $descriptionUseRecordOut .= '</table></div>';
1670
        if ($hasUseRecords) {
1671
          $descriptionOut .= $descriptionUseRecordOut . '</li>';
1672
        }
1673
      }
1674
      else {
1675
        // TODO +/- duplicate of above, unify this code
1676
        $synonymOut .= '<li class="descriptionText DescriptionElement">';
1677
        $name_used_in_source_link_to_show_use = l($source->originalNameString, path_to_name($originalTaxonUsedInSource->uuid), array(
1678
          'absolute' => TRUE,
1679
          'html' => TRUE,
1680
        ));
1681

    
1682
        $synonymOut .= $name_used_in_source_link_to_show_use . ': ';
1683
        $synonymOut .= $useSummary;
1684
        foreach ($description->sources as $source) {
1685
          $synonymOut .= " (" . theme('cdm_OriginalSource', array('source' => $source, 'doLink' => TRUE)) . ")";
1686
        }
1687

    
1688
        $hasUseRecords = FALSE;
1689
        $useRecordTableOut = '<div id=useRecords><table><th>Use Category</th><th>Use Sub Category</th><th>Plant Part</th><th>Human Group</th><th>Ethnic Group</th><th>Country</th>';
1690
        foreach ($description->elements as $descriptionElement) {
1691
          if ($descriptionElement->feature->uuid == UUID_USE_RECORD) {
1692
            $hasUseRecords = TRUE;
1693
            $useRecordTags = explode(';', $descriptionElement->modifyingText_l10n);
1694
            $useRecordTableOut .= '<tr>';
1695
            $useRecordTableOut .= '<td>' . $useRecordTags[0] . '</td>' . '<td>' . $useRecordTags[1] . '</td>' . '<td>' . $useRecordTags[3] . '</td>' . '<td>' . $useRecordTags[4] . '</td>' . '<td>' . $useRecordTags[5] . '</td>' . '<td>' . $useRecordTags[2] . '</td>';
1696
            $useRecordTableOut .= '</tr>';
1697
          }
1698
        }
1699
        $useRecordTableOut .= '</table></div>';
1700
        if ($hasUseRecords) {
1701
          $synonymOut .= $useRecordTableOut . '</li>';
1702
        }
1703
      }
1704

    
1705
      // }
1706
    }
1707
  }
1708
  $out .= $descriptionOut . $synonymOut;
1709
  $out .= "</ul></div>";
1710
  return $out;
1711
}
1712

    
1713

    
1714
/**
1715
 * The theming function for a block of Uses Descriptions for a given taxon.
1716
 *
1717
 * The Uses block has been removed from the code but the according theme function
1718
 * is kept for compatibility reasons with existing code regarding palmweb.
1719
 *
1720
 */
1721
function theme_cdm_block_Uses($variables) {
1722
  $taxonUuid = $variables['taxonUuid'];
1723
  RenderHints::pushToRenderStack('block_Uses');
1724

    
1725
  if ($taxonUuid == NULL) {
1726
    return;
1727
  }
1728
  $out = '';
1729
  $markerTypes = array();
1730
  $markerTypes['markerTypes'] = UUID_MARKERTYPE_USE;
1731
  $useDescriptions = cdm_ws_get(CDM_WS_PORTAL_TAXON_DESCRIPTIONS, $taxonUuid, queryString($markerTypes));
1732
  if (!empty($useDescriptions)) {
1733
    // FIXME use theme_block instaed of hardcoding the block html here !!!!
1734
    $out .= '<div id="block-cdm_dataportal-feature-description" class="clear-block block block-cdm_dataportal-feature"><H2><a name="userecords"> </a> Uses </H2>';
1735
    $formatUseDescriptions = theme('cdm_UseDescription', array('description' => $useDescriptions, 'taxonUuid' => $taxonUuid));
1736

    
1737
    $out .= $formatUseDescriptions;
1738
    $out .= "</div>";
1739
  }
1740

    
1741
  return $out;
1742
}
(3-3/10)