Project

General

Profile

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