Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

cdm-dataportal / 7.x / modules / cdm_dataportal / theme / cdm_dataportal.descriptions.theme @ 8e432522

History | View | Annotate | Download (62.1 KB)

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 subordinate 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
                    if(isset($element->multilanguageText_L10n->text)){
148
                      $out_child_elements = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
149
                    }
150
                    $out_child_elements = str_replace($child->feature->titleCache, '<em>' . $child->feature->representation_L10n . '</em>', $out_child_elements);
151
                    break;
152
                  case 'CategoricalData':
153
                    $out_child_elements  = '<em>' . $child->feature->representation_L10n . '</em> '
154
                      . theme('cdm_descriptionElement_CategoricalData', array('element' => $element));
155
                    break;
156
                  case 'QuantitativeData':
157
                    $out_child_elements = '<em>' . $child->feature->representation_L10n . '</em> '
158
                      . theme('cdm_descriptionElement_QuantitativeData', array('element' => $element));
159

    
160
                }
161

    
162
              }
163
              $text .= " " . $out_child_elements;
164
              $out_child_elements = '';
165
            }
166
          }
167
          $block_content_is_empty = $block_content_is_empty && empty($text);
168
          $block->content[] = markup_to_render_array($text);
169
          $block_content_is_empty = $block_content_is_empty && empty($media_list);
170
          }
171

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

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

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

    
189
  RenderHints::popFromRenderStack();
190

    
191
  return _block_get_renderable_array($block_list);
192
}
193

    
194
  /**
195
   * @param $node
196
   * @param $media_list
197
   * @param $gallery_settings
198
   * @return array
199
   */
200
  function compose_feature_media_gallery($node, $media_list, $gallery_settings) {
201

    
202
    if (isset($node->descriptionElements)) {
203
      $media_list = array_merge($media_list, cdm_dataportal_media_from_descriptionElements($node->descriptionElements));
204
    }
205

    
206
    $captionElements = array('title', 'rights');
207

    
208
    if (isset($media_list[0]) && isset($gallery_settings['cdm_dataportal_media_maxextend']) && isset($gallery_settings['cdm_dataportal_media_cols'])) {
209
      $gallery = theme('cdm_media_gallerie', array(
210
        'mediaList' => $media_list,
211
        'galleryName' => CDM_DATAPORTAL_DESCRIPTION_GALLERY_NAME . '_' . $node->feature->uuid,
212
        'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
213
        'cols' => $gallery_settings['cdm_dataportal_media_cols'],
214
        'captionElements' => $captionElements,
215
      ));
216
      return markup_to_render_array($gallery);
217
    }
218

    
219
    return markup_to_render_array('');
220
  }
221

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

    
238
    $distributionElements = NULL;
239
    $distribution_info_dto = NULL;
240
    $distribution_sortOutArray = FALSE;
241

    
242
    if (variable_get('distribution_sort', 'NO_SORT') != 'NO_SORT') {
243
      $distribution_glue = '';
244
      $distribution_enclosingTag = 'dl';
245
    } else {
246
      $distribution_glue = '';
247
      $distribution_enclosingTag = 'ul';
248
    }
249

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

    
255
    $block = feature_block(
256
      cdm_term_representation($feature, 'Unnamed Feature'),
257
      $feature
258
    );
259

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

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

    
281

    
282
    if ($text_data_out_array && variable_get(DISTRIBUTION_TEXTDATA_DISPLAY_ON_TOP, 0)) {
283
      $block->content[] = compose_cdm_feature_block_elements(
284
        $text_data_out_array,
285
        $feature,
286
        $text_data_glue,
287
        $text_data_sortOutArray,
288
        $text_data_enclosingTag
289
      );
290
    }
291

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

    
300
    // --- tree or list
301
    $dto_out_array = array();
302
    if (isset($descriptionElements['DistributionInfoDTO'])) {
303
      $distribution_info_dto = $descriptionElements['DistributionInfoDTO'];
304

    
305
      // --- tree
306
      if (is_object($distribution_info_dto->tree)) {
307
        $dto_out_array[] = theme('cdm_description_ordered_distributions', array('distribution_tree' => $distribution_info_dto->tree));
308
      }
309

    
310
      // --- sorted element list
311
      if (is_array($distribution_info_dto->elements) && count($distribution_info_dto->elements) > 0) {
312
        foreach ($distribution_info_dto->elements as $descriptionElement) {
313
          if (is_object($descriptionElement->area)) {
314
            $sortKey = $descriptionElement->area->representation_L10n;
315
            $distributionElements[$sortKey] = $descriptionElement;
316
          }
317
        }
318
        ksort($distributionElements);
319
        $distribution_element_render_array = compose_cdm_descriptionElement_Distribution($distributionElements);
320
        $dto_out_array[] = drupal_render($distribution_element_render_array);
321

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

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

    
344
    $block->content[] = markup_to_render_array(theme('cdm_footnotes', array('footnoteListKey' => UUID_DISTRIBUTION)));
345
    $block->content[] = markup_to_render_array(theme('cdm_annotation_footnotes', array('footnoteListKey' => UUID_DISTRIBUTION)));
346

    
347
    return $block;
348
  }
349

    
350

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

    
357
  $FeatureTreeUuid = $variables['FeatureTreeUuid'];
358
  if (!is_uuid($FeatureTreeUuid)) {
359
    return;
360
  }
361

    
362
  $out = '';
363
  $featureTree = cdm_ws_get(CDM_WS_FEATURETREE, array(
364
    $FeatureTreeUuid,
365
  ));
366

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

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

    
381
  $node = $variables['node'];
382
  $out = '';
383
  if (isset($node->childNodes)) {
384

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

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

    
414
  $feature_block_settings = get_feature_block_settings($feature->uuid);
415
  if($feature_block_settings['as_list']){
416
    $enclosing_tag = $feature_block_settings['as_list'];
417
  }
418

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

    
421
  if ($sort) {
422
    sort($elements);
423
  }
424

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

    
429
  $out .= '</' . $enclosing_tag . '>';
430
  return markup_to_render_array($out);
431
}
432

    
433

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

    
447
  $state_data_strings = array();
448
  if (isset($element->stateData)) {
449
    foreach ($element->stateData as $stateData) {
450

    
451
      $state  = NULL;
452

    
453
      if(isset($stateData->state)){
454
        $state = cdm_term_representation($stateData->state);
455
      }
456

    
457
      if (isset($stateData->modifyingText_L10n)) {
458
        $state = ' ' . $stateData->modifyingText_L10n;
459
      }
460

    
461
      $modifiers_strings = cdm_modifers_representations($stateData);
462

    
463
      $state_data_strings[] = $state . ($modifiers_strings ? ' ' . $modifiers_strings : '');
464

    
465
    }
466
  }
467

    
468
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
469

    
470
  $out = '<span class="' . html_class_attribute_ref($element) . '">' . implode(', ', $state_data_strings) . '</span>';
471
  return $out . $footnote_key_list_str;
472
}
473

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

    
497
  $out = '';
498

    
499
  $type_representation = NULL;
500
  $modifiers_strings = array();
501

    
502

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

    
511
    $out .= implode($value_array, ', ');
512
  }
513

    
514
  if (isset($element->unit)) {
515
    $out .= ' '. cdm_term_representation($element->unit);
516
  }
517

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

    
524
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
525

    
526
  return $out . $footnote_key_list_str;
527

    
528
}
529

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

    
542
  $element = $variables['element'];
543

    
544
  $out = '';
545

    
546
  $render_array = compose_cdm_specimenOrObservation($element->associatedSpecimenOrObservation);
547

    
548
  if (isset($element->description_L10n)) {
549
    $out .=  ' ' . $element->description_L10n;
550
  }
551

    
552
  $out .= drupal_render($render_array);
553

    
554
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
555

    
556
  return $out . $footnote_key_list_str;
557

    
558

    
559
}
560

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

    
573
  $element = $variables['element'];
574

    
575
  $out = '';
576

    
577
  if (isset($element->description_L10n)) {
578
    $out .=  ' ' . $element->description_L10n;
579
  }
580

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

    
590
  $footnote_key_list_str = cdm_create_description_element_footnotes($element);
591

    
592
  return $out . $footnote_key_list_str;
593

    
594

    
595
}
596

    
597
/**
598
 * Composes a drupal render array for CDM TextData 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
  // FIXME $feature_block_settings should be passed as parameter!!!!!
623
  $feature_block_settings = get_feature_block_settings($feature_uuid);
624

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

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

    
644
  $element_text = '';
645
  if (isset($element->multilanguageText_L10n->text)) {
646
    // TODO replacement of \n by <br> should be configurable
647
    $element_text = str_replace("\n", "<br/>", $element->multilanguageText_L10n->text);
648
  }
649

    
650
  $annotations_and_sources = handle_annotations_and_sources($element, $feature_block_settings, $element_text, $footnote_list_key_suggestion);
651

    
652
  $names_used_in_source_markup = '';
653
  if (!empty($annotations_and_sources['names_used_in_source']) && empty($element_text)) {
654
    // $element_text ==  NULL  usually occurs only in the case of CITATIONS!!!
655
    $names_used_in_source_markup = join(', ', $annotations_and_sources['names_used_in_source']) . ': ';
656
  }
657

    
658
  $source_references_markup = '';
659
  if(!empty($annotations_and_sources['source_references'])){
660
    $source_references_markup = '<span class="sources">'. join(' ', $annotations_and_sources['source_references']) . '<span>';
661
  }
662

    
663
  $render_array['#value'] = $names_used_in_source_markup . $element_text . $source_references_markup;
664
  $render_array['#value-suffix'] = $annotations_and_sources['foot_note_keys'];
665

    
666
  return $render_array;
667
}
668

    
669
  /**
670
   * @param $element
671
   * @param $feature_block_settings
672
   * @param $element_text
673
   * @param $footnote_list_key_suggestion
674
   * @return array
675
   *   an associative array with the following elements:
676
   *   - foot_note_keys: all footnote keys as markup
677
   *   - source_references: an array of the source references citations
678
   *   - names used in source: an associative array of the names in source,
679
   *        the name in source string are de-duplicated
680
   *        !!!NOTE!!!!: this field will most probably be removed soon (TODO)
681
   *
682
   *
683
   */
684
  function handle_annotations_and_sources($element, $feature_block_settings, $element_text, $footnote_list_key_suggestion) {
685
    $annotations_and_sources = array(
686
      'foot_note_keys' => NULL,
687
      'source_references' => array(),
688
      'names_used_in_source' => array()
689
    );
690

    
691
    if ($feature_block_settings['sources_as_content']) {
692
      foreach ($element->sources as $source) {
693

    
694
        $referenceCitation = theme('cdm_OriginalSource',
695
          array(
696
            'source' => $source,
697
            'doLink' => $feature_block_settings['link_to_reference']
698
          )
699
        );
700

    
701
        if ($referenceCitation) {
702
          if (empty($element_text)) {
703
            $annotations_and_sources['source_references'][] = $referenceCitation;
704
          }
705
          else {
706
            $annotations_and_sources['source_references'][] = ' (' . $referenceCitation . ')';
707
          }
708
        }
709

    
710
        $name_in_source_render_array = compose_name_in_source(
711
          $source,
712
          $feature_block_settings['link_to_name_used_in_source']
713
        );
714

    
715
        if(!empty($name_in_source_render_array)){
716
          $annotations_and_sources['names_used_in_source'][$name_in_source_render_array['#_plaintext']] = drupal_render($name_in_source_render_array);
717
        }
718
      } // END of loop over sources
719

    
720
      // annotations footnotes separate.
721
      $annotations_and_sources['foot_note_keys'] = theme('cdm_annotations_as_footnotekeys',
722
        array(
723
          'cdmBase_list' => $element,
724
          'footnote_list_key' => $footnote_list_key_suggestion,
725
        )
726
      );
727

    
728
    } // END of references inline
729

    
730
    if (!$feature_block_settings['sources_as_content'] || $feature_block_settings['sources_as_content_to_bibliography']) {
731
      $annotations_and_sources['foot_note_keys'] = cdm_create_description_element_footnotes($element, ',', $footnote_list_key_suggestion);
732
    }
733

    
734
    return $annotations_and_sources;
735
  }
736

    
737
  /* compose nameInSource or originalNameString as markup
738
   *
739
   * @param $source
740
   * @param $do_link_to_name_used_in_source
741
   *
742
   * @return array
743
   *    A Drupal render array with an additional element, the render array is empty
744
   *    if the source had no name in source information
745
   *    - #_plaintext: contains the plaintext version of the name (custom element)
746
   *
747
   * @ingroup compose
748
   */
749
  function compose_name_in_source($source, $do_link_to_name_used_in_source) {
750

    
751
    $plaintext = NULL;
752
    $markup = NULL;
753
    $name_in_source_render_array = array();
754

    
755
    if (isset($source->nameUsedInSource->uuid) && isset($source->nameUsedInSource->titleCache)) {
756
      // it is a DescriptionElementSource !
757
      $plaintext = $source->nameUsedInSource->titleCache;
758
      $markup = theme('cdm_taxonName', array(
759
        'taxonName' => $source->nameUsedInSource
760
      ));
761
      if ($do_link_to_name_used_in_source) {
762
        $markup = l(
763
          $markup,
764
          path_to_name($source->nameUsedInSource->uuid),
765
          array(
766
            'attributes' => array(),
767
            'absolute' => TRUE,
768
            'html' => TRUE,
769
          ));
770
      }
771
    }
772
    else if (isset($source->originalNameString) && !empty($source->originalNameString)) {
773
      // the name used in source can not be expressed as valid taxon name,
774
      // so the editor has chosen to put the freetext name into ReferencedEntityBase.originalNameString
775
      // field
776
      // using the originalNameString as key to avoid duplicate entries
777
      $plaintext = $source->originalNameString;
778
      $markup = $source->originalNameString;
779
    }
780

    
781
    if ($plaintext) {
782
      $name_in_source_render_array = markup_to_render_array($markup);
783
      $name_in_source_render_array['#_plaintext'] = $plaintext;
784
    }
785

    
786
    return $name_in_source_render_array;
787
  }
788

    
789
  /**
790
 * Composes block of common names for the given DescriptionElements $elements which must be of the feature CommonName
791
 *
792
 * @parameter $elements
793
 *  an array of CDM DescriptionElements either of type CommonName or TextData
794
 * @parameter $feature
795
 *  the common feature of all $elements, must be CommonName
796
 *
797
 * @return
798
 *   A drupal render array
799
 *
800
 * @ingroup compose
801
 */
802
function compose_cdm_common_names($elements, $feature, $weight = FALSE) {
803

    
804
  $common_name_out = '';
805
  $common_name_feature_elements = array();
806
  $textData_commonNames = array();
807

    
808
  $footnote_key_suggestion = 'common-names-feature-block';
809

    
810
  $feature_block_settings = get_feature_block_settings(UUID_COMMON_NAME);
811

    
812
  $element_tag_name = cdm_feature_block_element_tag_name($feature_block_settings);
813

    
814
  if (is_array($elements)) {
815
    foreach ($elements as $element) {
816

    
817
      if ($element->class == 'CommonTaxonName') {
818

    
819
        // common name without a language or area, should not happen but is possible
820
        $language_area_key = '';
821
        if (isset($element->language->representation_L10n)) {
822
          $language_area_key .= '<b>' . $element->language->representation_L10n . '</b>';
823
        }
824
        if(isset($element->area->titleCache) && strlen($element->area->titleCache) > 0){
825
          $language_area_key .= ($language_area_key ? ' '  : '') . '(' . $element->area->titleCache . ')';
826
        }
827

    
828
        if(isset($common_names[$language_area_key][$element->name])) {
829
          // same name already exists for language and areae combination, se we merge the description elements
830
          cdm_merge_description_elements($common_names[$language_area_key][$element->name], $element);
831
        } else{
832
          // otherwise add as new entry
833
          $common_names[$language_area_key][$element->name] = $element;
834
        }
835

    
836
      }
837
      elseif ($element->class == 'TextData') {
838
        $textData_commonNames[] = $element;
839
      }
840
    }
841
  }
842
  // Handling common names.
843
  if (isset($common_names) && count($common_names) > 0) {
844
    // Sorting the array based on the key (language, + area if set).
845
    // Comment @WA there are common names without a language, so this sorting
846
    // can give strange results.
847
    ksort($common_names);
848

    
849
    // loop over set of elements per language area
850
    foreach ($common_names as $language_area_key => $elements) {
851
      ksort($elements); // sort names alphabetically
852
      $per_language_area_out = array();
853
      // loop over set of individual elements
854
      foreach ($elements as $element) {
855
        if ($element->name) {
856
          $annotations_and_sources = handle_annotations_and_sources($element, $feature_block_settings, $element->name, $footnote_key_suggestion);
857
          $source_references_markup = '';
858
          if(!empty($annotations_and_sources['source_references'])){
859
            $source_references_markup = ' ' . join(', ', $annotations_and_sources['source_references']);
860
          }
861
          $per_language_area_out[] = '<' . $element_tag_name. ' class="' . html_class_attribute_ref($element) . '">'
862
          . $element->name . $source_references_markup . $annotations_and_sources['foot_note_keys'] . '</' . $element_tag_name. '>';
863
        }
864
      } // End of loop over set of individual elements
865
      $common_name_feature_elements[] = ($language_area_key ? $language_area_key . ': ' : '' ) . join(', ', $per_language_area_out);
866
    } // End of loop over set of elements per language area
867

    
868

    
869
    $common_name_feature_elements_render_array = compose_cdm_feature_block_elements(
870
      $common_name_feature_elements,
871
      $feature,
872
      '; ',
873
      FALSE,
874
      $feature_block_settings['as_list']
875
      );
876
    $common_name_out .= $common_name_feature_elements_render_array['#markup'];
877

    
878
  }
879

    
880
  // Handling commons names as text data.
881
  $text_data_out = array();
882

    
883
  foreach ($textData_commonNames as $text_data_element) {
884
    /* footnotes are not handled correctly in theme_cdm_descriptionElementTextData,
885
       need to set 'common-names-feature-block' as $footnote_key_suggestion */
886
    RenderHints::setFootnoteListKey($footnote_key_suggestion);
887
    $text_data_render_array = compose_cdm_descriptionElementTextData($text_data_element, TRUE, $text_data_element->feature->uuid);
888
    $text_data_out[] = drupal_render($text_data_render_array);
889
  }
890

    
891
  $common_name_out_text_data = compose_cdm_feature_block_elements(
892
        $text_data_out,
893
        $feature
894
      );
895

    
896

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

    
900
  return  markup_to_render_array(
901
    '<div class="common_names_as_common_names">' . $common_name_out . '</div>'
902
    .'<div class="common_names_as_text_data">' . $common_name_out_text_data['#markup'] . '</div>'
903
    .$footnotes,
904
    $weight
905
  );
906
}
907

    
908
/**
909
 * Return HTML for a list of description elements.
910
 *
911
 * Usually these are of a specific feature type.
912
 *
913
 * @param $descriptionElements
914
 *   array of descriptionElements which belong to the same feature.
915
 *   These descriptions elements of a Description must be ordered by the chosen feature tree by
916
 *   calling the function _mergeFeatureTreeDescriptions().
917
 *   @see _mergeFeatureTreeDescriptions()
918
 *
919
 * @param  $feature_uuid
920
 *
921
 * @return
922
 *    A drupal render array for the $descriptionElements, may be an empty array if the textual content was empty.
923
 *    Footnote key or anchors are not considered to be textual content.
924
 *
925
 * @ingroup compose
926
 */
927
function compose_cdm_descriptionElements($descriptionElements, $feature) {
928

    
929
  $render_array = array();
930
  $elements_out_array = array();
931
  $distribution_tree = null;
932

    
933
  /*
934
   * $feature_block_has_content will be set true if at least one of the
935
   * $descriptionElements contains some text which makes up some content
936
   * for the feature block. Footnote keys are not considered
937
   * to be content in this sense.
938
   */
939
  $feature_block_has_content = false;
940

    
941
  /*
942
  $userDefined = mixed_variable_get(LAYOUT_SETTING_PREFIX . $feature_uuid, FEATURE_TREE_LAYOUT_DEFAULTS);
943
  if(variable_get('distribution_sort',
944
      'NO_SORT') != 'NO_SORT'){
945
      $glue = '';
946
      $enclosingTag = 'dl';
947
      $entryEnclosingTag = NULL;
948
  } else if($userDefined &&
949
      $userDefined['enabled']){
950
    $glue = $userDefined['glue'];
951
    $enclosingTag =  $userDefined['enclosingTag'];
952
    $entryEnclosingTag = $userDefined['entryEnclosingTag'];
953
  } else { // TODO remove once  LAYOUT_SETTING_PREFIX-{uuid} setting are configured to work for all portals(selenium test still missing!!!)
954
    $glue = ''; $enclosingTag = 'ul';
955
    $entryEnclosingTag = NULL ;
956
  }
957
  */
958

    
959
  RenderHints::pushToRenderStack('cdm_descriptionElements');
960

    
961
  if (is_array($descriptionElements)) {
962
    // --- normal description element arrays
963
    foreach ($descriptionElements as $descriptionElement) {
964

    
965
      // --- IMAGE_SOURCES --- //
966
      if ($descriptionElement->feature->uuid == UUID_IMAGE_SOURCES) {
967
        $image_sources[] = $descriptionElement;
968
      }
969
      // --- USE TEXTDATA --- //
970
      elseif ($descriptionElement->feature->uuid == UUID_USE) {
971
        // Do nothing to avoid rendering.
972
      } else {
973
        /* decide based on the description element class
974
         *
975
         * Features handled here:
976
         * all except DISTRIBUTION, COMMON_NAME, USES, IMAGES,
977
         *
978
         *
979
         * TODO provide api_hook as extension point for this?
980
         */
981
        $feature_block_settings = get_feature_block_settings($descriptionElement->feature->uuid);
982
        $asListElement  = $feature_block_settings['as_list'] == 'ul';
983
        switch ($descriptionElement->class) {
984
          case 'TextData':
985
              $text_data_render_array = compose_cdm_descriptionElementTextData($descriptionElement, $asListElement, $descriptionElement->feature->uuid);
986
              $feature_block_has_content = $feature_block_has_content || !empty($text_data_render_array['#value']);
987
              $elements_out_array[] = drupal_render($text_data_render_array);
988
            break;
989
          case 'CategoricalData':
990
            $feature_block_has_content = true;
991
            $elements_out_array[] = theme('cdm_descriptionElement_CategoricalData', array('element' => $descriptionElement));
992
            break;
993
          case 'QuantitativeData':
994
            $feature_block_has_content = true;
995
            $elements_out_array[] = theme('cdm_descriptionElement_QuantitativeData', array('element' => $descriptionElement));
996
            break;
997
          case 'IndividualsAssociation':
998
            $feature_block_has_content = true;
999
            $elements_out_array[] = theme('cdm_descriptionElement_IndividualsAssociation', array('element' => $descriptionElement));
1000
            break;
1001
          case 'TaxonInteraction':
1002
            $feature_block_has_content = true;
1003
            $elements_out_array[] = theme('cdm_descriptionElement_TaxonInteraction', array('element' => $descriptionElement));
1004
            break;
1005
          case 'Uses':
1006
          /* IGNORE Uses classes, these are handled completely in theme_cdm_UseDescription */
1007
          break;
1008
        default:
1009
          $feature_block_has_content = true;
1010
          $elements_out_array[] = '<li>No method for rendering unknown description class: ' . $descriptionElement->class . '</li>';
1011
      }
1012
    }
1013
    } // --- END loop over normal description element arrays
1014

    
1015
    // If feature = CITATION sort the list of sources.
1016
    // This is ONLY for FLORA MALESIANA and FLORE d'AFRIQUE CENTRALE.
1017
    if ($descriptionElement->feature->uuid == UUID_CITATION) {
1018
      sort($elements_out_array);
1019
    }
1020

    
1021
    if (isset($image_sources)) {
1022
      $elements_out_array[] = theme('cdm_description_element_image_source', array('image_sources' => $image_sources, 'asListElement' => TRUE));
1023
    }
1024
  } // END normal description element arrays
1025

    
1026
  if($feature_block_has_content){
1027
    $render_array = compose_cdm_feature_block_elements(
1028
      $elements_out_array,
1029
      $feature
1030
    );
1031
  }
1032

    
1033
  RenderHints::popFromRenderStack();
1034
  return $render_array;
1035
}
1036

    
1037
/**
1038
 * @todo Please document this function.
1039
 * @see http://drupal.org/node/1354
1040
 */
1041
function compare_image_sources($a, $b) {
1042
  if ($a->multilanguageText_L10n->text == $b->multilanguageText_L10n->text) {
1043
    return 0;
1044
  }
1045
  return ($a->multilanguageText_L10n->text < $b->multilanguageText_L10n->text) ? -1 : 1;
1046
}
1047

    
1048
/**
1049
 * @todo Please document this function.
1050
 * @see http://drupal.org/node/1354
1051
 */
1052
function theme_cdm_description_element_image_source($variables) {
1053
  $image_sources = $variables['image_sources'];
1054
  $asListElement = $variables['asListElement'];
1055
  $out = '';
1056
  $separator = ',';
1057
  RenderHints::pushToRenderStack('descriptionElementImageSource');
1058
  RenderHints::setFootnoteListKey(UUID_IMAGE_SOURCES);
1059

    
1060
  // Sorting the image sources.
1061
  usort($image_sources, "compare_image_sources");
1062
  // Generate the footnotes.
1063
  foreach ($image_sources as $image_source) {
1064
    $footNoteKeys = cdm_annotations_as_footnotekeys($image_source);
1065
    foreach ($image_source->sources as $source) {
1066
      if (_is_original_source_type($source)) {
1067
        $fn_key = FootnoteManager::addNewFootnote(original_source_footnote_list_key(), theme('cdm_OriginalSource', array(
1068
          'source' => $source,
1069
          'doLink' => FALSE,
1070
        )));
1071
        // Ensure uniqueness of the footnote keys.
1072
        cdm_add_footnote_to_array($footNoteKeys, $fn_key);
1073
      }
1074
    }
1075
    // Sort and render footnote keys.
1076
    $footnote_key_list_str = '';
1077
    asort($footNoteKeys);
1078
    foreach ($footNoteKeys as $footNoteKey) {
1079
      $footnote_key_list_str .= theme('cdm_footnote_key', array('footnoteKey' => $footNoteKey, 'separator' => ($footnote_key_list_str ? $separator : '')));
1080
    }
1081
    // Return value!
1082
    $out .= '<span class="descriptionElement descriptionElement-' . $image_source->uuid . '">' . $image_source->multilanguageText_L10n->text . $footnote_key_list_str . '; </span>';
1083
  }
1084

    
1085
  RenderHints::popFromRenderStack();
1086
  return $out;
1087
}
1088

    
1089
/**
1090
 * Composes the render array for a CDM Distribution element
1091
 *
1092
 * @param $descriptionElements
1093
 *   The CDM Distribution element
1094
 * @param $enclosingTag
1095
 *   The html tag to be use for the enclosing element
1096
 *
1097
 * @return array
1098
 *   A Drupal render array
1099
 *
1100
 * @ingroup compose
1101
 */
1102
function compose_cdm_descriptionElement_Distribution($descriptionElements, $enclosingTag = "span"){
1103

    
1104
  $out = '';
1105
  RenderHints::pushToRenderStack('descriptionElementDistribution');
1106
  RenderHints::setFootnoteListKey(UUID_DISTRIBUTION);
1107

    
1108
  $feature_block_settings = get_feature_block_settings(UUID_DISTRIBUTION);
1109

    
1110
  foreach ($descriptionElements as $descriptionElement) {
1111
    $annotations_and_sources = handle_annotations_and_sources(
1112
      $descriptionElement,
1113
      $feature_block_settings,
1114
      $descriptionElement->area->representation_L10n,
1115
      UUID_DISTRIBUTION
1116
    );
1117

    
1118

    
1119

    
1120
    $out .= '<' . $enclosingTag . ' class="descriptionElement descriptionElement-' . $descriptionElement->uuid . '">'
1121
        . $descriptionElement->area->representation_L10n;
1122
    if(!empty($annotations_and_sources['source_references'])){
1123
      $out .= ' ' . join(' ', $annotations_and_sources['source_references'] );
1124
    }
1125
    $out .= $annotations_and_sources['foot_note_keys']   . ' </' . $enclosingTag . '>';
1126
  }
1127

    
1128
  RenderHints::popFromRenderStack();
1129
  return markup_to_render_array($out);
1130
}
1131

    
1132

    
1133
/**
1134
 * Compare two different footnotes objects.
1135
 *
1136
 * The comparison is based on the footnote key. The one which is
1137
 * displayed as footnote number.
1138
 *
1139
 * @param mixed $a
1140
 *   Footnote object $a.
1141
 * @param mixed $b
1142
 *   Footnote object $b.
1143
 */
1144
function footnotes_key_compare($a, $b) {
1145
  $res = 0;
1146
  if (empty($a) || empty($b)) {
1147
    return $res;
1148
  }
1149
  if ($a->keyStr < $b->keyStr) {
1150
    $res = -1;
1151
  }
1152
  elseif ($a->keyStr > $b->keyStr) {
1153
    $res = 1;
1154
  }
1155
  return $res;
1156
}
1157

    
1158
/**
1159
 * @todo Please document this function.
1160
 * @see http://drupal.org/node/1354
1161
 */
1162
function theme_cdm_description_ordered_distributions($variables) {
1163

    
1164
  $distribution_tree = $variables['distribution_tree'];
1165

    
1166
  // Returning NULL if there are no description elements.
1167
  if ($distribution_tree == null) {
1168
    return NULL;
1169
  }
1170

    
1171
  // Initialization of some variables.
1172
  $out = '';
1173
  $separator = ',';
1174
  RenderHints::pushToRenderStack('descriptionElementDistribution');
1175
  RenderHints::setFootnoteListKey(UUID_DISTRIBUTION);
1176

    
1177
  $ordered_areas = $distribution_tree;
1178
  if (isset($ordered_areas->rootElement->children)) {
1179
    $ordered_areas = $ordered_areas->rootElement->children;
1180
  }
1181

    
1182
  // Printing the distributions.
1183
  if (is_array($ordered_areas) && count($ordered_areas) > 0) {
1184
    foreach ($ordered_areas as $element_level1) {
1185
      // Level1.
1186
      $out .= '<dt>' . $element_level1->nodeId->representation_L10n . ':</dt> ';
1187
      $out .= '<dd>';
1188

    
1189
      // Level3.
1190
      foreach ($element_level1->children as $element_level3) {
1191
        $text_l3 = $element_level3->nodeId->representation_L10n;
1192
        $fnKeysLevel3Str = '';
1193
        $fnKeysLevel3 = cdm_annotations_as_footnotekeys($element_level3->data);
1194
        if (isset($element_level3->data[0])) {
1195
          foreach ($element_level3->data as $description_level3){
1196
            foreach ($description_level3->sources as $source) {
1197
              if (_is_original_source_type($source)) {
1198
                $fn_key3 = FootnoteManager::addNewFootnote(
1199
                  original_source_footnote_list_key(),
1200
                  theme('cdm_OriginalSource', array('source' => $source, 'doLink' => FALSE)
1201
                ));
1202
                cdm_add_footnote_to_array($fnKeysLevel3, $fn_key3);
1203
              }
1204
            }
1205
          }
1206
        }
1207
        // Level4.
1208
        $l4_regions = array();
1209
        foreach ($element_level3->children as $element_level4) {
1210
          if (isset($element_level4->data[0])) {
1211
            $text_l4 = $element_level4->nodeId->representation_L10n;
1212
            $l4_regions[$element_level3->nodeId->representation_L10n] = array();
1213
            $fnKeysLevel4Str = '';
1214
            foreach($element_level4->data as $description_level4) {
1215
              $fnKeysLevel4 = cdm_annotations_as_footnotekeys($description_level4);
1216
              foreach ($description_level4->sources as $source) {
1217
                if (_is_original_source_type($source)) {
1218
                  $fn_key4 = FootnoteManager::addNewFootnote(
1219
                      original_source_footnote_list_key(),
1220
                      theme('cdm_OriginalSource', array('source' => $source, 'doLink' => FALSE)));
1221
                  cdm_add_footnote_to_array($fnKeysLevel4, $fn_key4);
1222
                }
1223
              }
1224
              usort($fnKeysLevel4, "footnotes_key_compare");
1225
              if(!isset( $l4_regions[$text_l4])){
1226
                $l4_regions[$text_l4] = $fnKeysLevel4;
1227
              } else {
1228
                $l4_regions[$text_l4] = array_merge($l4_regions[$text_l4], $fnKeysLevel4);
1229
              }
1230
            }
1231
          }
1232
        }// Level4.
1233
        // Managing level3 and level4 for generating the right output.
1234
        usort($fnKeysLevel3, "footnotes_key_compare");
1235
        foreach ($fnKeysLevel3 as $key3) {
1236
          foreach ($l4_regions as $key4 => $value4) {
1237
            cdm_add_footnote_to_array($l4_regions[$key4], $key3);
1238
          }
1239
        }
1240
        if ($element_level3->numberOfChildren == 1 && $text_l3 == $element_level3->children[0]->nodeId->representation_L10n) {
1241
          // var_dump($element_level3->children[0]->data->area->representation_L10n);
1242
          $fnStr = '';
1243
          $region = array_pop($l4_regions);
1244
          foreach ($region as $key) {
1245
            $fnStr .= theme('cdm_footnote_key', array('footnoteKey' => $key, 'separator' => ($fnStr ? $separator : '')));
1246
          }
1247
          $out .= "$text_l3 $fnStr; ";
1248
          // Removing whitespaces when &fnStr is empty.
1249
          if (substr($out, -3) == ' ; ') {
1250
            $out = substr($out, 0, -3) . '; ';
1251
          }
1252
        } else {
1253
          $fnKeysLevel3Str = '';
1254
          foreach ($fnKeysLevel3 as $key) {
1255
            $fnKeysLevel3Str .= theme('cdm_footnote_key', array('footnoteKey' => $key, 'separator' => ($fnKeysLevel3Str ? $separator : '')));
1256
          }
1257
          $text_l4_aux = '';
1258
          foreach ($l4_regions as $key => $value) {
1259
            $fnKeysLevel4Str = '';
1260
            if (is_array($l4_regions[$key])) {
1261
              foreach ($l4_regions[$key] as $fnkey) {
1262
                $fnKeysLevel4Str .= theme('cdm_footnote_key', array('footnoteKey' => $fnkey, 'separator' => ($fnKeysLevel4Str ? $separator : '')));
1263
              }
1264
            }
1265
            // if ($key != $text_l3 || sizeof($l4_regions > 1)){
1266
            if ($key != $text_l3) {
1267
              $text_l4_aux .= "$key $fnKeysLevel4Str, ";
1268
            }
1269
          }
1270
          $text_l4_aux = substr($text_l4_aux, 0, -2);
1271

    
1272
          if (strlen($text_l4_aux) > 0) {
1273
            $out .= "$text_l3 $fnKeysLevel3Str ($text_l4_aux); ";
1274
          }
1275
          else {
1276
            $out .= "$text_l3 $fnKeysLevel3Str; ";
1277
          }
1278
        }
1279
      }// Level3.
1280
      $out = substr($out, 0, -2);
1281
      $out .= '.</dd>';
1282
    }// Level1.
1283
  }
1284
  RenderHints::popFromRenderStack();
1285
  return $out;
1286
}
1287

    
1288
/**
1289
 * Returns a list of a specific type of IdentificationKeys.
1290
 *
1291
 * The list can be restricteded by a taxon.
1292
 *
1293
 * @param string $type
1294
 *   The simple name of the cdm class implementing the interface
1295
 *   IdentificationKey, valid values are:
1296
 *   PolytomousKey, MediaKey, MultiAccessKey.
1297
 * @param string $taxonUuid
1298
 *   If given this parameter restrict the listed keys to those which have
1299
 *   the taxon identified be this uuid in scope.
1300
 *
1301
 * @return array
1302
 *   List with identification keys.
1303
 */
1304
function _list_IdentificationKeys($type, $taxonUuid = NULL, $pageSize = NULL, $pageNumber = NULL) {
1305
  if (!$type) {
1306
    drupal_set_message(t('Type parameter is missing'), 'error');
1307
    return;
1308
  }
1309
  $cdm_ws_pasepath = NULL;
1310
  switch ($type) {
1311
    case "PolytomousKey":
1312
      $cdm_ws_pasepath = CDM_WS_POLYTOMOUSKEY;
1313
      break;
1314

    
1315
    case "MediaKey":
1316
      $cdm_ws_pasepath = CDM_WS_MEDIAKEY;
1317
      break;
1318

    
1319
    case "MultiAccessKey":
1320
      $cdm_ws_pasepath = CDM_WS_MULTIACCESSKEY;
1321
      break;
1322

    
1323
  }
1324

    
1325
  if (!$cdm_ws_pasepath) {
1326
    drupal_set_message(t('Type parameter is not valid: ') . $type, 'error');
1327
  }
1328

    
1329
  $queryParameters = '';
1330
  if (is_numeric($pageSize)) {
1331
    $queryParameters = "pageSize=" . $pageSize;
1332
  }
1333
  else {
1334
    $queryParameters = "pageSize=0";
1335
  }
1336

    
1337
  if (is_numeric($pageNumber)) {
1338
    $queryParameters = "pageNumber=" . $pageNumber;
1339
  }
1340
  else {
1341
    $queryParameters = "pageNumber=0";
1342
  }
1343
  $queryParameters = NULL;
1344
  if ($taxonUuid) {
1345
    $queryParameters = "findByTaxonomicScope=$taxonUuid";
1346
  }
1347
  $pager = cdm_ws_get($cdm_ws_pasepath, NULL, $queryParameters);
1348

    
1349
  if (!$pager || $pager->count == 0) {
1350
    return array();
1351
  }
1352
  return $pager->records;
1353
}
1354

    
1355
/**
1356
 * @todo Please document this function.
1357
 * @see http://drupal.org/node/1354
1358
 */
1359
function theme_cdm_IdentificationKey($variables) {
1360
  $out = '';
1361
  $identificationKey = $variables['identificationKey'];
1362
  $doLinkToKeyPage = $variables['doLinkToKeyPage'];
1363
  $showIdentificationKeyTitle = $variables['showIdentificationKeyTitle'];
1364
  $parentRenderPath = RenderHints::getRenderPath();
1365
  RenderHints::pushToRenderStack("IdentificationKey");
1366

    
1367
  if ($showIdentificationKeyTitle) {
1368
    if ($doLinkToKeyPage) {
1369
      $out = l($identificationKey->titleCache, path_to_key($identificationKey->class, $identificationKey->uuid));
1370
    }
1371
    else {
1372
      $out = $identificationKey->titleCache;
1373
    }
1374
  }
1375
  if (isset($identificationKey->sources) && is_array($identificationKey->sources)) {
1376
    // order and display sources.
1377
    $sources = oder_sources($identificationKey->sources, TRUE);
1378
    $out .= '<div class="sources">';
1379
    $out .=  implode('', $sources);
1380
    $out .= '</div>';
1381
  }
1382
  // Display annotations.
1383
  $out .= theme('cdm_annotations', array('annotations' => cdm_ws_getAnnotationsFor($identificationKey), 'enclosingTag' => 'div'));
1384
  RenderHints::popFromRenderStack();
1385
  return $out;
1386
}
1387

    
1388
/**
1389
 * @todo Please document this function.
1390
 * @see http://drupal.org/node/1354
1391
 */
1392
function theme_cdm_polytomousKey($variables) {
1393
  $polytomousKey = $variables['polytomousKey'];
1394

    
1395
  // TODO settings needed.
1396
  // @see http://en.wikipedia.org/wiki/Single_access_key#Presentation_styles
1397
  // @see http://dev.e-taxonomy.eu/trac/ticket/2152
1398
  $keyStyle = "linkedStyle";
1399

    
1400
  RenderHints::pushToRenderStack("polytomousKey");
1401
  // Key nodes in linked style.
1402
  $out = '<table class="polytomousKey polytomousKey_' . $keyStyle . '">';
1403
  $out .= theme('cdm_polytomousKey_' . $keyStyle . '_subgraph', array('polytomousKeyNode' => $polytomousKey->root));
1404
  $out .= '</table>';
1405
  RenderHints::popFromRenderStack();
1406
  return $out;
1407
}
1408

    
1409
/**
1410
 * @todo Please document this function.
1411
 * @see http://drupal.org/node/1354
1412
 */
1413
function theme_cdm_polytomousKey_linkedStyle_subgraph($variables) {
1414
  $polytomousKeyNode = $variables['polytomousKeyNode'];
1415
  static $statementCountCharacter = '\'';
1416
  $out = "";
1417

    
1418
  if (is_array($polytomousKeyNode->children)) {
1419
    $childIndex = 0;
1420

    
1421
    // Render edges of the current node.
1422
    foreach ($polytomousKeyNode->children as &$child) {
1423

    
1424
      if (!isset($child->statement) && isset($child->taxon->uuid)) {
1425
        // Skip node with empty statements (see below for explanation: "Special
1426
        // case").
1427
        // this skipping here happens always in the next deeper level of iteration
1428
        // the check below is node on the level above
1429
        continue;
1430
      }
1431

    
1432
      /*
1433
       * Special case: Child nodes with empty statements but taxa as leaf are to
1434
       * treated as if all those taxa where direct children of the source node.
1435
       */
1436
      $islinkToManyTaxa = !isset($child->children[0]->statement) && isset($child->children[0]->taxon->uuid);
1437
      $islinkToTaxon = isset($child->taxon->uuid);
1438
      $islinkToSubKey = isset($child->subkey->uuid);
1439
      $islinkToOtherNode = isset($child->otherNode);
1440
      // Either NULL or 0.
1441
      $islinkToNode = $child->nodeNumber && !$islinkToManyTaxa && !$islinkToOtherNode;
1442
      $hasQuestion = !empty($polytomousKeyNode->question->label_l10n);
1443
      $hasFeature = isset($polytomousKeyNode->feature);
1444

    
1445
      // $indentEdge = $hasQuestion && $childIndex > 0;
1446
      // Question.
1447
      if ($hasQuestion && $childIndex == 0) {
1448
        // Place question, as extra table row.
1449
        $out .= '<tr class="question new_section">';
1450
        $out .= '<td class="nodeNumber">' . uuid_anchor($polytomousKeyNode->uuid, $polytomousKeyNode->nodeNumber) . "</td>";
1451
        $out .= '<td class="question">' . $polytomousKeyNode->question->label_l10n . '</td>';
1452
        $out .= '</tr>';
1453
      }
1454

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

    
1457
      if ($hasQuestion) {
1458
        $out .= '<td class="nodeNumber"></td>';
1459
      }
1460
      else {
1461
        $out .= '<td class="nodeNumber">' . uuid_anchor($polytomousKeyNode->uuid, $polytomousKeyNode->nodeNumber . str_pad("", $childIndex, $statementCountCharacter)) . "</td>";
1462
      }
1463

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

    
1466
      // Feature.
1467
      if ($hasFeature) {
1468
        $out .= $polytomousKeyNode->feature->representation_L10n . ": ";
1469
      }
1470

    
1471
      // Statement.
1472
      $out .= $child->statement->label_l10n;
1473

    
1474
      // --- Links to nodes taxa and subkeys.
1475
      $out .= '<div class="nodeLink">';
1476

    
1477
      // Link to a PolytomousKeyNode.
1478
      if ($islinkToNode) {
1479
        $out .= '<div class="nodeLinkToNode">';
1480
        if (isset($child->modifyingText)) {
1481
          $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $child->modifyingText));
1482
        }
1483
        $out .= l($child->nodeNumber, request_path(), array(
1484
          'attributes' => NULL,
1485
          'query' => NULL,
1486
          'fragment' => $child->uuid,
1487
        )) . '</div>';
1488
      }
1489

    
1490
      // Link to a PolytomousKeyNode.
1491
      if ($islinkToOtherNode) {
1492
        $out .= '<div class="nodeLinkToOtherNode">';
1493
        if (isset($child->modifyingText)) {
1494
          $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $child->modifyingText));
1495
        }
1496
        $out .= l($child->otherNode->nodeNumber, $_REQUEST["q"], array(
1497
          'attributes' => NULL,
1498
          'query' => NULL,
1499
          'fragment' => $child->otherNode->uuid,
1500
        )) . '</div>';
1501
      }
1502

    
1503
      // Link to one or many taxa.
1504
      if ($islinkToTaxon || $islinkToManyTaxa) {
1505

    
1506
        if ($islinkToManyTaxa) {
1507
          $taxonChildren = $child->children;
1508
        }
1509
        else {
1510
          $taxonChildren = array(
1511
            $child,
1512
          );
1513
        }
1514

    
1515
        foreach ($taxonChildren as $taxonChild) {
1516
          // TODO many taxa $child->children->taxon.
1517
          $out .= '<div class="nodeLinkToTaxon">';
1518
          if (isset($taxonChild->modifyingText)) {
1519
            $out .= theme('cdm_poytomousKeyNode_modifyingText', array('modifyingText' => $taxonChild->modifyingText));
1520
          }
1521
          $out .= theme("cdm_taxonName", array('taxonName' => $taxonChild->taxon->name, 'nameLink' => url(path_to_taxon($taxonChild->taxon->uuid))));
1522
          $out .= '</div>';
1523
        }
1524

    
1525
        // Link to a subkey.
1526
        if ($islinkToSubKey) {
1527
          $out .= '<div class="nodeLinkToSubkey">' . theme('cdm_IdentificationKey', array('identificationKey' => $child->subkey)) . '</div>';
1528
        }
1529
      }
1530

    
1531
      $out .= '</div>'; // End node link.
1532
      $out .= '</td>'; // End edge.
1533
      $out .= '</tr>';
1534

    
1535
      $childIndex++;
1536
    }
1537

    
1538
    // Recurse into child nodes.
1539
    foreach ($polytomousKeyNode->children as &$child) {
1540
      $out .= theme('cdm_polytomousKey_linkedStyle_subgraph', array('polytomousKeyNode' => $child));
1541
    }
1542
  }
1543

    
1544
  return $out;
1545
}
1546

    
1547
/**
1548
 * @todo Please document this function.
1549
 * @see http://drupal.org/node/1354
1550
 */
1551
function theme_cdm_poytomousKeyNode_modifyingText($variables) {
1552
  $out = '';
1553
  $modifyingText = $variables['modifyingText'];
1554
  if (is_object($modifyingText)) {
1555
    $i = 0;
1556
    foreach (get_object_vars($modifyingText) as $lang => $languageString) {
1557
      $out .= ($i++ > 0 ? ', ' : '') . '<span class="modifyingText">' . $languageString->text . '</span> ';
1558
    }
1559
  }
1560
  return $out;
1561
}
1562

    
1563
/**
1564
 * Returns HTML for a list of a specific type of IdentificationKeys.
1565
 *
1566
 * The list can be restricteded by a taxon.
1567
 *
1568
 * @param array $variables
1569
 *   An associative array containing:
1570
 *   - type: The simple name of the cdm class implementing the interface
1571
 *     IdentificationKey, valid values are:
1572
 *     PolytomousKey, MediaKey, MultiAccessKey
1573
 *   - taxonUuid: If given, this parameter restrict the listed keys to those
1574
 *     which have the taxon identified be this uuid in scope.
1575
 *
1576
 * @ingroup themeable
1577
 */
1578
function theme_cdm_list_IdentificationKeys($variables) {
1579
  $type = $variables['type'];
1580
  $taxonUuid = $variables['taxonUuid'];
1581
  $keyList = _list_IdentificationKeys($type, $taxonUuid);
1582
  if (!$keyList || count($keyList) == 0) {
1583
    return;
1584
  }
1585

    
1586
  RenderHints::pushToRenderStack('list_IdentificationKeys');
1587
  $out = '<ul>';
1588
  foreach ($keyList as $key) {
1589
    $out .= '<li>';
1590
    $out .= theme('cdm_IdentificationKey', array('identificationKey' => $key));
1591
    $out .= '</li>';
1592
  }
1593
  $out .= '</ul>';
1594
  $out .= theme("cdm_annotation_footnotes", array('footnoteListKey' => RenderHints::getRenderPath()));
1595
  RenderHints::popFromRenderStack();
1596

    
1597
  return $out;
1598
}
1599

    
1600
/**
1601
 * @todo Please document this function.
1602
 * @see http://drupal.org/node/1354
1603
 */
1604
function theme_cdm_block_IdentificationKeys($variables) {
1605
  $taxonUuid = $variables['taxonUuid'];
1606
  static $types = array(
1607
    "PolytomousKey" => "Polytomous",
1608
    "MediaKey" => "Media",
1609
    "MultiAccessKey" => "Multiaccess",
1610
  );
1611
  RenderHints::pushToRenderStack('block_IdentificationKeys');
1612
  $out = '';
1613
  foreach ($types as $type => $label) {
1614
    $keylist = theme('cdm_list_IdentificationKeys', array('type' => $type, 'taxonUuid' => $taxonUuid));
1615
    if (!$keylist) {
1616
      continue;
1617
    }
1618
    $out .= '<div class="' . $type . '">';
1619
    $out .= '<h3>' . t($label) . "</h3>";
1620
    $out .= $keylist;
1621
    $out .= '</div>';
1622
  }
1623
  RenderHints::popFromRenderStack();
1624
  return $out;
1625
}
1626

    
1627
/**
1628
 * This theming function formats the use description and use record list for
1629
 * these descriptions.
1630
 *
1631
 * @see http://drupal.org/node/1354
1632
 */
1633
function theme_cdm_UseDescription($variables) {
1634
  $descriptions = $variables['description'];
1635
  $taxonUuid = $variables['taxonUuid'];
1636
  $out = '<div id="content"><ul id="Description" class ="description">';
1637
  if ($descriptions == NULL) {
1638
    return;
1639
  }
1640
  $descriptionSynonyms = '';
1641
  $descriptionOut = '';
1642
  $synonymOut = '';
1643
  $currentTaxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $taxonUuid);
1644

    
1645
  foreach ($descriptions as $description) {
1646
    $useSummary = '';
1647
    foreach ($description->elements as $element) {
1648

    
1649
      if ($element->feature->uuid == UUID_USE && !(strlen($useSummary) > 0) && isset($element->multilanguageText_L10n)) {
1650
        $useSummary = $element->multilanguageText_L10n->text;
1651
      }
1652
    }
1653
    // uses will be ordered by source
1654
    foreach ($description->sources as $source) {
1655
      $is_about_current_taxon = FALSE;
1656
      $originalTaxonUsedInSource = NULL;
1657
      $originalTaxonPager = NULL;
1658
      if ($source->originalNameString) {
1659
        $request_params = array();
1660
        $request_params['query'] = $source->originalNameString;
1661
        $request_params['matchMode'] = "EXACT";
1662
        $originalTaxonPager = cdm_ws_get(CDM_WS_PORTAL_NAME_FINDBYNAME, NULL, queryString($request_params));
1663
        if ($originalTaxonPager->count > 0) {
1664
          $originalTaxonUsedInSource = $originalTaxonPager->records[0];
1665
        }
1666
        else {
1667
          $originalTaxonUsedInSource = $currentTaxon->name;
1668
        }
1669
      }
1670
      else {
1671
        $originalTaxonUsedInSource = $currentTaxon->name;
1672
      }
1673

    
1674
      $is_about_current_taxon = $currentTaxon->name->uuid == $originalTaxonUsedInSource->uuid;
1675

    
1676
      if (!$is_about_current_taxon) {
1677
        $descriptionOut .= '<li class="descriptionText DescriptionElement">';
1678
        $name_used_in_source_link_to_show_use = l($source->originalNameString, path_to_name($originalTaxonUsedInSource->uuid), array(
1679
          'absolute' => TRUE,
1680
          'html' => TRUE,
1681
        ));
1682
        $descriptionOut .= $name_used_in_source_link_to_show_use . ': ';
1683
        $descriptionOut .= $useSummary;
1684
        foreach ($description->sources as $source) {
1685
          $descriptionOut .= " (" . theme('cdm_OriginalSource', array('source' => $source, 'doLink' => TRUE)) . ")";
1686
        }
1687
        $hasUseRecords = FALSE;
1688
        $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>';
1689
        foreach ($description->elements as $descriptionElement) {
1690
          if ($descriptionElement->feature->uuid == UUID_USE_RECORD) {
1691
            $hasUseRecords = TRUE;
1692
            // FIXME localization hardcoded to English
1693
            $useRecordTags = explode(';', $descriptionElement->modifyingText_l10n);
1694
            $descriptionUseRecordOut .= '<tr>';
1695
            $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>';
1696
            $descriptionUseRecordOut .= '</tr>';
1697
          }
1698
        }
1699
        $descriptionUseRecordOut .= '</table></div>';
1700
        if ($hasUseRecords) {
1701
          $descriptionOut .= $descriptionUseRecordOut . '</li>';
1702
        }
1703
      }
1704
      else {
1705
        // TODO +/- duplicate of above, unify this code
1706
        $synonymOut .= '<li class="descriptionText DescriptionElement">';
1707
        $name_used_in_source_link_to_show_use = l($source->originalNameString, path_to_name($originalTaxonUsedInSource->uuid), array(
1708
          'absolute' => TRUE,
1709
          'html' => TRUE,
1710
        ));
1711

    
1712
        $synonymOut .= $name_used_in_source_link_to_show_use . ': ';
1713
        $synonymOut .= $useSummary;
1714
        foreach ($description->sources as $source) {
1715
          $synonymOut .= " (" . theme('cdm_OriginalSource', array('source' => $source, 'doLink' => TRUE)) . ")";
1716
        }
1717

    
1718
        $hasUseRecords = FALSE;
1719
        $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>';
1720
        foreach ($description->elements as $descriptionElement) {
1721
          if ($descriptionElement->feature->uuid == UUID_USE_RECORD) {
1722
            $hasUseRecords = TRUE;
1723
            $useRecordTags = explode(';', $descriptionElement->modifyingText_l10n);
1724
            $useRecordTableOut .= '<tr>';
1725
            $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>';
1726
            $useRecordTableOut .= '</tr>';
1727
          }
1728
        }
1729
        $useRecordTableOut .= '</table></div>';
1730
        if ($hasUseRecords) {
1731
          $synonymOut .= $useRecordTableOut . '</li>';
1732
        }
1733
      }
1734

    
1735
      // }
1736
    }
1737
  }
1738
  $out .= $descriptionOut . $synonymOut;
1739
  $out .= "</ul></div>";
1740
  return $out;
1741
}
1742

    
1743

    
1744
/**
1745
 * The theming function for a block of Uses Descriptions for a given taxon.
1746
 *
1747
 * The Uses block has been removed from the code but the according theme function
1748
 * is kept for compatibility reasons with existing code regarding palmweb.
1749
 *
1750
 */
1751
function theme_cdm_block_Uses($variables) {
1752
  $taxonUuid = $variables['taxonUuid'];
1753
  RenderHints::pushToRenderStack('block_Uses');
1754

    
1755
  if ($taxonUuid == NULL) {
1756
    return;
1757
  }
1758
  $out = '';
1759
  $markerTypes = array();
1760
  $markerTypes['markerTypes'] = UUID_MARKERTYPE_USE;
1761
  $useDescriptions = cdm_ws_get(CDM_WS_PORTAL_TAXON_DESCRIPTIONS, $taxonUuid, queryString($markerTypes));
1762
  if (!empty($useDescriptions)) {
1763
    // FIXME use theme_block instaed of hardcoding the block html here !!!!
1764
    $out .= '<div id="block-cdm_dataportal-feature-description" class="clear-block block block-cdm_dataportal-feature"><H2><a name="userecords"> </a> Uses </H2>';
1765
    $formatUseDescriptions = theme('cdm_UseDescription', array('description' => $useDescriptions, 'taxonUuid' => $taxonUuid));
1766

    
1767
    $out .= $formatUseDescriptions;
1768
    $out .= "</div>";
1769
  }
1770

    
1771
  return $out;
1772
}
Add picture from clipboard (Maximum size: 40 MB)