Project

General

Profile

Download (24 KB) Statistics
| Branch: | Tag: | Revision:
1 2bdf5f11 Andreas Kohlbecker
<?php
2 f19f47fa Andreas Kohlbecker
/**
3
 * @file
4
 * Functions for dealing with CDM entities from the package model.common
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 2bdf5f11 Andreas Kohlbecker
 */
18
19 5b26b91a Andreas Kohlbecker
/**
20
 * @defgroup compose Compose functions
21
 * @{
22
 * Functions which are composing Drupal render arays
23
 *
24 31765b7b Andreas Kohlbecker
 * The cdm_dataportal module needs to compose rather complex render arrays from
25 ce29c528 Andreas Kohlbecker
 * the data returned by the CDM REST service. The compose functions are
26
 * responsible for creating the render arrays.
27 5b26b91a Andreas Kohlbecker
 *
28 ce29c528 Andreas Kohlbecker
 * All these functions are also implementations of the compose_hook()
29
 * which is used in the proxy_content() function.
30 5b26b91a Andreas Kohlbecker
 * @}
31
 */
32
33 2bdf5f11 Andreas Kohlbecker
/**
34
 * Compose an render array from a CDM Marker object.
35
 *
36
 * compose_hook() implementation
37
 *
38
 * @param object $marker
39
 *   CDM instance of type Marker
40
 * @return array
41
 *   A drupal render array
42 5b26b91a Andreas Kohlbecker
 *
43
 * @ingroup compose
44 2bdf5f11 Andreas Kohlbecker
 */
45
function compose_cdm_marker($marker) {
46
47
  $render_array = array(
48
      // ---- generic
49
      //  these entries should be common to all cdm enitiy render arrays
50
      '#theme' => 'cdm_marker', // TODO   add alternative theme funcitons: 'cdm_marker_' . marker.type.label
51 f19f47fa Andreas Kohlbecker
      '#attributes' => array('class' => html_class_attribute_ref($marker)),
52 2bdf5f11 Andreas Kohlbecker
53
      // ---- individual
54
      '#label' => $marker->markerType->representation_L10n . ': ' . (($marker->flag !== TRUE ? t('yes') : t('no'))),
55
  );
56
57
  return $render_array;
58
}
59 19e097a3 Andreas Kohlbecker
60
/**
61
 * Checks if the given $cdm_entitiy has a marker the type references by the
62
 * $marker_type_uuid and returns TRUE if a matching marker has been found.
63
 *
64 ce29c528 Andreas Kohlbecker
 * @param object $cdm_entitiy A CDM Entity
65 19e097a3 Andreas Kohlbecker
 * @param string $marker_type_uuid
66
 */
67
function cdm_entity_has_marker($cdm_entitiy, $marker_type_uuid) {
68
  if(isset($cdm_entitiy->markers[0]) && !is_uuid($marker_type_uuid)){
69
    foreach ($cdm_entitiy->markers as $marker) {
70
      if(isset($marker->markerType) && $marker->markerType->uuid == $marker_type_uuid){
71
        return TRUE;
72
      }
73
    }
74
  }
75
  return FALSE;
76 c2486c6b Andreas Kohlbecker
}
77
78
/**
79 c7c53f4e Andreas Kohlbecker
 * Sorts an array of CDM IdentifiableSource instances by 1. by the
80 ce29c528 Andreas Kohlbecker
 * author teams family names and 2. by the publication date.
81 c2486c6b Andreas Kohlbecker
 *
82 ce29c528 Andreas Kohlbecker
 * @param array $sources
83 c2486c6b Andreas Kohlbecker
 *    The array of CDM IdentifiableSource instances
84 bb93d5d1 Andreas Kohlbecker
 * @return array
85
 *  An array of drupal render arrays
86 c2486c6b Andreas Kohlbecker
 */
87 bb93d5d1 Andreas Kohlbecker
function oder_and_render_original_sources($sources){
88 c2486c6b Andreas Kohlbecker
    $sort_array = array();
89
    foreach ($sources as $source) {
90 c7c53f4e Andreas Kohlbecker
91
      $order_key = '';
92
93
      // find the familynames
94 1ce9afb7 Patric Plitzner
      if(isset($source->citation->uuid) && !isset($source->citation->authorship)){
95 c7c53f4e Andreas Kohlbecker
        $authorteam = cdm_ws_get(CDM_WS_REFERENCE_AUTHORTEAM, $source->citation->uuid);
96
97
        $persons = array();
98
        if($authorteam->class == 'Team'){
99
          if(isset($authorteam->teamMembers)){
100
            $persons = $authorteam->teamMembers;
101
          }
102
        } else {
103
          $persons[] = $authorteam;
104
        }
105
106
        foreach($persons as $person){
107
          if(!empty($person->lastname)){
108
            $order_key .= $person->lastname;
109
          } else {
110
            $order_key .= $person->titleCache;
111
          }
112
        }
113
        if(empty($order_key)){
114
          $order_key = $authorteam->titleCache;
115
        }
116
117 c2486c6b Andreas Kohlbecker
      }
118 c7c53f4e Andreas Kohlbecker
      $order_key = str_pad($order_key, 50);
119
120
      // add publication date to the key
121
      if(isset($source->citation->datePublished)){
122
        $order_key .= '_' . timePeriodAsOrderKey($source->citation->datePublished);
123
      } else {
124
        $order_key .= '_' . "0000";
125 c2486c6b Andreas Kohlbecker
      }
126 c7c53f4e Andreas Kohlbecker
127
      // padd key until unique
128 c2486c6b Andreas Kohlbecker
      while(array_key_exists($order_key, $sort_array)){
129
        $order_key .= "_";
130
      }
131 c7c53f4e Andreas Kohlbecker
132 bb93d5d1 Andreas Kohlbecker
      $sort_array[$order_key] = render_original_source($source);
133 c2486c6b Andreas Kohlbecker
    }
134
    ksort($sort_array);
135
    return array_values ($sort_array);
136 ce29c528 Andreas Kohlbecker
}
137
138 9e2aa1ff Andreas Kohlbecker
/**
139
 * Compare callback to be used in usort to sort image sources of CDM OriginalSource instances.
140
 *
141 bb93d5d1 Andreas Kohlbecker
 * TODO the compare strategy implemented in oder_and_render_original_sources() is probably better but is not taking the
142 9e2aa1ff Andreas Kohlbecker
 * originalName into account.
143
 *
144
 * @param $a
145
 * @param $b
146
 */
147
function compare_original_sources($a, $b){
148
149 7c0c59d8 Andreas Kohlbecker
  $a_string = '';
150
  if(isset($a->citation->titleCache)) {
151
    $a_string = $a->citation->titleCache;
152
  }
153 9e2aa1ff Andreas Kohlbecker
  if((isset($a->nameUsedInSource))){
154
    $a_string .= $a->nameUsedInSource->titleCache;
155
  } elseif (isset($a->originalNameString)){
156
    $a_string .= $a->originalNameString;
157
  }
158
159 7c0c59d8 Andreas Kohlbecker
  $b_string = '';
160
  if(isset($b->citation->titleCache)) {
161
    $b_string = $b->citation->titleCache;
162
  };
163 9e2aa1ff Andreas Kohlbecker
  if((isset($b->nameUsedInSource))){
164
    $b_string .= $b->nameUsedInSource->titleCache;
165
  } elseif (isset($b->originalNameString)){
166
    $b_string .= $b->originalNameString;
167
  }
168
169
  if ($a_string == $b_string) {
170
    return 0;
171
  }
172
  return ($a_string < $b_string) ? -1 : 1;
173
}
174
175
/**
176
 * Compare callback to be used in usort to sort image sources of CDM Media instances.
177
 *
178
 * @param $a
179
 * @param $b
180
 */
181 50a67433 Andreas Kohlbecker
function compare_text_data($a, $b) {
182 9e2aa1ff Andreas Kohlbecker
183
  if ($a->multilanguageText_L10n->text == $b->multilanguageText_L10n->text) {
184
    return 0;
185
  }
186
  return ($a->multilanguageText_L10n->text < $b->multilanguageText_L10n->text) ? -1 : 1;
187
}
188
189 ce29c528 Andreas Kohlbecker
  /**
190
   * Compare two different footnotes objects.
191
   *
192
   * The comparison is based on the footnote key. The one which is
193
   * displayed as footnote number.
194
   *
195
   * @param mixed $a
196
   *   Footnote object $a.
197
   * @param mixed $b
198
   *   Footnote object $b.
199
   */
200
  function footnotes_key_compare($a, $b) {
201
    $res = 0;
202
    if (empty($a) || empty($b)) {
203
      return $res;
204
    }
205
    if ($a->keyStr < $b->keyStr) {
206
      $res = -1;
207
    }
208
    elseif ($a->keyStr > $b->keyStr) {
209
      $res = 1;
210
    }
211
    return $res;
212
  }
213 74ee6b54 Andreas Kohlbecker
214 cd3ea2e8 Andreas Kohlbecker
/**
215 2f4646e0 Andreas Kohlbecker
 * Provides an explanatory text on the statistical values representation as generated by statistical_values()
216 cd3ea2e8 Andreas Kohlbecker
 *
217
 * @return string
218
 *     the text
219
 */
220
  function statistical_values_explanation(){
221
    return t("A single or the first number in square brackets denotes sample size");
222
  }
223 74ee6b54 Andreas Kohlbecker
224
/**
225 2f4646e0 Andreas Kohlbecker
 * Creates an array suitable to be used in statistical_values()
226 f63479ae Andreas Kohlbecker
 * The min max structure is suitable for being used in the context
227 2eb6acb7 Andreas Kohlbecker
 * of GatheringEvents and StatisticalMeasures (see render_quantitative_statistics()).
228
 *
229
 * The order of the items is important for the display and must not be changed.
230 74ee6b54 Andreas Kohlbecker
 *
231
 * @return array
232
 */
233 2f4646e0 Andreas Kohlbecker
function statistical_values_array() {
234 f63479ae Andreas Kohlbecker
235
  $min_max = [
236
    'Min' => NULL,
237
    'TypicalLowerBoundary' => NULL,
238
    'TypicalUpperBoundary' => NULL,
239
    'Max' => NULL,
240 2eb6acb7 Andreas Kohlbecker
    'SampleSize' => NULL,
241
    'Average' => NULL,
242 f63479ae Andreas Kohlbecker
    'Variance' => NULL,
243
    'StandardDeviation' => NULL,
244
  ];
245 74ee6b54 Andreas Kohlbecker
  return $min_max;
246
}
247
248
/**
249 5a079dbf Andreas Kohlbecker
 * Creates markup from a min max array.
250
 *
251 2f4646e0 Andreas Kohlbecker
 * NOTE: use  statistical_values_array() to create an appropriate array
252 74ee6b54 Andreas Kohlbecker
 *
253 f63479ae Andreas Kohlbecker
 * Internally Min will be translated to TypicalLowerBoundary if no such value is present.
254
 * The same also accounts for Max and TypicalUpperBoundary.
255
 *
256
 * For further details see #3742, #8766
257
 *
258 2f4646e0 Andreas Kohlbecker
 * @param $stat_vals_arr
259
 *  the statistical values array as produced by statistical_values_array()
260 5a079dbf Andreas Kohlbecker
 * @param $unit
261
 *  Defaults to no unit
262 74ee6b54 Andreas Kohlbecker
 * @return string
263
 */
264 2f4646e0 Andreas Kohlbecker
function statistical_values($stat_vals_arr, $unit = '') {
265 74ee6b54 Andreas Kohlbecker
266 2eb6acb7 Andreas Kohlbecker
  static $xbar_equals = 'x&#x304='; // x&#x304 is x-bar
267
268 74ee6b54 Andreas Kohlbecker
  $min_max_markup = '';
269 2eb6acb7 Andreas Kohlbecker
  $other_vals_array = [];
270 f63479ae Andreas Kohlbecker
271
  // --- sanitize values
272 2f4646e0 Andreas Kohlbecker
  if(statistical_values_equals($stat_vals_arr, 'Min', 'TypicalLowerBoundary')){
273
    $stat_vals_arr['Min'] = NULL;
274 f63479ae Andreas Kohlbecker
  }
275
276 2f4646e0 Andreas Kohlbecker
  if(statistical_values_equals($stat_vals_arr, 'Max', 'TypicalUpperBoundary')){
277
    $stat_vals_arr['Max'] = NULL;
278 f63479ae Andreas Kohlbecker
  }
279
280 2f4646e0 Andreas Kohlbecker
  if($stat_vals_arr['TypicalLowerBoundary'] === null && $stat_vals_arr['Min'] !== null){
281
    $stat_vals_arr['TypicalLowerBoundary'] = $stat_vals_arr['Min'];
282
    $stat_vals_arr['Min'] = NULL;
283 f63479ae Andreas Kohlbecker
  }
284
285 2f4646e0 Andreas Kohlbecker
  if($stat_vals_arr['TypicalUpperBoundary'] === null && $stat_vals_arr['Max']  !== null){
286
    $stat_vals_arr['TypicalUpperBoundary'] = $stat_vals_arr['Max'];
287
    $stat_vals_arr['Max'] = NULL;
288 f63479ae Andreas Kohlbecker
  }
289
290 2f4646e0 Andreas Kohlbecker
  if (statistical_values_equals($stat_vals_arr, 'TypicalUpperBoundary', 'TypicalLowerBoundary')) {
291
    $stat_vals_arr['Average'] = $stat_vals_arr['TypicalUpperBoundary'];
292
    $stat_vals_arr['TypicalLowerBoundary'] = NULL;
293
    $stat_vals_arr['TypicalUpperBoundary'] = NULL;
294 74ee6b54 Andreas Kohlbecker
  }
295
296 f63479ae Andreas Kohlbecker
  // --- check for inconsistent cases, eg. only Max and average given
297 2f4646e0 Andreas Kohlbecker
  if ($stat_vals_arr['TypicalLowerBoundary'] === NULL && $stat_vals_arr['TypicalUpperBoundary']  !== null) {
298 5a079dbf Andreas Kohlbecker
    // min missing
299 2f4646e0 Andreas Kohlbecker
    $stat_vals_arr['TypicalLowerBoundary'] = '?';
300 74ee6b54 Andreas Kohlbecker
  }
301 2f4646e0 Andreas Kohlbecker
  if ($stat_vals_arr['TypicalLowerBoundary'] !== null && $stat_vals_arr['TypicalUpperBoundary'] === NULL) {
302 5a079dbf Andreas Kohlbecker
    // max missing
303 2f4646e0 Andreas Kohlbecker
    $stat_vals_arr['TypicalUpperBoundary'] = '?';
304 74ee6b54 Andreas Kohlbecker
  }
305
306 793df790 Andreas Kohlbecker
  if($stat_vals_arr['Average'] && $stat_vals_arr['TypicalUpperBoundary'] !== null && $stat_vals_arr['TypicalLowerBoundary'] !== null) {
307
//    $stat_vals_arr['TypicalUpperBoundary']->_value = 0.123457;
308
//    $stat_vals_arr['TypicalLowerBoundary']->_value = 0.123456;
309
//    $stat_vals_arr['Average']->_value = 0.1234565234234;
310
    statistical_values_adjust_significant_figures($stat_vals_arr['Average'], $stat_vals_arr['TypicalLowerBoundary'], $stat_vals_arr['TypicalUpperBoundary']);
311
  }
312
313 2f4646e0 Andreas Kohlbecker
  foreach ($stat_vals_arr as $key => $statistical_val) {
314 2eb6acb7 Andreas Kohlbecker
315 74ee6b54 Andreas Kohlbecker
    if ($statistical_val !== NULL) {
316
      if ($statistical_val == '?') {
317
        $val_markup = $statistical_val;
318
      } else {
319
        $val_markup = '<span class="'
320
            . html_class_attribute_ref($statistical_val) . ' '
321 f63479ae Andreas Kohlbecker
            . (isset($statistical_val->type) ? $statistical_val->type->termType : '') . ' ' . $key .'" title="'. $key. '">'
322 74ee6b54 Andreas Kohlbecker
            . $statistical_val->_value . '</span>';
323
      }
324
325 f63479ae Andreas Kohlbecker
      switch ($key) {
326 2eb6acb7 Andreas Kohlbecker
        // ---- min_max_element
327 f63479ae Andreas Kohlbecker
        case 'Min':
328 2eb6acb7 Andreas Kohlbecker
          $min_max_markup .= "($val_markup&ndash;)";
329
          break;
330 f63479ae Andreas Kohlbecker
        case 'Max':
331 2eb6acb7 Andreas Kohlbecker
          $min_max_markup .= "(&ndash;$val_markup)";
332
          break;
333
        case 'TypicalLowerBoundary':
334
          $min_max_markup .= "$val_markup";
335
          break;
336
        case 'TypicalUpperBoundary':
337
          $min_max_markup .= "&ndash;$val_markup";
338
          break;
339
          // ---- other values
340
        case 'SampleSize':
341
          $other_vals_array[$key] = $val_markup;
342
          break;
343
        case 'Average':
344
          $other_vals_array[$key] = $xbar_equals . $val_markup;
345 f63479ae Andreas Kohlbecker
          break;
346
        case 'Variance':
347 2eb6acb7 Andreas Kohlbecker
          $other_vals_array[$key] = 'σ²=' . $val_markup;
348 f63479ae Andreas Kohlbecker
          break;
349
        case 'StandardDeviation':
350 2eb6acb7 Andreas Kohlbecker
          $other_vals_array[$key] = 'σ=' . $val_markup;
351 f63479ae Andreas Kohlbecker
          break;
352 74ee6b54 Andreas Kohlbecker
      }
353
    }
354
  }
355 f63479ae Andreas Kohlbecker
356 2eb6acb7 Andreas Kohlbecker
  if(!$min_max_markup && $other_vals_array['Average']){
357
    // this could be the case in which we only have one value for Average
358
    // this trivial case needs to be displayed a simpler way
359
    $min_max_markup = str_replace($xbar_equals, '' ,$other_vals_array['Average']);
360
    if($other_vals_array['SampleSize']){
361
      $min_max_markup .= '['. $other_vals_array['SampleSize'] .']';
362
    }
363
  } else {
364
    if(count($other_vals_array)){
365
      $min_max_markup .= '[' . join(';', $other_vals_array) . ']';
366
    }
367
  }
368 f63479ae Andreas Kohlbecker
369 ad7fa57c Andreas Kohlbecker
  return $min_max_markup . ($unit ? ' ' . $unit : '');
370 5a079dbf Andreas Kohlbecker
}
371
372 793df790 Andreas Kohlbecker
/**
373
 * Calculates the required precision for the taget value to be significantly different from min and may and rounds it.
374
 *
375
 * @param $target
376
 *    The statistical value to be rounded to the least significant precision
377
 * @param $min
378
 *    The lower bound to calculate the least significant precision
379
 * @param $max
380
 *    The upper bound to calculate the least significant precision
381
 * @param int $threshold
382
 *    Per default 1, but can be set to any other value > 0 and < 1 to define
383
 *    another threshold for the transition to the next precision level.
384
 *    E.g. A value of 0.5 will cause values > 50 and <= 500 to be shown with
385
 *    a precision of 2, whereas with a threshold of 1 the values > 10 and <= 100
386
 *    will be shown with a precision of 2 figures
387
 */
388
function statistical_values_adjust_significant_figures(&$target, $min,  $max, $threshold = 1){
389
390
  $precision = 1;
391
  if($min->_value !== $max->_value){
392
    $precision = floor(log10(abs($max->_value - $min->_value) * (1 / $threshold)));
393
    // increase precision by one
394
    $precision += $precision < 0 ? - 1 : 1;
395
  }
396
397
  $target->_value = sigFig($target->_value, $precision);
398
}
399
400
/**
401
 * based on an idea taken from https://stackoverflow.com/questions/37618679/format-number-to-n-significant-digits-in-php#answer-48283297
402
 *
403
 * @param $value
404
 * @param $digits
405
 *
406
 * @return float|string
407
 */
408
function sigFig($value, $digits, $round_only = true)
409
{
410
  if ($value == 0) {
411
    $decimalPlaces = $digits - 1;
412
  } elseif ($value < 0) {
413
    $decimalPlaces = $digits - floor(log10($value * -1)) - 1;
414
  } else {
415
    $decimalPlaces = $digits - floor(log10($value)) - 1;
416
  }
417
418
  $answer = ($decimalPlaces > 0) && !$round_only ?
419
    number_format($value, $decimalPlaces) : round($value, abs($decimalPlaces));
420
  return $answer;
421
}
422
423
424
425 f63479ae Andreas Kohlbecker
/**
426 2f4646e0 Andreas Kohlbecker
 * Used internally in statistical_values() do determine equality of stat_vals_arr values
427 f63479ae Andreas Kohlbecker
 *
428 2f4646e0 Andreas Kohlbecker
 * @param $stat_vals_arr
429 f63479ae Andreas Kohlbecker
 * @param $key1
430
 * @param $key2
431
 *
432
 * @return bool
433
 */
434 2f4646e0 Andreas Kohlbecker
function statistical_values_equals($stat_vals_arr, $key1, $key2){
435 f63479ae Andreas Kohlbecker
436 2f4646e0 Andreas Kohlbecker
  return $stat_vals_arr[$key1] !== NULL && $stat_vals_arr[$key2] !== NULL && $stat_vals_arr[$key1]->_value ==  $stat_vals_arr[$key2]->_value;
437 f63479ae Andreas Kohlbecker
}
438
439 5a079dbf Andreas Kohlbecker
/**
440
 * Creates min max markup to represent a min-average-max measure optionally with an error value.
441
 *
442
 * The fields that are taken into account are:
443
 * - field_base_name = min
444
 * - field_base_nameMax = max
445
 * - field_base_nameText = free text
446
 * - field_base_nameError = error value
447
 *
448
 * @param $object
449 f63479ae Andreas Kohlbecker
 *    The object having min max measurement fields e.g.: GatheringEvent
450 5a079dbf Andreas Kohlbecker
 * @param string $field_base_name
451
 *    The base name for all measurement fields. This name is at the same time the full name of the
452
 *    min value.
453 dbc2bfa9 Andreas Kohlbecker
 * @return string
454
 *   The markup for the min max
455 2f4646e0 Andreas Kohlbecker
 *
456
 * @see statistical_values()
457 5a079dbf Andreas Kohlbecker
 */
458 2f4646e0 Andreas Kohlbecker
function statistical_values_from_gathering_event($object, $field_base_name)
459 5a079dbf Andreas Kohlbecker
{
460
  static $default_unit = 'm';
461
462
  $field_name = $field_base_name . 'Text';
463 0820cdc0 Andreas Kohlbecker
  if (@is_string($object->$field_name)) {
464 dbc2bfa9 Andreas Kohlbecker
    // Freetext overrides all other data
465
    $min_max_markup = ' ' . $object->$field_name;
466
  } else {
467
    // create markup for the atomized min max data
468 2f4646e0 Andreas Kohlbecker
    $min_max_array = statistical_values_array();
469 dbc2bfa9 Andreas Kohlbecker
    if (@is_numeric($object->$field_base_name)) {
470
      $min_max_array['Min'] = new stdClass();
471
      $min_max_array['Min']->_value = $object->$field_base_name;
472
    }
473
    $field_name = $field_base_name . 'Max';
474
    if (@is_numeric($object->$field_name)) {
475
      $min_max_array['Max'] = new stdClass();
476
      $min_max_array['Max']->_value = $object->$field_name;
477
    }
478 2f4646e0 Andreas Kohlbecker
    $min_max_markup = statistical_values($min_max_array, $default_unit);
479 5a079dbf Andreas Kohlbecker
  }
480 dbc2bfa9 Andreas Kohlbecker
481 74ee6b54 Andreas Kohlbecker
  return $min_max_markup;
482
}
483 d9763fd3 Andreas Kohlbecker
484
// TODO  move below code into new file: agent.inc
485
486
/*
487
 * Compose an render array from a CDM TaxonNodeAgentRelation object as Taxon Expert.
488
 *
489
 * compose_hook() implementation
490
 *
491
 * @param object $taxon_node_agent_relation
492
 *   CDM instance of type TaxonNodeAgentRelation
493
 * @return array
494
 *   A drupal render array
495
 *
496
 * @ingroup compose
497
 */
498
function compose_cdm_taxon_expert($taxon_node_agent_relation) {
499
500
  $label_suffix = ':';
501
502
  if($taxon_node_agent_relation->class == 'DefaultPagerImpl'){
503
    // oops this is a pager
504
    // this situation will occur when this compose is executed
505
    // through the proxy_content() method
506
    $taxon_node_agent_relation = $taxon_node_agent_relation->records[0];
507
508
  }
509
510
  if(is_object($taxon_node_agent_relation->agent)) {
511
    $agent_details = compose_cdm_team_or_person_base($taxon_node_agent_relation->agent);
512
    // all data will be added to the groups of the agent_details render array
513
    $groups = &$agent_details[0]['#groups'];
514
515 bf90783c Andreas Kohlbecker
    @_description_list_group_add($groups, t('Role'). $label_suffix, $taxon_node_agent_relation->type->representation_L10n);
516 d9763fd3 Andreas Kohlbecker
517
    $family_tnars = cdm_ws_fetch_all(CDM_WS_PORTAL_AGENT . '/' . $taxon_node_agent_relation->agent->uuid . '/taxonNodeAgentRelations', array("rank"=>"Familia"));
518
519
    $taxa_markup = array(
520
      '#theme_wrappers' => array('container'),
521
      '#attributes' => array('class' => array('managed_taxa')),
522
      '#wrapper_attributes' => array('class' => 'sublist-container')
523
      );
524
    foreach($family_tnars as $tnar){
525
      if(is_object($tnar->taxonNode->taxon)){
526 bf2387cc Andreas Kohlbecker
        $taxa_markup[$tnar->taxonNode->taxon->titleCache] = markup_to_render_array(render_taxon_or_name($tnar->taxonNode->taxon, url(path_to_taxon($tnar->taxonNode->taxon->uuid))));
527 d9763fd3 Andreas Kohlbecker
      }
528
    }
529
    ksort($taxa_markup);
530
531
    @_description_list_group_add($groups, t('Families'). $label_suffix, array($taxa_markup));
532
533
  }
534
535
  return $agent_details;
536
}
537
538
539
/*
540
 * Compose an render array from a CDM TeamOrPersonBase object.
541
 *
542
 * compose_hook() implementation
543
 *
544
 * TODO: currently mainly implemented for Agent, add Team details
545
 *
546
 * @param object $team_or_person
547
 *   CDM instance of type TeamOrPersonBase
548
 * @return array
549
 *   A drupal render array
550
 *
551
 * @ingroup compose
552
 */
553
function compose_cdm_team_or_person_base($team_or_person, $data = array()) {
554
555
  $groups = array();
556
557
  $label_suffix = ':';
558
559
  // $weight = 0;
560
  if($team_or_person){
561
562
    if(is_object($team_or_person->lifespan)){
563
      // ToDo render as date* - date† ?
564
      @_description_list_group_add($groups, t('Lifespan'). $label_suffix, timePeriodToString($team_or_person->lifespan) /*, '' , $weight++ */);
565
    }
566
567
    // nomenclaturalTitle
568
    @_description_list_group_add($groups, "Nomenclatural Title". $label_suffix, $team_or_person->nomenclaturalTitle);
569
    // collectorTitle
570
    @_description_list_group_add($groups, "Collector Title". $label_suffix, $team_or_person->collectorTitle);
571
572
    // institutionalMemberships
573
    if(is_array($team_or_person->institutionalMemberships)){
574
575
      $institutes_ra =  array();
576
      foreach($team_or_person->institutionalMemberships as $membership) {
577
        $membership_groups = array();
578
        @_description_list_group_add($membership_groups, t('Department'). $label_suffix, $membership->department);
579
        @_description_list_group_add($membership_groups, t('Role'). $label_suffix, $membership->role);
580
        if(is_object($membership->period)){
581
          @_description_list_group_add($membership_groups, t('Period'). $label_suffix, timePeriodToString($membership->period));
582
        }
583
        if(is_object($membership->institute->contact)){
584
          $institute_contact_details = compose_cdm_contact($membership->institute->contact, $membership->institute->titleCache);
585
          if(is_array($institute_contact_details[0]['#groups'])){
586
            $membership_groups = array_merge($membership_groups, $institute_contact_details[0]['#groups']);
587
          }
588
        }
589
        if(count($membership_groups) > 0){
590
          $institutes_ra[]  = array(
591
            '#title' => $membership->institute->titleCache,
592
            '#theme' => 'description_list',
593
            '#groups' => $membership_groups,
594
            '#attributes' => array('class' => html_class_attribute_ref($membership)),
595
            '#wrapper_attributes' => array('class' => 'sublist-container')
596
          );
597
        } else {
598
          // no further details for the membership, display the title
599
          $institutes_ra[] = markup_to_render_array('<h3>' . $membership->institute->titleCache . '</h3>');
600
        }
601
602
      }
603
604
      $label = count($institutes_ra) > 1 ? t('Institutes'):  t('Institute');
605
      @_description_list_group_add($groups, $label. $label_suffix, $institutes_ra /*, '' , $weight++ */);
606
    }
607
608
609
    // Contact
610
    $agent_contact_details = compose_cdm_contact($team_or_person->contact, $team_or_person->titleCache);
611
    if(is_array($agent_contact_details[0]['#groups'])){
612
      $groups = array_merge($groups, $agent_contact_details[0]['#groups']);
613
    }
614
615
    // additional data
616
    foreach($data as $key=>$value){
617 7cc085da Andreas Kohlbecker
      @_description_list_group_add($sub_dl_groups, t('@key', array('@key' => $key)), $value /*, '' , $weight++ */);
618 d9763fd3 Andreas Kohlbecker
    }
619
620
  }
621
622
  $team_or_person_details = array(
623
    '#title' => $team_or_person->titleCache,
624
    '#theme' => 'description_list',
625
    '#groups' => $groups,
626
    '#attributes' => array('class' => html_class_attribute_ref($team_or_person)),
627
  );
628
  return array($team_or_person_details);
629
}
630
631
632
/*
633
 * Compose an render array from a CDM Contact object.
634
 *
635
 * compose_hook() implementation
636
 *
637
 * TODO: currently mainly implemented for Agent, add Team details
638
 *
639
 * @param object $contact
640
 *   CDM instance of type Contact
641
 * @param $title
642
 *   The title for the description list header
643
 * @param $weight
644
 *   Optional weight for the description list entries
645
 * @return array
646
 *   A drupal render array
647
 *
648
 * @ingroup compose
649
 */
650
function compose_cdm_contact($contact, $title, $weight = 0)
651
{
652
653
  $groups = array();
654
655 0820cdc0 Andreas Kohlbecker
  $contact_details = null;
656
657 d9763fd3 Andreas Kohlbecker
  $label_suffix = ':';
658
659
  $contact_field_names_map = array(
660
    'emailAddresses' => t('Email'),
661
    'urls' => t('Urls'),
662
    'phoneNumbers' => t('Phone'),
663
    'faxNumbers' => t('Fax'),
664
  );
665
666
  // Contact
667
  if(is_object($contact)){
668
    if(isset($contact->addresses)){
669
      // TODO ....
670
      // $sub_groups = array();
671
      // foreach($contact->addresses as $address){
672
      //   @_description_list_group_add($sub_groups, $label, $contact->$fieldName, '', $weight++);
673
      // }
674
    }
675
    foreach($contact_field_names_map as $fieldName => $label){
676
      if(is_array($contact->$fieldName)){
677
        @_description_list_group_add($groups, $label . $label_suffix, $contact->$fieldName, '', $weight++);
678
      }
679
    }
680
    $contact_details = array(
681
      '#title' => $title,
682
      '#theme' => 'description_list',
683
      '#groups' => $groups
684
    );
685
686
687
  } else if(is_string($title)) {
688
    // if the contact entity is empty but the title is given anyway
689
    // we are only adding the title, using the description_list
690
    // structure is not possible since it would be empty due to
691
    // missing group data
692
    $contact_details = array('#markup' => '<h3>' . $title . '</h3>');
693
  }
694
695
  return array($contact_details);
696
697
}
698 0820cdc0 Andreas Kohlbecker
699
/**
700
 * Compose an render array from a CDM Extension objects.
701
 *
702
 * @param $extensions
703
 *    An array of CDM Extension objects
704
 * @return array
705
 *   A render array containing the fields of the supplied $sequence
706
 *
707
 * @ingroup compose
708
 */
709
function compose_extensions($extensions)
710
{
711
  $extensions_render_array= null;
712
  $extensions_by_type = array();
713
  foreach ($extensions as $extension) {
714
    if (@is_string($extension->value)) {
715
      if (!isset($extensions_by_type[$extension->type->representation_L10n])) {
716
        $extensions_by_type[$extension->type->representation_L10n] = array();
717
      }
718
      $extensions_by_type[$extension->type->representation_L10n][] = markup_to_render_array($extension->value);
719
    }
720
  }
721
722
  if (count($extensions_by_type)) {
723
    $sub_dl_groups = array();
724
    foreach ($extensions_by_type as $type_label => $text_list) {
725
      @_description_list_group_add($sub_dl_groups, $type_label . ':', $text_list);
726
    }
727
    $extensions_render_array = array(
728
      array('#theme' => 'description_list', '#groups' => $sub_dl_groups)
729
    );
730
    return $extensions_render_array;
731
  }
732
  return $extensions_render_array;
733
}
734 eaff53f7 Andreas Kohlbecker
735 6eaec849 Katja Luther
function formatParams($params) {
736
    if (is_array($params)){
737
        $keys =array_keys($params);
738
        $paramString = '';
739
        foreach ($keys as $k ){
740
            if ($k != 'pageNumber' && $k != 'pageSize'){
741
                $paramString .= ' -'.$k.'='.urlencode($params[$k]);
742
            }
743
        }
744
    }
745
    return $paramString;
746
}
747 eaff53f7 Andreas Kohlbecker
748 72d57201 Katja Luther
function formatWSParams($params) {
749
    if (is_array($params)){
750
        $keys =array_keys($params);
751
        $paramString = '';
752
        foreach ($keys as $k ){
753
            if ($k != 'pageNumber' && $k != 'pageSize'){
754
                $paramString .= '&'.$k.'='.urlencode($params[$k]);
755
            }
756
        }
757
    }
758
    return $paramString;
759
}
760
761 fe3a5674 Andreas Kohlbecker
/**
762
 *
763
 * @param $cdm_entity
764
 *
765
 * @return string the markup
766
 */
767 ab025781 Andreas Kohlbecker
function render_cdm_entity_link($cdm_entity) {
768 fe3a5674 Andreas Kohlbecker
769
  switch ($cdm_entity->class) {
770
    case 'TaxonDescription':
771 2d78d276 Andreas Kohlbecker
    case 'NameDescription':
772
    case 'SpecimenDescription':
773 92e522db Andreas Kohlbecker
      $link =  '<span class="' . html_class_attribute_ref($cdm_entity) . '">' . $cdm_entity->titleCache . '</span> ' . icon_link(path_to_description($cdm_entity->uuid));
774 fe3a5674 Andreas Kohlbecker
      break;
775
    default:
776 ab025781 Andreas Kohlbecker
      $link = '<span class="error">UNSUPPORTED CDM ENTITY TYPE</span>';
777 fe3a5674 Andreas Kohlbecker
  }
778 ab025781 Andreas Kohlbecker
  return $link;
779 fe3a5674 Andreas Kohlbecker
}
780
781 ab025781 Andreas Kohlbecker
/**
782
 * Creates an icon which links to the given path
783
 * @param $path
784
 *
785
 * @return string
786
 */
787 fec3fd41 Andreas Kohlbecker
function icon_link($path, $fragment = '') {
788
  $iconlink = l(custom_icon_font_markup('icon-interal-link-alt-solid', ['class' => ['superscript']]), $path, ['html' => TRUE, 'fragment' => $fragment] );
789 ab025781 Andreas Kohlbecker
  return $iconlink;
790
}