Project

General

Profile

Download (76.4 KB) Statistics
| Branch: | Tag: | Revision:
1 6657531f Andreas Kohlbecker
<?php
2
/**
3
 * @file
4
 * Module to provide a CDM Dataportal.
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
 *   - Wouter Addink <w.addink@eti.uva.nl> (migration from Drupal 5 to Drupal7)
18
 */
19
20 38b27a36 Andreas Kohlbecker
  module_load_include('php', 'cdm_dataportal', 'node_types');
21
  module_load_include('php', 'cdm_dataportal', 'settings');
22
  module_load_include('php', 'cdm_dataportal', 'help');
23
  module_load_include('php', 'cdm_dataportal', 'cdm_dataportal.search');
24
25
  module_load_include('inc', 'cdm_dataportal', 'includes/common');
26 2e31ea9e Andreas Kohlbecker
  module_load_include('inc', 'cdm_dataportal', 'includes/name');
27 b7a20282 Andreas Kohlbecker
  module_load_include('inc', 'cdm_dataportal', 'includes/taxon');
28
  module_load_include('inc', 'cdm_dataportal', 'includes/references');
29 38b27a36 Andreas Kohlbecker
  module_load_include('inc', 'cdm_dataportal', 'includes/pages');
30
  module_load_include('inc', 'cdm_dataportal', 'includes/media');
31
  module_load_include('inc', 'cdm_dataportal', 'includes/maps');
32
  module_load_include('inc', 'cdm_dataportal', 'includes/occurrences');
33
  module_load_include('inc', 'cdm_dataportal', 'includes/descriptions');
34
  module_load_include('inc', 'cdm_dataportal', 'includes/pre-drupal8');
35
36
  module_load_include('inc', 'cdm_dataportal', 'theme/theme_registry');
37
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.common');
38
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.descriptions');
39
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.media');
40
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.occurrence');
41
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.page');
42
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.taxon');
43
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.name');
44
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.references');
45
46
  module_load_include('php', 'cdm_dataportal', 'classes/footnotemanager');
47
  module_load_include('php', 'cdm_dataportal', 'classes/footnote');
48
  module_load_include('php', 'cdm_dataportal', 'classes/footnotekey');
49
  module_load_include('php', 'cdm_dataportal', 'classes/renderhints');
50
51
52
  /* ============================ java script functions ============================= */
53
54
55
  /**
56
  * loads external java script files asynchronously.
57
  *
58
  * @param unknown_type $script_url
59
  */
60
  function drupal_add_js_async($script_url, $callback){
61
62
    drupal_add_js("
63
          jQuery(document).ready(function() {
64
            jQuery.ajax({
65
              url: '" . $script_url . "',
66
              dataType: 'script',
67
              cache: true, // otherwise will get fresh copy every page load
68
              success: function() {
69
                    " . $callback . "
70
              }
71
            });
72
          });"
73
    , 'inline');
74 6657531f Andreas Kohlbecker
  }
75
76 38b27a36 Andreas Kohlbecker
  /**
77
   */
78
  function drupal_add_js_rowToggle($tableId){
79 6657531f Andreas Kohlbecker
80 38b27a36 Andreas Kohlbecker
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/table_modification.js');
81
      drupal_add_js('jQuery(document).ready(function(){
82
          addRowToggle("' . $tableId . '");
83 6657531f Andreas Kohlbecker
      });
84 38b27a36 Andreas Kohlbecker
      ', array('type' => 'inline'));
85
  }
86 d2fd2a4c Andreas Kohlbecker
87 38b27a36 Andreas Kohlbecker
  /**
88
   * @param unknown_type $link_element_selector
89
   * @param unknown_type $progress_element_selector
90
   */
91
  function _add_js_cdm_ws_progressbar($link_element_selector, $progress_element_selector){
92
93
    $callback = "jQuery('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');";
94
95
    drupal_add_js_async(variable_get('cdm_webservice_url', '').'js/cdm_ws_progress.js', $callback);
96
97
    //   drupal_add_js("
98
    //   	  if (Drupal.jsEnabled) {
99
    //         $(document).ready(function() {
100
    //       		$('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');
101
    //         });
102
    //       }", 'inline');
103
    }
104
105
  /**
106
   * @todo Please document this function.
107
   * @see http://drupal.org/node/1354
108
   */
109
  function _add_js_treeselector() {
110
    // drupal_add_js(drupal_get_path('module', 'cdm_dataportal').'/js/treeselector.js');
111
    drupal_add_js("
112
        jQuery(document).ready(function() {
113
           jQuery('#cdm-taxonomictree-selector-form #edit-val').change(function () {
114
                jQuery('#cdm-taxonomictree-selector-form').submit();
115
            });
116
117
        });
118
      ",
119
      array(
120
        'type' => 'inline',
121
        'scope' => 'footer'
122
      )
123
    );
124 5ea8b301 Andreas Kohlbecker
  }
125
126 38b27a36 Andreas Kohlbecker
  function _add_js_openlayers() {
127
128
    $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.js';
129
    $proj4js = '/js/map/proj4js-1.1.0/proj4js-compressed.js';
130
131
    if(variable_get('cdm_js_devel_mode', FALSE)){
132
      // develooper mode libs
133
  //     $openlayers = '/js/map/OpenLayers-2.13.1/lib/OpenLayers.js';
134
      $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.debug.js';
135
      $proj4js = '/js/map/proj4js-1.1.0/proj4js-combined.js';
136
    }
137
138
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $openlayers,
139
      array(
140
        'type' => 'file',
141
        'weight' => JS_LIBRARY,
142
        'cache' => TRUE,
143
        'preprocess' => FALSE
144
      )
145
    );
146
147
    // see https://github.com/proj4js/proj4js
148
    // http://openlayers.org/dev/examples/using-proj4js.html
149
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $proj4js,
150
      array(
151
        'type' => 'file',
152
        'weight' => JS_LIBRARY,
153
        'cache' => TRUE,
154
      )
155
    );
156
157
    // configure the theme
158
    $openlayers_theme_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/OpenLayers-2.13.1/theme/default/';
159
    $openlayers_imp_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/img/dark/';
160
    drupal_add_js('OpenLayers.ImgPath="' . base_path() . $openlayers_imp_path . '";', array(
161
        'type' => 'inline',
162
        'weight' => JS_LIBRARY,
163
        'cache' => TRUE,
164
        'preprocess' => FALSE
165
      ));
166
167
    drupal_add_css($openlayers_theme_path . 'style.tidy.css',
168
      array(
169
        'type' => 'file',
170
        'cache' => TRUE,
171
        'preprocess' => FALSE
172
      )
173
    );
174 e3026d72 Andreas Kohlbecker
175 38b27a36 Andreas Kohlbecker
  }
176 e3026d72 Andreas Kohlbecker
177 38b27a36 Andreas Kohlbecker
  /**
178
   * @todo Please document this function.
179
   * @see http://drupal.org/node/1354
180
   */
181
  function _add_js_thickbox() {
182
    // ---- jQuery thickbox:
183
    /*
184
    * bug: compat-1.0.js && thickbox.js line 237 .trigger("unload") -> event is
185
    * not triggered because of problems with compat-1.0.js' see INSTALL.txt
186
    */
187
    // drupal_add_js(drupal_get_path('module',
188
    // 'cdm_dataportal').'/js/jquery.imagetool.min.js');
189
    //
190
    // Add a setting for the path to cdm_dataportal module, used to find the path
191
    // for the loading animation image in thickbox.
192
    drupal_add_js(array(
193
    'cdm_dataportal' => array(
194
    'cdm_dataportal_path' => base_path() . drupal_get_path('module', 'cdm_dataportal'),
195 10f6aa4b Andreas Kohlbecker
    )
196 38b27a36 Andreas Kohlbecker
    ),
197
    'setting'
198
        );
199
        drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/thickbox.js');
200
        drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/cdm_thickbox.css');
201
  }
202 94550ff9 Andreas Kohlbecker
203 38b27a36 Andreas Kohlbecker
  /**
204
   * @todo Please document this function.
205
   * @see http://drupal.org/node/1354
206
   */
207
  function _add_js_lightbox($galleryID) {
208
    /*
209
     * Important Notice: The jquery.lightbox-0.5.js has been modified in order to
210
    * allow using the "alt" attribute for captions instead of the "title"
211
    * attribute
212
    */
213
    $lightbox_base_path =  drupal_get_path('module', 'cdm_dataportal') . '/js/jquery-lightbox-0.5';
214
    $lightbox_image_path = base_path() . $lightbox_base_path . '/images/';
215
    drupal_add_js($lightbox_base_path . '/js/jquery.lightbox-0.5.js');
216
    drupal_add_css($lightbox_base_path . '/css/jquery.lightbox-0.5.css');
217
    drupal_add_js('jQuery(document).ready(function() {
218
        jQuery(\'#' . $galleryID . ' a.lightbox\').lightBox({
219
          fixedNavigation:  true,
220
          imageLoading:     \'' . $lightbox_image_path . 'lightbox-ico-loading.gif\',
221
          imageBtnPrev:     \'' . $lightbox_image_path . 'lightbox-btn-prev.gif\',
222
          imageBtnNext:     \'' . $lightbox_image_path . 'lightbox-btn-next.gif\',
223
          imageBtnClose:    \'' . $lightbox_image_path . 'lightbox-btn-close.gif\',
224
          imageBlank:       \'' . $lightbox_image_path . 'lightbox-blank.gif\',
225
          adjustToWindow: true
226
        });
227 94550ff9 Andreas Kohlbecker
      });
228 38b27a36 Andreas Kohlbecker
      ', array('type' => 'inline'));
229
  }
230 94550ff9 Andreas Kohlbecker
231 38b27a36 Andreas Kohlbecker
  /**
232
   * @todo Please document this function.
233
   * @see http://drupal.org/node/1354
234
   */
235
  function _add_js_footnotes() {
236
    _add_js_domEvent();
237
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/footnotes.js');
238
  }
239 94550ff9 Andreas Kohlbecker
240 38b27a36 Andreas Kohlbecker
  /**
241
   * @todo Please document this function.
242
   * @see http://drupal.org/node/1354
243
   */
244
  function _add_js_cluetip() {
245
246
    // TODO replace by
247
    // @see http://www.socialembedded.com/labs/jQuery-Tooltip-Plugin/jQuery-Tooltip-Plugin.html
248
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.min.js');
249
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/jquery.dimensions.js');
250
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.hoverIntent.js');
251
    if(variable_get('cdm_js_devel_mode', FALSE)){
252
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.js');
253
    }
254
    drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.css');
255
    drupal_add_js("jQuery(document).ready(function(){
256
        jQuery('.cluetip').css({color: '#0062C2'}).cluetip({
257
          splitTitle: '|',
258
          showTitle: true,
259
          activation: 'hover',
260
          sicky: true,
261
          arrows: true,
262
          dropShadow: false,
263
          cluetipClass: 'rounded'
264
        });
265
      });", array('type' => 'inline'));
266 5ea8b301 Andreas Kohlbecker
  }
267 94550ff9 Andreas Kohlbecker
268 38b27a36 Andreas Kohlbecker
  /**
269
   * @todo Please document this function.
270
   * @see http://drupal.org/node/1354
271
   */
272
  function _add_js_ahah() {
273 b386ae48 Andreas Kohlbecker
274 38b27a36 Andreas Kohlbecker
    _add_js_domEvent(); // requires domEvent.js
275
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/ahah-content.js');
276
  }
277 94550ff9 Andreas Kohlbecker
278 38b27a36 Andreas Kohlbecker
  /**
279
   * Adds the external javascript file for domEvent.js.
280
   *
281
   * @see drupal_add_js()
282
   */
283
  function _add_js_domEvent() {
284
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/domEvent.js');
285
  }
286 b386ae48 Andreas Kohlbecker
287 087bb473 Andreas Kohlbecker
  function _add_jquery_ui()
288
  {
289
    drupal_add_css(drupal_get_path('module',
290
        'cdm_dataportal') . '/js/jquery-ui-1.8.24/themes/base/jquery.ui.all.css');
291
    drupal_add_js(drupal_get_path('module',
292
        'cdm_dataportal') . '/js/jquery-ui-1.8.24/ui/jquery-ui.js',
293
      array(
294
        'type' => 'file',
295
        'weight' => JS_LIBRARY,
296
        'cache' => TRUE,
297
        'preprocess' => FALSE
298
      )
299
    );
300
  }
301
302 38b27a36 Andreas Kohlbecker
  /**
303
   * Provides the markup for an font awesome icon.
304
   *
305
   * The icons is created in default size without any extra features.
306
   *
307
   * The available icons are listed here http://fontawesome.io/cheatsheet/
308 ef12d0c6 Andreas Kohlbecker
   * fontawesome icons have much more features than implemented here in this function,
309
   * for spinning icons, fixed width icons, rotation, etc please checkout the
310 38b27a36 Andreas Kohlbecker
   * examples at http://fontawesome.io/examples/
311
   *
312
   * @parameter $icon_name
313
   *  The name of the icon which starts with 'fa-'
314
   *
315
   * @return String
316
   *    the markup for the icon in an <i> tag
317
   *
318
   */
319 b0aa9a8f Andreas Kohlbecker
  function font_awesome_icon_markup($icon_name = NULL, $attributes = array()){
320 38b27a36 Andreas Kohlbecker
321
322
    //<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
323
324 b0aa9a8f Andreas Kohlbecker
    $font_awesome_css_uri=drupal_get_path('module', 'cdm_dataportal').'/font-awesome/4.5.0/css/font-awesome.min.css';
325
    $font_awesome_css_uri="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css";
326 38b27a36 Andreas Kohlbecker
327
    drupal_add_html_head_link(
328
      array(
329
        'href' => $font_awesome_css_uri,
330
        'rel' => 'stylesheet'
331
      )
332
    );
333
334 b0aa9a8f Andreas Kohlbecker
    if($icon_name){
335
      if(!isset($attributes['class'])){
336
        $attributes['class'] = array();
337
      }
338
      $attributes['class'][] = 'fa';
339
      $attributes['class'][] = $icon_name;
340
341
      return '<i ' . drupal_attributes($attributes) . '></i>';
342 38b27a36 Andreas Kohlbecker
    }
343
344 b0aa9a8f Andreas Kohlbecker
    return '';
345 38b27a36 Andreas Kohlbecker
  }
346 94550ff9 Andreas Kohlbecker
347 38b27a36 Andreas Kohlbecker
348
  /* ====================== hook implementations ====================== */
349
  /**
350
   * Implements hook_permission().
351
   *
352
   * Valid permissions for this module.
353
   *
354
   * @return array
355
   *   An array of valid permissions for the portfolio module.
356
   */
357
  function cdm_dataportal_permission() {
358
    return array(
359
      'administer cdm_dataportal' => array(
360
        'title' => t('administer cdm_dataportal'),
361
        'description' => t("TODO Add a description for 'administer cdm_dataportal'"),
362
      ),
363
      'cdm_dataportal view notes' => array(
364
        'title' => t('cdm_dataportal view notes'),
365
        'description' => t("TODO Add a description for 'cdm_dataportal view notes'"),
366
      ),
367
      // TODO Which other permissions are required?
368
      // -> check the WP6 requirements document.
369
    );
370
  }
371 6657531f Andreas Kohlbecker
372
/**
373 f19f47fa Andreas Kohlbecker
 * Implements hook_menu().
374
 */
375 6657531f Andreas Kohlbecker
function cdm_dataportal_menu() {
376
  $items = array();
377
378
  // @see settings.php.
379
  cdm_dataportal_menu_admin($items);
380
  cdm_dataportal_menu_help($items);
381
382
  $items['cdm_dataportal/names'] = array(
383
    'page callback' => 'cdm_dataportal_view_names',
384
    'access arguments' => array('access content'),
385
    'type' => MENU_CALLBACK,
386
  );
387
388
  // Optional callback arguments: page.
389
  $items['cdm_dataportal/taxon'] = array(
390
    'page callback' => 'cdm_dataportal_taxon_page_view',
391
    'access arguments' => array('access content'),
392
    'type' => MENU_CALLBACK,
393
    // Expected callback arguments: uuid.
394
  );
395
396 9d37c9d9 Patric Plitzner
   // Optional callback arguments: page.
397 d6d4cc03 Patric Plitzner
    //FIXME point to view/page method in this module
398 9d37c9d9 Patric Plitzner
    $items['cdm_dataportal/specimen'] = array(
399 b810158e Patric Plitzner
        'page callback' => 'cdm_dataportal_specimen_page_view',
400 9d37c9d9 Patric Plitzner
        'access arguments' => array('access content'),
401
        'type' => MENU_CALLBACK,
402
        // Expected callback arguments: uuid.
403
    );
404
405 6657531f Andreas Kohlbecker
  $items['cdm_dataportal/name'] = array(
406
    'page callback' => 'cdm_dataportal_name_page_view',
407
      /*
408
    'page arguments' => array(
409
       'taxon_name_uuid',
410
       'taxon_to_hide_uuid',
411
       'synonym_uuid' => NULL
412
      ),
413
      */
414
    'access arguments' => array('access content'),
415
    'type' => MENU_CALLBACK,
416
    // Expected callback arguments: uuid.
417
  );
418
419
  $items['cdm_dataportal/reference'] = array(
420
    'page callback' => 'cdm_dataportal_view_reference',
421
    'access arguments' => array('access content'),
422
    'type' => MENU_CALLBACK,
423
    // Expected callback arguments: uuid.
424
  );
425
426
  $items['cdm_dataportal/reference/list'] = array(
427
    'page callback' => 'cdm_dataportal_view_reference_list',
428
    'access arguments' => array('access content'),
429
    'type' => MENU_CALLBACK,
430
    // Expected callback arguments: uuid.
431
  );
432
433
  $items['cdm_dataportal/media'] = array(
434
    'page callback' => 'cdm_dataportal_view_media',
435
    'access arguments' => array('access content'),
436
    'type' => MENU_CALLBACK,
437
    // Expected callback arguments:
438
    // uuid, mediarepresentation_uuid, part_uuid or part#.
439
  );
440
441
  $items['cdm_dataportal/polytomousKey'] = array(
442
    'page callback' => 'cdm_dataportal_view_polytomousKey',
443
    'access arguments' => array('access content'),
444
    'type' => MENU_CALLBACK,
445
    // Expected callback arguments: polytomousKey->uuid.
446
  );
447
448
  $items['cdm_dataportal/search'] = array(
449
    'page callback' => 'cdm_dataportal_view_search_advanced',
450
    'access arguments' => array('access content'),
451
    'type' => MENU_CALLBACK,
452
  );
453
454
  $items['cdm_dataportal/search/advanced'] = array(
455 a49b6521 Andreas Kohlbecker
    'title' => 'Advanced tt', // will be passed through t()
456
   // 'title arguments' => array('!title' => 'Advanced tt'), // will be passed through t()
457 6657531f Andreas Kohlbecker
    'page callback' => 'cdm_dataportal_view_search_advanced',
458
    'access arguments' => array('access content'),
459
    'type' => MENU_DEFAULT_LOCAL_TASK,
460
  );
461
462
  $items['cdm_dataportal/search/taxon_by_description'] = array(
463 a49b6521 Andreas Kohlbecker
    'title' => 'By factual data tt', // will be passed through t()
464
    'title arguments' => array('!title' => 'By factual data tt'), // will be passed through t()
465 6657531f Andreas Kohlbecker
    'page callback' => 'cdm_dataportal_view_search_taxon_by_description',
466
    'access arguments' => array('access content'),
467
    'type' => MENU_LOCAL_TASK,
468
  );
469
470
  $items['cdm_dataportal/search/results/taxon'] = array(
471
    'page callback' => 'cdm_dataportal_view_search_results_taxon',
472
    'access arguments' => array('access content'),
473
    'type' => MENU_CALLBACK,
474
  );
475
  /*
476
   $items['cdm/xml2json'] = array(
477
   'page callback' => 'cdm_view_xml2json',
478
   'access arguments' => array('access content'),
479
   'type' => MENU_CALLBACK,
480
   );
481
   */
482
483
  // if (arg(0)=='user' && ($uid=arg(1)) && is_numeric($uid)) {
484
  // User configuration of cdm_dataportal.
485
  $items['user/%/cdm_dataportal'] = array(
486
    'title' => 'cdm_dataportal',
487
    'access arguments' => array('access content'),
488
    'page callback' => 'drupal_get_form',
489
    'page arguments' => array('cdm_dataportal_user_form'),
490
    'type' => MENU_LOCAL_TASK,
491
    'weight' => 10,
492
  );
493
  // }
494
495
  // 'May not cache' in D5.
496
  $items['cdm_dataportal/name/%'] = array(
497
    // 'page callback' => 'cdm_dataportal_view_name',
498
    'page callback' => 'cdm_dataportal_name_page_view',
499
    'page arguments' => array(2, 3, 4),
500
    'access arguments' => array('access content'),
501
    'type' => MENU_CALLBACK,
502
  );
503
504 6f1a217c Andreas Kohlbecker
  // --- Local tasks for Taxon.
505
  // --- tabbed taxon page
506 6657531f Andreas Kohlbecker
  if (variable_get('cdm_dataportal_taxonpage_tabs', 1)) {
507
    $items['cdm_dataportal/taxon/%'] = array(
508
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
509
      'page callback' => 'cdm_dataportal_taxon_page_view',
510
      'access arguments' => array('access content'),
511
      'type' => MENU_CALLBACK,
512
      'weight' => 1,
513
      'page arguments' => array(2, "description")
514 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
515 6657531f Andreas Kohlbecker
    );
516
517
    $items['cdm_dataportal/taxon/%/all'] = array(
518
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
519
      'page callback' => 'cdm_dataportal_taxon_page_view',
520
      'access arguments' => array('access content'),
521
      'type' => MENU_CALLBACK,
522
      'weight' => 2,
523
      'page arguments' => array(2, "all")
524 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
525 6657531f Andreas Kohlbecker
    );
526
527
    $items['cdm_dataportal/taxon/%/description'] = array(
528
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
529
      'page callback' => 'cdm_dataportal_taxon_page_view',
530
      'access arguments' => array('access content'),
531
      'type' => MENU_DEFAULT_LOCAL_TASK,
532
      'weight' => 2,
533
      'page arguments' => array(2, "description")
534 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
535 6657531f Andreas Kohlbecker
    );
536
537
    $items['cdm_dataportal/taxon/%/synonymy'] = array(
538
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Synonymy')),
539
      'page callback' => 'cdm_dataportal_taxon_page_view',
540
      'access arguments' => array('access content'),
541
      'type' => MENU_LOCAL_TASK,
542
      'weight' => 4,
543
      'page arguments' => array(2, "synonymy", 4)
544 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid and ...
545 6657531f Andreas Kohlbecker
    );
546
    $items['cdm_dataportal/taxon/%/images'] = array(
547
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Images')),
548
      'page callback' => 'cdm_dataportal_taxon_page_view',
549
      'access arguments' => array('access content'),
550
      'type' => MENU_LOCAL_TASK,
551
      'weight' => 5,
552
      'page arguments' => array(2, "images")
553 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
554 6657531f Andreas Kohlbecker
    );
555
556
    $items['cdm_dataportal/taxon/%/specimens'] = array(
557
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Specimens')),
558
      'page callback' => 'cdm_dataportal_taxon_page_view',
559
      'access arguments' => array('access content'),
560
      'type' => MENU_LOCAL_TASK,
561
      'weight' => 6,
562
      'page arguments' => array(2, "specimens")
563 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
564 6657531f Andreas Kohlbecker
    );
565
566
    $items['cdm_dataportal/taxon/%/keys'] = array(
567
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Keys')),
568
      'page callback' => 'cdm_dataportal_taxon_page_view',
569
      'access arguments' => array('access content'),
570
      'type' => MENU_LOCAL_TASK,
571
      'weight' => 6,
572
      'page arguments' => array(2, "keys")
573 7663cd0b Andreas Kohlbecker
      , // Expected callback arguments: taxon_uuid.
574
    );
575
576
    $items['cdm_dataportal/taxon/%/experts'] = array(
577
        'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Experts')),
578
        'page callback' => 'cdm_dataportal_taxon_page_view',
579
        'access arguments' => array('access content'),
580
        'type' => MENU_LOCAL_TASK,
581
        'weight' => 6,
582
        'page arguments' => array(2, "experts")
583
    , // Expected callback arguments: taxon_uuid.
584 6657531f Andreas Kohlbecker
    );
585
  }
586
587 6f1a217c Andreas Kohlbecker
  // --- refresh link for all cdmnode types
588
  foreach (cdm_get_nodetypes() as $type=>$name) {
589
    $items['cdm_dataportal/' . $name . '/%/refresh'] = array(
590
        'title' => t('Refresh'),
591
        'page callback' => 'cdm_dataportal_refresh_node',
592 3113db26 Andreas Kohlbecker
        'access arguments' => array('administer cdm_dataportal'),
593 6f1a217c Andreas Kohlbecker
        'type' => MENU_LOCAL_TASK,
594
        'weight' => 100,
595
        'page arguments' => array($name, 2)
596
    );
597
  }
598
599 6657531f Andreas Kohlbecker
  return $items;
600
}
601
602
/**
603 b85ab055 Andreas Kohlbecker
 * Implements hook_init().
604
 *
605 6657531f Andreas Kohlbecker
 */
606
function cdm_dataportal_init() {
607 5ea8b301 Andreas Kohlbecker
  //FIXME To add CSS or JS that should be present on all pages, modules
608
  //      should not implement this hook, but declare these files in their .info file.
609 6657531f Andreas Kohlbecker
  drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal.css');
610
  // drupal_add_css(drupal_get_path('module', 'cdm_dataportal').'/cdm_dataportal_print.css', 'print');
611
  drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal_screen.css', array('type' => 'screen'));
612 2dd59bb5 Andreas Kohlbecker
613
  if(variable_get('cdm_debug_mode', FALSE)){
614
    $file = 'temporary://drupal_debug.txt';
615
    file_put_contents($file, 'CDM DEBUG LOG for ' . $_GET['q']. "\n"); // will overwrite the file
616
  }
617 5611d467 Andreas Kohlbecker
618
  $bibliography_settings = get_bibliography_settings();
619 57d513cb Andreas Kohlbecker
  $enclosing_tag = $bibliography_settings['enabled'] == 1 ? 'div' : 'span';
620
  FootnoteManager::registerFootnoteSet('BIBLIOGRAPHY', $enclosing_tag, $bibliography_settings['key_format']);
621 6657531f Andreas Kohlbecker
}
622
623 6f1a217c Andreas Kohlbecker
function cdm_dataportal_refresh_node($cdm_node_name, $uuid, $parameters = array()){
624
625
  $base_path = 'cdm_dataportal/' . $cdm_node_name . '/' . $uuid;
626
627
  if($cdm_node_name == 'taxon' && variable_get('cdm_dataportal_taxonpage_tabs', 1)){
628
    // force reloading of all and notify user about this special loading
629
    drupal_set_message(t('The level 2 cache has been cleared for all tabs of this taxon page at once, please click here to return to the tabbed page: ')
630
        . l('Back to tabbed taxon page', $base_path));
631
    $base_path .= '/all';
632
  } else {
633
    drupal_set_message(t('The level 2 cache has been cleared for this page'));
634
  }
635
636
  $parameters['cacheL2_refresh'] ='1';
637
638
639
  drupal_goto($base_path, array('query' => $parameters));
640
}
641
642 6657531f Andreas Kohlbecker
/**
643
 * The function generate form for own user cdm dataportal configurations.
644
 */
645
function cdm_dataportal_user_form($form, &$form_state) {
646 36818236 Andreas Kohlbecker
647 6657531f Andreas Kohlbecker
  global $user;
648
  $checkbox_value = 'cdm_dataportal_' . $user->uid . '_default_tab_active';
649
650 8e1dc7ec Andreas Kohlbecker
  $form['taxon_page_tabs'] = array(
651
      '#type' => 'fieldset',
652 36818236 Andreas Kohlbecker
      '#tree' => true,
653 8e1dc7ec Andreas Kohlbecker
      '#title' => t('Taxon page tabs'),
654
  );
655 36818236 Andreas Kohlbecker
656
  $form['taxon_page_tabs']['user_defined'] = array(
657 6657531f Andreas Kohlbecker
    '#type' => 'checkbox',
658
    '#title' => t('Activate user default configuration'),
659
    '#default_value' => variable_get($checkbox_value, 0),
660
    '#description' => t('Check this if you want configure your own default tab from the below menu.'),
661
  );
662
663 36818236 Andreas Kohlbecker
  $form['taxon_page_tabs']['default_tab'] = array(
664 6657531f Andreas Kohlbecker
    '#type' => 'select',
665
    '#title' => t('Default tab to display'),
666
    '#default_value' => get_default_taxon_tab(TRUE),
667
    '#options' => unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB),
668
    '#description' => t('<p>Select the default tab to display when visiting a taxon page. Only available if Tabbed Taxon Page is enable.</p>
669
              <strong>Note:</strong> After performing a search and clicking in any synonym, the taxon tab
670 36818236 Andreas Kohlbecker
              to be rendered will be the synonymy of the accepted taxon and not the above selected tab.'),
671
  );
672
673
674 f695daf4 Andreas Kohlbecker
  if(false){
675
    $form['developer_options'] = array(
676
        '#type' => 'fieldset',
677
        '#tree' => true,
678
        '#title' => t('Developer options'),
679
    );
680
681
    $form['developer_options']['show_render_path'] = array(
682
      '#type' => 'checkbox',
683
      '#title' => t('Display the render path for each taxon name.'),
684
      '#default_value' => variable_get($checkbox_value, 0),
685
      '#description' => t('This option is very helpful if you are editing the !link for taxon names.',
686
        array(
687
            '!link' => l(
688
              'render template', 'admin/config/cdm_dataportal/settings/layout', array('fragment' => 'edit-cdm-name-render-templates'))
689
            )
690
        ),
691
    );
692
  }
693 6657531f Andreas Kohlbecker
694
  $form['submit'] = array(
695
    '#type' => 'submit',
696
    '#value' => t('Submit'),
697
  );
698
699
  return $form;
700
}
701
702
/**
703
 * Form submission handler for user_form().
704
 *
705
 * Submits the user cdm dataportal configurations.
706
 */
707
function cdm_dataportal_user_form_submit($form, &$form_state) {
708
  global $user;
709
  $msg_type = 'status';
710
  $username = $user->name;
711
  $variable_to_use = 'cdm_dataportal_' . $user->uid . '_default_tab';
712
713 36818236 Andreas Kohlbecker
  // FIXME: this is completely wrong, see user_profile_form_submit()
714
715
  // it is only possible to change own user settings
716
  if (arg(0) == 'user' && is_numeric(arg(1)) && $user->uid == arg(1)) {
717
718
    // DEFAULT_TAXON_TAB
719 6657531f Andreas Kohlbecker
    $variable = unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB);
720 36818236 Andreas Kohlbecker
    variable_set($variable_to_use . '_active', $form_state['values']['taxon_page_tabs']['user_defined']);
721
    variable_set($variable_to_use, $form_state['values']['taxon_page_tabs']['default_tab']);
722
    if ($form_state['values']['taxon_page_tabs']['user_defined']) {
723 6657531f Andreas Kohlbecker
      drupal_set_message(check_plain(t('The user default tab will be used for the next taxon site visit.')));
724
      drupal_set_message(check_plain(t('The user default tab has been changed to: !tab for the user !user', array(
725
        '!tab' => $variable[variable_get($variable_to_use, 0)],
726
        '!user' => $username,
727
      ))), $msg_type);
728
    }
729
    else {
730
      drupal_set_message(check_plain(t('The user default tab wont be used for
731
        the next taxon site, check the box if you want to use the user default configuration.')));
732
    }
733 36818236 Andreas Kohlbecker
734 6657531f Andreas Kohlbecker
  }
735
  else {
736 36818236 Andreas Kohlbecker
    // Problem with the user id => variables wont be saved.
737 6657531f Andreas Kohlbecker
    $msg_type = 'warning';
738
    drupal_set_message(check_plain(t('Default tab has not been saved due to user id problems')), $msg_type);
739
  }
740
}
741
742
/**
743
 * Implements hook_block_info().
744
 */
745
function cdm_dataportal_block_info() {
746
747
    // $block[0]["info"] = t("CDM DataPortal DevLinks");
748
    // $block[1]["info"] = t("CDM DataPortal Credits");
749 fc13aa30 Andreas Kohlbecker
    $block["2"] = array(
750
        "info" => t("CDM Search Taxa"),
751
        "cache" => DRUPAL_NO_CACHE
752
      );
753 6657531f Andreas Kohlbecker
    // $block[3]["info"] = t("CDM Filters");
754
    $block["4"]["info"] = t("CDM Dataportal Print");
755
    $block["keys"]["info"] = t("CDM identification keys");
756
    $block["fundedByEDIT"]["info"] = t('Funded by EDIT');
757 f9a3d0f6 Andreas Kohlbecker
    $block["classification_breadcrumbs"] =  array(
758
        'info' => t('Classification breadcrumbs'),
759
        'cache' => DRUPAL_CACHE_PER_PAGE
760
      );
761 6657531f Andreas Kohlbecker
762
    return $block;
763
}
764
765
/**
766
 * Implements hook_block_view().
767
 */
768
function cdm_dataportal_block_view($delta) {
769
  // TODO Rename block deltas (e.g. '2') to readable strings.
770
  switch ($delta) {
771
    // case 'delta-1':
772
    // $block['subject'] = t('Credits');
773
    // $block['content'] = theme('cdm_credits');
774
    // return $block;
775
    case '2':
776
      $block['subject'] = t('Search taxa');
777 191f88fd Andreas Kohlbecker
      $form = drupal_get_form('cdm_dataportal_search_taxon_form');
778
      $block['content'] = drupal_render($form);
779 6657531f Andreas Kohlbecker
780
      if (variable_get('cdm_dataportal_show_advanced_search', 1)) {
781
        $block['content'] .= '<div>' . l(t('Advanced Search'), 'cdm_dataportal/search') . '</div>';
782
      }
783
      return $block;
784
    case '4':
785 c8234bdf Andreas Kohlbecker
      $block['subject'] = '';
786 6657531f Andreas Kohlbecker
      $block['content'] = theme('cdm_print_button');
787
      return $block;
788
    case "keys":
789
      $block['subject'] = t('Identification Keys');
790
      $block['content'] = theme('cdm_block_IdentificationKeys', array('taxonUuid' => NULL));
791
      return $block;
792
    case "fundedByEDIT":
793
      // t('Funded by EDIT');
794
      $text = '<none>';
795
      $block['subject'] = $text;
796 889c74b7 Andreas Kohlbecker
      $img_tag = '<img src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/powered_by_edit.png' . '" alt="' . $text . '"/>';
797
      $block['content'] = l($img_tag, "http://cybertaxonomy.org/", array(
798 6657531f Andreas Kohlbecker
        'attributes' => array("target" => "EDIT"),
799
        'absolute' => TRUE,
800
        'html' => TRUE,
801
      ));
802
      return $block;
803 f9a3d0f6 Andreas Kohlbecker
    case 'classification_breadcrumbs':
804
      if (arg(1) == 'taxon' && is_uuid(arg(2))) {
805
        $block['subject'] = '<none>';
806
        $block['content'] = compose_classification_breadcrumbs(arg(2));
807
        return $block;
808
      }
809
      break;
810 6657531f Andreas Kohlbecker
  }
811
}
812
813
/*
814
 function cdm_dataportal_session_clear($cdm_ws_uri_update = FALSE){
815
 $_SESSION['cdm'] = NULL;
816
 if(is_string($cdm_ws_uri_update)){
817
 $_SESSION['cdm'] = array('ws_uri'=>$cdm_ws_uri_update);
818
 }
819
 }
820
821
 function cdm_dataportal_session_validate(){
822
 if(!isset($_SESSION['cdm']['ws_uri'])){
823
 $_SESSION['cdm'] = array('ws_uri'=>variable_get('cdm_webservice_url', FALSE));
824
 } else if($_SESSION['cdm']['ws_uri'] != variable_get('cdm_webservice_url', FALSE)){
825
 cdm_dataportal_session_clear(variable_get('cdm_webservice_url', FALSE));
826
 }
827
 }
828
 */
829
830
/**
831 d7588d36 Andreas Kohlbecker
 * creates a  selector form for taxonomic trees.
832
 *
833
 * @return a drupal form array
834 6657531f Andreas Kohlbecker
 */
835
function cdm_taxonomictree_selector() {
836
  _add_js_treeselector();
837
838 a8a8f23c Andreas Kohlbecker
  $form = drupal_get_form('cdm_taxonomictree_selector_form');
839 d7588d36 Andreas Kohlbecker
  return $form;
840 6657531f Andreas Kohlbecker
}
841
842
/**
843
 * @todo Please document this function.
844
 * @see http://drupal.org/node/1354
845
 */
846
function cdm_taxonomictree_selector_form($form, &$form_state) {
847
848
  $url = url('cdm_api/setvalue/session', array('query' => NULL));
849
  $form['#action'] = $url;
850
851
  $form['var'] = array(
852
    '#weight' => -3,
853
    '#type' => 'hidden',
854
    '#value' => '[cdm][taxonomictree_uuid]',
855
  );
856
857
  $destination_array = drupal_get_destination();
858
  $destination = $destination_array['destination'];
859
860
  $form['destination'] = array(
861
    '#weight' => -3,
862
    '#type' => 'hidden',
863
    '#value' =>  $destination,
864
  );
865
866 26fb3778 Andreas Kohlbecker
  $options = cdm_get_taxontrees_as_options();
867
  $taxontree_includes = variable_get(CDM_TAXONTREE_INCLUDES, null);
868
  if($taxontree_includes){
869
    $filtered_options = array();
870
    foreach($options as $uuid=>$label){
871
      if(!empty($taxontree_includes[$uuid])){
872
        $filtered_options[$uuid] = $label;
873
      }
874
    }
875
    $options = $filtered_options;
876
  }
877
878 6657531f Andreas Kohlbecker
  $form['val'] = array(
879
    '#type' => 'select',
880
    '#title' => t('Available classifications'),
881 7663cd0b Andreas Kohlbecker
    '#default_value' => get_current_classification_uuid(),
882 26fb3778 Andreas Kohlbecker
    '#options' => $options,
883 088a7028 Andreas Kohlbecker
    '#attributes' => array('class' => array('highlite-first-child'))
884 6657531f Andreas Kohlbecker
  );
885
886
  return $form;
887
888
}
889
890
/* UNREACHABLE since action of form directly links to view.
891
 function cdm_dataportal_search_taxon_form_submit($form_id, $form_values) {
892
893
 $_SESSION['cdm']['search'] = $form_values;
894
 //return '/cdm_dataportal/search/taxon/'.$form_values['queryString'].'/'.($form_values['vernacular']?'1':'0').'/'.$form_values['language'];
895
 return '/cdm_dataportal/search/taxon/'.$form_values['queryString'].'/'.($form_values['onlyAccepted']?'1':'0');
896
 //$paramstr = compose_url_prameterstr($form_values);
897
 //return url('/cdm_dataportal/search/taxon/', array('query' => $paramstr));
898
 }
899
 */
900
/* ====================== menu callback functions ====================== */
901
/**
902
 * @todo Please document this function.
903
 * @see http://drupal.org/node/1354
904
 */
905
/*
906
function cdm_dataportal_form_alter(&$form, &$form_state, $form_id) {
907
  static $comment_node_disabled =  0;
908
  static $comment_node_read_only =  1;
909
  static $comment_node_read_write =  2;
910
911
  if ($form_id == 'node_type_form'
912
   && isset($form['identity']['type'])
913
   && array_key_exists($form['#node_type']->type, cdm_get_nodetypes())
914
  ) {
915
    $form['workflow']['comment'] = array(
916
      '#type' => 'radios',
917
      '#title' => t('Default comment setting'),
918
      '#default_value' => variable_get('comment__' . $node->type . $form['#node_type']->type, $comment_node_disabled),
919
      '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
920
      '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'),
921
    );
922
  }
923
}
924
*/
925
926
/**
927
 * Displays a list of the known taxonomic names.
928
 *
929
 * When the list of taxonomic names is displayed, long lists are split up into
930
 * multiple pages.
931
 *
932
 * TODO: Parameters are still preliminary.
933
 *
934
 * @param string $beginsWith
935
 * @param string $page
936
 *   Page number to diplay defaults to page 1.
937
 * @param bool $onlyAccepted
938
 */
939
function cdm_dataportal_view_names($beginsWith = 'A', $page = 1, $onlyAccepted = FALSE) {
940
941
  $out = t('<h3>Sorry, the name list feature is not yet available in this version of the DataPortal software<h3>');
942
943
  /*
944
  // FIXME the filter for accepted names will be a form element, thus this
945
  // widget should be generated via form api preferably as block.
946
  $out  = theme('cdm_dataportal_widget_filter_accepted', $onlyAccepted);
947
  $out .= theme('cdm_dataportal_widget_names_list', $names, $page);
948
  $out .= theme('cdm_listof_taxa', $taxonPager);
949
  return $out;
950
  */
951
}
952
953
/**
954
 * @todo Please document this function.
955
 * @see http://drupal.org/node/1354
956
 */
957
function cdm_dataportal_view_reference($uuid, $arg2 = NULL) {
958 f26245c8 Andreas Kohlbecker
959
  cdm_check_valid_portal_page();
960
961 6657531f Andreas Kohlbecker
  $reference = cdm_ws_get(CDM_WS_REFERENCE, $uuid);
962
  return theme('cdm_reference_page', array('reference' => $reference));
963
}
964
965
/**
966 b5dca1e2 Andreas Kohlbecker
 * Created a view on a all references contained in the portal.
967
 *
968
 * This function is used at the path cdm_dataportal/reference/list
969 6657531f Andreas Kohlbecker
 */
970
function cdm_dataportal_view_reference_list($pageNumber) {
971
  $referencePager = cdm_ws_page(CDM_WS_REFERENCE, variable_get('cdm_dataportal_search_items_on_page', CDM_DATAPORTAL_SEARCH_ITEMS_ON_PAGE), $pageNumber);
972
  return theme('cdm_reference_pager', array(
973
    'referencePager' => $referencePager,
974
    'path' => 'cdm_dataportal/reference/list/',
975
    ));
976
}
977
978
/**
979
 * @todo Please document this function.
980
 * @see http://drupal.org/node/1354
981
 */
982
function cdm_dataportal_view_media($mediaUuid, $mediarepresentation_uuid = FALSE, $part = 0) {
983 f26245c8 Andreas Kohlbecker
984
  cdm_check_valid_portal_page();
985
986 6657531f Andreas Kohlbecker
  $media = cdm_ws_get(CDM_WS_PORTAL_MEDIA, $mediaUuid);
987
  return theme('cdm_media_page', array(
988
    'media' => $media,
989
    'mediarepresentation_uuid' => $mediarepresentation_uuid,
990
    'partId' => $part,
991
    ));
992
}
993
994
/**
995
 * @todo Please document this function.
996
 * @see http://drupal.org/node/1354
997
 */
998
function _load_taxonBase(&$taxonBase) {
999
  if (isset($taxonBase->uuid)) {
1000
    $taxonBase->name = cdm_ws_get(CDM_WS_TAXON, array($taxonBase->uuid, "name"));
1001
    $taxonBase->name->taggedName = cdm_ws_get(CDM_WS_NAME, array($taxonBase->name->uuid, "taggedName"));
1002
    $taxonBase->name->nomenclaturalReference = cdm_ws_get(CDM_WS_NAME, array($taxonBase->name->uuid, "nomenclaturalReference"));
1003
  }
1004
}
1005
1006 9438ad3a Andreas Kohlbecker
/**
1007
 * Loads the media associated to the given taxon from the cdm server.
1008
 * The aggregation settings regarding taxon relathionships and
1009
 * taxonnomic childen are taken into account.
1010
 *
1011
 * The media lists are cached in a static variable.
1012
 *
1013
 * @param Taxon $taxon
1014
 *   A CDM Taxon entitiy
1015
 *
1016
 * @return array
1017
 *   An array of CDM Media entities
1018
 *
1019
 */
1020
function _load_media_for_taxon($taxon) {
1021
1022
  static $media = NULL;
1023
1024
  if(!isset($media)) {
1025
    $media = array();
1026
  }
1027
  if (!isset($media[$taxon->uuid])) {
1028
1029 f19f47fa Andreas Kohlbecker
    // --- GET Images --- //
1030
    $mediaQueryParameters = array(
1031
        "type" => "ImageFile",
1032
    );
1033
1034
    $relationship_choice = variable_get(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS, unserialize(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS_DEFAULT));
1035
    $mediaQueryParameters['relationships'] = implode(',', get_selection($relationship_choice['direct']));
1036 a950f2f9 Andreas Kohlbecker
    $mediaQueryParameters['relationshipsInvers'] = implode(',', get_selection($relationship_choice['invers']));
1037
1038
    $taxon_media_filter_choice = variable_get(CDM_TAXON_MEDIA_FILTER, unserialize(CDM_TAXON_MEDIA_FILTER_DEFAULT));
1039
    $mediaQueryParameters['includeTaxonDescriptions'] = (boolean) $taxon_media_filter_choice['includeTaxonDescriptions'] != 0;
1040
    $mediaQueryParameters['includeOccurrences'] = (boolean) $taxon_media_filter_choice['includeOccurrences'] != 0;
1041
    $mediaQueryParameters['includeTaxonNameDescriptions'] = (boolean) $taxon_media_filter_choice['includeTaxonNameDescriptions'] != 0;
1042 9438ad3a Andreas Kohlbecker
1043 f19f47fa Andreas Kohlbecker
    $ws_endpoint = NULL;
1044 9438ad3a Andreas Kohlbecker
    if ( variable_get('cdm_images_include_children', 0) == 0) {
1045
      $ws_endpoint = CDM_WS_PORTAL_TAXON_MEDIA;
1046
    } else {
1047
      $ws_endpoint = CDM_WS_PORTAL_TAXON_SUBTREE_MEDIA;
1048
    }
1049 f19f47fa Andreas Kohlbecker
1050
    $media[$taxon->uuid] = cdm_ws_get($ws_endpoint,
1051
        array(
1052
            $taxon->uuid,
1053
        ),
1054 9438ad3a Andreas Kohlbecker
        queryString($mediaQueryParameters)
1055
       );
1056
  }
1057
1058
  return $media[$taxon->uuid];
1059
}
1060
1061
/**
1062
 *
1063
 * @param Taxon $taxon
1064
 *   A CDM Taxon entitiy
1065
 *
1066
 * @return array
1067
 *   An array of CDM SpecimenOrObservation entities
1068
 *
1069
function _load_occurences_for_taxon($taxon){
1070
1071
  static $occurences = NULL;
1072 f19f47fa Andreas Kohlbecker
1073
  if(!isset($occurences)) {
1074
    $occurences = array();
1075
  }
1076 9438ad3a Andreas Kohlbecker
1077
  if (!isset($occurences[$taxon->uuid])){
1078
1079
    $relationship_choice = variable_get(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS, unserialize(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS_DEFAULT));
1080
    $relationship_choice['direct'] = get_selection($relationship_choice['direct']);
1081 f19f47fa Andreas Kohlbecker
    $relationship_choice['invers'] = get_selection($relationship_choice['invers']);
1082
1083
    $by_associatedtaxon_query = http_build_query(array(
1084
        'relationshipsInvers' => implode(',', $relationship_choice['invers']),
1085
        'relationships' => implode(',', $relationship_choice['direct']),
1086
        'pageSize' => null // all hits in one page
1087
    )
1088
    );
1089
1090
    $pager = cdm_ws_get(CDM_WS_OCCURRENCE_BY_ASSOCIATEDTAXON,
1091
        null,
1092
        $by_associatedtaxon_query . '&taxonUuid=' . $taxon->uuid
1093
    );
1094
1095
1096
    if(isset($pager->records[0])){
1097
      $occurences[$taxon->uuid] =  $pager->records;
1098
    }
1099
  }
1100 9438ad3a Andreas Kohlbecker
  return $occurences[$taxon->uuid];
1101
}
1102
 */
1103
1104 6657531f Andreas Kohlbecker
/**
1105
 * Gets a Drupal variable, string or array and returns it.
1106
 *
1107
 * Similar to the variable_get() function of Drupal, except that this function
1108
 * is able to handle arrays correctly. This function is especially useful
1109 8c962983 Andreas Kohlbecker
 * when dealing with collections of settings form elements (#tree = TRUE).
1110 6657531f Andreas Kohlbecker
 *
1111
 * @param string $variableKey
1112
 *   The Unique key of the Drupal variable in the Drupal variables table.
1113
 * @param string $defaultValueString
1114
 *   A string as for example derived from a CONSTANT.
1115
 *
1116
 * @return mixed
1117 8c962983 Andreas Kohlbecker
 *   usually an array, depending on the nature of the variable.
1118
 *
1119
 * TODO compare with get_array_variable_merged() duplicate functions?
1120 0f7c9d15 Andreas Kohlbecker
 * @deprecated rather use get_array_variable_merged() since this function
1121
 * used an array as second parameter
1122 6657531f Andreas Kohlbecker
 */
1123
function mixed_variable_get($variableKey, $defaultValueString) {
1124
  $systemDefaults = unserialize($defaultValueString);
1125
  $storedSettings = variable_get($variableKey, array());
1126
  if (is_array($storedSettings)) {
1127 8c962983 Andreas Kohlbecker
    // TODO better use drupal_array_merge_deep() ?
1128 6657531f Andreas Kohlbecker
    $settings = array_merge($systemDefaults, $storedSettings);
1129
  }
1130
  else {
1131
    $settings = $systemDefaults;
1132
  }
1133
  return $settings;
1134
}
1135
1136 b5519d3a Andreas Kohlbecker
/**
1137 0f7c9d15 Andreas Kohlbecker
 * Recursive function to convert an object into an array.
1138 b5519d3a Andreas Kohlbecker
 * also subordinate objects will be converted.
1139
 *
1140
 * @param object $object
1141
 * @return the array
1142
 */
1143
function convert_to_array($object) {
1144
  if(is_object($object) || is_array($object)) {
1145
    $array = (array)$object;
1146
    foreach ($array as $key=>$value){
1147
      $array[$key] = convert_to_array($value);
1148
    }
1149
    return $array;
1150
  } else {
1151
    return $object;
1152
  }
1153
}
1154
1155 2fd6da0b Andreas Kohlbecker
/**
1156
 * Searches the $collection for the cdm entitiy given as $element.
1157
 *
1158
 * The elements are compared by their UUID.
1159
 *
1160
 * @param $element
1161
 *  the CDM entitiy to search for
1162
 * @param $collection
1163
 *  the list of CDM entities to search in
1164
 *
1165
 * @return boolean TRUE if the $collection contains the $element, otheriwse FALSE
1166
 *
1167
 */
1168
function contains_cdm_entitiy($element, $collection) {
1169
  $result = FALSE;
1170
  foreach ($collection as $a) {
1171
    if ($a->uuid == $element->uuid) {
1172
      $result = TRUE;
1173
    }
1174
  }
1175
  return $result;
1176
}
1177
1178
/**
1179
 * Fiters the array $entity_list of CDM entities by the list
1180
 * of $excludes. Any element contained in the $excludes will be removed
1181
 * from included int the retuned list.
1182
 *
1183
 * If the $entity_list is not an array the $excludes will be returned.
1184
 */
1185
function filter_cdm_entity_list($entity_list, $excludes) {
1186
  if (is_array($entity_list)) {
1187
    $result = $entity_list;
1188
    if ($excludes) {
1189
      foreach ($excludes as $exclude) {
1190
        if (!contains_cdm_entitiy($exclude, $entity_list)) {
1191
          $result[] = $exclude;
1192
        }
1193
      }
1194
    }
1195
  }
1196
  else {
1197
    $result = $excludes;
1198
  }
1199
  return $result;
1200
}
1201
1202 0a1151a4 Andreas Kohlbecker
/**
1203 6f5c7f2a Andreas Kohlbecker
 * Wraps the given $html string into a render array suitable for drupal_render()
1204 0a1151a4 Andreas Kohlbecker
 *
1205 65345976 Andreas Kohlbecker
 * @param $html
1206 0a1151a4 Andreas Kohlbecker
 *   the html string, see
1207
 *   http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#markup
1208 65345976 Andreas Kohlbecker
 * @param $weight
1209 0a1151a4 Andreas Kohlbecker
 *   A positive or negative number (integer or decimal).
1210
 *   see http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#weightval
1211 65345976 Andreas Kohlbecker
 * @param $prefix
1212
 *   Optional markup for the '#prefix' element of the render array
1213
 * @param $suffix
1214
 *   Optional markup for the '#suffix' element of the render array
1215 0a1151a4 Andreas Kohlbecker
 *
1216 65345976 Andreas Kohlbecker
 * @return array
1217 0a1151a4 Andreas Kohlbecker
 *   A render array
1218
 *
1219
 */
1220 65345976 Andreas Kohlbecker
function markup_to_render_array($html, $weight = FALSE, $prefix = NULL, $suffix = NULL) {
1221 6f5c7f2a Andreas Kohlbecker
  $render_array = array(
1222
    '#markup' => $html
1223 1ce9afb7 Patric Plitzner
      );
1224 6f5c7f2a Andreas Kohlbecker
  if (is_numeric($weight)) {
1225
    $render_array['#weight'] = $weight;
1226 65345976 Andreas Kohlbecker
  }
1227
  if($prefix){
1228
    $render_array['#prefix'] = $prefix;
1229
  }
1230
  if($suffix) {
1231
    $render_array['#suffix'] = $suffix;
1232
  }
1233 6f5c7f2a Andreas Kohlbecker
  return $render_array;
1234 0a1151a4 Andreas Kohlbecker
}
1235
1236 6657531f Andreas Kohlbecker
/**
1237
 * Loads the subgraph of a given PolytomousKeyNode.
1238
 *
1239
 * Loads the subgraph of the given PolytomousKeyNode recursively from
1240
 * the CDM REST service.
1241
 *
1242
 * @param mixed $polytomousKeyNode
1243
 *   PolytomousKeyNode passed by reference.
1244
 *
1245
 * @return void
1246
 */
1247
function _load_polytomousKeySubGraph(&$polytomousKeyNode) {
1248
1249
  if (!$polytomousKeyNode) {
1250
    return;
1251
  }
1252
  if ($polytomousKeyNode->class != "PolytomousKeyNode") {
1253 f19f47fa Andreas Kohlbecker
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1254 6657531f Andreas Kohlbecker
    return;
1255
  }
1256
  if (!is_uuid($polytomousKeyNode->uuid)) {
1257 f19f47fa Andreas Kohlbecker
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1258 6657531f Andreas Kohlbecker
    return;
1259
  }
1260
1261
  $polytomousKeyNode = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, $polytomousKeyNode->uuid);
1262
1263
  if (!$polytomousKeyNode) {
1264
    // drupal_set_message("_load_polytomousKeyChildNodes() : could not load polytomousKeyNode", "error");
1265
    return;
1266
  }
1267
1268
  // Load children.
1269
  foreach ($polytomousKeyNode->children as &$childNode) {
1270
    _load_polytomousKeySubGraph($childNode);
1271
  }
1272
1273
  // Load subkey.
1274
  $polytomousKeyNode->subkey = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, array($polytomousKeyNode->uuid, "subkey"));
1275
1276
  // Load taxon.
1277
  $polytomousKeyNode->taxon = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, array($polytomousKeyNode->uuid, "taxon"));
1278
  _load_taxonBase($polytomousKeyNode->taxon);
1279
  return;
1280
}
1281
1282
/**
1283
 * @todo Please document this function.
1284
 * @see http://drupal.org/node/1354
1285
 */
1286
function cdm_dataportal_view_polytomousKey($polytomousKeyUuid) {
1287 f26245c8 Andreas Kohlbecker
1288
  cdm_check_valid_portal_page();
1289
1290 6657531f Andreas Kohlbecker
  $polytomousKey = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, $polytomousKeyUuid);
1291
1292
  $sourcePager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1293
  if (is_array($sourcePager->records)) {
1294
    $polytomousKey->sources = $sourcePager->records;
1295
    // $polytomousKey->sources->citation = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1296
  }
1297
1298
  $annotationPager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'annotations'));
1299
  if (is_array($annotationPager->records)) {
1300
    $polytomousKey->annotations = $annotationPager->records;
1301
  }
1302
1303
  _load_polytomousKeySubGraph($polytomousKey->root);
1304
  return theme('cdm_polytomousKey_page', array('polytomousKey' => $polytomousKey));
1305
}
1306
1307
/**
1308
 * Creates a taxon page view or a chapter of it.
1309
 *
1310
 * The taxon page gives detailed information on a taxon, it shows:
1311
 *  - Taxon name.
1312
 *  - Full list of synonyms homotypic synonyms on top, followed by the
1313
 *    heterotypic and finally followed by misapplied names.
1314
 *    The list is ordered historically.
1315
 *  - All description associated with the taxon.
1316
 *
1317
 * @param string $uuid
1318
 * @param string $chapter
1319
 *   Name of the part to display, valid values are:
1320
 *   'description', 'images', 'synonymy', 'specimens', 'all'.
1321
 *
1322
 * @return unknown_type
1323
 */
1324
function cdm_dataportal_taxon_page_view($uuid, $chapter = 'all', $synonym_uuid = NULL) {
1325 5ea8b301 Andreas Kohlbecker
1326 f26245c8 Andreas Kohlbecker
  cdm_check_valid_taxon_page($chapter);
1327 2dd59bb5 Andreas Kohlbecker
  cdm_dd("START OF TAXON PAGE [" . $chapter . "] " . $uuid . ' for ' . $_GET['q']);
1328 5ea8b301 Andreas Kohlbecker
  // show a warning in case the javascript development mode is anabled
1329
  if(variable_get('cdm_js_devel_mode', FALSE)) {
1330
    drupal_set_message(t('The !url1 is enabled.
1331
        WARNING: this is a performance penalty and must be turned off on production websites.', array(
1332
          '!url1' => l('java-script development mode', 'admin/config/cdm_dataportal/settings', array('fragment' => 'edit-cdm-js-devel-mode'))
1333
    )),
1334
    'warning'
1335
        );
1336
  }
1337
1338 6657531f Andreas Kohlbecker
  // Display the page for the taxon defined by $uuid.
1339
  // set_last_taxon_page_tab(arg(3));
1340
  $taxonpage = cdm_dataportal_taxon_view($uuid, $chapter, $synonym_uuid);
1341
  if (!empty($taxonpage)) {
1342 2dd59bb5 Andreas Kohlbecker
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid);
1343 6657531f Andreas Kohlbecker
    return cdm_node_show(NODETYPE_TAXON, $uuid, $taxonpage->title, $taxonpage->content);
1344
  }
1345
  else {
1346 2dd59bb5 Andreas Kohlbecker
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid . ' !!! PAGE IS EMPTY !!!');
1347 6657531f Andreas Kohlbecker
    return '';
1348
  }
1349
}
1350
1351
/**
1352 59f6da42 Andreas Kohlbecker
 * This function will genreate the taxon page part ($chapter) and returns a taxonpage object
1353
 * which has two fields, one for the page title and one for the content. Later on in the
1354
 * process chain the value contained in these fields will be passed to the cdm_node_show()
1355
 * function as the function parameters $title and $content.
1356 6657531f Andreas Kohlbecker
 *
1357
 * @param string $uuid
1358 59f6da42 Andreas Kohlbecker
 *   the uuid of the taxon to show
1359 6657531f Andreas Kohlbecker
 * @param string $chapter
1360
 *   Name of the part to display, valid values are:
1361
 *   'description', 'images', 'synonymy', 'all'.
1362
 *
1363 59f6da42 Andreas Kohlbecker
 * @return taxonpage object with the following fields:
1364
 *   - title : the title of the page
1365
 *   - content: the content of the page
1366
 *
1367 6657531f Andreas Kohlbecker
 */
1368 8cf9238f Andreas Kohlbecker
function cdm_dataportal_taxon_view($uuid, $chapter = 'all') {
1369 6657531f Andreas Kohlbecker
  // Taxon object.
1370
  $taxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $uuid);
1371
  if (empty($taxon)) {
1372
    drupal_set_title(t('Taxon does not exist'), PASS_THROUGH);
1373
    return FALSE;
1374
  }
1375
  $taxonpage = new stdClass();
1376
1377
  $taxonpage->title = theme('cdm_taxon_page_title', array(
1378 8cf9238f Andreas Kohlbecker
    'taxon' => $taxon
1379 6657531f Andreas Kohlbecker
  ));
1380
1381
  // Check if the taxon id contained in the currently selected tree.
1382 7663cd0b Andreas Kohlbecker
  $taxon_in_current_classification = taxon_in_current_classification($uuid);
1383 61b6ee11 Andreas Kohlbecker
1384 7663cd0b Andreas Kohlbecker
  if (!$taxon_in_current_classification) {
1385 61b6ee11 Andreas Kohlbecker
    $classifications = get_classifications_for_taxon($taxon);
1386 e24d373b Andreas Kohlbecker
    RenderHints::pushToRenderStack('not_in_current_classification');
1387
    $taxon_name_markup = render_taxon_or_name($taxon);
1388
1389 61b6ee11 Andreas Kohlbecker
    if (count($classifications) == 0) {
1390 e24d373b Andreas Kohlbecker
      drupal_set_message(t('This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification.',
1391 fba00a4f Andreas Kohlbecker
        array(
1392 e24d373b Andreas Kohlbecker
        '!taxonname' => $taxon_name_markup,
1393 fba00a4f Andreas Kohlbecker
        )
1394
      ), 'warning');
1395 6657531f Andreas Kohlbecker
    }
1396
    else {
1397
      $trees = '';
1398 61b6ee11 Andreas Kohlbecker
      foreach ($classifications as $classification) {
1399
        if (isset($classification->titleCache)) {
1400
          $trees .= ($trees ? ', ' : '') . '<strong>' . $classification->titleCache . '</strong>';
1401 6657531f Andreas Kohlbecker
        }
1402
      }
1403
1404 15b7c460 Andreas Kohlbecker
      drupal_set_message(format_plural(count($trees),
1405 e24d373b Andreas Kohlbecker
          'This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification, but in this one: !trees',
1406
          'This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification, but in one of these: !trees',
1407
          array('!taxonname' => $taxon_name_markup, '!trees' => $trees)
1408 fba00a4f Andreas Kohlbecker
        ) ,
1409
        'warning');
1410 6657531f Andreas Kohlbecker
    }
1411 e24d373b Andreas Kohlbecker
    RenderHints::popFromRenderStack();
1412 6657531f Andreas Kohlbecker
  }
1413
1414
  // Render the taxon page.
1415 9a607f17 Andreas Kohlbecker
  $render_array = compose_cdm_taxon_page($taxon, $chapter);
1416
  $taxonpage->content = drupal_render($render_array);
1417 6657531f Andreas Kohlbecker
1418
  return $taxonpage;
1419
}
1420
1421 9d37c9d9 Patric Plitzner
/**
1422
 * Creates a specimen page view.
1423
 * @param string $uuid the UUID of the specimen
1424
 * @return array|string
1425
 */
1426
function cdm_dataportal_specimen_page_view($uuid) {
1427
1428
    //cdm_check_valid_taxon_page($chapter);
1429
    //cdm_dd("START OF TAXON PAGE [" . $chapter . "] " . $uuid . ' for ' . $_GET['q']);
1430
    // show a warning in case the javascript development mode is anabled
1431
    if(variable_get('cdm_js_devel_mode', FALSE)) {
1432
        drupal_set_message(t('The !url1 is enabled.
1433
        WARNING: this is a performance penalty and must be turned off on production websites.', array(
1434
            '!url1' => l('java-script development mode', 'admin/config/cdm_dataportal/settings', array('fragment' => 'edit-cdm-js-devel-mode'))
1435
        )),
1436
            'warning'
1437
        );
1438
    }
1439
1440
    // Display the page for the specimen defined by $uuid.
1441
    $specimenpage = cdm_dataportal_specimen_view($uuid);
1442
    if (!empty($specimenpage)) {
1443
        return cdm_node_show(NODETYPE_TAXON, $uuid, $specimenpage->title, $specimenpage->content);
1444
    }
1445
    else {
1446
        return '';
1447
    }
1448
}
1449
1450
/**
1451
 *
1452
 * Creates a specimen view.
1453
 * @param string $uuid the UUID of the specimen
1454
 * @return array|string
1455
 */
1456
function cdm_dataportal_specimen_view($uuid) {
1457
    $specimen = cdm_ws_get(CDM_WS_OCCURRENCE, $uuid);
1458
    if (empty($specimen)) {
1459
        drupal_set_title(t('Specimen does not exist'), PASS_THROUGH);
1460
        return FALSE;
1461
    }
1462
    $specimenpage = new stdClass();
1463
1464
    $specimenpage->title = theme('cdm_specimen_page_title', array(
1465
        'specimen' => $specimen
1466
    ));
1467
1468 b810158e Patric Plitzner
    // Render the specimen page.
1469
    $render_array = compose_cdm_specimen_page($uuid);
1470 9d37c9d9 Patric Plitzner
    $specimenpage->content = drupal_render($render_array);
1471
1472
    return $specimenpage;
1473
}
1474
1475 6657531f Andreas Kohlbecker
/**
1476
 * Returns a name page as a Drupal node ready to be renderized by Drupal.
1477
 *
1478
 * The node page shows the taxon name title and the list of taxon related
1479
 * with such taxon. Name on the tree already in use.
1480
 *
1481 51b04faf Andreas Kohlbecker
 * @param UUID $taxon_name_uuid
1482
 *   The uuid of the CDM TaxonNameBase to show a name page for
1483
 * @param UUID $taxon_to_hide_uuid
1484
 *   A taxon which should not be displayed in the taxon list
1485
 * @param UUID $highlite_synonym_uuid
1486
 *   Optinal parameter wich takes another taxon uuid, if given the
1487
 *   target taxon pages will show the syonymy tab where the taxon
1488
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1489
 *   in case it is found on this page.
1490 6657531f Andreas Kohlbecker
 *
1491
 * @return mixed
1492
 *   The formatted name page as node.
1493
 */
1494
function cdm_dataportal_name_page_view($taxon_name_uuid, $taxon_to_hide_uuid, $synonym_uuid = NULL) {
1495
1496 f26245c8 Andreas Kohlbecker
  cdm_check_valid_portal_page();
1497
1498 6657531f Andreas Kohlbecker
  $taxonname_page = cdm_dataportal_name_view($taxon_name_uuid, $taxon_to_hide_uuid, $synonym_uuid);
1499
  if (!empty($taxonname_page)) {
1500
    return cdm_node_show(NODETYPE_NAME, $taxon_name_uuid, $taxonname_page->title, $taxonname_page->content);
1501
  }
1502
  else {
1503
    return '';
1504
  }
1505
}
1506
1507
/**
1508 e3001c8d Andreas Kohlbecker
 * View function for a TaxonNameBase page.
1509 6657531f Andreas Kohlbecker
 *
1510 e3001c8d Andreas Kohlbecker
 * The name page lists all taxa for which the name specified by the
1511
 * $taxon_name_uuid is being used. I case there is only one name the
1512
 * page automatically redirects ti the according taxon page. Otherwise
1513
 * the list of names is displayed.
1514 6657531f Andreas Kohlbecker
 *
1515 e3001c8d Andreas Kohlbecker
 * The parameter $taxon_to_hide_uuid allows to exclude a taxon from the
1516
 * list of taxa. This is useful for example when referencing from a taxon
1517
 * to the name page and the referring taxon should not be repeaded in the
1518
 * name page.
1519 6657531f Andreas Kohlbecker
 *
1520 e3001c8d Andreas Kohlbecker
 *
1521
 * @param UUID $taxon_name_uuid
1522
 *   The uuid of the CDM TaxonNameBase to show a name page for
1523
 * @param UUID $taxon_to_hide_uuid
1524
 *   A taxon which should not be displayed in the taxon list
1525
 * @param UUID $highlite_synonym_uuid
1526
 *   Optinal parameter wich takes another taxon uuid, if given the
1527
 *   target taxon pages will show the syonymy tab where the taxon
1528
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1529
 *   in case it is found on this page.
1530
 *
1531
 * @return object
1532
 *   An object with two fields:
1533
 *     - title: the page title
1534
 *     - content: the page content
1535 6657531f Andreas Kohlbecker
 */
1536 e3001c8d Andreas Kohlbecker
function cdm_dataportal_name_view($taxon_name_uuid, $taxon_to_hide_uuid, $highlite_synonym_uuid = NULL) {
1537 6657531f Andreas Kohlbecker
  // Getting the full taxonname object from the server.
1538 d0d068e9 Andreas Kohlbecker
  $taxon_name = cdm_ws_get(CDM_WS_PORTAL_NAME, array($taxon_name_uuid));
1539 6657531f Andreas Kohlbecker
  if (!$taxon_name) {
1540
    drupal_set_title(t('Taxon name does not exist'), PASS_THROUGH);
1541
    return FALSE;
1542
  }
1543
  // Searching for all the taxa connected with the taxon name on the tree
1544
  // in use.
1545
  $name_cache = cdm_ws_get(CDM_WS_NAME_NAMECAHE, array($taxon_name_uuid));
1546
  $request_params = array();
1547
  $request_params['query'] = $name_cache;
1548 7663cd0b Andreas Kohlbecker
  $request_params['tree'] = get_current_classification_uuid();
1549 6657531f Andreas Kohlbecker
  $request_params['doTaxa'] = 1;
1550
  $request_params['doSynonyms'] = 1;
1551
  $request_params['doTaxaByCommonNames'] = 0;
1552
  $request_params['matchMode'] = "EXACT";
1553
  $taxon_pager = cdm_ws_get(CDM_WS_PORTAL_TAXON_FIND, NULL, queryString($request_params));
1554
1555 d0d068e9 Andreas Kohlbecker
  // Removing the name where we came from.
1556 6657531f Andreas Kohlbecker
  foreach ($taxon_pager->records as $k => &$taxon) {
1557
    if ($taxon->uuid == $taxon_to_hide_uuid) {
1558
      unset($taxon_pager->records[$k]);
1559
    }
1560
  }
1561
  // Show the taxa list or go to the singular taxon.
1562
  if (sizeof($taxon_pager->records) == 1) {// Single taxon case.
1563 e3001c8d Andreas Kohlbecker
    $singleTaxon = array_pop($taxon_pager->records);
1564 6657531f Andreas Kohlbecker
    if ($singleTaxon->class != "Taxon") {
1565
      // It is a Synonym -> look for the accepted.
1566 7663cd0b Andreas Kohlbecker
      $accepted_taxa = cdm_ws_get(CDM_WS_PORTAL_TAXON_ACCEPTED, array($singleTaxon->uuid, get_current_classification_uuid()));
1567 e3001c8d Andreas Kohlbecker
      if (!empty($highlite_synonym_uuid)) {
1568 f0bf24e7 Andreas Kohlbecker
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxa[0]->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
1569 6657531f Andreas Kohlbecker
      }
1570
      else {
1571 f0bf24e7 Andreas Kohlbecker
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxa[0]->uuid . '/synonymy', array('query' => array('highlite' => $singleTaxon->uuid)));
1572 6657531f Andreas Kohlbecker
      }
1573
    }
1574
    else {
1575
      // It is an accepted taxon.
1576 e3001c8d Andreas Kohlbecker
      if (!empty($highlite_synonym_uuid)) {
1577
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
1578 6657531f Andreas Kohlbecker
      }
1579
      else {
1580
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid);
1581
      }
1582
    }
1583
  }
1584
  else {// More than one taxa case.
1585
    $taxon_name_page = new stdClass();
1586 4f225a0f Andreas Kohlbecker
    $taxon_name_page->title = theme('cdm_name_page_title', array('taxon_name' => $taxon_name));
1587 6657531f Andreas Kohlbecker
    if ($taxon_pager->records) {
1588 7272d19c Andreas Kohlbecker
      $taxon_name_page->content = compose_list_of_taxa($taxon_pager->records);
1589 6657531f Andreas Kohlbecker
    }
1590
    else {
1591
      $taxon_name_page->content = 'This name has no taxa';
1592
    }
1593
    return $taxon_name_page;
1594
  }
1595
}
1596
1597
/**
1598 84b13813 Andreas Kohlbecker
 * Creates a page with the advance search form.
1599
 *
1600
 * NOTE: The advance search form allows searching for taxa.
1601 6657531f Andreas Kohlbecker
 */
1602
function cdm_dataportal_view_search_advanced() {
1603
  drupal_set_title(t('Advanced search'), PASS_THROUGH);
1604
  return drupal_get_form('cdm_dataportal_search_taxon_form_advanced');
1605
}
1606
1607
/**
1608 84b13813 Andreas Kohlbecker
 * Creates a page with the search form for searching by taxon descriptions.
1609 6657531f Andreas Kohlbecker
 */
1610
function cdm_dataportal_view_search_taxon_by_description() {
1611 6441ddfb Andreas Kohlbecker
  drupal_set_title(t('Search by factual data'), PASS_THROUGH);
1612 6657531f Andreas Kohlbecker
  return drupal_get_form('cdm_dataportal_search_taxon_by_description_form');
1613
}
1614
1615
/**
1616
 * Executes the search and generates the result list of taxa.
1617
 */
1618
function cdm_dataportal_view_search_results_taxon() {
1619
1620
  $taxonPager = cdm_dataportal_search_execute();
1621
1622 f19f47fa Andreas Kohlbecker
  $showThumbnails = do_showThumbnails();
1623
1624
  $setSessionUri = url('cdm_api/setvalue/session', array(
1625
      'query' => array('var' => '[pageoption][searchtaxa][showThumbnails]', 'val' => ''),
1626
  ));
1627
1628
  drupal_add_js('jQuery(document).ready(function() {
1629
1630
      // init
1631
      if(' . $showThumbnails . ' == 1){
1632 1d69a96c Andreas Kohlbecker
          jQuery(\'.media_gallery\').show(20);
1633
      } else {
1634
          jQuery(\'.media_gallery\').hide(20);
1635
      }
1636
1637
      // add change handler
1638
      jQuery(\'#showThumbnails input.showThumbnails\').change(
1639 f19f47fa Andreas Kohlbecker
      function(event){
1640 1d69a96c Andreas Kohlbecker
        var state = 0;
1641
        if(jQuery(this).is(\':checked\')){
1642
          jQuery(\'.media_gallery\').show(20);
1643
          state = 1;
1644
        } else {
1645
          jQuery(\'.media_gallery\').hide(20);
1646
        }
1647
        // store state in session variable
1648
        var uri = \'' . $setSessionUri . '\' + state;
1649
        jQuery.get(uri);
1650
      });
1651 78e178e2 Andreas Kohlbecker
  });',
1652 f19f47fa Andreas Kohlbecker
  array('type' => "inline", 'scope' => JS_DEFAULT));
1653
1654 78e178e2 Andreas Kohlbecker
  drupal_set_title(t('Search results'), PASS_THROUGH);
1655
1656 6657531f Andreas Kohlbecker
  return theme('cdm_search_results', array(
1657
    'pager' => $taxonPager,
1658
    'path' => 'cdm_dataportal/search/results/taxon',
1659
    ));
1660
}
1661
1662 94550ff9 Andreas Kohlbecker
/**
1663
 * Provides the standart image wich indicated a loading process
1664
 *
1665
 * @return string
1666
 *  The img html tag
1667
 */
1668
function loading_image_html() {
1669
  return '<img class="loading" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal')
1670
    . '/images/loading_circle_grey_16.gif" style="display:none;">';
1671
}
1672
1673 78e178e2 Andreas Kohlbecker
/**
1674
 * Returns the state of the the showThumbnails flag set in the
1675
 * users session ($_SESSION['pageoption']['searchtaxa']['showThumbnails']).
1676
 *
1677 c5ed6357 Andreas Kohlbecker
 * @return boolean
1678 78e178e2 Andreas Kohlbecker
 *    returns 1 if the flag is set
1679
 */
1680
function do_showThumbnails() {
1681
  static $showThumbnails = null;
1682
1683
  if($showThumbnails == null) {
1684 c5ed6357 Andreas Kohlbecker
    $showThumbnails = 0;
1685
    if (!isset($_SESSION['pageoption']['searchtaxa']['showThumbnails'])) {
1686
      $showThumbnails = 0;
1687
      $search_gallery_settings = variable_get(CDM_DATAPORTAL_SEARCH_GALLERY_NAME, null);
1688
      $showThumbnails = is_array($search_gallery_settings)
1689
        && isset($search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'])
1690
        && (
1691
            $search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'] +
1692
            $search_gallery_settings['cdm_dataportal_show_synonym_thumbnails'] +
1693
            $search_gallery_settings['cdm_dataportal_show_thumbnail_captions'] > 0
1694
            )
1695
         ? 1 : 0;
1696 f19f47fa Andreas Kohlbecker
1697 c5ed6357 Andreas Kohlbecker
       drupal_array_set_nested_value($_SESSION, array('pageoption', 'searchtaxa', 'showThumbnails'), $showThumbnails);
1698
    }
1699 f19f47fa Andreas Kohlbecker
    $showThumbnails = $_SESSION['pageoption']['searchtaxa']['showThumbnails'];
1700
    if (!is_numeric($showThumbnails)) {
1701
      $showThumbnails = 1;
1702
    }
1703 78e178e2 Andreas Kohlbecker
  }
1704
1705
  return $showThumbnails;
1706
}
1707
1708 6657531f Andreas Kohlbecker
/**
1709
 * View which transforms XML output from a given webservice endpoint into JSON.
1710
 */
1711
/*
1712
 function cdm_view_xml2json(){
1713
 $file = arg(2);
1714
 $datastr = file_get_contents(variable_get('cdm_webservice_url', '').$file);
1715
 return  xml2json::transformXmlStringToJson($datastr);
1716
 }
1717
 */
1718
1719
/* ====================== other functions ====================== */
1720
/**
1721
 * Creates a URL to the taxon page specified by the $uuid parameter.
1722
 *
1723
 * The URL will be prepended with a path element to a specific taxon page tab.
1724
 *
1725
 * This tab is either taken from the CDM_DATAPORTAL_DEFAULT_TAXON_TAB which can
1726
 * be set globally in the administrative settings or individually in the user
1727
 * profile. If the CDM_DATAPORTAL_DEFAULT_TAXON_TAB value is set to LAST_VISITED_TAB
1728
 * the last portal will stay on this last tab.
1729
 *
1730
 * A third option is offerered by the $page_tab parameter which allows overwriting this
1731
 * internal mechanism by a specific value.
1732
 *
1733
 * @param string $uuid
1734
 *   The UUID of the taxon.
1735
 * @param string $page_tab
1736
 *   Overwriting the preset mechanism by defining specific value for the
1737
 *   taxon page tab.
1738
 *
1739
 * @return string
1740
 *   The created URL.
1741
 */
1742
function path_to_taxon($uuid, $page_tab = FALSE) {
1743
1744
  $tab = get_default_taxon_tab();
1745
  $values = unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB);
1746
1747
  if (!$uuid) {
1748
    return FALSE;
1749
  }
1750
1751
  if ($page_tab) {
1752
    return 'cdm_dataportal/taxon/' . $uuid . '/' . $page_tab;
1753
  }
1754
  elseif (!$tab || strtolower($tab) == 'general') {
1755
    return 'cdm_dataportal/taxon/' . $uuid;
1756
  }
1757
  elseif (get_last_taxon_page_tab() &&   $tab == $values[CDM_DATAPORTAL_LAST_VISITED_TAB_ARRAY_INDEX]) {
1758
    return 'cdm_dataportal/taxon/' . $uuid . '/' . get_last_taxon_page_tab();
1759
  }
1760
  else {
1761
    return 'cdm_dataportal/taxon/' . $uuid . '/' . strtolower($tab);
1762
  }
1763
}
1764
1765 9d37c9d9 Patric Plitzner
function path_to_specimen($uuid) {
1766
1767
    if (!$uuid) {
1768
        return FALSE;
1769
    }
1770
    else {
1771
        return 'cdm_dataportal/specimen/' . $uuid;
1772
    }
1773
}
1774
1775 6657531f Andreas Kohlbecker
/**
1776 630c7044 Andreas Kohlbecker
 * Creates a URL to show a synonmy in the according taxon page.
1777
 *
1778
 * The URL will point to the synonymy tab of the taxon page of the accepted taxon given as parameter $acceptedUuid.
1779
 * The resulting URI will include query parameters to highlight the synonym, and to optionally display
1780
 * the accepted taxons name in aform like "Foo bar is accepted taxon for Ree doo". The URI will also
1781
 * include the sysnonym uuid as fragment in order to let the browser scroll to the according location
1782
 * in the page
1783
 *
1784
 * @param string $synonymUuid
1785
 *    The uuid of the synonym
1786
 * @param string $acceptedUuid
1787
 *    The uuid of the according accepted taxon
1788
 * @return string
1789
 *    The URL to show a synonmy in the according taxon page
1790 6657531f Andreas Kohlbecker
 */
1791
function uri_to_synonym($synonymUuid, $acceptedUuid) {
1792
  $acceptedPath = path_to_taxon($acceptedUuid, "synonymy");
1793 d071bed7 Andreas Kohlbecker
  return url($acceptedPath, array(
1794
      'query' => array(
1795
        // highlite the synony in the synonymy
1796
        'highlite' => $synonymUuid,
1797
        // the taxon page is refered from a synonym and the synonym can optionally be named in the page title
1798
        // see theme_taxon_page_title()
1799
        'acceptedFor' => $synonymUuid
1800 630c7044 Andreas Kohlbecker
      ),
1801
      'fragment' => $synonymUuid
1802 d071bed7 Andreas Kohlbecker
  ));
1803
1804 6657531f Andreas Kohlbecker
}
1805
1806
/**
1807 b8bfa4bd Andreas Kohlbecker
 * Compses the drupal path to the key identified by the uuid.
1808
 *
1809
 * @param string $keyType
1810
 *    the key typer corresponds to the specific class of the CDM
1811
 *    IdentificationKey. Possible values are
1812
 *      -PolytomousKey
1813
 *      -MultimediaKey
1814
 *      - ...
1815
 * @param UUID $keyUuid
1816
 *   The UUID of the key
1817 6657531f Andreas Kohlbecker
 */
1818
function path_to_key($keyType, $keyUuid) {
1819
  if (!$keyUuid || !$keyType) {
1820
    return FALSE;
1821
  }
1822
  $keyType{0} = strtolower($keyType{0});
1823
  return "cdm_dataportal/" . $keyType . "/$keyUuid";
1824
}
1825
1826
/**
1827
 * @todo Please document this function.
1828
 * @see http://drupal.org/node/1354
1829
 */
1830
function path_to_reference($uuid) {
1831
  if (!$uuid) {
1832
    return FALSE;
1833
  }
1834
  return 'cdm_dataportal/reference/' . $uuid;
1835
}
1836
1837
/**
1838 51b04faf Andreas Kohlbecker
 * Creates the path to a cdm_dataportal taxon name page.
1839
 *
1840
 * @param UUID $taxon_name_uuid
1841
 *   The uuid of the CDM TaxonNameBase to show a name page for
1842
 * @param UUID $taxon_to_hide_uuid
1843
 *   A taxon which should not be displayed in the taxon list
1844
 * @param UUID $highlite_synonym_uuid
1845
 *   Optinal parameter wich takes another taxon uuid, if given the
1846
 *   target taxon pages will show the syonymy tab where the taxon
1847
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1848
 *   in case it is found on this page.
1849
 *
1850
 * @return a URI path element as string
1851 6657531f Andreas Kohlbecker
 */
1852 51b04faf Andreas Kohlbecker
function path_to_name($name_uuid, $taxon_to_hide_uuid = NULL, $synonym_uuid  = NULL) {
1853 6657531f Andreas Kohlbecker
  $res = FALSE;
1854
  if ($name_uuid) {
1855
    $res = 'cdm_dataportal/name/' . $name_uuid;
1856
  }
1857 51b04faf Andreas Kohlbecker
  if($taxon_to_hide_uuid){
1858
    $res .= '/' . $taxon_to_hide_uuid;
1859
    if($synonym_uuid){
1860
      $res .= '/' . $synonym_uuid;
1861
    }
1862
  }
1863 6657531f Andreas Kohlbecker
  return $res;
1864
}
1865
1866
/**
1867
 * @todo Please document this function.
1868
 * @see http://drupal.org/node/1354
1869
 */
1870
function path_to_media($uuid, $representaion_uuid = FALSE, $partId = FALSE) {
1871
  if (!$uuid) {
1872
    return FALSE;
1873
  }
1874
  $out = 'cdm_dataportal/media/' . $uuid;
1875
  if ($representaion_uuid) {
1876
    $out .= '/' . $representaion_uuid;
1877
    if ($partId !== FALSE) {
1878
      $out .= '/' . $partId;
1879
    }
1880
  }
1881
  return $out;
1882
}
1883
1884
/**
1885
 * Compares thisRank with thatRank.
1886
 *
1887
 * Returns a negative integer, zero, or a positive integer
1888
 * as the of thisRank is higher than, equal to, or lower than thatRank.
1889
 * e.g:
1890
 * <ul>
1891
 * <li>rank_compare({species_uuid}, {genus_uuid}) = -1</li>
1892
 * <li>rank_compare({genus_uuid}, {genus_uuid}) = 0</li>
1893
 * <li>rank_compare({genus_uuid}, {tribus_uuid}) = 1</li>
1894
 * </ul>
1895
 * <p>
1896
 * This compare logic of the underlying webservice is the
1897
 * <b>inverse logic</b> of the the one implemented in
1898
 * java.lang.Comparable#compareTo(java.lang.Object)
1899
 *
1900
 * @param $thisRankUuid
1901
 * @param $thatRankUuid
1902
 *
1903
 * @return int
1904
 *   A negative integer, zero, or a positive integer
1905
 *   as the thisRank is lower than, equal to, or higher than thatRank.
1906
 */
1907
function rank_compare($thisRankUuid, $thatRankUuid) {
1908
  $result = cdm_ws_get(CDM_WS_TERM_COMPARE, array($thisRankUuid, $thatRankUuid));
1909
  return $result->Integer;
1910
}
1911
1912
/**
1913
 * Composes an HTML element class attribute value composed of
1914
 * the shortname of the cdm class and the uuid of the entity.
1915
 * This class attribute should be used whereever an cdm-entity is rendered.
1916
 *
1917
 * These according class selectors in css must be escaped, eg:
1918
 *    .cdm\:TextData
1919
 *
1920
 * @param $cdmEntity
1921
 */
1922 f19f47fa Andreas Kohlbecker
function html_class_attribute_ref($cdmEntity) {
1923 6657531f Andreas Kohlbecker
1924
  if (is_cdm_entity($cdmEntity)) {
1925
    return "cdm:" . $cdmEntity->class . " uuid:" . $cdmEntity->uuid;
1926
  }
1927
}
1928
1929
1930
/**
1931
 * Creates a short taxonname.
1932
 *
1933 e90899ac Andreas Kohlbecker
 * The short name is created by using the taggedTitle field of
1934 6657531f Andreas Kohlbecker
 * NameSTO or NameTO instances.
1935 e90899ac Andreas Kohlbecker
 * If the taggedTitle if empty the fullname will be returned.
1936 6657531f Andreas Kohlbecker
 *
1937
 * @param unknown_type $name
1938
 *   Name or TreeNode.
1939
 *
1940
 * @return string
1941
 */
1942
function cdm_dataportal_shortname_of($name) {
1943
  $nameStr = '';
1944
1945 e90899ac Andreas Kohlbecker
  normalize_tagged_text($name->taggedTitle);
1946 6657531f Andreas Kohlbecker
1947
  // Get all tagged text tokens of the scientific name.
1948
  foreach ($name->taggedTitle as $tagtxt) {
1949
    if ($tagtxt->type == 'name' || $tagtxt->type == 'rank') {
1950
      $nameStr .= ($nameStr ? ' ' : '') . $tagtxt->text;
1951
    }
1952
  }
1953
  $nameStr = trim($nameStr);
1954
1955
  if ($nameStr) {
1956
1957
    // Do not return short names for these.
1958
    if ($name->unplaced || $name->excluded) {
1959
      return $nameStr;
1960
    }
1961
1962
    /*
1963
    1st capture group (^[a-zA-Z]): First letter of uninomial.
1964
    Second capture group ([\p{L}]+): remaining letters of uninomial ([\p{L} = an UTF-8 letter).
1965
    Third capture group (\s+[^(\x2E]+\s+.+$|\s+[a-zA-Z]+$): letters of name,
1966
    but only matching if no '(' or '.' in second word of name,        ( \x2E = '.')
1967
    OR only one specific epithet \s+[\p{L}\x22\x2D\xD7]+$             (\x22= '"', \x2D='-', \xD7='×' )
1968
    */
1969
    $pattern = '/(^[a-zA-Z])([\p{L}]+)(\s+[^(\x2E]+\s+.+$|\s+[\p{L}\x22\x2D\xD7]+$)/u';
1970
    if (preg_match($pattern, $nameStr, $matches, PREG_OFFSET_CAPTURE)) {
1971
      return $matches[1][0] . "." . $matches[3][0];
1972
    }
1973
    else {
1974
      return $nameStr;
1975
    }
1976
  }
1977
  else {
1978
    return $name->titleCache;
1979
  }
1980
}
1981
1982
/**
1983
 * Check if a taxon is accepted by the current taxonomic tree.
1984
 *
1985
 * @param mixed $taxon
1986
 *   The Taxon obkect to check.
1987
 *
1988
 * @return bool
1989
 *   Returns TRUE if $taxon is accepted, FALSE otherwise.
1990
 */
1991
function _cdm_dataportal_acceptedByCurrentView($taxon) {
1992
1993 7663cd0b Andreas Kohlbecker
  $defaultTreeUuid = get_current_classification_uuid();
1994 6657531f Andreas Kohlbecker
1995
  if (isset($taxon->taxonNodes)) {
1996
    $taxonNodes = $taxon->taxonNodes;
1997
  }
1998
  else {
1999
    $taxonNodes = cdm_ws_get(CDM_WS_PORTAL_TAXON_TAXONNODES, $taxon->uuid);
2000
  }
2001
2002
  if ($taxon->class == "Taxon" && isset($taxonNodes)) {
2003
    foreach ($taxonNodes as $node) {
2004 586fc780 Andreas Kohlbecker
      if (isset($node->classification)){
2005
        if(is_object($node->classification)) {
2006
          if ($node->classification->uuid == $defaultTreeUuid) {
2007
            return TRUE;
2008
          }
2009 6657531f Andreas Kohlbecker
        }
2010 586fc780 Andreas Kohlbecker
        else {
2011
          if ($node->classification == $defaultTreeUuid) {
2012
            return TRUE;
2013
          }
2014 6657531f Andreas Kohlbecker
        }
2015
      }
2016
    }
2017
  }
2018
2019
  return FALSE;
2020
}
2021
2022
/**
2023 54cfa718 Andreas Kohlbecker
 * Checks is the source has one of the given types.
2024
 *
2025
 * @param object $source
2026
 *   The original source entity
2027
 * @param array $types
2028
 *   An array of elementd of the OriginalSourceType enumeration
2029
 *   If not set the default will be used which is:
2030
 *    - Lineage
2031
 *    - PrimaryMediaSource
2032
 *    - PrimaryTaxonomicSource
2033
 *    - Unknown
2034
 *    - Other
2035
 * @return boolean
2036 6657531f Andreas Kohlbecker
 */
2037 54cfa718 Andreas Kohlbecker
  function _is_original_source_type($source, $types = null) {
2038
    // this is the default
2039
    // maybe this should also be put into the settings
2040
    static $default = array(
2041
      OriginalSourceType::Lineage,
2042
      OriginalSourceType::PrimaryMediaSource,
2043
      OriginalSourceType::PrimaryTaxonomicSource,
2044
      OriginalSourceType::Unknown,
2045
      OriginalSourceType::Other,
2046
    );
2047
2048
    if(!$types){
2049
      $types = $default;
2050
    }
2051
    return isset($source->type) && in_array($source->type, $types);
2052
  }
2053 6657531f Andreas Kohlbecker
2054
/**
2055
 * @todo Please document this function.
2056
 * @see http://drupal.org/node/1354
2057
 */
2058
function _is_invers_taxonRelationship($taxonRelationship, $focusedTaxon) {
2059
  return $taxonRelationship->toTaxon->uuid == $focusedTaxon->uuid;
2060
}
2061
2062
2063
/**
2064
 * Collects all the media from a list of description elements.
2065
 *
2066
 * @param array $descriptionElements
2067
 *   The description elements from which to collect the media.
2068
 *
2069
 * @return array
2070
 *   The output with all the collected media.
2071
 */
2072
function cdm_dataportal_media_from_descriptionElements($descriptionElements) {
2073
2074
  $outArrayOfMedia = array();
2075
2076
  // Avoiding a warning box in Drupal for Flora Malesiana.
2077
  if (isset($descriptionElements) && is_array($descriptionElements)) {
2078
    foreach ($descriptionElements as $descriptionElement) {
2079
      if (isset($descriptionElement->media) && is_array($descriptionElement->media)) {
2080
        foreach ($descriptionElement->media as $media) {
2081
          if (is_object($media)) {
2082
            $outArrayOfMedia[] = $media;
2083
          }
2084
        }
2085
      }
2086
    }
2087
  }
2088
  return $outArrayOfMedia;
2089
}
2090
2091
/**
2092
 * @todo Please document this function.
2093
 * @see http://drupal.org/node/1354
2094
 *
2095 65345976 Andreas Kohlbecker
 * @param array $cdm_entities
2096 6657531f Andreas Kohlbecker
 *   An array of CdmBase instances or a single instance.
2097 28c5c87a Andreas Kohlbecker
 * @param string $footnote_list_key_suggestion
2098 6657531f Andreas Kohlbecker
 *
2099
 * @return unknown
2100
 */
2101 65345976 Andreas Kohlbecker
function cdm_annotations_as_footnotekeys($cdm_entities, $footnote_list_key_suggestion = NULL) {
2102 90597e37 Andreas Kohlbecker
2103
   static $annotations_types_filter = null;
2104 6657531f Andreas Kohlbecker
   if(!$annotations_types_filter) {
2105 90597e37 Andreas Kohlbecker
     $annotations_types_filter = unserialize(ANNOTATIONS_TYPES_AS_FOOTNOTES_DEFAULT);
2106 6657531f Andreas Kohlbecker
   }
2107
2108
  $footNoteKeys = array();
2109
2110
  // Is argument cdmBase an array?
2111 65345976 Andreas Kohlbecker
  if (!is_array($cdm_entities)) {
2112 6657531f Andreas Kohlbecker
    $cdmBase_array = array();
2113 65345976 Andreas Kohlbecker
    $cdmBase_array[] = $cdm_entities;
2114 6657531f Andreas Kohlbecker
  }
2115
  else {
2116 65345976 Andreas Kohlbecker
    $cdmBase_array = $cdm_entities;
2117 6657531f Andreas Kohlbecker
  }
2118
2119
  // Getting the key for the footnotemanager.
2120 28c5c87a Andreas Kohlbecker
  if (isset($footnote_list_key_suggestion)) {
2121
    $footnote_list_key = $footnote_list_key_suggestion;
2122 6657531f Andreas Kohlbecker
  }
2123
  else {
2124 28c5c87a Andreas Kohlbecker
    $footnote_list_key = RenderHints::getFootnoteListKey() . '-annotations';
2125 6657531f Andreas Kohlbecker
  }
2126
2127
  // Adding the footnotes keys.
2128
  foreach ($cdmBase_array as $cdmBase_element) {
2129
    $annotations = cdm_ws_getAnnotationsFor($cdmBase_element, variable_get('annotations_types_as_footnotes', $annotations_types_filter));
2130
    if (is_array($annotations)) {
2131
      foreach ($annotations as $annotation) {
2132 28c5c87a Andreas Kohlbecker
        $footNoteKeys[] = FootnoteManager::addNewFootnote($footnote_list_key, $annotation->text);
2133 6657531f Andreas Kohlbecker
      }
2134
    }
2135
  }
2136
2137
  return $footNoteKeys;
2138
}
2139
2140 d9763fd3 Andreas Kohlbecker
2141 6657531f Andreas Kohlbecker
/**
2142 d9763fd3 Andreas Kohlbecker
 * Creates a CDM Dynabox.
2143
 *
2144 c1f5d897 Andreas Kohlbecker
 * @param string $dynabox_id
2145 d9763fd3 Andreas Kohlbecker
 *   a uninque name for tha dynabox, using a cdm entity uuid as id is good practice.
2146 6657531f Andreas Kohlbecker
 * @param string $label
2147
 *   The clickable text to show.
2148
 * @param string $content_url
2149
 *   The cdm REST service request url wich will deliver the content to be shown
2150
 *   once the dynabox toggles open.
2151
 * @param string $theme
2152 1ce9afb7 Patric Plitzner
 *   The theme to be used for rendering the cdm REST service response with is
2153 6657531f Andreas Kohlbecker
 *   returned from the $content_url.
2154
 * @param string $link_alt_text
2155
 *   The value for the alt attribute of the dynabox link.
2156
 * @param array $enclosingtags
2157
 *   An array with two elements: $enclosingtags[0] will be used for the dynabox
2158
 *   element itself, $enclosingtags[1] is the tag to be used for the
2159 c1f5d897 Andreas Kohlbecker
 *   dynabox_content (optional)
2160 d9763fd3 Andreas Kohlbecker
 * @param array $attributes
2161
 * @param $content_element_selector
2162
 *   Optional jQuery selector which can be used to reference a dom element which should
2163
 *   be used as container for the content to be shown. The dynabox-<dynabox id>-content
2164
 *  element will be placed in this container.
2165
 *
2166 c1f5d897 Andreas Kohlbecker
 * @param string $open_callback
2167 1ce9afb7 Patric Plitzner
 *   optional javascript call back function to be triggered after toggling the box to
2168 c1f5d897 Andreas Kohlbecker
 *   the open state.
2169
 * @param string $close_callback
2170 1ce9afb7 Patric Plitzner
 *   optional javascript call back function to be triggered after toggling the box to
2171 c1f5d897 Andreas Kohlbecker
 *   the closed state.
2172 d9763fd3 Andreas Kohlbecker
 * @return string Returns HTML for a dynabox.
2173
 * Returns HTML for a dynabox.
2174 6657531f Andreas Kohlbecker
 */
2175 d9763fd3 Andreas Kohlbecker
function cdm_dynabox($dynabox_id, $label, $content_url, $theme, $link_alt_text,
2176
                     $enclosingtags = array('li', 'ul'), $attributes = array(),
2177
                     $content_element_selector = null,
2178
                     $open_callback = 'function(){}', $close_callback = 'function(){}' ) {
2179 6657531f Andreas Kohlbecker
  $out = '';
2180 c1f5d897 Andreas Kohlbecker
2181
  // check for plain class attribute string
2182
  $dynabox_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $dynabox_id);
2183
2184 9c9d11f7 Andreas Kohlbecker
  if(!array_key_exists('class', $attributes)) {
2185
    $attributes['class'] = array();
2186
  }
2187 d9763fd3 Andreas Kohlbecker
  $attributes['id'][] = 'dynabox-' . $dynabox_id;
2188 9c9d11f7 Andreas Kohlbecker
  $dynabox_attributes = drupal_attributes($attributes);
2189
2190
2191 b386ae48 Andreas Kohlbecker
  _add_js_domEvent(); // requires domEvent.js
2192 6657531f Andreas Kohlbecker
  drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cdm_dynabox.js');
2193 c1f5d897 Andreas Kohlbecker
  drupal_add_js("
2194 94bb8db6 Andreas Kohlbecker
  jQuery(document).ready(
2195
      function() {
2196
        dynabox('". $dynabox_id ."',
2197
          {
2198
            open_callback: " . $open_callback .",
2199 d9763fd3 Andreas Kohlbecker
            close_callback: " . $close_callback .
2200
            ($content_element_selector ? ",\n content_container_selector: '" . $content_element_selector . "'" : "") . "
2201 94bb8db6 Andreas Kohlbecker
          }
2202
        );
2203
      }
2204
   );",
2205
   array(
2206
    'type'=>'inline',
2207
    'scope'=>'footer'
2208
    )
2209
  );
2210 6657531f Andreas Kohlbecker
2211 9c9d11f7 Andreas Kohlbecker
2212 6657531f Andreas Kohlbecker
  $cdm_proxy_url = url('cdm_api/proxy/' . urlencode($content_url) . "/$theme");
2213 9c9d11f7 Andreas Kohlbecker
  $out .= '<!-- dynabox for ' . $content_url . ' -->';
2214 dcd1f0e0 Andreas Kohlbecker
  $out .= '<' . $enclosingtags[0] . ' ' .  $dynabox_attributes. '><a href="' . $cdm_proxy_url . '" class="label" alt="' . t($link_alt_text) . '">' . $label . '</a>';
2215 d9763fd3 Andreas Kohlbecker
  $out .= '  <' . $enclosingtags[1] . ' id="dynabox-' . $dynabox_id . '-content">';
2216
  $out .= '    <' . $enclosingtags[0] . ' class="dynabox-content-inner">' . loading_image_html() . '</' . $enclosingtags[0] . '>';
2217
  $out .= '    </' . $enclosingtags[1] . '>';
2218
  $out .= '  </' . $enclosingtags[0] . '>';
2219 9c9d11f7 Andreas Kohlbecker
  $out .= '<!-- dynabox end -->';
2220 6657531f Andreas Kohlbecker
  return $out;
2221
}
2222
2223
/**
2224
 * Checks whether a feature has any description elements.
2225
 *
2226
 * @param mixed $featureNode
2227
 *   A feature node as produced by the function _mergeFeatureTreeDescriptions().
2228
 *
2229
 * @see _mergeFeatureTreeDescriptions()
2230
 *
2231
 * @return bool
2232
 *   Returns TRUE if the given $featureNode or any of its subordinate nodes
2233
 *   contains at least one non empty TextData or at least one DescriptionElement
2234
 *   of an other type. A TextData element holding a multilanguageText or a
2235
 *   source reference is considered to be not empty.
2236 159cd9bb Andreas Kohlbecker
 *
2237
 * @TODO this function may have become obsolete by the new method of detecting empty blocks,
2238 aa26f9f0 Andreas Kohlbecker
 *       see $block_content_is_not_empty in compose_feature_blocks() and
2239 0ebb6efc Andreas Kohlbecker
 *       $feature_block_has_content in compose_feature_block_items_generic
2240 6657531f Andreas Kohlbecker
 */
2241 f19f47fa Andreas Kohlbecker
function has_feature_node_description_elements($featureNode) {
2242 6657531f Andreas Kohlbecker
2243
  if (isset($featureNode->descriptionElements) && is_array($featureNode->descriptionElements) && count($featureNode->descriptionElements) > 0) {
2244 092744e1 Andreas Kohlbecker
    if(!isset($featureNode->descriptionElements['#type'])){ // #type is used to identify e.g. DTO elements: '#type' => 'DTO'
2245
      foreach ($featureNode->descriptionElements as $descriptionElement) {
2246 159cd9bb Andreas Kohlbecker
        if ($descriptionElement->class != "TextData" || isset($descriptionElement->multilanguageText_L10n->text)
2247
          && $descriptionElement->multilanguageText_L10n->text != ''
2248
          || isset($descriptionElement->sources[0])
2249
          || isset($descriptionElement->media[0]) ) {
2250 092744e1 Andreas Kohlbecker
          return TRUE;
2251
        }
2252 6657531f Andreas Kohlbecker
      }
2253
    }
2254
  }
2255 092744e1 Andreas Kohlbecker
  else if (isset($featureNode->childNodes) && is_array($featureNode->childNodes)) {
2256 fae36a2a Andreas Kohlbecker
    foreach ($featureNode->childNodes as $child) {
2257 f19f47fa Andreas Kohlbecker
      if (has_feature_node_description_elements($child)) {
2258 6657531f Andreas Kohlbecker
        return TRUE;
2259
      }
2260
    }
2261
  }
2262
  return FALSE;
2263
}
2264 f26245c8 Andreas Kohlbecker
2265
/**
2266
 * Checks if the current page is a valid taxon portal page and responds with HTTP status 404 (not found) otherwise
2267
 *
2268
 * @param $chapter
2269
 *   The taxon page chapter or part
2270
 */
2271
function cdm_check_valid_taxon_page($chapter){
2272
  static $taxon_tabs = null;
2273
2274
  cdm_check_valid_portal_page();
2275
2276
  if($taxon_tabs == null){
2277
    $taxon_tabs = array('all', 'description');
2278
    foreach(get_taxon_tabs_list() as $tab){
2279
      $taxon_tabs[] = strtolower($tab);
2280
    }
2281
  }
2282
2283
  if(!in_array($chapter, $taxon_tabs)){
2284
    // oops this is not a valid chapter name
2285 b4a5c2be Andreas Kohlbecker
    http_response_code(404); // 404 = Not Found
2286 f26245c8 Andreas Kohlbecker
  }
2287
2288
}
2289
2290
/**
2291
 * Checks if the current page is a valid portal page and responds with HTTP status 404 (not found) otherwise
2292
 *
2293
 * @param $chapter
2294
 *   The taxon page chapter or part
2295
 */
2296
function cdm_check_valid_portal_page(){
2297 595de9f0 Andreas Kohlbecker
  $ends_with_file_suffix_pattern = '/\/[^\.\/]*[\.][^\.\/]*$/';
2298 f26245c8 Andreas Kohlbecker
  if(preg_match($ends_with_file_suffix_pattern, $_GET['q'])){
2299
    // oops this urls ends with a file_suffix and thus does not refer to a portal page
2300 b4a5c2be Andreas Kohlbecker
    http_response_code(404); // 404 = Not Found
2301 595de9f0 Andreas Kohlbecker
    exit('HTTP 404');
2302 f26245c8 Andreas Kohlbecker
  }
2303
}
2304 b2b9e057 Andreas Kohlbecker
2305
/**
2306
 * Generates the diff of the texts and presents it in a HTML diff viewer.
2307
 *
2308
 * @param $text_a
2309
 * @param $text_b
2310
 * @return string
2311
 */
2312
function diff_viewer($text_a, $text_b) {
2313
2314
  static $diff_viewer_count = 0;
2315
2316
  $element_id = 'part_definitions_diff_' . $diff_viewer_count++;
2317
2318
  // http://code.stephenmorley.org/php/diff-implementation/
2319
  module_load_include('php', 'cdm_dataportal', 'lib/class.Diff');
2320
  drupal_add_css(drupal_get_path('module',
2321
      'cdm_dataportal') . '/css/diff.css');
2322 087bb473 Andreas Kohlbecker
  _add_jquery_ui();
2323 b2b9e057 Andreas Kohlbecker
  drupal_add_js(
2324
    'jQuery(document).ready( function(){
2325
        jQuery(\'#' . $element_id . '\').accordion({
2326
        collapsible: true,
2327
        active: false,
2328
        fillSpace: true,
2329
        }).children(\'div\').css({ \'height\': \'auto\' });
2330
        jQuery(\'#' . $element_id . ' table.diff\').prepend(\'<thead><tr><th>Default</th><th>User defined<th></th><tr></thead>\');
2331
     });'
2332
    , array(
2333
    'type' => 'inline',
2334
    'scope' => 'footer'
2335
  ));
2336
2337
  $diff = Diff::compare($text_a,
2338
    $text_b);
2339
  $diff_viewer_markup = '<div id="' . $element_id . '"><h3>View Diff</h3><div>'
2340
    . Diff::toTable($diff, '', '')
2341
    . '</div></div>';
2342
  return $diff_viewer_markup;
2343
}
2344