Project

General

Profile

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