Project

General

Profile

Download (16 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
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
 */
18

    
19
/**
20
 * @defgroup compose Compose functions
21
 * @{
22
 * Functions which are composing Drupal render arays
23
 *
24
 * The cdm_dataporal module needs to compose rather complex render arrays from
25
 * the data returned by the CDM REST service. The compose functions are
26
 * responsible for creating the render arrays.
27
 *
28
 * All these functions are also implementations of the compose_hook()
29
 * which is used in the proxy_content() function.
30
 * @}
31
 */
32

    
33
/**
34
 * 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
 *
43
 * @ingroup compose
44
 */
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
      '#attributes' => array('class' => html_class_attribute_ref($marker)),
52

    
53
      // ---- individual
54
      '#label' => $marker->markerType->representation_L10n . ': ' . (($marker->flag !== TRUE ? t('yes') : t('no'))),
55
  );
56

    
57
  return $render_array;
58
}
59

    
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
 * @param object $cdm_entitiy A CDM Entity
65
 * @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
}
77

    
78
/**
79
 * Sorts an array of CDM IdentifiableSource instances by 1. by the
80
 * author teams family names and 2. by the publication date.
81
 *
82
 * @param array $sources
83
 *    The array of CDM IdentifiableSource instances
84
 * @param bool $do_theme if set TRUE the sources will be themed
85
 *        by theme_cdm_OriginalSource
86
 * @return multitype:
87
 */
88
function oder_sources($sources, $do_theme = false){
89
    $sort_array = array();
90
    foreach ($sources as $source) {
91

    
92
      $order_key = '';
93

    
94
      // find the familynames
95
      if(isset($source->citation->uuid) && !isset($source->citation->authorship)){
96
        $authorteam = cdm_ws_get(CDM_WS_REFERENCE_AUTHORTEAM, $source->citation->uuid);
97

    
98
        $persons = array();
99
        if($authorteam->class == 'Team'){
100
          if(isset($authorteam->teamMembers)){
101
            $persons = $authorteam->teamMembers;
102
          }
103
        } else {
104
          $persons[] = $authorteam;
105
        }
106

    
107
        foreach($persons as $person){
108
          if(!empty($person->lastname)){
109
            $order_key .= $person->lastname;
110
          } else {
111
            $order_key .= $person->titleCache;
112
          }
113
        }
114
        if(empty($order_key)){
115
          $order_key = $authorteam->titleCache;
116
        }
117

    
118
      }
119
      $order_key = str_pad($order_key, 50);
120

    
121
      // add publication date to the key
122
      if(isset($source->citation->datePublished)){
123
        $order_key .= '_' . timePeriodAsOrderKey($source->citation->datePublished);
124
      } else {
125
        $order_key .= '_' . "0000";
126
      }
127

    
128
      // padd key until unique
129
      while(array_key_exists($order_key, $sort_array)){
130
        $order_key .= "_";
131
      }
132

    
133

    
134
      if($do_theme) {
135
        $sort_array[$order_key] = theme('cdm_OriginalSource', array('source' => $source));
136
      } else {
137
        $sort_array[$order_key] = $source;
138
      }
139
    }
140
    ksort($sort_array);
141
    return array_values ($sort_array);
142
}
143

    
144
/**
145
 * Compare callback to be used in usort to sort image sources of CDM OriginalSource instances.
146
 *
147
 * TODO the compare strategy implemnted in oder_sources() is probably better but is not taking the
148
 * originalName into account.
149
 *
150
 * @param $a
151
 * @param $b
152
 */
153
function compare_original_sources($a, $b){
154

    
155
  $a_string = '';
156
  if(isset($a->citation->titleCache)) {
157
    $a_string = $a->citation->titleCache;
158
  }
159
  if((isset($a->nameUsedInSource))){
160
    $a_string .= $a->nameUsedInSource->titleCache;
161
  } elseif (isset($a->originalNameString)){
162
    $a_string .= $a->originalNameString;
163
  }
164

    
165
  $b_string = '';
166
  if(isset($b->citation->titleCache)) {
167
    $b_string = $b->citation->titleCache;
168
  };
169
  if((isset($b->nameUsedInSource))){
170
    $b_string .= $b->nameUsedInSource->titleCache;
171
  } elseif (isset($b->originalNameString)){
172
    $b_string .= $b->originalNameString;
173
  }
174

    
175
  if ($a_string == $b_string) {
176
    return 0;
177
  }
178
  return ($a_string < $b_string) ? -1 : 1;
179
}
180

    
181
/**
182
 * Compare callback to be used in usort to sort image sources of CDM Media instances.
183
 *
184
 * @param $a
185
 * @param $b
186
 */
187
function compare_text_data($a, $b) {
188

    
189
  if ($a->multilanguageText_L10n->text == $b->multilanguageText_L10n->text) {
190
    return 0;
191
  }
192
  return ($a->multilanguageText_L10n->text < $b->multilanguageText_L10n->text) ? -1 : 1;
193
}
194

    
195
  /**
196
   * Compare two different footnotes objects.
197
   *
198
   * The comparison is based on the footnote key. The one which is
199
   * displayed as footnote number.
200
   *
201
   * @param mixed $a
202
   *   Footnote object $a.
203
   * @param mixed $b
204
   *   Footnote object $b.
205
   */
206
  function footnotes_key_compare($a, $b) {
207
    $res = 0;
208
    if (empty($a) || empty($b)) {
209
      return $res;
210
    }
211
    if ($a->keyStr < $b->keyStr) {
212
      $res = -1;
213
    }
214
    elseif ($a->keyStr > $b->keyStr) {
215
      $res = 1;
216
    }
217
    return $res;
218
  }
219

    
220

    
221
/**
222
 * Creates an array suitable to be used in min_max_markup()
223
 *
224
 * @return array
225
 */
226
function min_max_array()
227
{
228
// FIXME use UUIDs instead? how about idInVocab?
229
  $min_max = array(
230
      'Extreme Min' => NULL,
231
      'Min' => NULL,
232
      'Average' => NULL,
233
      'Max' => NULL,
234
      'Extreme Max' => NULL,
235
  );
236
  return $min_max;
237
}
238

    
239
/**
240
 * Creates markup from a min max array.
241
 *
242
 * NOTE: use  min_max_array() to create an appropriate array
243
 *
244
 * @param $min_max
245
 *  the min-max array
246
 * @param $unit
247
 *  Defaults to no unit
248
 * @return string
249
 */
250
function min_max_markup($min_max, $unit = '') {
251

    
252
  $min_max_markup = '';
253
  // create min-max string
254
  if ($min_max['Min'] !== NULL && $min_max['Max'] !== NULL && $min_max['Min']->_value == $min_max['Max']->_value) {
255
    // min and max are identical
256
    $min_max['Average'] = $min_max['Min'];
257
    $min_max['Min'] = NULL;
258
    $min_max['Max'] = NULL;
259
  }
260

    
261
  // check for inconsistent cases, eg. only Max and average given
262
  if ($min_max['Min'] === NULL && $min_max['Max'] !== NULL) {
263
    // min missing
264
    $min_max['Min'] = '?';
265
  }
266
  if ($min_max['Min'] !== NULL && $min_max['Max'] === NULL) {
267
    // max missing
268
    $min_max['Max'] = '?';
269
  }
270

    
271

    
272
  foreach ($min_max as $key => $statistical_val) {
273
    if ($statistical_val !== NULL) {
274

    
275
      if ($statistical_val == '?') {
276
        $val_markup = $statistical_val;
277
      } else {
278
        $val_markup = '<span class="'
279
            . html_class_attribute_ref($statistical_val) . ' '
280
            . (isset($statistical_val->type) ? $statistical_val->type->termType : '') . ' ">'
281
            . $statistical_val->_value . '</span>';
282
      }
283

    
284
      if (strlen($min_max_markup)) {
285
        $min_max_markup .= '–';
286
      }
287
      if (str_beginsWith($key, 'Extreme')) {
288
        $val_markup = "($val_markup)";
289
      }
290
      $min_max_markup .= $val_markup;
291
    }
292
  }
293
  return $min_max_markup . ' ' . $unit;
294
}
295

    
296
/**
297
 * Creates min max markup to represent a min-average-max measure optionally with an error value.
298
 *
299
 * The fields that are taken into account are:
300
 * - field_base_name = min
301
 * - field_base_nameMax = max
302
 * - field_base_nameText = free text
303
 * - field_base_nameError = error value
304
 *
305
 * @param $object
306
 *    The object having min max measurement fields
307
 * @param string $field_base_name
308
 *    The base name for all measurement fields. This name is at the same time the full name of the
309
 *    min value.
310
 * @return array
311
 *   the resulting min max array
312
 */
313
function min_max_measure($object, $field_base_name)
314
{
315
  static $default_unit = 'm';
316

    
317
  $min_max_array = min_max_array();
318
  if (is_numeric($object->$field_base_name)) {
319
    $min_max_array['Min'] = new stdClass();
320
    $min_max_array['Min']->_value = $object->$field_base_name;
321
  }
322

    
323
  $field_name = $field_base_name . 'Max';
324
  if (is_numeric($object->$field_name)) {
325
    $min_max_array['Max'] = new stdClass();
326
    $min_max_array['Max']->_value = $object->$field_name;
327
  }
328
  $min_max_markup = min_max_markup($min_max_array, $default_unit);
329

    
330
  $field_name = $field_base_name . 'Error';
331
  if (is_numeric($object->$field_name )) {
332
    $min_max_markup .= ' +/- ' . $object->$field_name . ' ' . $default_unit;
333
  }
334
  $field_name = $field_base_name . 'Text';
335
  if (is_string($object->$field_name)) {
336
    $min_max_markup .= ' ' . $object->$field_name;
337
  }
338
  return $min_max_markup;
339
}
340

    
341
// TODO  move below code into new file: agent.inc
342

    
343
/*
344
 * Compose an render array from a CDM TaxonNodeAgentRelation object as Taxon Expert.
345
 *
346
 * compose_hook() implementation
347
 *
348
 * @param object $taxon_node_agent_relation
349
 *   CDM instance of type TaxonNodeAgentRelation
350
 * @return array
351
 *   A drupal render array
352
 *
353
 * @ingroup compose
354
 */
355
function compose_cdm_taxon_expert($taxon_node_agent_relation) {
356

    
357
  $label_suffix = ':';
358

    
359
  if($taxon_node_agent_relation->class == 'DefaultPagerImpl'){
360
    // oops this is a pager
361
    // this situation will occur when this compose is executed
362
    // through the proxy_content() method
363
    $taxon_node_agent_relation = $taxon_node_agent_relation->records[0];
364

    
365
  }
366

    
367
  if(is_object($taxon_node_agent_relation->agent)) {
368
    $agent_details = compose_cdm_team_or_person_base($taxon_node_agent_relation->agent);
369
    // all data will be added to the groups of the agent_details render array
370
    $groups = &$agent_details[0]['#groups'];
371

    
372
    @_description_list_group_add($groups, t('Role'). $label_suffix, $taxon_node_agent_relation->type->representation_L10n);
373

    
374
    $family_tnars = cdm_ws_fetch_all(CDM_WS_PORTAL_AGENT . '/' . $taxon_node_agent_relation->agent->uuid . '/taxonNodeAgentRelations', array("rank"=>"Familia"));
375

    
376
    $taxa_markup = array(
377
      '#theme_wrappers' => array('container'),
378
      '#attributes' => array('class' => array('managed_taxa')),
379
      '#wrapper_attributes' => array('class' => 'sublist-container')
380
      );
381
    foreach($family_tnars as $tnar){
382
      if(is_object($tnar->taxonNode->taxon)){
383
        $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))));
384
      }
385
    }
386
    ksort($taxa_markup);
387

    
388
    @_description_list_group_add($groups, t('Families'). $label_suffix, array($taxa_markup));
389

    
390
  }
391

    
392
  return $agent_details;
393
}
394

    
395

    
396
/*
397
 * Compose an render array from a CDM TeamOrPersonBase object.
398
 *
399
 * compose_hook() implementation
400
 *
401
 * TODO: currently mainly implemented for Agent, add Team details
402
 *
403
 * @param object $team_or_person
404
 *   CDM instance of type TeamOrPersonBase
405
 * @return array
406
 *   A drupal render array
407
 *
408
 * @ingroup compose
409
 */
410
function compose_cdm_team_or_person_base($team_or_person, $data = array()) {
411

    
412
  $groups = array();
413

    
414
  $label_suffix = ':';
415

    
416
  // $weight = 0;
417
  if($team_or_person){
418

    
419
    if(is_object($team_or_person->lifespan)){
420
      // ToDo render as date* - date† ?
421
      @_description_list_group_add($groups, t('Lifespan'). $label_suffix, timePeriodToString($team_or_person->lifespan) /*, '' , $weight++ */);
422
    }
423

    
424
    // nomenclaturalTitle
425
    @_description_list_group_add($groups, "Nomenclatural Title". $label_suffix, $team_or_person->nomenclaturalTitle);
426
    // collectorTitle
427
    @_description_list_group_add($groups, "Collector Title". $label_suffix, $team_or_person->collectorTitle);
428

    
429
    // institutionalMemberships
430
    if(is_array($team_or_person->institutionalMemberships)){
431

    
432
      $institutes_ra =  array();
433
      foreach($team_or_person->institutionalMemberships as $membership) {
434
        $membership_groups = array();
435
        @_description_list_group_add($membership_groups, t('Department'). $label_suffix, $membership->department);
436
        @_description_list_group_add($membership_groups, t('Role'). $label_suffix, $membership->role);
437
        if(is_object($membership->period)){
438
          @_description_list_group_add($membership_groups, t('Period'). $label_suffix, timePeriodToString($membership->period));
439
        }
440
        if(is_object($membership->institute->contact)){
441
          $institute_contact_details = compose_cdm_contact($membership->institute->contact, $membership->institute->titleCache);
442
          if(is_array($institute_contact_details[0]['#groups'])){
443
            $membership_groups = array_merge($membership_groups, $institute_contact_details[0]['#groups']);
444
          }
445
        }
446
        if(count($membership_groups) > 0){
447
          $institutes_ra[]  = array(
448
            '#title' => $membership->institute->titleCache,
449
            '#theme' => 'description_list',
450
            '#groups' => $membership_groups,
451
            '#attributes' => array('class' => html_class_attribute_ref($membership)),
452
            '#wrapper_attributes' => array('class' => 'sublist-container')
453
          );
454
        } else {
455
          // no further details for the membership, display the title
456
          $institutes_ra[] = markup_to_render_array('<h3>' . $membership->institute->titleCache . '</h3>');
457
        }
458

    
459
      }
460

    
461
      $label = count($institutes_ra) > 1 ? t('Institutes'):  t('Institute');
462
      @_description_list_group_add($groups, $label. $label_suffix, $institutes_ra /*, '' , $weight++ */);
463
    }
464

    
465

    
466
    // Contact
467
    $agent_contact_details = compose_cdm_contact($team_or_person->contact, $team_or_person->titleCache);
468
    if(is_array($agent_contact_details[0]['#groups'])){
469
      $groups = array_merge($groups, $agent_contact_details[0]['#groups']);
470
    }
471

    
472
    // additional data
473
    foreach($data as $key=>$value){
474
      @_description_list_group_add($sub_dl_groups, t('@key', array('@key' => $key)), $value /*, '' , $weight++ */);
475
    }
476

    
477
  }
478

    
479
  $team_or_person_details = array(
480
    '#title' => $team_or_person->titleCache,
481
    '#theme' => 'description_list',
482
    '#groups' => $groups,
483
    '#attributes' => array('class' => html_class_attribute_ref($team_or_person)),
484
  );
485
  return array($team_or_person_details);
486
}
487

    
488

    
489
/*
490
 * Compose an render array from a CDM Contact object.
491
 *
492
 * compose_hook() implementation
493
 *
494
 * TODO: currently mainly implemented for Agent, add Team details
495
 *
496
 * @param object $contact
497
 *   CDM instance of type Contact
498
 * @param $title
499
 *   The title for the description list header
500
 * @param $weight
501
 *   Optional weight for the description list entries
502
 * @return array
503
 *   A drupal render array
504
 *
505
 * @ingroup compose
506
 */
507
function compose_cdm_contact($contact, $title, $weight = 0)
508
{
509

    
510
  $groups = array();
511

    
512
  $label_suffix = ':';
513

    
514
  $contact_field_names_map = array(
515
    'emailAddresses' => t('Email'),
516
    'urls' => t('Urls'),
517
    'phoneNumbers' => t('Phone'),
518
    'faxNumbers' => t('Fax'),
519
  );
520

    
521
  // Contact
522
  if(is_object($contact)){
523
    if(isset($contact->addresses)){
524
      // TODO ....
525
      // $sub_groups = array();
526
      // foreach($contact->addresses as $address){
527
      //   @_description_list_group_add($sub_groups, $label, $contact->$fieldName, '', $weight++);
528
      // }
529
    }
530
    foreach($contact_field_names_map as $fieldName => $label){
531
      if(is_array($contact->$fieldName)){
532
        @_description_list_group_add($groups, $label . $label_suffix, $contact->$fieldName, '', $weight++);
533
      }
534
    }
535
    $contact_details = array(
536
      '#title' => $title,
537
      '#theme' => 'description_list',
538
      '#groups' => $groups
539
    );
540

    
541

    
542
  } else if(is_string($title)) {
543
    // if the contact entity is empty but the title is given anyway
544
    // we are only adding the title, using the description_list
545
    // structure is not possible since it would be empty due to
546
    // missing group data
547
    $contact_details = array('#markup' => '<h3>' . $title . '</h3>');
548
  }
549

    
550
  return array($contact_details);
551

    
552
}
(1-1/10)