Project

General

Profile

Download (74.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
3
 * @file
4
 * Functions for dealing with CDM entities of type SpecimenOrOccurrences
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
 * @author
16
 *   - Andreas Kohlbecker <a.kohlbecker@BGBM.org>
17
 */
18

    
19

    
20
/**
21
 * Renders a DerivedUnit either in a compact form or with full details.
22
 *
23
 * @param $derived_unit_dto
24
 *  The DerivedUnitDTO
25
 * @param $with_full_details
26
 *  Wether to render the dertived unit data with full details, like for example for the specimen page
27
 *
28
 * @return string
29
 *  The markup for a specimen page
30
 */
31
function render_cdm_specimenDTO_page($derived_unit_dto, $with_full_details = false)
32
{
33
    $detail_html = "";
34
    //link to specimen page
35
    $path_to_specimen = path_to_specimen($derived_unit_dto->uuid);
36
    if (!$with_full_details) {
37
        $specimenPageLink = l($derived_unit_dto->specimenShortTitle, $path_to_specimen);
38
        $detail_html .= "<strong>Specimen summary: $specimenPageLink</strong><br>";
39
    }
40

    
41
    if($with_full_details) {
42
        if($derived_unit_dto->summaryLabel){
43
            $detail_html .= "<br>".$derived_unit_dto->summaryLabel."<br>";
44

    
45
        }
46
    }
47
    if ($derived_unit_dto->preferredStableUri) {
48
        $stableIdentifierLink = l($derived_unit_dto->preferredStableUri, $derived_unit_dto->preferredStableUri);
49
        $detail_html .= create_label("Preferred stable URI") . $stableIdentifierLink . "<br>";
50
    }
51
    if ($with_full_details) {
52
        // associated taxa
53
        if ($derived_unit_dto->associatedTaxa) {
54
            $detail_html .= "<br>";
55
            $detail_html .= create_label("Associated with");
56
            if (sizeof($derived_unit_dto->associatedTaxa) > 1) {
57
                $detail_html .= "<br>";
58
            }
59
            foreach ($derived_unit_dto->associatedTaxa as $associatedTaxon) {
60
                $detail_html .= l($associatedTaxon->label, path_to_taxon($associatedTaxon->uuid, "specimens"));//$associatedTaxon->second."<br>";
61
            }
62
            $detail_html .= "<br>";
63
        }
64
    }
65
    // - type information
66
    $types = "";
67
    if (isset($derived_unit_dto->types)) {
68
        //typed taxa
69
        foreach ($derived_unit_dto->types as $typeStatus => $typedTaxa) {
70
            if($derived_unit_dto->types){
71
                if(empty($typeStatus) || $typeStatus == "_empty_"|| $typeStatus == ""){
72
                    $detail_html .= "<i>Type for:</i> ";
73
                } else {
74
                    $detail_html .= "<i>".ucfirst($typeStatus)."</i> of ";
75
                }
76
                foreach($typedTaxa as $typedTaxon){
77
                    $detail_html .= $typedTaxon." ";
78

    
79
                }
80
            } else {
81
                $types .= $typeStatus . " ";
82
            }
83
           $detail_html .= '<br>';
84
        }
85
    }
86
    $derivation_tree_summary_dto = $derived_unit_dto->derivationTreeSummary;
87
    // - specimen scans
88
    $specimenScans = create_html_links($derivation_tree_summary_dto->specimenScans, true);
89
    // - molecular data
90
    $molecularData = "";
91
    if ($derivation_tree_summary_dto->molecularDataList) {
92
        foreach ($derivation_tree_summary_dto->molecularDataList as $molecular) {
93
            //provider link
94
            if (isset($molecular->providerLink)) {
95
                $molecularData .= create_html_link($molecular->providerLink, true);
96
            } else {
97
                $molecularData .= "[no provider]";
98
            }
99
            //contig link
100
            if (isset($molecular->contigFiles)) {
101
                $molecularData .= "[";
102
                if (sizeof($molecular->contigFiles) > 0) {
103
                    foreach ($molecular->contigFiles as $contigFile) {
104
                        if (isset($contigFile->contigLink)) {
105
                            if (isset($contigFile->contigLink->uri) and $contigFile->contigLink->uri != null) {
106
                                $molecularData .= create_html_link($contigFile->contigLink, true) . " ";
107
                            }
108
                        } else {
109
                            $molecularData .= "no contig ";
110
                        }
111
                        //primer links
112
                        if (isset($contigFile->primerLinks)) {
113
                            $molecularData .= create_html_links($contigFile->primerLinks, true);
114
                        }
115
                    }
116
                }
117
                $molecularData = rtrim($molecularData, " ");
118
                $molecularData .= "]";
119
            }
120
            //FIXME separate with comma (remove trailing comma)
121
        }
122
    }
123
    // - detail images
124
    $detailImages = create_html_links($derivation_tree_summary_dto->detailImages, true);
125

    
126
    if ($types) {
127
        $detail_html .= $with_full_details ? "<br>" : "";
128
        $detail_html .= create_label("Type(s)") . $types . "<br>";
129
    }
130
    if ($specimenScans and !$with_full_details) {
131
        $detail_html .= create_label("Specimen Scans") . $specimenScans . "<br>";
132
    }
133
    //specimen scan image gallery
134
    if ($with_full_details and isset($derivation_tree_summary_dto->specimenScanUuids) and !empty($derivation_tree_summary_dto->specimenScanUuids)) {
135
        $detail_html .= addImageGallery("Specimen scans", $derivation_tree_summary_dto->specimenScanUuids);
136
    }
137

    
138
    if ($molecularData) {
139
        $detail_html .= $with_full_details ? "<br>" : "";
140
        $detail_html .= create_label("Molecular Data") . $molecularData . "<br>";
141
    }
142

    
143
    if ($detailImages and !$with_full_details) {
144
        $detail_html .= create_label("Detail Images") . $detailImages . "<br>";
145
    }
146

    
147
    //detail image gallery
148
    if ($with_full_details and isset($derivation_tree_summary_dto->detailImageUuids) and !empty($derivation_tree_summary_dto->detailImageUuids)) {
149
        $detail_html .= addImageGallery("Detail Images", $derivation_tree_summary_dto->detailImageUuids);
150
    }
151

    
152
    //character data
153
    if ($derived_unit_dto->characterData) {
154
        $detail_html .= $with_full_details ? "<br>" : "";
155
        $detail_html .= create_label("Character Data");
156
        if ($with_full_details) {
157
            $detail_html .= "<br>";
158
            foreach ($derived_unit_dto->characterData as $characterStatePair) {
159
                $detail_html .= "<i>" . $characterStatePair->first . "</i>:" . $characterStatePair->second;
160
                $detail_html .= "<br>";
161
        }
162
        } else {
163
            $detail_html .= l("detail page", $path_to_specimen);
164
            $detail_html .= "<br>";
165
        }
166
    }
167
    return $detail_html;
168
}
169

    
170
function addImageGallery($galleryName, $imageUuids)
171
{
172
    $images = array();
173
    foreach ($imageUuids as $uuid) {
174
        $images[] = cdm_ws_get(CDM_WS_PORTAL_MEDIA, $uuid);
175
    }
176

    
177
    $gallery_html = '';
178
    if (count($imageUuids) > 0) {
179
        $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
180
        $captionElements = array(
181
            'title',
182
            'rights',
183
        );
184
        $alternativeMediaUris = array();
185
        foreach ($images as $image) {
186
            $mediaUri = getMediaUri($image);
187
            if ($mediaUri) {
188
                $alternativeMediaUris[] = $mediaUri;
189
            } else {
190
                $alternativeMediaUris[] = path_to_media($image->uuid);
191
            }
192
        }
193

    
194

    
195

    
196
        $gallery_html = compose_cdm_media_gallery(array(
197
            'mediaList' => $images,
198
            'galleryName' => $galleryName,
199
            'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
200
            'cols' => $gallery_settings['cdm_dataportal_media_cols'],
201
            'maxRows' => isset($gallery_settings['cdm_dataportal_media_maxRows']) ? isset($gallery_settings['cdm_dataportal_media_maxRows']) : null,
202
            'captionElements' => $captionElements,
203
            'mediaLinkType' => 'LIGHTBOX',
204
          // 'alternativeMediaUri' => $alternativeMediaUris,
205
            'alternativeMediaUri' => NULL,
206
            'galleryLinkUri' => NULL,
207
        ));
208
    }
209
    return "<br>" . create_label($galleryName) . "<br>" . $gallery_html;
210
}
211

    
212
function getMediaUri($media)
213
{
214
    if (isset($media->representations) && sizeof($media->representations) == 1
215
        && isset($media->representations[0]->parts) &&
216
        sizeof($media->representations[0]->parts) == 1) {
217
        return $media->representations[0]->parts[0]->uri;
218
    }
219
    return null;
220
}
221

    
222

    
223
/**
224
 * Formats the given string to a label for displaying key-object pairs in HTML
225
 * @return string
226
 */
227
function create_label($label)
228
{
229
    return "<span class='specimen_table_label'>" . $label . ": </span>";
230
}
231

    
232
/**
233
 * Provides a humane representation for an occurrence or observation field name.
234
 * @param string $field
235
 *    The field name.
236
 * @return string
237
 *    The label for the fieldname.
238
 */
239
function cdm_occurrence_field_name_label($field){
240

    
241
  static $field_labels = array(
242
    'class' => 'Basis of Record',
243
    'fieldNumber' => 'Collecting number',
244
    'absoluteElevation' => 'Altitude',
245
    'absoluteElevationMinimum' => 'Altitude maximum',
246
    'absoluteElevationMaximum' => 'Altitude minimum',
247
    'getGatheringPeriod' => 'Gathering period'
248
  );
249

    
250
  if(str_endsWith($field,'_L10n')){
251
    $field = str_replace('_L10n', '', $field );
252
  }
253
  if (isset($field_labels[$field])) {
254
    $field = $field_labels[$field];
255
  }
256

    
257
  $field = preg_replace_callback(
258
    '/([a-z])([A-Z])/',
259
    function ($m) {
260
      return $m[1] . ' ' . strtolower ($m[2]);
261
    },
262
    $field);
263

    
264
  return t('@field-name:', array('@field-name' => ucfirst($field)));
265
}
266

    
267
/**
268
 * Compose an render array from a CDD SpecimenOrObservation entity.
269
 *
270
 * compose_hook() implementation
271
 *
272
 * @param object $specimen_or_observation
273
 *   the CDM FieldUnit or DerivedUnit to compose
274
 *   the render array for.
275
 * @param bool $isSpecimen_page
276
 * @param array $derivatives
277
 *   the render array which contains the compositions of the derivatives
278
 *   of the supplied $specimenOrObservation
279
 *
280
 * @return array
281
 *   the supplied render array $derivatives to which the composition of the supplied
282
 *   $specimenOrObservation has been added to
283
 *
284
 * @throws \Exception
285
 * @ingroup compose
286
 */
287

    
288
function compose_cdm_specimen_or_observation($specimen_or_observation, $isSpecimen_page = false, &$derivatives = null)
289
{
290
    $exclude_occurrence_fields = &drupal_static(__FUNCTION__);
291
    if (!isset($exclude_occurrence_fields)) {
292
        $exclude_occurrence_fields = array(
293
            'uuid',
294
            'titleCache',
295
            'protectedTitleCache',
296
            'derivedUnitMedia',
297
            'created',
298
            'publish',
299
            'updated',
300
            'class',
301
            'collectionCode'
302
        );
303
    }
304
    if ((variable_get(CDM_SPECIMEN_LIST_VIEW_MODE, CDM_SPECIMEN_LIST_VIEW_MODE_DEFAULT) == CDM_SPECIMEN_LIST_VIEW_MODE_OPTION_DERIVATE_TABLE) || !$isSpecimen_page){
305
        $exclude_occurrence_fields[] = 'derivationEvents';
306
    }
307

    
308
    if (!isset($derivatives)) {
309
        $derivatives = array();
310
    }
311
    $descriptions = null;
312
    $derivedFrom = null;
313

    
314
    if (is_object($specimen_or_observation)) {
315

    
316
        // request again for deeper initialization
317
        $specimen_or_observation = cdm_ws_get("portal/" . CDM_WS_OCCURRENCE, $specimen_or_observation->uuid);
318
        if ($specimen_or_observation->class == 'FieldUnit'){
319
            // WARNING: adding a List<MediaDTO> as $specimen_or_observation->_derivedUnitMedia
320
            $specimen_or_observation->_derivedUnitMedia = cdm_ws_get(CDM_WS_DERIVEDUNIT_FACADE, array(
321
                $specimen_or_observation->uuid,
322
                'fieldObjectMediaDTO',
323
            ));
324
        }else{
325
            // WARNING: adding a List<Media> as $specimen_or_observation->_derivedUnitMedia
326
            $specimen_or_observation->_derivedUnitMedia = cdm_ws_get(CDM_WS_DERIVEDUNIT_FACADE, array(
327
                $specimen_or_observation->uuid,
328
                'derivedUnitMedia',
329
            ));
330
        }
331

    
332
        $type_label = $specimen_or_observation->class;
333
        RenderHints::setFootnoteListKey($type_label . '-' . $specimen_or_observation->uuid);
334

    
335
        // collect typeStatus as label
336
        if (isset($specimen_or_observation->specimenTypeDesignations)) {
337
            $type_status = array();
338
            foreach ($specimen_or_observation->specimenTypeDesignations as $typeDesignation) {
339
                if (isset($typeDesignation->typeStatus_L10n)) {
340
                    $type_status[] = $typeDesignation->typeStatus_L10n;
341
                }
342
            }
343
            if (count($type_status) > 0) {
344
                $type_label = implode(', ', $type_status);
345
            }
346
        }
347

    
348
        $title = $type_label . ': ' . $specimen_or_observation->titleCache;
349

    
350
        $groups = array();
351

    
352
        // --- add initialized fields
353
        foreach (get_object_vars($specimen_or_observation) as $field => $value) {
354
            if (!in_array($field, $exclude_occurrence_fields) && ($value && ($field == 'recordBasis' || !is_object($value) || isset($value->class)))) {
355
                switch ($field) {
356

    
357
                  case 'recordBasis':
358
                    $label = $value->representation_L10n;
359
                    if($label == 'Dna Sample'){
360
                      $label = 'DNA Sample';
361
                    }
362
                    _description_list_group_add($groups, cdm_occurrence_field_name_label($field), $label,NULL, -10);
363
                    break;
364

    
365
                    /* ---- java.lang.Object --- */
366
                    case 'class':
367
                        if ($value != '' /* FieldUnit' */) {
368
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value);
369
                        }
370
                        break;
371

    
372
                    case 'markers':
373
                        $dd_elements = array();
374
                        foreach ($value as $marker) {
375
                            $dd_elements[] = compose_cdm_marker($marker);
376
                        }
377
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements);
378
                        break;
379
                  case 'status':
380
                    $dd_elements = array();
381
                    foreach ($value as $status) {
382
                      $dd_elements[] = compose_cdm_status($status);
383
                    }
384
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements);
385
                    break;
386

    
387

    
388
                    case 'annotations':
389
                        $dd_elements = array();
390
                        foreach ($value as $annotation) {
391
                            // TODO respect annotation type filter settings
392
                            $dd_elements[] = $annotation->text;
393
                        }
394
                        @_description_list_group_add($groups, t('Notes:'), $dd_elements);
395
                        break;
396

    
397
                    /* ---- SpecimenOrObservationBase --- */
398
                    case 'sex':
399
                    case 'lifeStage':
400
                    case 'kindOfUnit':
401
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value->representation_L10n);
402
                        break;
403

    
404
                    case 'definition':
405
                        // TODO
406
                        break;
407

    
408
                    case 'preferredStableUri':
409

    
410
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), array(array('#markup' => cdm_external_uri($value, false))));
411
                        break;
412

    
413
                    case 'specimenTypeDesignations':
414

    
415
                        //TODO: better display of details!!
416
                        @_description_list_group_add(
417
                            $groups,
418
                            cdm_occurrence_field_name_label($field),
419
                            array(
420
                                '#markup' => render_type_designations($value),
421
                            )
422
                        );
423
                        break;
424

    
425
                    case 'determinations':
426
                        $dd_elements = array();
427
                        $glue = ', ';
428

    
429
                        foreach ($value as $determinationEvent) {
430
                            $timeperiod_string = NULL;
431
                            if (isset_not_empty($determinationEvent->timeperiod)) {
432
                                $timeperiod_string = timePeriodToString($determinationEvent->timeperiod);
433
                            }
434
                            $weight = isset($determinationEvent->preferred) && $determinationEvent->preferred == 1 ? '0' : ($timeperiod_string ? $timeperiod_string : '1');
435
                            // check key exists
436
                            while (array_key_exists($weight, $dd_elements)) {
437
                                $weight .= '0';
438
                            }
439

    
440
                            $taxon_name = '';
441
                            $name_link = '';
442
                            if ($determinationEvent->taxonName) {
443
                                $taxon_name = cdm_ws_get(CDM_WS_NAME, $determinationEvent->taxonName->uuid);
444
                                $taxon_name->taggedName = cdm_ws_get(CDM_WS_NAME, array($determinationEvent->taxonName->uuid, "taggedName"));
445
                                $name_link = path_to_name($determinationEvent->taxonName->uuid);
446
                            } else if ($determinationEvent->taxon) {
447
                                $taxon_name = cdm_ws_get(CDM_WS_TAXON . '/$0/name', $determinationEvent->taxon->uuid);
448
                                $name_link = path_to_taxon($determinationEvent->taxon->uuid);
449
                            }
450
                            if ($taxon_name) {
451
                                //$taxon_html = render_taxon_or_name($taxon_name, $name_link);
452

    
453
                                $taxon_html = l($taxon_name->titleCache, $name_link);
454
                                $dd_elements[$weight] = $taxon_html;
455
                            }
456
                            if (isset_not_empty($determinationEvent->modifier)) {
457
                                $dd_elements[$weight] .= cdm_term_representation($determinationEvent->modifier);
458
                            }
459
                            if ($timeperiod_string) {
460
                                $dd_elements[$weight] .= $glue . $timeperiod_string;
461
                            }
462
                            if (isset_not_empty($determinationEvent->actor) && isset_not_empty($determinationEvent->actor->titleCache)) {
463
                                $dd_elements[$weight] .= $glue . $determinationEvent->actor->titleCache;
464
                            }
465
                            if (isset_not_empty($determinationEvent->description)) {
466
                                $dd_elements[$weight] .= $glue . $determinationEvent->description;
467
                            }
468
                        }
469
                        ksort($dd_elements);
470
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('determinations'), $dd_elements);
471
                        break;
472

    
473
                    case 'descriptions':
474
                        $dd_elements = array();
475
                        foreach ($value as $description) {
476
                            $description = cdm_ws_get(CDM_WS_PORTAL_DESCRIPTION, $description->uuid);
477

    
478
                            if ($description->imageGallery == TRUE) {
479
                                continue;
480
                            }
481
                            $description_string = render_description_string(get_root_nodes_for_dataset($description));
482
                            $dd_elements[] = markup_to_render_array($description_string);
483
                        }
484
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements);
485
                        break;
486
                    case '_derivedUnitMedia':
487
                        if ($isSpecimen_page) {
488
                            $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
489
                            $captionElements = array(
490
                                '#uri' => t('open media'),
491
                            );
492
                            $gallery_html = compose_cdm_media_gallery(array(
493
                                'mediaList' => $value, // WARNING: this is either a List<Media> or List<MediaDTO>, see above ~line 361
494
                                'galleryName' => $specimen_or_observation->titleCache,
495
                                'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
496
                                'cols' => $gallery_settings['cdm_dataportal_media_cols'],
497
                                'maxRows' => isset($gallery_settings['cdm_dataportal_media_maxRows']) ? isset($gallery_settings['cdm_dataportal_media_maxRows']) : null,
498
                                'captionElements' => $captionElements,
499
                                'mediaLinkType' => 'LIGHTBOX',
500
                                'alternativeMediaUri' => NULL,
501
                                'galleryLinkUri' => NULL,
502
                            ));
503
                            @_description_list_group_add($groups, "Detail Images:", markup_to_render_array($gallery_html), '', 20);
504
                        }
505

    
506
                        // $dd_elements[] = markup_to_render_array($gallery_html);
507

    
508
                        break;
509
                    case 'sources':
510
                        RenderHints::setAnnotationsAndSourceConfig([
511
                          'sources_as_content' => TRUE,
512
                          'link_to_name_used_in_source' => TRUE,
513
                          'link_to_reference' => FALSE,
514
                          'add_footnote_keys' => FALSE,
515
                          'bibliography_aware' => FALSE
516
                        ]);
517
                        $annotations_and_sources = handle_annotations_and_sources($specimen_or_observation);
518
                        if ($annotations_and_sources->hasSourceReferences()) {
519
                            @_description_list_group_add($groups, t('Sources') . ':', join(', ', $annotations_and_sources->getSourceReferences()), '', 12);
520
                        }
521
                        break;
522

    
523

    
524
                    /* ---- DerivedUnitBase --- */
525
                    case 'derivedFrom':
526
                        $derivedFrom = $value;
527
                        if ($isSpecimen_page) {
528
                            foreach ($derivedFrom->originals as $original) {
529
                                $pathToSpecimen = path_to_specimen($original->uuid);
530
                                $description = "";
531
                                if (isset($derivedFrom->description) && $derivedFrom->description != '') {
532
                                    $description = $derivedFrom->description . ": ";
533
                                }
534

    
535
                                $originals[] = markup_to_render_array(l($description . $original->titleCache, $pathToSpecimen));
536
                                if ($original->class == 'FieldUnit') {
537
                                    $label = t('Field data');
538
                                } else {
539
                                    $label = t('Derived from');
540
                                }
541
                                @_description_list_group_add($groups, $label . ':',
542
                                    $originals,
543
                                    '', 13);
544
                            }
545
                        }
546
                        break;
547
                    case 'derivationEvents':
548
                        $derivationEvents = $value;
549
                        $derived_units = array();
550
                        if ($isSpecimen_page) {
551
                            foreach ($derivationEvents as $derivationEvent) {
552
                                foreach ($derivationEvent->derivatives as $derived_unit) {
553
                                    $pathToSpecimen = path_to_specimen($derived_unit->uuid);
554
                                    $description = "";
555
                                    if (isset($derived_unit->description) && $derived_unit->description != '') {
556
                                        $description = $derived_unit->description . ": ";
557
                                    }
558

    
559
                                    $derived_units[] = markup_to_render_array(l($description . $derived_unit->titleCache, $pathToSpecimen));
560
                                }
561
                            }
562
                            @_description_list_group_add($groups, t('Derivatives') . ':',
563
                                $derived_units,
564
                                '', 100);
565

    
566
                        }
567
                        break;
568

    
569
                    case 'collection':
570
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), array(
571
                          array('#markup' => render_collection($value))
572
                        ));
573
                        break;
574

    
575
                    case 'storedUnder':
576
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('storedUnder'), array(
577
                          array('#markup' => render_taxon_or_name($value))
578
                        ));
579
                        break;
580
                    case 'dnaQuality':
581
                        $sub_dl_groups = array();
582

    
583
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('purificationMethod'), $value->purificationMethod, NULL, 1);
584
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('ratioOfAbsorbance260_230'), $value->ratioOfAbsorbance260_230, NULL, 2);
585
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('ratioOfAbsorbance260_280'), $value->ratioOfAbsorbance260_280, NULL, 3);
586
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('concentration'), $value->concentration, NULL, 4);
587
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('concentrationUnit'), $value->concentrationUnit, NULL, 4);
588
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('qualityTerm'), $value->qualityTerm, NULL, 4);
589
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('qualityCheckDate'), $value->qualityCheckDate, NULL, 4);
590

    
591
                        if (is_array($sub_dl_groups) && sizeof($sub_dl_groups)>0) {
592
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label($field),
593
                                array(
594
                                    array('#markup' => $value->titleCache),
595
                                    array('#theme' => 'description_list', '#groups' => $sub_dl_groups)
596
                                )
597
                            );
598
                        }
599
                        break;
600

    
601
                    case 'preservation':
602
                        $sub_dl_groups = array();
603

    
604
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('medium'), $value->medium, NULL, 1);
605
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('temperature'), $value->temperature, NULL, 2);
606
                        @_description_list_group_add($sub_dl_groups, cdm_occurrence_field_name_label('definedMaterialOrMethod'), $value->definedMaterialOrMethod, NULL, 3);
607

    
608
                        if (is_array($sub_dl_groups) && sizeof($sub_dl_groups)>0) {
609
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label($field),
610
                                array(
611
                                    array('#markup' => $value->titleCache),
612
                                    array('#theme' => 'description_list', '#groups' => $sub_dl_groups)
613
                                )
614
                            );
615
                        }
616
                        break;
617

    
618
                    /* ---- Specimen --- */
619
                    case 'sequences':
620
                        $dd_elements = array();
621
                        foreach ($value as $sequence) {
622
                            $dd_elements[] = compose_cdm_sequence($sequence);
623
                        }
624
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements);
625
                        break;
626

    
627
                    // TODO preservation
628
                    // TODO exsiccatum
629

    
630

    
631
                    /* ---- FieldObservation --- */
632
                    case 'gatheringEvent':
633
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('collector'), $value->actor->titleCache, '', 1);
634
                        @_description_list_group_add($groups, t('Gathering date'), timePeriodToString($value->timeperiod), '', 2);
635
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('description'), $value->description, '', 3);
636
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('locality'), $value->locality->text, '', 10);
637
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('country'), $value->country->representation_L10n, '', 4);
638
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('collectingMethod'), $value->collectingMethod,'',5);
639
                        if (isset_not_empty($value->absoluteElevation)) {
640
                            $min_max_markup = statistical_values_from_gathering_event($value, 'absoluteElevation');
641
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label('absoluteElevation'), $min_max_markup, '',6);
642
                        }
643
                        if (isset_not_empty($value->distanceToGround)) {
644
                            $min_max_markup = statistical_values_from_gathering_event($value, 'distanceToGround');
645
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label('distanceToGround'), $min_max_markup,'',7);
646
                        }
647
                        if (isset_not_empty($value->distanceToWaterSurface)) {
648
                            $min_max_markup = statistical_values_from_gathering_event($value, 'distanceToWaterSurface');
649
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label('distanceToWaterSurface'), $min_max_markup, '',8);
650
                        }
651
                        if (isset_not_empty($value->collectingAreas)) {
652
                            $area_representations = array();
653
                            foreach ($value->collectingAreas as $area) {
654
                                $area_representations[] = l($area->representation_L10n, path_to_named_area($area->uuid));
655
                            }
656
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label('collectingAreas'),
657
                                array(
658
                                    array('#markup' => implode(', ', $area_representations))
659
                                ),'',9
660
                            );
661
                        }
662
                        if (isset_not_empty($value->exactLocation->sexagesimalString)) {
663
                            @_description_list_group_add($groups, cdm_occurrence_field_name_label('exactLocation'),
664
                                array(
665
                                    array('#markup' => render_point($value->exactLocation)),
666

    
667
                                ),'',11
668
                            );
669
                        }
670
                        break;
671

    
672
                    default:
673
                        if (is_object($value) || is_array($value)) {
674
                            drupal_set_message("Unhandled type in compose_cdm_specimen_or_observation() for field " . $field, "warning");
675
                        } else {
676
                            if ($field == 'RecordBase' && $value == 'DnaSample') {
677
                                _description_list_group_add($groups, cdm_occurrence_field_name_label($field), 'DNA Sample');
678
                            } else {
679
                                _description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value);
680
                            }
681
                        }
682

    
683
                }
684

    
685
            }
686
        } // END of loop over $derivedUnitFacade fields
687

    
688
        // Extensions
689
        // TODO: filter by using visible_extensions_sorted()
690
        // TODO: treat as top level element, see https://dev.e-taxonomy.eu/redmine/issues/2985#note-23
691
        $extensions = cdm_ws_fetch_all(CDM_WS_PORTAL_OCCURRENCE . '/'  . $specimen_or_observation->uuid . '/extensions', array($specimen_or_observation->uuid));
692
        if ($extensions && count($extensions)) {
693

    
694
            $extensions_render_array = compose_extensions($extensions);
695
            @_description_list_group_add($groups, t('Extensions') . ':',
696
                $extensions_render_array,
697
                '', 100);
698
        }
699

    
700

    
701

    
702
        // template_preprocess_description_list() is not worting by weight so we do it right here
703
        uasort($groups, 'element_sort');
704

    
705
        $occurrence_elements = array(
706
           // '#title' => $title,
707
            '#theme' => 'description_list',
708
            '#groups' => $groups,
709
            '#attributes' => array('class' => html_class_attribute_ref($specimen_or_observation)),
710
        );
711

    
712
        $derivatives[] = $occurrence_elements;
713
        // all footnotes which has been assembled so far (e.g. from typeDesignations) to here
714
//       $foonote_li_elements = render_footnotes(RenderHints::getFootnoteListKey(), 'span');
715
//        if (!empty($foonote_li_elements)) {
716
//            $derivatives[] =  array(
717
//                '#markup' =>  '<div class="footnotes">' . $foonote_li_elements . '</div>',
718
//            );
719
//        }
720

    
721
        // --- recurse into originals
722
        if (!isset($derivedFrom)  && !$isSpecimen_page) {
723
            $derivedFrom = cdm_ws_get(
724
                CDM_WS_OCCURRENCE,
725
                array($specimen_or_observation->uuid, 'derivedFrom')
726
            );
727
        }
728
        if (isset($derivedFrom) && !$isSpecimen_page) {
729
            if (isset($derivedFrom->originals)) {
730
                $derived_from_label = t('derived');
731
                $preposition = t('from');
732
                if(isset($derivedFrom->type)){
733
                    $derived_from_label = $derivedFrom->type->representation_L10n;
734
                    if($derivedFrom->type->uuid == UUID_DERIVATIONEVENTTYPE_ACCESSIONING){
735
                        $preposition = t('of');
736
                    }
737
                }
738
                if (count($groups) > 0) {
739
                    // TODO  annotations
740

    
741
                    // only display the derived from information when the derivative has any element which will be diplayed
742
                    $derivatives[] = array(
743
                        '#markup' => '<div class="derived_from">' . $derived_from_label . ' ' . $preposition . ': </div>',
744
                    );
745
                }
746
                foreach ($derivedFrom->originals as $original) {
747
                    compose_cdm_specimen_or_observation($original, $isSpecimen_page, $derivatives);
748
                }
749
            }
750
        }
751

    
752

    
753

    
754

    
755
    } // END of $specimenOrObservation exists
756

    
757
    return $derivatives;
758
}
759

    
760

    
761
/**
762
 * Compose an render array from a CDM Sequence object.
763
 *
764
 * compose_hook() implementation
765
 *
766
 * @param object $sequence
767
 *   CDM instance of type Sequence
768
 * @return array
769
 *   A render array containing the fields of the supplied $sequence
770
 *
771
 * @ingroup compose
772
 */
773
function compose_cdm_sequence($sequence, $isSpecimenPage = false)
774
{
775

    
776
    $exclude_sequence_fields = &drupal_static(__FUNCTION__);
777
    if (!isset($exclude_sequence_fields)) {
778
        $exclude_sequence_fields = array(
779
            'titleCache',
780
            'protectedTitleCache',
781
            'microReference',
782
            'created',
783
            'updated',
784
            'class',
785
        );
786
    }
787

    
788
    $groups = array();
789

    
790
    // -- retrieve additional data if necessary
791
    // TODO below call disabled since sequences are not yet supported,
792
    //      see  #3347 (services and REST service controller for molecular classes implemented)
793
    //
794
    // fetch_visible_annotations($sequence);
795

    
796
    foreach (get_object_vars($sequence) as $field => $value) {
797

    
798

    
799
        if (!in_array($field, $exclude_sequence_fields) && ($value && (!is_object($value) || isset($value->class)))) {
800
            switch ($field) {
801

    
802
                case 'geneticAccessionNumber';
803

    
804
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value, NULL, 2);
805
                    break;
806

    
807

    
808
                case 'dnaMarker': // FIXME 3.3 now dnaMarker (DefinedTerm)  if multiple amplifications where used to build this consensus sequence it may be the super set of the markers used in amplification.
809
                    if (isset($value->name)) {
810
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value->name, NULL, 3);
811
                    }
812
                    if (isset($value->description)) {
813
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label($field) . ' ' . t('description'), $value->description, NULL, 4);
814
                    }
815
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field) , $value, NULL, 4);
816
                    break;
817

    
818
                case 'consensusSequence':
819
                    // format in genbank style, force linebreaks after each 70 nucleotites
820
                    // see also http://stackoverflow.com/questions/499137/css-how-can-i-force-a-long-string-without-any-blank-to-be-wrapped-in-xul-and
821
                    if ($value->length > 0) {
822
                        @_description_list_group_add(
823
                            $groups,
824
                            cdm_occurrence_field_name_label($field),
825
                            array(
826
                                array(
827
                                    '#markup' => '<div class="sequence-length">' . $value->length . ' ' . t('pb') . '</div><div>' . wordwrap($value->string, 70, '</br>', TRUE) . '</div>',
828
                                    '#wrapper_attributes' => array('class' => 'dna-sequence')
829
                                )
830
                            ),
831
                            5);
832
                    }
833
                    break;
834

    
835
                case 'dnaSample': // FIXME 3.3 implement
836
                    break;
837
                case 'singleReads': // FIXME 3.3 implement
838
                    break;
839
                case 'contigFile': // FIXME 3.3 implement - Media
840
                    break;
841
                case 'pherograms': // FIXME 3.3 implement - Media
842
                    break;
843
                case 'haplotype': // FIXME 3.3 implement
844
                    break;
845
                case 'dateSequenced': // FIXME 3.3 now in SingelRead
846
                    @_description_list_group_add($groups, t('Sequencing date'), timePeriodToString($value), NULL, 6);
847
                    break;
848

    
849
                case 'barcode': // boolean
850
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value ? 'Yes' : 'No', NULL, 7);
851
                    break;
852
                case 'barcodeSequencePart': // FIXME 3.3 implement, compose sequence
853
                    break;
854

    
855
                case 'citation':
856
                    @_description_list_group_add($groups,
857
                        cdm_occurrence_field_name_label($field),
858
                        cdm_reference_markup($value, $sequence->microReference),
859
                        NULL,
860
                        8
861
                    );
862
                    break;
863

    
864
                case 'publishedIn':
865
                    @_description_list_group_add($groups,
866
                        cdm_occurrence_field_name_label($field),
867
                        theme('cdm_reference', array('reference' => $value)),
868
                        NULL,
869
                        7
870
                    );
871
                    break;
872

    
873
                case 'rights':
874
                    array_merge($groups, cdm_rights_as_dl_groups($value));
875
                    break;
876

    
877
                case 'annotations':
878
                    $dd_elements = array();
879
                    foreach ($value as $annotation) {
880
                        // TODO respect annotation type filter settings
881
                        $dd_elements[] = $annotation->text;
882
                    }
883
                    @_description_list_group_add($groups, t('Notes'), $dd_elements, NULL, 9);
884
                    break;
885

    
886
                case 'markers':
887
                    $dd_elements = array();
888
                    foreach ($value as $marker) {
889
                        $dd_elements[] = compose_cdm_marker($marker);
890
                    }
891
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements, NULL, 10);
892
                    break;
893

    
894
                case 'chromatograms':
895
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field),
896
                        array(
897
                            '#markup' => compose_cdm_media_gallery(array('medialist' => $value)),
898
                        ),
899
                        NULL,
900
                        11);
901
                    break;
902

    
903
                default:
904
                    if (is_object($value) || is_array($value)) {
905
                        drupal_set_message("Unhandled type in compose_cdm_sequence() for field " . $field, "warning");
906
                    } else {
907
                        if (!is_array($value) && strpos($value, 'http:') !== false ){
908
                            //make links for urls
909
                            $value = l($value, $value);
910
                            $value = markup_to_render_array($value);
911
                        }
912

    
913
                       _description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value, NULL, 20);
914
                    }
915
            }
916
        }
917
    }
918

    
919
    // template_preprocess_description_list() is not worting by weight so we do it right here
920
    uasort($groups, 'element_sort');
921
    if ($isSpecimenPage) {
922
        $sequence_elements = array(
923
            '#title' => $sequence->dnaMarker,
924
            '#theme' => 'description_list',
925
            '#groups' => $groups
926
        );
927
    } else{
928
        $sequence_elements = array(
929
            '#title' => $sequence->dnaMarker -> titleCache,
930
            '#theme' => 'description_list',
931
            '#groups' => $groups
932
        );
933
    }
934

    
935
    return $sequence_elements;
936
}
937

    
938
/**
939
 * Creates render array items for FieldUnitDTO or DerivedUnitDTO.
940
 *
941
 * @param array $root_unit_dtos
942
 *     list of SpecimenOrObservationDTOs
943
 * @return array
944
 *    An array which can be used in render arrays to be passed to the
945
 * theme_table() and theme_list().
946
 */
947
function specimen_render_array_items(array $root_unit_dtos){
948

    
949
  $render_array_items = array();
950
  $items = array();
951

    
952
  //we need one more item to contain the items of one level (fieldunit, derivate data etc.)
953
  foreach ($root_unit_dtos as &$sob_dto) {
954
    $items['data'] = $sob_dto->label;
955
    $specimen = compose_cdm_specimen_or_observation_tree_entry($sob_dto);
956
    $children = array();
957
    $child = array();
958
    $child['data'] =$specimen;
959
    // $children[] = create_specimen_array($specimenOrObservation->derivatives);
960
    if (isset($sob_dto->derivatives) && sizeof($sob_dto->derivatives) > 0){
961
      usort($sob_dto->derivatives, 'compare_specimen_or_observation_dtos');
962
      $child['children']= specimen_render_array_items($sob_dto->derivatives);
963
    }
964
    $children[]=$child;
965
    $items['children'] = $children;
966
    $render_array_items[] = $items;
967
  }
968
  return $render_array_items;
969
}
970

    
971
/**
972
 * Composes a compressed derivate table showing all derivatives which
973
 * stem from a common gathering event.
974
 *
975
 * @param $root_unit_uuids array
976
 *  An array of uuids for cdm root units of the derivation graphs.
977
 *
978
 * @return array
979
 *  A drupal render array for a table
980
 *
981
 * @see CDM_SPECIMEN_LIST_VIEW_MODE_OPTION_DERIVATE_TABLE
982
 *
983
 * @ingroup compose
984
 */
985

    
986
function compose_compressed_specimen_derivate_table($root_unit_uuids) {
987

    
988
  // prepare font icons
989
  $expand_icon = font_awesome_icon_markup(
990
    'fa-plus-square-o',
991
    array(
992
      'alt' => 'Show details',
993
      'class' => array('expand_icon')
994
    )
995
  );
996
  $collapse_icon = font_awesome_icon_markup(
997
    'fa-minus-square-o',
998
    array(
999
      'alt' => 'Show details',
1000
      'class' => array('collapse_icon')
1001
    )
1002
  );
1003
  $detail_image_icon = '<img title="Detail Image" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/detail_image_derivate-16x16-32.png' . '"/>';
1004
  $checked_box_icon = '<img src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/step_done.gif' . '"/>';
1005
  $sequence_icon = '<img title="Molecular Data" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/sequence_derivate-16x16-32.png' . '"/>';
1006
  $character_data_icon = '<img title="Character Data" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/character_data_derivate-16x16-32.png' . '"/>';
1007

    
1008
  $rowcount = 0;
1009
  $rows = array();
1010

    
1011
  foreach ($root_unit_uuids as $root_unit_uuid) {
1012

    
1013
    //get derivate hierarchy for the FieldUnit
1014
    $sob_dto = cdm_ws_get(CDM_WS_PORTAL_OCCURRENCE_AS_DTO, array($root_unit_uuid));
1015
    if ($sob_dto) {
1016
      //summary row
1017
      if($sob_dto->class == "FieldUnitDTO"){
1018

    
1019
        $rows[] = array(
1020
          'id' => 'derivate_summary' . $rowcount, // summary row id
1021
          'class' => array('summary_row'),
1022
          'data' => array(
1023
            array(
1024
              'data' => $expand_icon . $collapse_icon,
1025
              'class' => array('summary_row_cell', 'summary_row_icon', 'expand_column')
1026
            ),
1027
            array(
1028
              'data' => $sob_dto->country,
1029
              'class' => array('summary_row_cell')
1030
            ),
1031
            array(
1032
              'data' => partialToDate($sob_dto->date),
1033
              'class' => array('summary_row_cell')
1034
            ),
1035
            array(
1036
              'data' => $sob_dto->collectingString,
1037
              'class' => array('summary_row_cell')
1038
            ),
1039
            @array(
1040
              'data' => $sob_dto->collectionStatistics,
1041
              'class' => array('summary_row_cell')
1042
            ),
1043
            array(
1044
              'data' => $sob_dto->hasType ? $checked_box_icon : "",
1045
              'class' => array('summary_row_cell', 'summary_row_icon')
1046
            ),
1047
            array(
1048
              'data' => $sob_dto->hasSpecimenScan ? $checked_box_icon : "",
1049
              'class' => array('summary_row_cell', 'summary_row_icon')
1050
            ),
1051
            array(
1052
              'data' => ($sob_dto->hasDna ? $sequence_icon : "") . " "
1053
                . ($sob_dto->hasDetailImage ? $detail_image_icon : "") . " "
1054
                . ($sob_dto->hasCharacterData ? $character_data_icon : ""),
1055
              'class' => array('summary_row_cell', 'summary_row_icon')
1056
            )
1057
          )
1058
        );
1059
      } else {
1060
        $rows[] = array(
1061
          'id' => 'derivate_summary' . $rowcount, // summary row id
1062
          'class' => array('summary_row'),
1063
          'data' => array(
1064
            array(
1065
              'data' => $expand_icon . $collapse_icon,
1066
              'class' => array('summary_row_cell', 'summary_row_icon', 'expand_column')
1067
            ),
1068
            array(
1069
              'data' => $sob_dto->label,
1070
              'class' => array('summary_row_cell'),
1071
              'colspan' => 5
1072
            ),
1073
            array(
1074
              'data' => $sob_dto->hasSpecimenScan ? $checked_box_icon : "",
1075
              'class' => array('summary_row_cell', 'summary_row_icon')
1076
            ),
1077
            array(
1078
              'data' => ($sob_dto->hasDna ? $sequence_icon : "") . " "
1079
                . ($sob_dto->hasDetailImage ? $detail_image_icon : "") . " "
1080
                . ($sob_dto->hasCharacterData ? $character_data_icon : ""),
1081
              'class' => array('summary_row_cell', 'summary_row_icon')
1082
            )
1083
          )
1084
        );
1085
      }
1086

    
1087
      //assemble field unit details
1088
      $detail_html = "";
1089
      if ($sob_dto->summaryLabel) {
1090
        $detail_html .= create_label("Citation") . $sob_dto->summaryLabel . "<br>";
1091
      }
1092
      //assemble specimen details
1093
      if ($sob_dto->derivatives) {
1094
        $derivatives_orderd = [];
1095
        foreach ($sob_dto->derivatives as $derivative_dto) {
1096
          $derivatives_orderd[$derivative_dto->specimenShortTitle] = $derivative_dto;
1097
        }
1098
        ksort($derivatives_orderd);
1099
        foreach ($derivatives_orderd as $derivative_dto) {
1100
          $detail_html .= "<br>";
1101
          $detail_html .= render_cdm_specimenDTO_page($derivative_dto);
1102
        }
1103
      }
1104
      $detail_html .= "<br>";
1105
      //detail row resp. one BIG detail cell
1106
      $rows[] = array(
1107
        'data' => array(
1108
          array(
1109
            'data' => "", //empty first column
1110
            'class' => array('expand_column')
1111
          ),
1112
          array(
1113
            'data' => $detail_html,
1114
            'colspan' => 7,
1115
          ),
1116
        ),
1117
        'id' => 'derivate_details' . $rowcount,//details row ID
1118
        'class' => array('detail_row'),
1119
      );
1120
      $rowcount++;
1121
    }
1122
  }
1123

    
1124
  $tableId = "derivate_hierarchy_table";
1125
  $derivateHierarchyTable = array(
1126
    "#theme" => "table",
1127
    "#weight" => 2,
1128
    "#header" => array(
1129
      array(
1130
        'data' => "",
1131
        'class' => array('expand_column')
1132
      ),
1133
      "Country", "Date", "Collector + collecting number", "Herbaria", "Type", "Scan", "Derivatives"),
1134
    "#rows" => $rows,
1135
    "#attributes" => array(
1136
      "id" => $tableId,
1137
      "border" => 2
1138
    )
1139
  );
1140

    
1141
  //add toggle functionality to derivate hierarchy table
1142
  drupal_add_js_rowToggle("#" . $tableId);
1143

    
1144
  return $derivateHierarchyTable;
1145
}
1146

    
1147

    
1148
/**
1149
 * Renders a FieldUnitDTO or DerivedUnitDTO
1150
 *
1151
 * @param object $specimen_or_observation_dto
1152
 *   A FieldUnitDTO or DerivedUnitDTO object
1153
 *   the render array for
1154
 *
1155
 * @return string
1156
 *   the supplied render array $derivatives to which the composition of the
1157
 *   supplied
1158
 *   $specimenOrObservation has been added to
1159
 *
1160
 * @ingroup compose
1161
 *
1162
 * @throws \Exception
1163
 */
1164
function compose_cdm_specimen_or_observation_tree_entry($specimen_or_observation_dto) {
1165
  $exclude_occurrence_fields = &drupal_static(__FUNCTION__);
1166
  if (!isset($exclude_occurrence_fields)) {
1167
    $exclude_occurrence_fields = [
1168
      'uuid',
1169
      'titleCache',
1170
      'protectedTitleCache',
1171
      'label',
1172
      'class',
1173
      'type',
1174
      'types',
1175
      'taxonRelatedDerivedUnits',
1176
      'collectionCode',
1177
      'derivatives',
1178
      'derivateDataDTO',
1179
      'summaryLabel',
1180
      'derivationTreeSummary',
1181
      'specimenIdentifier', // combination like  collection code + accession number
1182
      'mostSignificantIdentifier',
1183
      // -----
1184
      // needed later on?
1185
      'hasDetailImage',
1186
      'hasType',
1187
      'hasSpecimenScan',
1188
      'collectionStatistics',
1189
      'collectingString'
1190
      // ----
1191
    ];
1192
  }
1193

    
1194
  if (is_object($specimen_or_observation_dto)) {
1195

    
1196
    if(isset($specimen_or_observation_dto->recordBase)){
1197
        $type_label = $specimen_or_observation_dto->recordBase->representation_L10n;
1198
    }
1199
      RenderHints::setFootnoteListKey($type_label . '-' . $specimen_or_observation_dto->uuid);
1200

    
1201
      // collect typeStatus as label
1202
      if (isset($specimen_or_observation_dto->specimenTypeDesignations)) {
1203
          $type_status = array();
1204
          foreach ($specimen_or_observation_dto->specimenTypeDesignations as $typeDesignation) {
1205
              if (isset($typeDesignation->typeStatus_L10n)) {
1206
                  $type_status[] = $typeDesignation->typeStatus_L10n;
1207
              }
1208
          }
1209
          if (count($type_status) > 0) {
1210
              $type_label = implode(', ', $type_status);
1211
        }
1212
      }
1213

    
1214
      if (isset($typeDesignation->typifiedNames)){
1215
          $title = $type_label . ' for: ' . $typeDesignation->typifiedNames;
1216
      }else{
1217
          $title = $type_label;
1218
      }
1219

    
1220
        $groups = array();
1221
        $children_items = array();
1222
        // --- add initialized fields
1223
        foreach (get_object_vars($specimen_or_observation_dto) as $field => $value) {
1224
            $child_item = array();
1225

    
1226
            if (!in_array($field, $exclude_occurrence_fields) && $value ) {
1227
              switch ($field) {
1228

    
1229
                /* ---- SpecimenOrObservationBase --- */
1230
                case 'recordBase':
1231
                  $label = $value->representation_L10n;
1232
                  if($label == 'Dna Sample'){
1233
                    $label = 'DNA Sample';
1234
                  }
1235
                  _description_list_group_add($groups, cdm_occurrence_field_name_label($field), $label,NULL, -10);
1236
                break;
1237
                case 'derivationEvent':
1238
                    @_description_list_group_add($groups, 'Gathering type:', ucfirst($value->eventType), NULL, 1);
1239
                    break;
1240
                case 'accessionNumber':
1241
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value, NULL, 0);
1242
                    break;
1243
                case 'preferredStableUri':
1244
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), array(array('#markup' => cdm_external_uri($value, false))));
1245
                    break;
1246
                case 'characterData':
1247
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), array(array('#markup' => icon_link(path_to_specimen($specimen_or_observation_dto->uuid), '', FALSE), false)));
1248
                  break;
1249
                case 'specimenTypeDesignations':
1250
                    @_description_list_group_add(
1251
                        $groups,
1252
                        cdm_occurrence_field_name_label($field),
1253
                        array(
1254
                            '#markup' => render_specimen_typedesignation_dto($value),
1255
                        )
1256
                    );
1257
                    break;
1258

    
1259
                case 'listOfMedia':
1260
                    $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
1261

    
1262
                    $captionElements = array(
1263
                        'title',
1264
                        '#uri' => t('open media'),
1265
                    );
1266
                    $gallery_html = compose_cdm_media_gallery(array(
1267
                        'mediaList' => $value,
1268
                        'galleryName' => $specimen_or_observation_dto->uuid,
1269
                        'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
1270
                        'cols' => $gallery_settings['cdm_dataportal_media_cols'],
1271
                        'maxRows' => isset($gallery_settings['cdm_dataportal_media_maxRows']) ? isset($gallery_settings['cdm_dataportal_media_maxRows']) : null,
1272
                        'captionElements' => $captionElements,
1273
                        'mediaLinkType' => 'LIGHTBOX',
1274
                        'alternativeMediaUri' => NULL,
1275
                        'galleryLinkUri' => NULL,
1276
                        'showCaption' => true
1277
                    ));
1278

    
1279
                  //FIXME re-enable: // @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $gallery_html);
1280
                  break;
1281

    
1282
                  case 'sex':
1283
                  case 'lifeStage':
1284
                  case 'kindOfUnit':
1285
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), cdm_term_representation($value));
1286
                    break;
1287

    
1288
                  case 'definition':
1289
                    // TODO
1290
                    break;
1291

    
1292
                  /* ---- DerivedUnitBase --- */
1293
                  case 'collection':
1294
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), array(
1295
                      array('#markup' => render_collection_dto($value))
1296
                    ));
1297
                    break;
1298

    
1299
                  /* ---- Specimen --- */
1300
                  case 'sequences':
1301
                      $dd_elements = array();
1302
                      foreach ($value as $sequence) {
1303
                          $dd_elements[] = compose_cdm_sequence($sequence, true);
1304
                          $dd_elements[] = "";
1305
                      }
1306
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label($field), $dd_elements,'', 100);
1307
                      break;
1308

    
1309
                  // TODO preservation
1310
                  case 'storedUnder':
1311
                    $taxon_name = cdm_ws_get(CDM_WS_PORTAL_NAME, array($value->uuid));
1312
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label('storedUnder'), array(
1313
                      array('#markup' => render_taxon_or_name($taxon_name, path_to_name($taxon_name->uuid)))
1314
                    ));
1315
                  break;
1316

    
1317
                  /* ---- FieldObservation --- */
1318
                  case 'gatheringEvent':
1319

    
1320
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label('collector'), $value->collector);
1321
                      @_description_list_group_add($groups, t('Gathering date'), timePeriodToString($value->timeperiod));
1322
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label('description'), $value->description);
1323
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label('locality'), $value->locality, '', 10);
1324
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label('country'), $value->country);
1325
                      @_description_list_group_add($groups, cdm_occurrence_field_name_label('collectingMethod'), $value->collectingMethod);
1326
                      if (isset($value->absoluteElevation)) {
1327
                          $min_max_markup = statistical_values_from_gathering_event($value, 'absoluteElevation');
1328
                          @_description_list_group_add($groups, cdm_occurrence_field_name_label('absoluteElevation'), $min_max_markup);
1329
                      }
1330
                      if (isset($value->distanceToGround) && $value->distanceToGround >0) {
1331
                          $min_max_markup = statistical_values_from_gathering_event($value, 'distanceToGround');
1332
                          @_description_list_group_add($groups, cdm_occurrence_field_name_label('distanceToGround'), $min_max_markup);
1333
                      }
1334
                      if (isset($value->distanceToWaterSurface) && $value->distanceToWaterSurface > 0) {
1335
                          $min_max_markup = statistical_values_from_gathering_event($value, 'distanceToWaterSurface');
1336
                          @_description_list_group_add($groups, cdm_occurrence_field_name_label('distanceToWaterSurface'), $min_max_markup);
1337
                      }
1338

    
1339
                      if (isset($value->collectingAreas)) {
1340
                          $area_representations = array();
1341
                          foreach ($value->collectingAreas as $area) {
1342
                             // $area_representations[] = l($area->representation_L10n, path_to_named_area($area->uuid));
1343
                              $area_representations[] = $area;
1344
                          }
1345
                          if (!empty($area_representations))
1346
                              @_description_list_group_add($groups, cdm_occurrence_field_name_label('collectingAreas'),
1347
                                  array(
1348
                                      array('#markup' => implode(', ', $area_representations))
1349
                                  )
1350
                              );
1351
                      }
1352
                      if (isset($value->exactLocation)  ) {
1353
                        @_description_list_group_add($groups, cdm_occurrence_field_name_label('exactLocation'),
1354
                          array(
1355
                            array('#markup' => render_point($value->exactLocation)),
1356
                          ),'',11
1357
                        );
1358
                      }
1359
                      break;
1360

    
1361
                  /* ---- DerivationEvent --- */
1362
                  case 'derivationEvents':
1363
                    //@_description_list_group_add($groups, t('Association type'), $value->description);
1364
                    break;
1365
                  case 'determinedNames':
1366
                    $dd_elements = array();
1367
                    foreach ($value as $name) {
1368
                      $taxon_name = cdm_ws_get(CDM_WS_PORTAL_NAME, $name->uuid);
1369
                      $dd_elements[] = render_taxon_or_name($taxon_name, url(path_to_name($taxon_name->uuid)));
1370
                    }
1371
                    @_description_list_group_add($groups, cdm_occurrence_field_name_label("Identification(s)"), $dd_elements,'', 100);
1372
                    break;
1373

    
1374
                  default:
1375
                    if (is_object($value) || is_array($value)) {
1376
                        drupal_set_message("Unhandled type in compose_cdm_specimen_or_observation_tree_entry() for field " . $field, "warning");
1377
                    } else {
1378
                      _description_list_group_add($groups, cdm_occurrence_field_name_label($field), $value);
1379
                    }
1380
              }
1381
            }
1382
        } // END of loop over $derivedUnitFacade fields
1383

    
1384
        // template_preprocess_description_list() is not worting by weight so we do it right here
1385
        uasort($groups, 'element_sort');
1386
        $occurrence_elements = array(
1387
           // '#title' => $title,
1388
            '#theme' => 'description_list',
1389
            '#groups' => $groups,
1390
            '#attributes' => array('class' => html_class_attribute_ref($specimen_or_observation_dto)),
1391
        );
1392
        $output = drupal_render($occurrence_elements);
1393
        if (isset($gallery_html)){
1394
            $output .= $gallery_html;
1395
        }
1396
        $pathToSpecimen = path_to_specimen($specimen_or_observation_dto->uuid);
1397
        $output .=  l("Detail page", $pathToSpecimen);
1398
    } // END of $specimenOrObservation exists
1399

    
1400
    return $output;
1401
}
1402

    
1403
function compose_table_of_blast_result(array $data){
1404
   // get icon images
1405
  $expand_icon = font_awesome_icon_markup(
1406
      'fa-plus-square-o',
1407
      array(
1408
          'alt' => 'Show details',
1409
          'class' => array('expand_icon')
1410
      )
1411
  );
1412
  $collapse_icon = font_awesome_icon_markup(
1413
      'fa-minus-square-o',
1414
      array(
1415
          'alt' => 'Show details',
1416
          'class' => array('collapse_icon')
1417
      )
1418
  );
1419
  //$detail_image_icon = '<img title="Detail Image" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/detail_image_derivate-16x16-32.png' . '"/>';
1420
    $rowcount = 0;
1421
    $rows = array();
1422

    
1423
    foreach ($data as $row_data){
1424
        $pathToSpecimen = path_to_specimen_by_accession_number($row_data['id']);
1425
        $specimenPageLink = l($row_data['id'], $pathToSpecimen);
1426
        $ncbiLink = l($row_data['id'], 'https://www.ncbi.nlm.nih.gov/nuccore/'.$row_data['id'].'?report=graph');
1427
        $rows[] =  array(
1428
            'data' => array(
1429
                array(
1430
                    'data' => $expand_icon . $collapse_icon,
1431
                    'class' => array('summary_row_cell', 'summary_row_icon', 'expand_column')
1432
                ),
1433
                array(
1434
                    'data' => $row_data['def'],
1435
                ),
1436
                array(
1437
                    'data' => $specimenPageLink,
1438
                ),
1439
                array(
1440
                    'data' => $row_data['hsp_align_length'],
1441
                ),
1442
                array(
1443
                   'data' => $ncbiLink,
1444
                ),
1445
                array(
1446
                    'data' => $row_data['hsp_identity']/$row_data['hsp_align_length']*100,
1447
                )
1448
            ),
1449
            'id' => 'blast_summary' . $rowcount, // summary row id
1450
            'class' => array('summary_row'),
1451
        );
1452
        $detail_html = "";
1453

    
1454
        $detail_html .= create_label("Details") . $row_data["hsp_align_length"] . "<br>";
1455

    
1456

    
1457
        $detail_html .= "<br>";
1458
        $detail_html .= $row_data["hsp_midline"];
1459

    
1460
        //$detail_html .= "<br>";
1461

    
1462
        $rows[] = array(
1463
            'data' => array(
1464
                array(
1465
                    'data' => "", //empty first column
1466
                    'class' => array('expand_column')
1467
                ),
1468
                array(
1469
                    'data' => $detail_html,
1470
                    'colspan' => 5,
1471
                ),
1472
            ),
1473
            'id' => 'blast_detail' . $rowcount,//details row ID
1474
            'class' => array('detail_row'),
1475
        );
1476
        $rowcount++;
1477
    }
1478

    
1479
    $tableId = "blast_result_table";
1480
    $blast_result_table = array(
1481
        "#theme" => "table",
1482
        "#weight" => 2,
1483
        "#header" => array(
1484
            array(
1485
                'data' => "",
1486
                'class' => array('expand_column')
1487
            ),
1488
                        "Name", "Accession Number", "Align Length", "NCBI", "% Identity"),
1489
        "#rows" => $rows,
1490
        "#attributes" => array(
1491
            "id" => $tableId,
1492
            "border" => 2
1493
        )
1494
    );
1495

    
1496
    drupal_add_js_rowToggle("#".$tableId);
1497

    
1498
    $render_array[$tableId] = $blast_result_table;
1499
    $out = drupal_render($render_array);
1500
   //$blast_result_page-> content = drupal_render($render_array);
1501
   return $out;
1502
}
1503

    
1504

    
1505
/**
1506
 * Composes a BOTTOM-UP-SPECIMEN-TABLE for the view mode
1507
 * CDM_SPECIMEN_LIST_VIEW_MODE_OPTION_DERIVATE_TREE
1508
 *
1509
 * @param $specimensOrObservations
1510
 * @return array
1511
 *  A drupal render array with the following keys:
1512
 *   - 'specimen_list'
1513
 *   - 'pager'
1514
 *
1515
 * @ingroup Compose
1516
 * @see CDM_SPECIMEN_LIST_VIEW_MODE_OPTION_DERIVATE_TREE
1517
 */
1518
function compose_specimens_table_bottom_up($specimensOrObservations)
1519
{
1520

    
1521
  // --- generate the specimen list as table
1522
  $specimen_table = array(
1523
    '#theme' => 'table',
1524
    '#weight' => 2,
1525
    // prefix attributes and rows with '#' to let it pass toF the theme function,
1526
    // otherwise it is handled as child render array
1527
    '#attributes' => array('class' => 'specimens '),
1528
    '#rows' => array(),
1529
  );
1530

    
1531
  if ($specimensOrObservations) {
1532

    
1533
    foreach ($specimensOrObservations as $specimenOrObservation) {
1534

    
1535
      $mediaList = array();
1536
      if (is_array($specimenOrObservation->_fieldObjectMedia)) {
1537
        $mediaList = array_merge($mediaList, $specimenOrObservation->_fieldObjectMedia);
1538
      }
1539
      if (is_array($specimenOrObservation->_derivedUnitMedia)) {
1540
        $mediaList = array_merge($mediaList, $specimenOrObservation->_derivedUnitMedia);
1541
      }
1542

    
1543

    
1544
      // typelabel will contain the typeStatus
1545
      $type_label = '';
1546
      $typeDesignationPager = cdm_ws_get(CDM_WS_OCCURRENCE . '/$0/specimenTypeDesignations', $specimenOrObservation->uuid);
1547
      if (isset($typeDesignationPager) and isset($typeDesignationPager->records)) {
1548
        $type_status = array();
1549
        foreach ($typeDesignationPager->records as $typeDesignation) {
1550
          if (isset($typeDesignation->typeStatus->representation_L10n)) {
1551
            $type_status[] = $typeDesignation->typeStatus->representation_L10n;
1552
          }
1553
        }
1554
        $type_label = implode(', ', $type_status);
1555
        if ($type_label) {
1556
          $type_label = ucfirst($type_label) . ': ';
1557
        }
1558
      }
1559

    
1560
      // --- Specimen entry as dynamic label:
1561
      //     -> Dynabox for the specimenOrObservation
1562
      $gallery_name = $specimenOrObservation->uuid;
1563

    
1564
      $derived_unit_ws_request = cdm_compose_ws_url(CDM_WS_OCCURRENCE, array($specimenOrObservation->uuid));
1565
      // --- Render associated media.
1566
      $gallery_html = '';
1567
      if (count($mediaList) > 0) {
1568
        $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
1569
        $captionElements = array(
1570
          '#uri' => t('open media'),
1571
        );
1572

    
1573
        $gallery_html = compose_cdm_media_gallery(array(
1574
          'mediaList' => $mediaList,
1575
          'galleryName' => $gallery_name,
1576
          'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
1577
          'cols' => $gallery_settings['cdm_dataportal_media_cols'],
1578
          'maxRows' => isset($gallery_settings['cdm_dataportal_media_maxRows']) ? isset($gallery_settings['cdm_dataportal_media_maxRows']) : null,
1579
          'captionElements' => $captionElements,
1580
          'mediaLinkType' => 'LIGHTBOX',
1581
          'alternativeMediaUri' => NULL,
1582
          'galleryLinkUri' => NULL,
1583
        ));
1584
      }
1585
      //here we should use the data we already have
1586
      $label_html = cdm_dynabox(
1587
        $specimenOrObservation->uuid,
1588
        $type_label . $specimenOrObservation->titleCache,
1589
        $derived_unit_ws_request,
1590
        'cdm_specimen_or_observation',
1591
        'Click for details',
1592
        array('div', 'div'),
1593
        array(),
1594
        null, // $content_element_selector
1595
        'function(){ jQuery(\'#media_gallery_' . $gallery_name . '\').hide(); }', // open_callback
1596
        'function(){ jQuery(\'#media_gallery_' . $gallery_name . '\').show(); }' // close_callback
1597
      );
1598

    
1599
      // --- Render associated media.
1600
      $gallery_html = '';
1601
      if (count($mediaList) > 0) {
1602
        $gallery_settings = getGallerySettings(CDM_DATAPORTAL_SPECIMEN_GALLERY_NAME);
1603
        $captionElements = array(
1604
          '#uri' => t('open media'),
1605
        );
1606

    
1607
        $gallery_html = compose_cdm_media_gallery(array(
1608
          'mediaList' => $mediaList,
1609
          'galleryName' => $gallery_name,
1610
          'maxExtend' => $gallery_settings['cdm_dataportal_media_maxextend'],
1611
          'cols' => $gallery_settings['cdm_dataportal_media_cols'],
1612
          'maxRows' => isset($gallery_settings['cdm_dataportal_media_maxRows']) ? isset($gallery_settings['cdm_dataportal_media_maxRows']) : null,
1613
          'captionElements' => $captionElements,
1614
          'mediaLinkType' => 'LIGHTBOX',
1615
          'alternativeMediaUri' => NULL,
1616
          'galleryLinkUri' => NULL,
1617
        ));
1618
      }
1619

    
1620
      $specimen_table['#rows'][] = array(
1621
        // An array of table rows. Every row is an array of cells, or an associative array
1622
        'data' => array(
1623
          // Each cell can be either a string or an associative array
1624
          $label_html . $gallery_html
1625
        ),
1626
        'class' => array(
1627
          'descriptionElement',
1628
          'descriptionElement_IndividualsAssociation'
1629
        ),
1630
      );
1631
    }
1632
  }
1633

    
1634
  return $specimen_table;
1635
}
1636

    
1637

    
1638
/**
1639
 * Orders occurrences by date but types should be on top of the list.
1640
 *
1641
 * @param array $specimens_or_observations
1642
 *  Array of SpecimenOrObservation or fieldUnitDTOs
1643
 *
1644
 * @return array
1645
 */
1646
function order_specimens_or_observations_by_date_and_type($specimens_or_observations)
1647
{
1648
  $type_specimens = array();
1649
  $other_occurrences = array();
1650
  if(is_array($specimens_or_observations)){
1651
    foreach ($specimens_or_observations as &$occurrence) {
1652
      $typeDesignationsPager = cdm_ws_get(CDM_WS_OCCURRENCE . '/$0/specimenTypeDesignations', $occurrence->uuid);
1653
      if (isset($typeDesignationsPager->count) && $typeDesignationsPager->count > 0) {
1654
        $type_specimens[] = $occurrence;
1655
      } else {
1656
        $other_occurrences[] = $occurrence;
1657
      }
1658
    }
1659
  }
1660
  $specimens_or_observations = array_merge($type_specimens, $other_occurrences);
1661
  return $specimens_or_observations;
1662
}
1663

    
1664
/**
1665
 * Orders FieldUnitDTOs by date but types should be on top of the list.
1666
 *
1667
 * Delegates internally to order_specimens_or_observations_by_date_and_type()
1668
 *
1669
 * @param array $fieldUnitDTOs
1670
 *
1671
 * @return array
1672
 */
1673
function order_fieldUnitDtos_by_date_and_type($fieldUnitDTOs)
1674
{
1675
  $units_with_types = [];
1676
  $units_no_types = [];
1677

    
1678
  foreach($fieldUnitDTOs as $dto){
1679
    if(isset($dto->specimenTypeDesignations[0])){
1680
      $units_with_types[] = $dto;
1681
    } else {
1682
      $units_no_types[] = $dto;
1683
    }
1684
  }
1685
  usort($units_with_types, 'compare_specimen_or_observation_dtos_by_date');
1686
  usort($units_no_types, 'compare_specimen_or_observation_dtos_by_date');
1687

    
1688
  return array_merge($units_with_types, $units_no_types);
1689
}
1690

    
1691
/**
1692
 * @param $specimen
1693
 *
1694
 * @return array
1695
 */
1696
function specimen_id_and_collection_for($specimen) {
1697
  $specimenID = '';
1698
  $collection = NULL;
1699
  if (!($specimen->class == 'FieldUnit')) {
1700
    if ($specimen->collection) {
1701
      if ($specimen->collection->code) {
1702
        $collection = $specimen->collection->code;
1703
      }
1704
      elseif ($specimen->collection->name) {
1705
        $collection = $specimen->collection->name;
1706
      }
1707
    }
1708
    if ($specimen->accessionNumber) {
1709
      $specimenID = $specimen->accessionNumber;
1710
    }
1711
    elseif ($specimen->barcode) {
1712
      $specimenID = $specimen->barcode;
1713
    }
1714
    elseif ($specimen->catalogNumber) {
1715
      $specimenID = $specimen->catalogNumber;
1716
    }
1717
    elseif ($specimen->titleCache) {
1718
      $specimenID = $specimen->titleCache;
1719
    }
1720
    if (!isset($specimenID) and !isset($collection)) {
1721
      $specimenID = $specimen->uuid;
1722
    }
1723
  }
1724
  else {
1725
    if ($specimen->titleCache) {
1726
      $specimenID = $specimen->titleCache;
1727
    }
1728
    if (!isset($specimenID) and !isset($collection)) {
1729
      $specimenID = $specimen->uuid;
1730
    }
1731
  }
1732
  return [$specimenID, $collection];
1733
}
1734

    
1735
/**
1736
 * Renders a cdm collection entity as html markup.
1737
 *
1738
 * institute and super-collections
1739
 *
1740
 * @param $collection_dto
1741
 *   The CollectionDTO
1742

    
1743
 * @return string
1744
 *  The markup for the collection,
1745
 */
1746
function render_collection_dto($collection_dto){
1747
  return render_collection($collection_dto);
1748
}
1749

    
1750
/**
1751
 * Renders a cdm collection entity as html markup.
1752
 *
1753
 * institute and super-collections
1754
 *
1755
 * @param $collection
1756
 *   The CDM Collection entity or CollectionDTO
1757
 * @param bool $do_link
1758
 *   Append a link to the collection page as clickable icon (default = true).
1759
 *
1760
 * @return string
1761
 *  The markup for the collection,
1762
 */
1763
function render_collection($collection, $do_link = false /* to be made true, see #9250 */ ){
1764
  if(!is_object($collection)){
1765
    return '';
1766
  }
1767
  $is_dto = $collection->class == 'CollectionDTO';
1768
  $collection_str_list = [];
1769
  $super_collection = $collection;
1770
  while($super_collection){
1771
    $collection_str = $is_dto ? $super_collection->label : $super_collection->titleCache;
1772
    if(
1773
    ($is_dto && $super_collection->institute) ||
1774
    (isset_not_empty($super_collection->institute) && isset_not_empty($super_collection->institute->titleCache))){
1775
      $collection_str .= ' at ' . ($is_dto ? $super_collection->institute : $super_collection->institute->titleCache);
1776
    }
1777
    $collection_str_list[] = $collection_str;
1778
    if(isset($super_collection->superCollection)){
1779
      $super_collection = $super_collection->superCollection;
1780
    } else {
1781
      $super_collection = null;
1782
    }
1783
  }
1784
  $markup = join(' in ', $collection_str_list);
1785
  if($markup){
1786
    if($do_link){
1787
      $markup .= ' ' . cdm_internal_link(path_to_collection($collection->uuid));
1788
    }
1789
    $markup = '<span class="' . html_class_attribute_ref($collection) . '">' . $markup . '</span>';
1790
  }
1791
  return $markup;
1792
}
1793

    
1794
/**
1795
 * Compares two SpecimenTypeDesignations by identifier and label
1796
 *
1797
 * @param object $a
1798
 *   A SpecimenOrObservationDTO.
1799
 * @param object $b
1800
 *   The SpecimenOrObservationDTO.
1801
 */
1802
function compare_specimen_or_observation_dtos($a, $b) {
1803
    // Sort alphabetically.
1804
    $a_text =  isset($a->specimenShortTitle) ? $a->specimenShortTitle : $a->label;
1805
    $b_text =  isset($b->specimenShortTitle) ? $b->specimenShortTitle : $b->label;
1806
    return strcasecmp($a_text, $b_text);
1807
}
1808

    
1809
/**
1810
 * Compares two SpecimenTypeDesignations by date or label
1811
 *
1812
 * @param object $a
1813
 *   A SpecimenOrObservationDTO.
1814
 * @param object $b
1815
 *   The SpecimenOrObservationDTO.
1816
 */
1817
function compare_specimen_or_observation_dtos_by_date($a, $b) {
1818
  // Sort alphabetically.
1819
  $a_text =  isset($a->date) ? $a->date : $a->label;
1820
  $b_text =  isset($b->date) ? $b->date : $b->label;
1821
  return strcasecmp($a_text, $b_text);
1822
}
(8-8/16)