Project

General

Profile

Download (76 KB) Statistics
| Branch: | Tag: | Revision:
1
<?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
  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
  module_load_include('inc', 'cdm_dataportal', 'includes/pages');
27
  module_load_include('inc', 'cdm_dataportal', 'includes/media');
28
  module_load_include('inc', 'cdm_dataportal', 'includes/maps');
29
  module_load_include('inc', 'cdm_dataportal', 'includes/occurrences');
30
  module_load_include('inc', 'cdm_dataportal', 'includes/descriptions');
31
  module_load_include('inc', 'cdm_dataportal', 'includes/pre-drupal8');
32

    
33
  module_load_include('inc', 'cdm_dataportal', 'theme/theme_registry');
34
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.common');
35
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.descriptions');
36
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.media');
37
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.occurrence');
38
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.page');
39
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.taxon');
40
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.name');
41
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.references');
42

    
43
  module_load_include('php', 'cdm_dataportal', 'classes/footnotemanager');
44
  module_load_include('php', 'cdm_dataportal', 'classes/footnote');
45
  module_load_include('php', 'cdm_dataportal', 'classes/footnotekey');
46
  module_load_include('php', 'cdm_dataportal', 'classes/renderhints');
47

    
48

    
49
  /* ============================ java script functions ============================= */
50

    
51

    
52
  /**
53
  * loads external java script files asynchronously.
54
  *
55
  * @param unknown_type $script_url
56
  */
57
  function drupal_add_js_async($script_url, $callback){
58

    
59
    drupal_add_js("
60
          jQuery(document).ready(function() {
61
            jQuery.ajax({
62
              url: '" . $script_url . "',
63
              dataType: 'script',
64
              cache: true, // otherwise will get fresh copy every page load
65
              success: function() {
66
                    " . $callback . "
67
              }
68
            });
69
          });"
70
    , 'inline');
71
  }
72

    
73
  /**
74
   */
75
  function drupal_add_js_rowToggle($tableId){
76

    
77
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/table_modification.js');
78
      drupal_add_js('jQuery(document).ready(function(){
79
          addRowToggle("' . $tableId . '");
80
      });
81
      ', array('type' => 'inline'));
82
  }
83

    
84
  /**
85
   * @param unknown_type $link_element_selector
86
   * @param unknown_type $progress_element_selector
87
   */
88
  function _add_js_cdm_ws_progressbar($link_element_selector, $progress_element_selector){
89

    
90
    $callback = "jQuery('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');";
91

    
92
    drupal_add_js_async(variable_get('cdm_webservice_url', '').'js/cdm_ws_progress.js', $callback);
93

    
94
    //   drupal_add_js("
95
    //   	  if (Drupal.jsEnabled) {
96
    //         $(document).ready(function() {
97
    //       		$('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');
98
    //         });
99
    //       }", 'inline');
100
    }
101

    
102
  /**
103
   * @todo Please document this function.
104
   * @see http://drupal.org/node/1354
105
   */
106
  function _add_js_treeselector() {
107
    // drupal_add_js(drupal_get_path('module', 'cdm_dataportal').'/js/treeselector.js');
108
    drupal_add_js("
109
        jQuery(document).ready(function() {
110
           jQuery('#cdm-taxonomictree-selector-form #edit-val').change(function () {
111
                jQuery('#cdm-taxonomictree-selector-form').submit();
112
            });
113

    
114
        });
115
      ",
116
      array(
117
        'type' => 'inline',
118
        'scope' => 'footer'
119
      )
120
    );
121
  }
122

    
123
  function _add_js_openlayers() {
124

    
125
    $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.js';
126
    $proj4js = '/js/map/proj4js-1.1.0/proj4js-compressed.js';
127

    
128
    if(variable_get('cdm_js_devel_mode', FALSE)){
129
      // develooper mode libs
130
  //     $openlayers = '/js/map/OpenLayers-2.13.1/lib/OpenLayers.js';
131
      $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.debug.js';
132
      $proj4js = '/js/map/proj4js-1.1.0/proj4js-combined.js';
133
    }
134

    
135
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $openlayers,
136
      array(
137
        'type' => 'file',
138
        'weight' => JS_LIBRARY,
139
        'cache' => TRUE,
140
        'preprocess' => FALSE
141
      )
142
    );
143

    
144
    // see https://github.com/proj4js/proj4js
145
    // http://openlayers.org/dev/examples/using-proj4js.html
146
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $proj4js,
147
      array(
148
        'type' => 'file',
149
        'weight' => JS_LIBRARY,
150
        'cache' => TRUE,
151
      )
152
    );
153

    
154
    // configure the theme
155
    $openlayers_theme_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/OpenLayers-2.13.1/theme/default/';
156
    $openlayers_imp_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/img/dark/';
157
    drupal_add_js('OpenLayers.ImgPath="' . base_path() . $openlayers_imp_path . '";', array(
158
        'type' => 'inline',
159
        'weight' => JS_LIBRARY,
160
        'cache' => TRUE,
161
        'preprocess' => FALSE
162
      ));
163

    
164
    drupal_add_css($openlayers_theme_path . 'style.tidy.css',
165
      array(
166
        'type' => 'file',
167
        'cache' => TRUE,
168
        'preprocess' => FALSE
169
      )
170
    );
171

    
172
  }
173

    
174
  /**
175
   * @todo Please document this function.
176
   * @see http://drupal.org/node/1354
177
   */
178
  function _add_js_thickbox() {
179
    // ---- jQuery thickbox:
180
    /*
181
    * bug: compat-1.0.js && thickbox.js line 237 .trigger("unload") -> event is
182
    * not triggered because of problems with compat-1.0.js' see INSTALL.txt
183
    */
184
    // drupal_add_js(drupal_get_path('module',
185
    // 'cdm_dataportal').'/js/jquery.imagetool.min.js');
186
    //
187
    // Add a setting for the path to cdm_dataportal module, used to find the path
188
    // for the loading animation image in thickbox.
189
    drupal_add_js(array(
190
    'cdm_dataportal' => array(
191
    'cdm_dataportal_path' => base_path() . drupal_get_path('module', 'cdm_dataportal'),
192
    )
193
    ),
194
    'setting'
195
        );
196
        drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/thickbox.js');
197
        drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/cdm_thickbox.css');
198
  }
199

    
200
  /**
201
   * @todo Please document this function.
202
   * @see http://drupal.org/node/1354
203
   */
204
  function _add_js_lightbox($galleryID) {
205
    /*
206
     * Important Notice: The jquery.lightbox-0.5.js has been modified in order to
207
    * allow using the "alt" attribute for captions instead of the "title"
208
    * attribute
209
    */
210
    $lightbox_base_path =  drupal_get_path('module', 'cdm_dataportal') . '/js/jquery-lightbox-0.5';
211
    $lightbox_image_path = base_path() . $lightbox_base_path . '/images/';
212
    drupal_add_js($lightbox_base_path . '/js/jquery.lightbox-0.5.js');
213
    drupal_add_css($lightbox_base_path . '/css/jquery.lightbox-0.5.css');
214
    drupal_add_js('jQuery(document).ready(function() {
215
        jQuery(\'#' . $galleryID . ' a.lightbox\').lightBox({
216
          fixedNavigation:  true,
217
          imageLoading:     \'' . $lightbox_image_path . 'lightbox-ico-loading.gif\',
218
          imageBtnPrev:     \'' . $lightbox_image_path . 'lightbox-btn-prev.gif\',
219
          imageBtnNext:     \'' . $lightbox_image_path . 'lightbox-btn-next.gif\',
220
          imageBtnClose:    \'' . $lightbox_image_path . 'lightbox-btn-close.gif\',
221
          imageBlank:       \'' . $lightbox_image_path . 'lightbox-blank.gif\',
222
          adjustToWindow: true
223
        });
224
      });
225
      ', array('type' => 'inline'));
226
  }
227

    
228
  /**
229
   * @todo Please document this function.
230
   * @see http://drupal.org/node/1354
231
   */
232
  function _add_js_footnotes() {
233
    _add_js_domEvent();
234
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/footnotes.js');
235
  }
236

    
237
  /**
238
   * @todo Please document this function.
239
   * @see http://drupal.org/node/1354
240
   */
241
  function _add_js_cluetip() {
242

    
243
    // TODO replace by
244
    // @see http://www.socialembedded.com/labs/jQuery-Tooltip-Plugin/jQuery-Tooltip-Plugin.html
245
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.min.js');
246
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/jquery.dimensions.js');
247
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.hoverIntent.js');
248
    if(variable_get('cdm_js_devel_mode', FALSE)){
249
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.js');
250
    }
251
    drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/js/cluetip/jquery.cluetip.css');
252
    drupal_add_js("jQuery(document).ready(function(){
253
        jQuery('.cluetip').css({color: '#0062C2'}).cluetip({
254
          splitTitle: '|',
255
          showTitle: true,
256
          activation: 'hover',
257
          sicky: true,
258
          arrows: true,
259
          dropShadow: false,
260
          cluetipClass: 'rounded'
261
        });
262
      });", array('type' => 'inline'));
263
  }
264

    
265
  /**
266
   * @todo Please document this function.
267
   * @see http://drupal.org/node/1354
268
   */
269
  function _add_js_ahah() {
270

    
271
    _add_js_domEvent(); // requires domEvent.js
272
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/ahah-content.js');
273
  }
274

    
275
  /**
276
   * Adds the external javascript file for domEvent.js.
277
   *
278
   * @see drupal_add_js()
279
   */
280
  function _add_js_domEvent() {
281
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/domEvent.js');
282
  }
283

    
284
  /**
285
   * Provides the markup for an font awesome icon.
286
   *
287
   * The icons is created in default size without any extra features.
288
   *
289
   * The available icons are listed here http://fontawesome.io/cheatsheet/
290
   * fontawesome icons have much more features than implemented here in this function,
291
   * for spinning icons, fixed width icons, rotation, etc please checkout the
292
   * examples at http://fontawesome.io/examples/
293
   *
294
   * @parameter $icon_name
295
   *  The name of the icon which starts with 'fa-'
296
   *
297
   * @return String
298
   *    the markup for the icon in an <i> tag
299
   *
300
   */
301
  function font_awesome_icon_markup($icon_name, $attributes = array()){
302

    
303

    
304
    //<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
305

    
306
    $font_awesome_css_uri=drupal_get_path('module', 'cdm_dataportal').'/font-awesome/4.2.0/css/font-awesome.min.css';
307
    $font_awesome_css_uri="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css";
308

    
309
    drupal_add_html_head_link(
310
      array(
311
        'href' => $font_awesome_css_uri,
312
        'rel' => 'stylesheet'
313
      )
314
    );
315

    
316
    if(!isset($attributes['class'])){
317
      $attributes['class'] = array();
318
    }
319
    $attributes['class'][] = 'fa';
320
    $attributes['class'][] = $icon_name;
321

    
322
    return '<i ' . drupal_attributes($attributes) . '></i>';
323
  }
324

    
325

    
326
  /* ====================== hook implementations ====================== */
327
  /**
328
   * Implements hook_permission().
329
   *
330
   * Valid permissions for this module.
331
   *
332
   * @return array
333
   *   An array of valid permissions for the portfolio module.
334
   */
335
  function cdm_dataportal_permission() {
336
    return array(
337
      'administer cdm_dataportal' => array(
338
        'title' => t('administer cdm_dataportal'),
339
        'description' => t("TODO Add a description for 'administer cdm_dataportal'"),
340
      ),
341
      'cdm_dataportal view notes' => array(
342
        'title' => t('cdm_dataportal view notes'),
343
        'description' => t("TODO Add a description for 'cdm_dataportal view notes'"),
344
      ),
345
      // TODO Which other permissions are required?
346
      // -> check the WP6 requirements document.
347
    );
348
  }
349

    
350
/**
351
 * Implements hook_menu().
352
 */
353
function cdm_dataportal_menu() {
354
  $items = array();
355

    
356
  // @see settings.php.
357
  cdm_dataportal_menu_admin($items);
358
  cdm_dataportal_menu_help($items);
359

    
360
  $items['cdm_dataportal/names'] = array(
361
    'page callback' => 'cdm_dataportal_view_names',
362
    'access arguments' => array('access content'),
363
    'type' => MENU_CALLBACK,
364
  );
365

    
366
  // Optional callback arguments: page.
367
  $items['cdm_dataportal/taxon'] = array(
368
    'page callback' => 'cdm_dataportal_taxon_page_view',
369
    'access arguments' => array('access content'),
370
    'type' => MENU_CALLBACK,
371
    // Expected callback arguments: uuid.
372
  );
373

    
374
   // Optional callback arguments: page.
375
    //FIXME point to view/page method in this module
376
    $items['cdm_dataportal/specimen'] = array(
377
        'page callback' => 'cdm_dataportal_specimen_page_view',
378
        'access arguments' => array('access content'),
379
        'type' => MENU_CALLBACK,
380
        // Expected callback arguments: uuid.
381
    );
382

    
383
  $items['cdm_dataportal/name'] = array(
384
    'page callback' => 'cdm_dataportal_name_page_view',
385
      /*
386
    'page arguments' => array(
387
       'taxon_name_uuid',
388
       'taxon_to_hide_uuid',
389
       'synonym_uuid' => NULL
390
      ),
391
      */
392
    'access arguments' => array('access content'),
393
    'type' => MENU_CALLBACK,
394
    // Expected callback arguments: uuid.
395
  );
396

    
397
  $items['cdm_dataportal/reference'] = array(
398
    'page callback' => 'cdm_dataportal_view_reference',
399
    'access arguments' => array('access content'),
400
    'type' => MENU_CALLBACK,
401
    // Expected callback arguments: uuid.
402
  );
403

    
404
  $items['cdm_dataportal/reference/list'] = array(
405
    'page callback' => 'cdm_dataportal_view_reference_list',
406
    'access arguments' => array('access content'),
407
    'type' => MENU_CALLBACK,
408
    // Expected callback arguments: uuid.
409
  );
410

    
411
  $items['cdm_dataportal/media'] = array(
412
    'page callback' => 'cdm_dataportal_view_media',
413
    'access arguments' => array('access content'),
414
    'type' => MENU_CALLBACK,
415
    // Expected callback arguments:
416
    // uuid, mediarepresentation_uuid, part_uuid or part#.
417
  );
418

    
419
  $items['cdm_dataportal/polytomousKey'] = array(
420
    'page callback' => 'cdm_dataportal_view_polytomousKey',
421
    'access arguments' => array('access content'),
422
    'type' => MENU_CALLBACK,
423
    // Expected callback arguments: polytomousKey->uuid.
424
  );
425

    
426
  $items['cdm_dataportal/search'] = array(
427
    'page callback' => 'cdm_dataportal_view_search_advanced',
428
    'access arguments' => array('access content'),
429
    'type' => MENU_CALLBACK,
430
  );
431

    
432
  $items['cdm_dataportal/search/advanced'] = array(
433
    'title' => 'Advanced',
434
    'page callback' => 'cdm_dataportal_view_search_advanced',
435
    'access arguments' => array('access content'),
436
    'type' => MENU_DEFAULT_LOCAL_TASK,
437
  );
438

    
439
  $items['cdm_dataportal/search/taxon_by_description'] = array(
440
    'title' => 'By description full text',
441
    'page callback' => 'cdm_dataportal_view_search_taxon_by_description',
442
    'access arguments' => array('access content'),
443
    'type' => MENU_LOCAL_TASK,
444
  );
445

    
446
  $items['cdm_dataportal/search/results/taxon'] = array(
447
    'page callback' => 'cdm_dataportal_view_search_results_taxon',
448
    'access arguments' => array('access content'),
449
    'type' => MENU_CALLBACK,
450
  );
451
  /*
452
   $items['cdm/xml2json'] = array(
453
   'page callback' => 'cdm_view_xml2json',
454
   'access arguments' => array('access content'),
455
   'type' => MENU_CALLBACK,
456
   );
457
   */
458

    
459
  // if (arg(0)=='user' && ($uid=arg(1)) && is_numeric($uid)) {
460
  // User configuration of cdm_dataportal.
461
  $items['user/%/cdm_dataportal'] = array(
462
    'title' => 'cdm_dataportal',
463
    'access arguments' => array('access content'),
464
    'page callback' => 'drupal_get_form',
465
    'page arguments' => array('cdm_dataportal_user_form'),
466
    'type' => MENU_LOCAL_TASK,
467
    'weight' => 10,
468
  );
469
  // }
470

    
471
  // 'May not cache' in D5.
472
  $items['cdm_dataportal/name/%'] = array(
473
    // 'page callback' => 'cdm_dataportal_view_name',
474
    'page callback' => 'cdm_dataportal_name_page_view',
475
    'page arguments' => array(2, 3, 4),
476
    'access arguments' => array('access content'),
477
    'type' => MENU_CALLBACK,
478
  );
479

    
480
  // --- Local tasks for Taxon.
481
  // --- tabbed taxon page
482
  if (variable_get('cdm_dataportal_taxonpage_tabs', 1)) {
483
    $items['cdm_dataportal/taxon/%'] = array(
484
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
485
      'page callback' => 'cdm_dataportal_taxon_page_view',
486
      'access arguments' => array('access content'),
487
      'type' => MENU_CALLBACK,
488
      'weight' => 1,
489
      'page arguments' => array(2, "description")
490
      , // Expected callback arguments: name_uuid.
491
    );
492

    
493
    $items['cdm_dataportal/taxon/%/all'] = array(
494
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
495
      'page callback' => 'cdm_dataportal_taxon_page_view',
496
      'access arguments' => array('access content'),
497
      'type' => MENU_CALLBACK,
498
      'weight' => 2,
499
      'page arguments' => array(2, "all")
500
      , // Expected callback arguments: name_uuid.
501
    );
502

    
503
    $items['cdm_dataportal/taxon/%/description'] = array(
504
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'General')),
505
      'page callback' => 'cdm_dataportal_taxon_page_view',
506
      'access arguments' => array('access content'),
507
      'type' => MENU_DEFAULT_LOCAL_TASK,
508
      'weight' => 2,
509
      'page arguments' => array(2, "description")
510
      , // Expected callback arguments: name_uuid.
511
    );
512

    
513
    $items['cdm_dataportal/taxon/%/synonymy'] = array(
514
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Synonymy')),
515
      'page callback' => 'cdm_dataportal_taxon_page_view',
516
      'access arguments' => array('access content'),
517
      'type' => MENU_LOCAL_TASK,
518
      'weight' => 4,
519
      'page arguments' => array(2, "synonymy", 4)
520
      , // Expected callback arguments: name_uuid.
521
    );
522
    $items['cdm_dataportal/taxon/%/images'] = array(
523
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Images')),
524
      'page callback' => 'cdm_dataportal_taxon_page_view',
525
      'access arguments' => array('access content'),
526
      'type' => MENU_LOCAL_TASK,
527
      'weight' => 5,
528
      'page arguments' => array(2, "images")
529
      , // Expected callback arguments: name_uuid.
530
    );
531

    
532
    $items['cdm_dataportal/taxon/%/specimens'] = array(
533
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Specimens')),
534
      'page callback' => 'cdm_dataportal_taxon_page_view',
535
      'access arguments' => array('access content'),
536
      'type' => MENU_LOCAL_TASK,
537
      'weight' => 6,
538
      'page arguments' => array(2, "specimens")
539
      , // Expected callback arguments: name_uuid.
540
    );
541

    
542
    $items['cdm_dataportal/taxon/%/keys'] = array(
543
      'title' => theme('cdm_taxonpage_tab', array('tabname' => 'Keys')),
544
      'page callback' => 'cdm_dataportal_taxon_page_view',
545
      'access arguments' => array('access content'),
546
      'type' => MENU_LOCAL_TASK,
547
      'weight' => 6,
548
      'page arguments' => array(2, "keys")
549
      , // Expected callback arguments: name_uuid.
550
    );
551
  }
552

    
553
  // --- refresh link for all cdmnode types
554
  foreach (cdm_get_nodetypes() as $type=>$name) {
555
    $items['cdm_dataportal/' . $name . '/%/refresh'] = array(
556
        'title' => t('Refresh'),
557
        'page callback' => 'cdm_dataportal_refresh_node',
558
        'access arguments' => array('administer cdm_dataportal'),
559
        'type' => MENU_LOCAL_TASK,
560
        'weight' => 100,
561
        'page arguments' => array($name, 2)
562
    );
563
  }
564

    
565
  return $items;
566
}
567

    
568
/**
569
 * Implements hook_init().
570
 *
571
 */
572
function cdm_dataportal_init() {
573
  //FIXME To add CSS or JS that should be present on all pages, modules
574
  //      should not implement this hook, but declare these files in their .info file.
575
  drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal.css');
576
  // drupal_add_css(drupal_get_path('module', 'cdm_dataportal').'/cdm_dataportal_print.css', 'print');
577
  drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal_screen.css', array('type' => 'screen'));
578

    
579
  if(variable_get('cdm_debug_mode', FALSE)){
580
    $file = 'temporary://drupal_debug.txt';
581
    file_put_contents($file, 'CDM DEBUG LOG for ' . $_GET['q']. "\n"); // will overwrite the file
582
  }
583

    
584
  $bibliography_settings = get_bibliography_settings();
585
  $enclosing_tag = $bibliography_settings['enabled'] == 1 ? 'div' : 'span';
586
  FootnoteManager::registerFootnoteSet('BIBLIOGRAPHY', $enclosing_tag, $bibliography_settings['key_format']);
587
}
588

    
589
function cdm_dataportal_refresh_node($cdm_node_name, $uuid, $parameters = array()){
590

    
591
  $base_path = 'cdm_dataportal/' . $cdm_node_name . '/' . $uuid;
592

    
593
  if($cdm_node_name == 'taxon' && variable_get('cdm_dataportal_taxonpage_tabs', 1)){
594
    // force reloading of all and notify user about this special loading
595
    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: ')
596
        . l('Back to tabbed taxon page', $base_path));
597
    $base_path .= '/all';
598
  } else {
599
    drupal_set_message(t('The level 2 cache has been cleared for this page'));
600
  }
601

    
602
  $parameters['cacheL2_refresh'] ='1';
603

    
604

    
605
  drupal_goto($base_path, array('query' => $parameters));
606
}
607

    
608
/**
609
 * The function generate form for own user cdm dataportal configurations.
610
 */
611
function cdm_dataportal_user_form($form, &$form_state) {
612
  global $user;
613
  $checkbox_value = 'cdm_dataportal_' . $user->uid . '_default_tab_active';
614

    
615
  $form['taxon_page_tabs'] = array(
616
      '#type' => 'fieldset',
617
      '#title' => t('Taxon page tabs'),
618
  );
619
  $form['taxon_page_tabs']['check'] = array(
620
    '#type' => 'checkbox',
621
    '#title' => t('Activate user default configuration'),
622
    '#default_value' => variable_get($checkbox_value, 0),
623
    '#description' => t('Check this if you want configure your own default tab from the below menu.'),
624
  );
625

    
626
  $form['taxon_page_tabs']['cdm_dataportal_user_form'] = array(
627
    '#type' => 'select',
628
    '#title' => t('Default tab to display'),
629
    '#default_value' => get_default_taxon_tab(TRUE),
630
    '#options' => unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB),
631
    '#description' => t('<p>Select the default tab to display when visiting a taxon page. Only available if Tabbed Taxon Page is enable.</p>
632
              <strong>Note:</strong> After performing a search and clicking in any synonym, the taxon tab
633
              to be renderized will be the synonymy of the accepted taxon and not the above selected tab.'),
634
  );
635

    
636
  $form['submit'] = array(
637
    '#type' => 'submit',
638
    '#value' => t('Submit'),
639
  );
640

    
641
  return $form;
642
}
643

    
644
/**
645
 * Form submission handler for user_form().
646
 *
647
 * Submits the user cdm dataportal configurations.
648
 */
649
function cdm_dataportal_user_form_submit($form, &$form_state) {
650
  global $user;
651
  $msg_type = 'status';
652
  $username = $user->name;
653
  $variable_to_use = 'cdm_dataportal_' . $user->uid . '_default_tab';
654

    
655
  // If is the right user the variables are setted.
656
  if (arg(0) == 'user' && ($uid = arg(1)) && is_numeric($uid) && $user->uid == $uid) {
657
    $variable = unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB);
658
    variable_set($variable_to_use . '_active', $form_state['values']['check']);
659
    variable_set($variable_to_use, $form_state['values']['cdm_dataportal_user_form']);
660
    if ($form_state['values']['check']) {
661
      drupal_set_message(check_plain(t('The user default tab will be used for the next taxon site visit.')));
662
      drupal_set_message(check_plain(t('The user default tab has been changed to: !tab for the user !user', array(
663
        '!tab' => $variable[variable_get($variable_to_use, 0)],
664
        '!user' => $username,
665
      ))), $msg_type);
666
    }
667
    else {
668
      drupal_set_message(check_plain(t('The user default tab wont be used for
669
        the next taxon site, check the box if you want to use the user default configuration.')));
670
    }
671
    // Problem with the user id => variables wont be saved.
672
  }
673
  else {
674
    $msg_type = 'warning';
675
    drupal_set_message(check_plain(t('Default tab has not been saved due to user id problems')), $msg_type);
676
  }
677
}
678

    
679
/**
680
 * Implements hook_block_info().
681
 */
682
function cdm_dataportal_block_info() {
683

    
684
    // $block[0]["info"] = t("CDM DataPortal DevLinks");
685
    // $block[1]["info"] = t("CDM DataPortal Credits");
686
    $block["2"] = array(
687
        "info" => t("CDM Search Taxa"),
688
        "cache" => DRUPAL_NO_CACHE
689
      );
690
    // $block[3]["info"] = t("CDM Filters");
691
    $block["4"]["info"] = t("CDM Dataportal Print");
692
    $block["keys"]["info"] = t("CDM identification keys");
693
    $block["fundedByEDIT"]["info"] = t('Funded by EDIT');
694

    
695
    return $block;
696
}
697

    
698
/**
699
 * Implements hook_block_view().
700
 */
701
function cdm_dataportal_block_view($delta) {
702
  // TODO Rename block deltas (e.g. '2') to readable strings.
703
  switch ($delta) {
704
    // case 'delta-1':
705
    // $block['subject'] = t('Credits');
706
    // $block['content'] = theme('cdm_credits');
707
    // return $block;
708
    case '2':
709
      $block['subject'] = t('Search taxa');
710
      $form = drupal_get_form('cdm_dataportal_search_taxon_form');
711
      $block['content'] = drupal_render($form);
712

    
713
      if (variable_get('cdm_dataportal_show_advanced_search', 1)) {
714
        $block['content'] .= '<div>' . l(t('Advanced Search'), 'cdm_dataportal/search') . '</div>';
715
      }
716
      return $block;
717
    case '4':
718
      $block['subject'] = '';
719
      $block['content'] = theme('cdm_print_button');
720
      return $block;
721
    case "keys":
722
      $block['subject'] = t('Identification Keys');
723
      $block['content'] = theme('cdm_block_IdentificationKeys', array('taxonUuid' => NULL));
724
      return $block;
725
    case "fundedByEDIT":
726
      // t('Funded by EDIT');
727
      $text = '<none>';
728
      $block['subject'] = $text;
729
      $img_tag = '<img src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/funded_by_EDIT.png' . '" alt="' . $text . '"/>';
730
      $block['content'] = l($img_tag, "http://www.e-taxonomy.eu/", array(
731
        'attributes' => array("target" => "EDIT"),
732
        'absolute' => TRUE,
733
        'html' => TRUE,
734
      ));
735
      return $block;
736
  }
737
}
738

    
739
/*
740
 function cdm_dataportal_session_clear($cdm_ws_uri_update = FALSE){
741
 $_SESSION['cdm'] = NULL;
742
 if(is_string($cdm_ws_uri_update)){
743
 $_SESSION['cdm'] = array('ws_uri'=>$cdm_ws_uri_update);
744
 }
745
 }
746

    
747
 function cdm_dataportal_session_validate(){
748
 if(!isset($_SESSION['cdm']['ws_uri'])){
749
 $_SESSION['cdm'] = array('ws_uri'=>variable_get('cdm_webservice_url', FALSE));
750
 } else if($_SESSION['cdm']['ws_uri'] != variable_get('cdm_webservice_url', FALSE)){
751
 cdm_dataportal_session_clear(variable_get('cdm_webservice_url', FALSE));
752
 }
753
 }
754
 */
755

    
756
/**
757
 * creates a  selector form for taxonomic trees.
758
 *
759
 * @return a drupal form array
760
 */
761
function cdm_taxonomictree_selector() {
762
  _add_js_treeselector();
763

    
764
  $form = drupal_get_form('cdm_taxonomictree_selector_form');
765
  return $form;
766
}
767

    
768
/**
769
 * @todo Please document this function.
770
 * @see http://drupal.org/node/1354
771
 */
772
function cdm_taxonomictree_selector_form($form, &$form_state) {
773

    
774
  $url = url('cdm_api/setvalue/session', array('query' => NULL));
775
  $form['#action'] = $url;
776

    
777
  $form['var'] = array(
778
    '#weight' => -3,
779
    '#type' => 'hidden',
780
    '#value' => '[cdm][taxonomictree_uuid]',
781
  );
782

    
783
  $destination_array = drupal_get_destination();
784
  $destination = $destination_array['destination'];
785

    
786
  $form['destination'] = array(
787
    '#weight' => -3,
788
    '#type' => 'hidden',
789
    '#value' =>  $destination,
790
  );
791

    
792
  $options = cdm_get_taxontrees_as_options();
793
  $taxontree_includes = variable_get(CDM_TAXONTREE_INCLUDES, null);
794
  if($taxontree_includes){
795
    $filtered_options = array();
796
    foreach($options as $uuid=>$label){
797
      if(!empty($taxontree_includes[$uuid])){
798
        $filtered_options[$uuid] = $label;
799
      }
800
    }
801
    $options = $filtered_options;
802
  }
803

    
804
  $form['val'] = array(
805
    '#type' => 'select',
806
    '#title' => t('Available classifications'),
807
    '#default_value' => get_taxonomictree_uuid_selected(),
808
    '#options' => $options,
809
    '#attributes' => array('class' => array('highlite-first-child'))
810
  );
811

    
812
  return $form;
813

    
814
}
815

    
816
/* UNREACHABLE since action of form directly links to view.
817
 function cdm_dataportal_search_taxon_form_submit($form_id, $form_values) {
818

    
819
 $_SESSION['cdm']['search'] = $form_values;
820
 //return '/cdm_dataportal/search/taxon/'.$form_values['queryString'].'/'.($form_values['vernacular']?'1':'0').'/'.$form_values['language'];
821
 return '/cdm_dataportal/search/taxon/'.$form_values['queryString'].'/'.($form_values['onlyAccepted']?'1':'0');
822
 //$paramstr = compose_url_prameterstr($form_values);
823
 //return url('/cdm_dataportal/search/taxon/', array('query' => $paramstr));
824
 }
825
 */
826
/* ====================== menu callback functions ====================== */
827
/**
828
 * @todo Please document this function.
829
 * @see http://drupal.org/node/1354
830
 */
831
/*
832
function cdm_dataportal_form_alter(&$form, &$form_state, $form_id) {
833
  static $comment_node_disabled =  0;
834
  static $comment_node_read_only =  1;
835
  static $comment_node_read_write =  2;
836

    
837
  if ($form_id == 'node_type_form'
838
   && isset($form['identity']['type'])
839
   && array_key_exists($form['#node_type']->type, cdm_get_nodetypes())
840
  ) {
841
    $form['workflow']['comment'] = array(
842
      '#type' => 'radios',
843
      '#title' => t('Default comment setting'),
844
      '#default_value' => variable_get('comment__' . $node->type . $form['#node_type']->type, $comment_node_disabled),
845
      '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
846
      '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'),
847
    );
848
  }
849
}
850
*/
851

    
852
/**
853
 * Displays a list of the known taxonomic names.
854
 *
855
 * When the list of taxonomic names is displayed, long lists are split up into
856
 * multiple pages.
857
 *
858
 * TODO: Parameters are still preliminary.
859
 *
860
 * @param string $beginsWith
861
 * @param string $page
862
 *   Page number to diplay defaults to page 1.
863
 * @param bool $onlyAccepted
864
 */
865
function cdm_dataportal_view_names($beginsWith = 'A', $page = 1, $onlyAccepted = FALSE) {
866

    
867
  $out = t('<h3>Sorry, the name list feature is not yet available in this version of the DataPortal software<h3>');
868

    
869
  /*
870
  // FIXME the filter for accepted names will be a form element, thus this
871
  // widget should be generated via form api preferably as block.
872
  $out  = theme('cdm_dataportal_widget_filter_accepted', $onlyAccepted);
873
  $out .= theme('cdm_dataportal_widget_names_list', $names, $page);
874
  $out .= theme('cdm_listof_taxa', $taxonPager);
875
  return $out;
876
  */
877
}
878

    
879
/**
880
 * @todo Please document this function.
881
 * @see http://drupal.org/node/1354
882
 */
883
function cdm_dataportal_view_reference($uuid, $arg2 = NULL) {
884

    
885
  cdm_check_valid_portal_page();
886

    
887
  $reference = cdm_ws_get(CDM_WS_REFERENCE, $uuid);
888
  return theme('cdm_reference_page', array('reference' => $reference));
889
}
890

    
891
/**
892
 * Created a view on a all references contained in the portal.
893
 *
894
 * This function is used at the path cdm_dataportal/reference/list
895
 */
896
function cdm_dataportal_view_reference_list($pageNumber) {
897
  $referencePager = cdm_ws_page(CDM_WS_REFERENCE, variable_get('cdm_dataportal_search_items_on_page', CDM_DATAPORTAL_SEARCH_ITEMS_ON_PAGE), $pageNumber);
898
  return theme('cdm_reference_pager', array(
899
    'referencePager' => $referencePager,
900
    'path' => 'cdm_dataportal/reference/list/',
901
    ));
902
}
903

    
904
/**
905
 * @todo Please document this function.
906
 * @see http://drupal.org/node/1354
907
 */
908
function cdm_dataportal_view_media($mediaUuid, $mediarepresentation_uuid = FALSE, $part = 0) {
909

    
910
  cdm_check_valid_portal_page();
911

    
912
  $media = cdm_ws_get(CDM_WS_PORTAL_MEDIA, $mediaUuid);
913
  return theme('cdm_media_page', array(
914
    'media' => $media,
915
    'mediarepresentation_uuid' => $mediarepresentation_uuid,
916
    'partId' => $part,
917
    ));
918
}
919

    
920
/**
921
 * @todo Please document this function.
922
 * @see http://drupal.org/node/1354
923
 */
924
function _load_taxonBase(&$taxonBase) {
925
  if (isset($taxonBase->uuid)) {
926
    $taxonBase->name = cdm_ws_get(CDM_WS_TAXON, array($taxonBase->uuid, "name"));
927
    $taxonBase->name->taggedName = cdm_ws_get(CDM_WS_NAME, array($taxonBase->name->uuid, "taggedName"));
928
    $taxonBase->name->nomenclaturalReference = cdm_ws_get(CDM_WS_NAME, array($taxonBase->name->uuid, "nomenclaturalReference"));
929
  }
930
}
931

    
932
/**
933
 * Loads the media associated to the given taxon from the cdm server.
934
 * The aggregation settings regarding taxon relathionships and
935
 * taxonnomic childen are taken into account.
936
 *
937
 * The media lists are cached in a static variable.
938
 *
939
 * @param Taxon $taxon
940
 *   A CDM Taxon entitiy
941
 *
942
 * @return array
943
 *   An array of CDM Media entities
944
 *
945
 */
946
function _load_media_for_taxon($taxon) {
947

    
948
  static $media = NULL;
949

    
950
  if(!isset($media)) {
951
    $media = array();
952
  }
953
  if (!isset($media[$taxon->uuid])) {
954

    
955
    // --- GET Images --- //
956
    $mediaQueryParameters = array(
957
        "type" => "ImageFile",
958
    );
959

    
960
    $relationship_choice = variable_get(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS, unserialize(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS_DEFAULT));
961
    $mediaQueryParameters['relationships'] = implode(',', get_selection($relationship_choice['direct']));
962
    $mediaQueryParameters['relationshipsInvers'] = implode(',', get_selection($relationship_choice['invers']));
963

    
964
    $taxon_media_filter_choice = variable_get(CDM_TAXON_MEDIA_FILTER, unserialize(CDM_TAXON_MEDIA_FILTER_DEFAULT));
965
    $mediaQueryParameters['includeTaxonDescriptions'] = (boolean) $taxon_media_filter_choice['includeTaxonDescriptions'] != 0;
966
    $mediaQueryParameters['includeOccurrences'] = (boolean) $taxon_media_filter_choice['includeOccurrences'] != 0;
967
    $mediaQueryParameters['includeTaxonNameDescriptions'] = (boolean) $taxon_media_filter_choice['includeTaxonNameDescriptions'] != 0;
968

    
969
    $ws_endpoint = NULL;
970
    if ( variable_get('cdm_images_include_children', 0) == 0) {
971
      $ws_endpoint = CDM_WS_PORTAL_TAXON_MEDIA;
972
    } else {
973
      $ws_endpoint = CDM_WS_PORTAL_TAXON_SUBTREE_MEDIA;
974
    }
975

    
976
    $media[$taxon->uuid] = cdm_ws_get($ws_endpoint,
977
        array(
978
            $taxon->uuid,
979
        ),
980
        queryString($mediaQueryParameters)
981
       );
982
  }
983

    
984
  return $media[$taxon->uuid];
985
}
986

    
987
/**
988
 *
989
 * @param Taxon $taxon
990
 *   A CDM Taxon entitiy
991
 *
992
 * @return array
993
 *   An array of CDM SpecimenOrObservation entities
994
 *
995
function _load_occurences_for_taxon($taxon){
996

    
997
  static $occurences = NULL;
998

    
999
  if(!isset($occurences)) {
1000
    $occurences = array();
1001
  }
1002

    
1003
  if (!isset($occurences[$taxon->uuid])){
1004

    
1005
    $relationship_choice = variable_get(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS, unserialize(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS_DEFAULT));
1006
    $relationship_choice['direct'] = get_selection($relationship_choice['direct']);
1007
    $relationship_choice['invers'] = get_selection($relationship_choice['invers']);
1008

    
1009
    $by_associatedtaxon_query = http_build_query(array(
1010
        'relationshipsInvers' => implode(',', $relationship_choice['invers']),
1011
        'relationships' => implode(',', $relationship_choice['direct']),
1012
        'pageSize' => null // all hits in one page
1013
    )
1014
    );
1015

    
1016
    $pager = cdm_ws_get(CDM_WS_OCCURRENCE_BY_ASSOCIATEDTAXON,
1017
        null,
1018
        $by_associatedtaxon_query . '&taxonUuid=' . $taxon->uuid
1019
    );
1020

    
1021

    
1022
    if(isset($pager->records[0])){
1023
      $occurences[$taxon->uuid] =  $pager->records;
1024
    }
1025
  }
1026
  return $occurences[$taxon->uuid];
1027
}
1028
 */
1029

    
1030
/**
1031
 * Gets a Drupal variable, string or array and returns it.
1032
 *
1033
 * Similar to the variable_get() function of Drupal, except that this function
1034
 * is able to handle arrays correctly. This function is especially useful
1035
 * when dealing with collections of settings form elements (#tree = TRUE).
1036
 *
1037
 * @param string $variableKey
1038
 *   The Unique key of the Drupal variable in the Drupal variables table.
1039
 * @param string $defaultValueString
1040
 *   A string as for example derived from a CONSTANT.
1041
 *
1042
 * @return mixed
1043
 *   usually an array, depending on the nature of the variable.
1044
 *
1045
 * TODO compare with get_array_variable_merged() duplicate functions?
1046
 * @deprecated rather use get_array_variable_merged() since this function
1047
 * used an array as second parameter
1048
 */
1049
function mixed_variable_get($variableKey, $defaultValueString) {
1050
  $systemDefaults = unserialize($defaultValueString);
1051
  $storedSettings = variable_get($variableKey, array());
1052
  if (is_array($storedSettings)) {
1053
    // TODO better use drupal_array_merge_deep() ?
1054
    $settings = array_merge($systemDefaults, $storedSettings);
1055
  }
1056
  else {
1057
    $settings = $systemDefaults;
1058
  }
1059
  return $settings;
1060
}
1061

    
1062
/**
1063
 * Recursive function to convert an object into an array.
1064
 * also subordinate objects will be converted.
1065
 *
1066
 * @param object $object
1067
 * @return the array
1068
 */
1069
function convert_to_array($object) {
1070
  if(is_object($object) || is_array($object)) {
1071
    $array = (array)$object;
1072
    foreach ($array as $key=>$value){
1073
      $array[$key] = convert_to_array($value);
1074
    }
1075
    return $array;
1076
  } else {
1077
    return $object;
1078
  }
1079
}
1080

    
1081
/**
1082
 * Wraps the given $html string into a render array suitable for drupal_render()
1083
 *
1084
 * @param string $html
1085
 *   the html string, see
1086
 *   http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#markup
1087
 * @param number $weight
1088
 *   A positive or negative number (integer or decimal).
1089
 *   see http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#weightval
1090
 *
1091
 * @return
1092
 *   A render array
1093
 *
1094
 */
1095
function markup_to_render_array($html, $weight = FALSE) {
1096
  $render_array = array(
1097
    '#markup' => $html
1098
      );
1099
  if (is_numeric($weight)) {
1100
    $render_array['#weight'] = $weight;
1101
}
1102
  return $render_array;
1103
}
1104

    
1105
/**
1106
 * Loads the subgraph of a given PolytomousKeyNode.
1107
 *
1108
 * Loads the subgraph of the given PolytomousKeyNode recursively from
1109
 * the CDM REST service.
1110
 *
1111
 * @param mixed $polytomousKeyNode
1112
 *   PolytomousKeyNode passed by reference.
1113
 *
1114
 * @return void
1115
 */
1116
function _load_polytomousKeySubGraph(&$polytomousKeyNode) {
1117

    
1118
  if (!$polytomousKeyNode) {
1119
    return;
1120
  }
1121
  if ($polytomousKeyNode->class != "PolytomousKeyNode") {
1122
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1123
    return;
1124
  }
1125
  if (!is_uuid($polytomousKeyNode->uuid)) {
1126
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1127
    return;
1128
  }
1129

    
1130
  $polytomousKeyNode = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, $polytomousKeyNode->uuid);
1131

    
1132
  if (!$polytomousKeyNode) {
1133
    // drupal_set_message("_load_polytomousKeyChildNodes() : could not load polytomousKeyNode", "error");
1134
    return;
1135
  }
1136

    
1137
  // Load children.
1138
  foreach ($polytomousKeyNode->children as &$childNode) {
1139
    _load_polytomousKeySubGraph($childNode);
1140
  }
1141

    
1142
  // Load subkey.
1143
  $polytomousKeyNode->subkey = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, array($polytomousKeyNode->uuid, "subkey"));
1144

    
1145
  // Load taxon.
1146
  $polytomousKeyNode->taxon = cdm_ws_get(CDM_WS_POLYTOMOUSKEY_NODE, array($polytomousKeyNode->uuid, "taxon"));
1147
  _load_taxonBase($polytomousKeyNode->taxon);
1148
  return;
1149
}
1150

    
1151
/**
1152
 * @todo Please document this function.
1153
 * @see http://drupal.org/node/1354
1154
 */
1155
function cdm_dataportal_view_polytomousKey($polytomousKeyUuid) {
1156

    
1157
  cdm_check_valid_portal_page();
1158

    
1159
  $polytomousKey = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, $polytomousKeyUuid);
1160

    
1161
  $sourcePager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1162
  if (is_array($sourcePager->records)) {
1163
    $polytomousKey->sources = $sourcePager->records;
1164
    // $polytomousKey->sources->citation = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1165
  }
1166

    
1167
  $annotationPager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'annotations'));
1168
  if (is_array($annotationPager->records)) {
1169
    $polytomousKey->annotations = $annotationPager->records;
1170
  }
1171

    
1172
  _load_polytomousKeySubGraph($polytomousKey->root);
1173
  return theme('cdm_polytomousKey_page', array('polytomousKey' => $polytomousKey));
1174
}
1175

    
1176
/**
1177
 * Creates a taxon page view or a chapter of it.
1178
 *
1179
 * The taxon page gives detailed information on a taxon, it shows:
1180
 *  - Taxon name.
1181
 *  - Full list of synonyms homotypic synonyms on top, followed by the
1182
 *    heterotypic and finally followed by misapplied names.
1183
 *    The list is ordered historically.
1184
 *  - All description associated with the taxon.
1185
 *
1186
 * @param string $uuid
1187
 * @param string $chapter
1188
 *   Name of the part to display, valid values are:
1189
 *   'description', 'images', 'synonymy', 'specimens', 'all'.
1190
 *
1191
 * @return unknown_type
1192
 */
1193
function cdm_dataportal_taxon_page_view($uuid, $chapter = 'all', $synonym_uuid = NULL) {
1194

    
1195
  cdm_check_valid_taxon_page($chapter);
1196
  cdm_dd("START OF TAXON PAGE [" . $chapter . "] " . $uuid . ' for ' . $_GET['q']);
1197
  // show a warning in case the javascript development mode is anabled
1198
  if(variable_get('cdm_js_devel_mode', FALSE)) {
1199
    drupal_set_message(t('The !url1 is enabled.
1200
        WARNING: this is a performance penalty and must be turned off on production websites.', array(
1201
          '!url1' => l('java-script development mode', 'admin/config/cdm_dataportal/settings', array('fragment' => 'edit-cdm-js-devel-mode'))
1202
    )),
1203
    'warning'
1204
        );
1205
  }
1206

    
1207
  // Display the page for the taxon defined by $uuid.
1208
  // set_last_taxon_page_tab(arg(3));
1209
  $taxonpage = cdm_dataportal_taxon_view($uuid, $chapter, $synonym_uuid);
1210
  if (!empty($taxonpage)) {
1211
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid);
1212
    return cdm_node_show(NODETYPE_TAXON, $uuid, $taxonpage->title, $taxonpage->content);
1213
  }
1214
  else {
1215
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid . ' !!! PAGE IS EMPTY !!!');
1216
    return '';
1217
  }
1218
}
1219

    
1220
/**
1221
 * This function will genreate the taxon page part ($chapter) and returns a taxonpage object
1222
 * which has two fields, one for the page title and one for the content. Later on in the
1223
 * process chain the value contained in these fields will be passed to the cdm_node_show()
1224
 * function as the function parameters $title and $content.
1225
 *
1226
 * @param string $uuid
1227
 *   the uuid of the taxon to show
1228
 * @param string $chapter
1229
 *   Name of the part to display, valid values are:
1230
 *   'description', 'images', 'synonymy', 'all'.
1231
 *
1232
 * @return taxonpage object with the following fields:
1233
 *   - title : the title of the page
1234
 *   - content: the content of the page
1235
 *
1236
 */
1237
function cdm_dataportal_taxon_view($uuid, $chapter = 'all') {
1238
  // Taxon object.
1239
  $taxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $uuid);
1240
  if (empty($taxon)) {
1241
    drupal_set_title(t('Taxon does not exist'), PASS_THROUGH);
1242
    return FALSE;
1243
  }
1244
  $taxonpage = new stdClass();
1245

    
1246
  $taxonpage->title = theme('cdm_taxon_page_title', array(
1247
    'taxon' => $taxon
1248
  ));
1249

    
1250
  // Check if the taxon id contained in the currently selected tree.
1251
  $taxon_in_current_tree = taxon_in_current_tree($uuid);
1252

    
1253
  if (!$taxon_in_current_tree) {
1254
    $classifications = get_classifications_for_taxon($taxon);
1255
    if (count($classifications) == 0) {
1256
      drupal_set_message(check_plain(t('This concept of the taxon !taxonname is not contained as an accepted taxon in currently chosen classification.', array(
1257
        '!taxonname' => theme('cdm_taxonName', array('taxonName' => $taxon->name)),
1258
      ))), 'warning');
1259
    }
1260
    else {
1261
      $trees = '';
1262
      foreach ($classifications as $classification) {
1263
        if (isset($classification->titleCache)) {
1264
          $trees .= ($trees ? ', ' : '') . '<strong>' . $classification->titleCache . '</strong>';
1265
        }
1266
      }
1267

    
1268
      drupal_set_message(format_plural(count($trees),
1269
          'This concept of the taxon !taxonname is not contained as an accepted taxon in currently chosen classification, but in this one: !trees',
1270
          'This concept of the taxon !taxonname is not contained as an accepted taxon in currently chosen classification, but in one of these: !trees',
1271
          array('!taxonname' => theme('cdm_taxonName', array('taxonName' => $taxon->name)), '!trees' => $trees)) , 'warning');
1272
    }
1273
  }
1274

    
1275
  // Render the taxon page.
1276
  $render_array = compose_cdm_taxon_page($taxon, $chapter);
1277
  $taxonpage->content = drupal_render($render_array);
1278

    
1279
  return $taxonpage;
1280
}
1281

    
1282
/**
1283
 * Creates a specimen page view.
1284
 * @param string $uuid the UUID of the specimen
1285
 * @return array|string
1286
 */
1287
function cdm_dataportal_specimen_page_view($uuid) {
1288

    
1289
    //cdm_check_valid_taxon_page($chapter);
1290
    //cdm_dd("START OF TAXON PAGE [" . $chapter . "] " . $uuid . ' for ' . $_GET['q']);
1291
    // show a warning in case the javascript development mode is anabled
1292
    if(variable_get('cdm_js_devel_mode', FALSE)) {
1293
        drupal_set_message(t('The !url1 is enabled.
1294
        WARNING: this is a performance penalty and must be turned off on production websites.', array(
1295
            '!url1' => l('java-script development mode', 'admin/config/cdm_dataportal/settings', array('fragment' => 'edit-cdm-js-devel-mode'))
1296
        )),
1297
            'warning'
1298
        );
1299
    }
1300

    
1301
    // Display the page for the specimen defined by $uuid.
1302
    $specimenpage = cdm_dataportal_specimen_view($uuid);
1303
    if (!empty($specimenpage)) {
1304
        return cdm_node_show(NODETYPE_TAXON, $uuid, $specimenpage->title, $specimenpage->content);
1305
    }
1306
    else {
1307
        return '';
1308
    }
1309
}
1310

    
1311
/**
1312
 *
1313
 * Creates a specimen view.
1314
 * @param string $uuid the UUID of the specimen
1315
 * @return array|string
1316
 */
1317
function cdm_dataportal_specimen_view($uuid) {
1318
    // Taxon object.
1319
    $specimen = cdm_ws_get(CDM_WS_OCCURRENCE, $uuid);
1320
    if (empty($specimen)) {
1321
        drupal_set_title(t('Specimen does not exist'), PASS_THROUGH);
1322
        return FALSE;
1323
    }
1324
    $specimenpage = new stdClass();
1325

    
1326
    $specimenpage->title = theme('cdm_specimen_page_title', array(
1327
        'specimen' => $specimen
1328
    ));
1329

    
1330
    // Render the specimen page.
1331
    $render_array = compose_cdm_specimen_page($uuid);
1332
    $specimenpage->content = drupal_render($render_array);
1333

    
1334
    return $specimenpage;
1335
}
1336

    
1337
/**
1338
 * Returns a name page as a Drupal node ready to be renderized by Drupal.
1339
 *
1340
 * The node page shows the taxon name title and the list of taxon related
1341
 * with such taxon. Name on the tree already in use.
1342
 *
1343
 * @param UUID $taxon_name_uuid
1344
 *   The uuid of the CDM TaxonNameBase to show a name page for
1345
 * @param UUID $taxon_to_hide_uuid
1346
 *   A taxon which should not be displayed in the taxon list
1347
 * @param UUID $highlite_synonym_uuid
1348
 *   Optinal parameter wich takes another taxon uuid, if given the
1349
 *   target taxon pages will show the syonymy tab where the taxon
1350
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1351
 *   in case it is found on this page.
1352
 *
1353
 * @return mixed
1354
 *   The formatted name page as node.
1355
 */
1356
function cdm_dataportal_name_page_view($taxon_name_uuid, $taxon_to_hide_uuid, $synonym_uuid = NULL) {
1357

    
1358
  cdm_check_valid_portal_page();
1359

    
1360
  $taxonname_page = cdm_dataportal_name_view($taxon_name_uuid, $taxon_to_hide_uuid, $synonym_uuid);
1361
  if (!empty($taxonname_page)) {
1362
    return cdm_node_show(NODETYPE_NAME, $taxon_name_uuid, $taxonname_page->title, $taxonname_page->content);
1363
  }
1364
  else {
1365
    return '';
1366
  }
1367
}
1368

    
1369
/**
1370
 * View function for a TaxonNameBase page.
1371
 *
1372
 * The name page lists all taxa for which the name specified by the
1373
 * $taxon_name_uuid is being used. I case there is only one name the
1374
 * page automatically redirects ti the according taxon page. Otherwise
1375
 * the list of names is displayed.
1376
 *
1377
 * The parameter $taxon_to_hide_uuid allows to exclude a taxon from the
1378
 * list of taxa. This is useful for example when referencing from a taxon
1379
 * to the name page and the referring taxon should not be repeaded in the
1380
 * name page.
1381
 *
1382
 *
1383
 * @param UUID $taxon_name_uuid
1384
 *   The uuid of the CDM TaxonNameBase to show a name page for
1385
 * @param UUID $taxon_to_hide_uuid
1386
 *   A taxon which should not be displayed in the taxon list
1387
 * @param UUID $highlite_synonym_uuid
1388
 *   Optinal parameter wich takes another taxon uuid, if given the
1389
 *   target taxon pages will show the syonymy tab where the taxon
1390
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1391
 *   in case it is found on this page.
1392
 *
1393
 * @return object
1394
 *   An object with two fields:
1395
 *     - title: the page title
1396
 *     - content: the page content
1397
 */
1398
function cdm_dataportal_name_view($taxon_name_uuid, $taxon_to_hide_uuid, $highlite_synonym_uuid = NULL) {
1399
  // Getting the full taxonname object from the server.
1400
  $taxon_name = cdm_ws_get(CDM_WS_NAME, array($taxon_name_uuid));
1401
  if (!$taxon_name) {
1402
    drupal_set_title(t('Taxon name does not exist'), PASS_THROUGH);
1403
    return FALSE;
1404
  }
1405
  // Searching for all the taxa connected with the taxon name on the tree
1406
  // in use.
1407
  $name_cache = cdm_ws_get(CDM_WS_NAME_NAMECAHE, array($taxon_name_uuid));
1408
  $request_params = array();
1409
  $request_params['query'] = $name_cache;
1410
  $request_params['tree'] = get_taxonomictree_uuid_selected();
1411
  $request_params['doTaxa'] = 1;
1412
  $request_params['doSynonyms'] = 1;
1413
  $request_params['doTaxaByCommonNames'] = 0;
1414
  $request_params['matchMode'] = "EXACT";
1415
  $taxon_pager = cdm_ws_get(CDM_WS_PORTAL_TAXON_FIND, NULL, queryString($request_params));
1416

    
1417
  // Removing the name where we come from.
1418
  foreach ($taxon_pager->records as $k => &$taxon) {
1419
    if ($taxon->uuid == $taxon_to_hide_uuid) {
1420
      unset($taxon_pager->records[$k]);
1421
    }
1422
  }
1423
  // Show the taxa list or go to the singular taxon.
1424
  if (sizeof($taxon_pager->records) == 1) {// Single taxon case.
1425
    $singleTaxon = array_pop($taxon_pager->records);
1426
    if ($singleTaxon->class != "Taxon") {
1427
      // It is a Synonym -> look for the accepted.
1428
      $accepted_taxa = cdm_ws_get(CDM_WS_PORTAL_TAXON_ACCEPTED, array($singleTaxon->uuid, get_taxonomictree_uuid_selected()));
1429
      if (!empty($highlite_synonym_uuid)) {
1430
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxa[0]->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
1431
      }
1432
      else {
1433
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxa[0]->uuid . '/synonymy', array('query' => array('highlite' => $singleTaxon->uuid)));
1434
      }
1435
    }
1436
    else {
1437
      // It is an accepted taxon.
1438
      if (!empty($highlite_synonym_uuid)) {
1439
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
1440
      }
1441
      else {
1442
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid);
1443
      }
1444
    }
1445
  }
1446
  else {// More than one taxa case.
1447
    $taxon_name_page = new stdClass();
1448
    $taxon_name_page->title = theme('cdm_name_page_title', array('taxon_name' => $taxon_name));
1449
    if ($taxon_pager->records) {
1450
      $taxon_name_page->content = theme_cdm_list_of_taxa($taxon_pager->records, FALSE);
1451
    }
1452
    else {
1453
      $taxon_name_page->content = 'This name has no taxa';
1454
    }
1455
    return $taxon_name_page;
1456
  }
1457
}
1458

    
1459
/**
1460
 * @todo Please document this function.
1461
 * @see http://drupal.org/node/1354
1462
 */
1463
function cdm_dataportal_view_search_advanced() {
1464

    
1465
  drupal_set_title(t('Advanced search'), PASS_THROUGH);
1466
  $form = array();
1467
  $form_state = array();
1468
  $searchForm = cdm_dataportal_search_taxon_form($form, $form_state, TRUE);
1469

    
1470
  return drupal_get_form('cdm_dataportal_search_taxon_form_advanced');
1471

    
1472
}
1473

    
1474
/**
1475
 * @todo Please document this function.
1476
 * @see http://drupal.org/node/1354
1477
 */
1478
function cdm_dataportal_view_search_taxon_by_description() {
1479
  drupal_set_title(t('Search by description full text'), PASS_THROUGH);
1480
  // $form_state = false;
1481
  // $searchForm = cdm_dataportal_search_taxon_by_description_form($form_state);
1482
  $searchForm = cdm_dataportal_search_taxon_by_description_form();
1483

    
1484
  return drupal_get_form('cdm_dataportal_search_taxon_by_description_form');
1485
}
1486

    
1487
/**
1488
 * Executes the search and generates the result list of taxa.
1489
 */
1490
function cdm_dataportal_view_search_results_taxon() {
1491

    
1492
  $taxonPager = cdm_dataportal_search_execute();
1493

    
1494
  $showThumbnails = do_showThumbnails();
1495

    
1496
  $setSessionUri = url('cdm_api/setvalue/session', array(
1497
      'query' => array('var' => '[pageoption][searchtaxa][showThumbnails]', 'val' => ''),
1498
  ));
1499

    
1500
  drupal_add_js('jQuery(document).ready(function() {
1501

    
1502
      // init
1503
      if(' . $showThumbnails . ' == 1){
1504
      jQuery(\'.media_gallery\').show(20);
1505
  } else {
1506
      jQuery(\'.media_gallery\').hide(20);
1507
  }
1508
      // add change hander
1509
      jQuery(\'#showThumbnails\').change(
1510
      function(event){
1511
      var state = 0;
1512
      if(jQuery(this).is(\':checked\')){
1513
      jQuery(\'.media_gallery\').show(20);
1514
      state = 1;
1515
  } else {
1516
      jQuery(\'.media_gallery\').hide(20);
1517
  }
1518
      // store state in session variable
1519
      var uri = \'' . $setSessionUri . '\' + state;
1520
      jQuery.get(uri);
1521
  });
1522
  });',
1523
  array('type' => "inline", 'scope' => JS_DEFAULT));
1524

    
1525
  drupal_set_title(t('Search results'), PASS_THROUGH);
1526

    
1527
  return theme('cdm_search_results', array(
1528
    'pager' => $taxonPager,
1529
    'path' => 'cdm_dataportal/search/results/taxon',
1530
    ));
1531
}
1532

    
1533
/**
1534
 * Provides the standart image wich indicated a loading process
1535
 *
1536
 * @return string
1537
 *  The img html tag
1538
 */
1539
function loading_image_html() {
1540
  return '<img class="loading" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal')
1541
    . '/images/loading_circle_grey_16.gif" style="display:none;">';
1542
}
1543

    
1544
/**
1545
 * Returns the state of the the showThumbnails flag set in the
1546
 * users session ($_SESSION['pageoption']['searchtaxa']['showThumbnails']).
1547
 *
1548
 * @return boolean
1549
 *    returns 1 if the flag is set
1550
 */
1551
function do_showThumbnails() {
1552
  static $showThumbnails = null;
1553

    
1554
  if($showThumbnails == null) {
1555
    $showThumbnails = 0;
1556
    if (!isset($_SESSION['pageoption']['searchtaxa']['showThumbnails'])) {
1557
      $showThumbnails = 0;
1558
      $search_gallery_settings = variable_get(CDM_DATAPORTAL_SEARCH_GALLERY_NAME, null);
1559
      $showThumbnails = is_array($search_gallery_settings)
1560
        && isset($search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'])
1561
        && (
1562
            $search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'] +
1563
            $search_gallery_settings['cdm_dataportal_show_synonym_thumbnails'] +
1564
            $search_gallery_settings['cdm_dataportal_show_thumbnail_captions'] > 0
1565
            )
1566
         ? 1 : 0;
1567

    
1568
       drupal_array_set_nested_value($_SESSION, array('pageoption', 'searchtaxa', 'showThumbnails'), $showThumbnails);
1569
    }
1570
    $showThumbnails = $_SESSION['pageoption']['searchtaxa']['showThumbnails'];
1571
    if (!is_numeric($showThumbnails)) {
1572
      $showThumbnails = 1;
1573
    }
1574
  }
1575

    
1576
  return $showThumbnails;
1577
}
1578

    
1579
/**
1580
 * View which transforms XML output from a given webservice endpoint into JSON.
1581
 */
1582
/*
1583
 function cdm_view_xml2json(){
1584
 $file = arg(2);
1585
 $datastr = file_get_contents(variable_get('cdm_webservice_url', '').$file);
1586
 return  xml2json::transformXmlStringToJson($datastr);
1587
 }
1588
 */
1589

    
1590
/* ====================== other functions ====================== */
1591
/**
1592
 * Creates a URL to the taxon page specified by the $uuid parameter.
1593
 *
1594
 * The URL will be prepended with a path element to a specific taxon page tab.
1595
 *
1596
 * This tab is either taken from the CDM_DATAPORTAL_DEFAULT_TAXON_TAB which can
1597
 * be set globally in the administrative settings or individually in the user
1598
 * profile. If the CDM_DATAPORTAL_DEFAULT_TAXON_TAB value is set to LAST_VISITED_TAB
1599
 * the last portal will stay on this last tab.
1600
 *
1601
 * A third option is offerered by the $page_tab parameter which allows overwriting this
1602
 * internal mechanism by a specific value.
1603
 *
1604
 * @param string $uuid
1605
 *   The UUID of the taxon.
1606
 * @param string $page_tab
1607
 *   Overwriting the preset mechanism by defining specific value for the
1608
 *   taxon page tab.
1609
 *
1610
 * @return string
1611
 *   The created URL.
1612
 */
1613
function path_to_taxon($uuid, $page_tab = FALSE) {
1614

    
1615
  $tab = get_default_taxon_tab();
1616
  $values = unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB);
1617

    
1618
  if (!$uuid) {
1619
    return FALSE;
1620
  }
1621

    
1622
  if ($page_tab) {
1623
    return 'cdm_dataportal/taxon/' . $uuid . '/' . $page_tab;
1624
  }
1625
  elseif (!$tab || strtolower($tab) == 'general') {
1626
    return 'cdm_dataportal/taxon/' . $uuid;
1627
  }
1628
  elseif (get_last_taxon_page_tab() &&   $tab == $values[CDM_DATAPORTAL_LAST_VISITED_TAB_ARRAY_INDEX]) {
1629
    return 'cdm_dataportal/taxon/' . $uuid . '/' . get_last_taxon_page_tab();
1630
  }
1631
  else {
1632
    return 'cdm_dataportal/taxon/' . $uuid . '/' . strtolower($tab);
1633
  }
1634
}
1635

    
1636
function path_to_specimen($uuid) {
1637

    
1638
    if (!$uuid) {
1639
        return FALSE;
1640
    }
1641
    else {
1642
        return 'cdm_dataportal/specimen/' . $uuid;
1643
    }
1644
}
1645

    
1646
/**
1647
 * Creates a URL to show a synonmy in the according taxon page.
1648
 *
1649
 * The URL will point to the synonymy tab of the taxon page of the accepted taxon given as parameter $acceptedUuid.
1650
 * The resulting URI will include query parameters to highlight the synonym, and to optionally display
1651
 * the accepted taxons name in aform like "Foo bar is accepted taxon for Ree doo". The URI will also
1652
 * include the sysnonym uuid as fragment in order to let the browser scroll to the according location
1653
 * in the page
1654
 *
1655
 * @param string $synonymUuid
1656
 *    The uuid of the synonym
1657
 * @param string $acceptedUuid
1658
 *    The uuid of the according accepted taxon
1659
 * @return string
1660
 *    The URL to show a synonmy in the according taxon page
1661
 */
1662
function uri_to_synonym($synonymUuid, $acceptedUuid) {
1663
  $acceptedPath = path_to_taxon($acceptedUuid, "synonymy");
1664
  return url($acceptedPath, array(
1665
      'query' => array(
1666
        // highlite the synony in the synonymy
1667
        'highlite' => $synonymUuid,
1668
        // the taxon page is refered from a synonym and the synonym can optionally be named in the page title
1669
        // see theme_taxon_page_title()
1670
        'acceptedFor' => $synonymUuid
1671
      ),
1672
      'fragment' => $synonymUuid
1673
  ));
1674

    
1675
}
1676

    
1677
/**
1678
 * Compses the drupal path to the key identified by the uuid.
1679
 *
1680
 * @param string $keyType
1681
 *    the key typer corresponds to the specific class of the CDM
1682
 *    IdentificationKey. Possible values are
1683
 *      -PolytomousKey
1684
 *      -MultimediaKey
1685
 *      - ...
1686
 * @param UUID $keyUuid
1687
 *   The UUID of the key
1688
 */
1689
function path_to_key($keyType, $keyUuid) {
1690
  if (!$keyUuid || !$keyType) {
1691
    return FALSE;
1692
  }
1693
  $keyType{0} = strtolower($keyType{0});
1694
  return "cdm_dataportal/" . $keyType . "/$keyUuid";
1695
}
1696

    
1697
/**
1698
 * @todo Please document this function.
1699
 * @see http://drupal.org/node/1354
1700
 */
1701
function path_to_reference($uuid) {
1702
  if (!$uuid) {
1703
    return FALSE;
1704
  }
1705
  return 'cdm_dataportal/reference/' . $uuid;
1706
}
1707

    
1708
/**
1709
 * Creates the path to a cdm_dataportal taxon name page.
1710
 *
1711
 * @param UUID $taxon_name_uuid
1712
 *   The uuid of the CDM TaxonNameBase to show a name page for
1713
 * @param UUID $taxon_to_hide_uuid
1714
 *   A taxon which should not be displayed in the taxon list
1715
 * @param UUID $highlite_synonym_uuid
1716
 *   Optinal parameter wich takes another taxon uuid, if given the
1717
 *   target taxon pages will show the syonymy tab where the taxon
1718
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1719
 *   in case it is found on this page.
1720
 *
1721
 * @return a URI path element as string
1722
 */
1723
function path_to_name($name_uuid, $taxon_to_hide_uuid = NULL, $synonym_uuid  = NULL) {
1724
  $res = FALSE;
1725
  if ($name_uuid) {
1726
    $res = 'cdm_dataportal/name/' . $name_uuid;
1727
  }
1728
  if($taxon_to_hide_uuid){
1729
    $res .= '/' . $taxon_to_hide_uuid;
1730
    if($synonym_uuid){
1731
      $res .= '/' . $synonym_uuid;
1732
    }
1733
  }
1734
  return $res;
1735
}
1736

    
1737
/**
1738
 * @todo Please document this function.
1739
 * @see http://drupal.org/node/1354
1740
 */
1741
function path_to_media($uuid, $representaion_uuid = FALSE, $partId = FALSE) {
1742
  if (!$uuid) {
1743
    return FALSE;
1744
  }
1745
  $out = 'cdm_dataportal/media/' . $uuid;
1746
  if ($representaion_uuid) {
1747
    $out .= '/' . $representaion_uuid;
1748
    if ($partId !== FALSE) {
1749
      $out .= '/' . $partId;
1750
    }
1751
  }
1752
  return $out;
1753
}
1754

    
1755
/**
1756
 * Compares thisRank with thatRank.
1757
 *
1758
 * Returns a negative integer, zero, or a positive integer
1759
 * as the of thisRank is higher than, equal to, or lower than thatRank.
1760
 * e.g:
1761
 * <ul>
1762
 * <li>rank_compare({species_uuid}, {genus_uuid}) = -1</li>
1763
 * <li>rank_compare({genus_uuid}, {genus_uuid}) = 0</li>
1764
 * <li>rank_compare({genus_uuid}, {tribus_uuid}) = 1</li>
1765
 * </ul>
1766
 * <p>
1767
 * This compare logic of the underlying webservice is the
1768
 * <b>inverse logic</b> of the the one implemented in
1769
 * java.lang.Comparable#compareTo(java.lang.Object)
1770
 *
1771
 * @param $thisRankUuid
1772
 * @param $thatRankUuid
1773
 *
1774
 * @return int
1775
 *   A negative integer, zero, or a positive integer
1776
 *   as the thisRank is lower than, equal to, or higher than thatRank.
1777
 */
1778
function rank_compare($thisRankUuid, $thatRankUuid) {
1779
  $result = cdm_ws_get(CDM_WS_TERM_COMPARE, array($thisRankUuid, $thatRankUuid));
1780
  return $result->Integer;
1781
}
1782

    
1783
/**
1784
 * Composes an HTML element class attribute value composed of
1785
 * the shortname of the cdm class and the uuid of the entity.
1786
 * This class attribute should be used whereever an cdm-entity is rendered.
1787
 *
1788
 * These according class selectors in css must be escaped, eg:
1789
 *    .cdm\:TextData
1790
 *
1791
 * @param $cdmEntity
1792
 */
1793
function html_class_attribute_ref($cdmEntity) {
1794

    
1795
  if (is_cdm_entity($cdmEntity)) {
1796
    return "cdm:" . $cdmEntity->class . " uuid:" . $cdmEntity->uuid;
1797
  }
1798
}
1799

    
1800
/**
1801
 * Preprocess the taggedName to normalize newly introduced
1802
 * tagtypes like hybridSign, separator, .. more?
1803
 *
1804
 * @param unknown_type $taggedTextList
1805
 */
1806
function normalize_TaggedName(&$taggedTextList) {
1807

    
1808
  if (is_array($taggedTextList)) {
1809

    
1810
    // First pass: rename.
1811
    for ($i = 0; $i < count($taggedTextList); $i++) {
1812

    
1813
      if ($taggedTextList[$i]->type == "hybridSign") {
1814
        $taggedTextList[$i]->type = "name";
1815
      }
1816
    }
1817

    
1818
    // Second pass: resolve separators.
1819
    $taggedNameListNew = array();
1820
    for ($i = 0; $i < count($taggedTextList); $i++) {
1821

    
1822
      if ($i + 1 < count($taggedTextList) && $taggedTextList[$i + 1]->type == "separator") {
1823

    
1824
        if ($taggedTextList[$i]->type == $taggedTextList[$i + 2]->type) {
1825
          $taggedName = $taggedTextList[$i];
1826
          $taggedName->text = $taggedName->text . $taggedTextList[$i + 1]->text . $taggedTextList[$i + 2]->text;
1827
          $taggedNameListNew[] = $taggedName;
1828
          ++$i;
1829
          ++$i;
1830
        }
1831
      }
1832
      else {
1833
        $taggedNameListNew[] = $taggedTextList[$i];
1834
      }
1835
    }
1836
    $taggedTextList = $taggedNameListNew;
1837
  }
1838
}
1839

    
1840
/**
1841
 * Creates a short taxonname.
1842
 *
1843
 * The short name is created by using the taggename field of
1844
 * NameSTO or NameTO instances.
1845
 * If the taggename if empty the fullname will be returned.
1846
 *
1847
 * @param unknown_type $name
1848
 *   Name or TreeNode.
1849
 *
1850
 * @return string
1851
 */
1852
function cdm_dataportal_shortname_of($name) {
1853
  $nameStr = '';
1854

    
1855
  normalize_TaggedName($name->taggedTitle);
1856

    
1857
  // Get all tagged text tokens of the scientific name.
1858
  foreach ($name->taggedTitle as $tagtxt) {
1859
    if ($tagtxt->type == 'name' || $tagtxt->type == 'rank') {
1860
      $nameStr .= ($nameStr ? ' ' : '') . $tagtxt->text;
1861
    }
1862
  }
1863
  $nameStr = trim($nameStr);
1864

    
1865
  if ($nameStr) {
1866

    
1867
    // Do not return short names for these.
1868
    if ($name->unplaced || $name->excluded) {
1869
      return $nameStr;
1870
    }
1871

    
1872
    /*
1873
    1st capture group (^[a-zA-Z]): First letter of uninomial.
1874
    Second capture group ([\p{L}]+): remaining letters of uninomial ([\p{L} = an UTF-8 letter).
1875
    Third capture group (\s+[^(\x2E]+\s+.+$|\s+[a-zA-Z]+$): letters of name,
1876
    but only matching if no '(' or '.' in second word of name,        ( \x2E = '.')
1877
    OR only one specific epithet \s+[\p{L}\x22\x2D\xD7]+$             (\x22= '"', \x2D='-', \xD7='×' )
1878
    */
1879
    $pattern = '/(^[a-zA-Z])([\p{L}]+)(\s+[^(\x2E]+\s+.+$|\s+[\p{L}\x22\x2D\xD7]+$)/u';
1880
    if (preg_match($pattern, $nameStr, $matches, PREG_OFFSET_CAPTURE)) {
1881
      return $matches[1][0] . "." . $matches[3][0];
1882
    }
1883
    else {
1884
      return $nameStr;
1885
    }
1886
  }
1887
  else {
1888
    return $name->titleCache;
1889
  }
1890
}
1891

    
1892
/**
1893
 * Check if a taxon is accepted by the current taxonomic tree.
1894
 *
1895
 * @param mixed $taxon
1896
 *   The Taxon obkect to check.
1897
 *
1898
 * @return bool
1899
 *   Returns TRUE if $taxon is accepted, FALSE otherwise.
1900
 */
1901
function _cdm_dataportal_acceptedByCurrentView($taxon) {
1902

    
1903
  $defaultTreeUuid = get_taxonomictree_uuid_selected();
1904

    
1905
  if (isset($taxon->taxonNodes)) {
1906
    $taxonNodes = $taxon->taxonNodes;
1907
  }
1908
  else {
1909
    $taxonNodes = cdm_ws_get(CDM_WS_PORTAL_TAXON_TAXONNODES, $taxon->uuid);
1910
  }
1911

    
1912
  if ($taxon->class == "Taxon" && isset($taxonNodes)) {
1913
    foreach ($taxonNodes as $node) {
1914
      if (isset($node->classification)){
1915
        if(is_object($node->classification)) {
1916
          if ($node->classification->uuid == $defaultTreeUuid) {
1917
            return TRUE;
1918
          }
1919
        }
1920
        else {
1921
          if ($node->classification == $defaultTreeUuid) {
1922
            return TRUE;
1923
          }
1924
        }
1925
      }
1926
    }
1927
  }
1928

    
1929
  return FALSE;
1930
}
1931

    
1932
/**
1933
 * Workaround for missing original source type.
1934
 *
1935
 * idNamespace is always set in these cases.
1936
 * @todo improve documentation of this function.
1937
 *
1938
 * @param unknown_type $source
1939
 *
1940
 * @return unknown_type
1941
 */
1942
function _is_original_source_type($source) {
1943
  return !$source->idNamespace && strlen($source->idNamespace) == 0;
1944
}
1945

    
1946
/**
1947
 * @todo Please document this function.
1948
 * @see http://drupal.org/node/1354
1949
 */
1950
function _is_invers_taxonRelationship($taxonRelationship, $focusedTaxon) {
1951
  return $taxonRelationship->toTaxon->uuid == $focusedTaxon->uuid;
1952
}
1953

    
1954
/**
1955
 * Gets the metadata info such as title or artist of a media file.
1956
 *
1957
 * The function tries at first to get all the info from the file metadata
1958
 * and if it is not avaible look at the media file info stored at the database.
1959
 *
1960
 * @param mixed $media
1961
 *   The media file object for which to get the metadata.
1962
 *
1963
 * @return array
1964
 *   The array with the available specified metadata info.
1965
 * TODO rename to read_media_metadata() and move to *.module.
1966
 */
1967
function cdm_read_media_metadata($media) {
1968

    
1969
  $metadata_caption = array(
1970
    'title' => '',// Media_metadata and media.
1971
    'artist' => '',// Media_metadata and media.
1972
    'rights',// Media_metadata and media.
1973
    'location',// Media_metadata.
1974
    'filename' => '',// Media.
1975
    'mediacreated' => '',// Media.
1976
    'description' => '',
1977
  );// Media.
1978

    
1979
  // Getting the media metadata.
1980
  $media_metadata = cdm_ws_get(CDM_WS_MEDIA_METADATA, array($media->uuid));
1981
  $media_metadata_aux = (array) $media_metadata;
1982

    
1983
  // Filename.
1984
  if (!empty($media->representations[0]->parts[0]->uri)) {
1985
    $fileUri = $media->representations[0]->parts[0]->uri;
1986
    $filename = substr($fileUri, strrpos($fileUri, "/") + 1);
1987
    $metadata_caption['filename'] = $filename;
1988
  }
1989
  else {
1990
    $metadata_caption['filename'] = '';
1991
  }
1992

    
1993
  // Title.
1994
  if (!empty($media_metadata->ObjectName)) {
1995
    $metadata_caption['title'] = $media_metadata->ObjectName;
1996
  }
1997
  elseif (!empty($media_metadata_aux['Object Name'])) {
1998
    $metadata_caption['title'] = $media_metadata_aux['Object Name'];
1999
  }
2000
  elseif (!empty($media->title_L10n)) {
2001
    $metadata_caption['title'] = $media->title_L10n;
2002
  }
2003
  elseif (!empty($media->titleCache)) {
2004
    $metadata_caption['title'] = $media->titleCache;
2005
  }
2006

    
2007
  // Append description to title.
2008
  if (!empty($media->description_L10n)) {
2009
    $metadata_caption['title'] .= '<span class="media-description">' . $media->description_L10n . '<span>';
2010
  }
2011

    
2012
  // Artist.
2013
  if (!empty($media_metadata->Artist)) {
2014
    $metadata_caption['artist'] = '' . $media_metadata->Artist;
2015
  }
2016
  elseif (!empty($media->artist->titleCache)) {
2017
    $metadata_caption['artist'] = $media->artist->titleCache;
2018
  }
2019

    
2020
  // Copyright.
2021
  $metadata_caption['rights'] = array(
2022
    'copyright' => array('agentNames' => array()),
2023
    'license' => array(
2024
      'agentNames' => array(),
2025
      'types' => array(),
2026
      'abbreviatedTexts' => array(),
2027
      'uris' => array(),
2028
    ),
2029
  );
2030
  if (!empty($media_metadata->Copyright)) {
2031
    $metadata_caption['rights']['copyright']['agentNames'][] = $media_metadata->Copyright;
2032
  }
2033
  elseif (isset($media->rights) && is_array($media->rights)) {
2034
    foreach ($media->rights as $right) {
2035
      if(isset($right->term)){
2036
        switch ($right->type->uuid) {
2037
          case UUID_RIGHTS_LICENCE:
2038
            $metadata_caption['rights']['license']['agentNames'][] = ($right->agent ? '' . $right->agent->firstname . ' ' . $right->agent->lastname : '');
2039
            $metadata_caption['rights']['license']['types'][] = ($right->representation_L10n ? '' . $right->representation_L10n : '');
2040
            $metadata_caption['rights']['license']['abbreviatedTexts'][] = ($right->abbreviatedText ? '' . $right->abbreviatedText : '');
2041
            $metadata_caption['rights']['license']['uris'][] = ($right->uri ? '' . $right->uri : '');
2042
            break;
2043
          case UUID_RIGHTS_COPYRIGHT:
2044
            $metadata_caption['rights']['copyright']['agentNames'][] = $right->agent->firstname . ' ' . $right->agent->lastname;
2045
            break;
2046
        }
2047
      }
2048
    }
2049
  }
2050
  else {
2051
    $metadata_caption['rights']['agentNames'][] = '';
2052
  }
2053

    
2054
  // Filling the description (though there is no description in the db???).
2055
  // $metadata_caption['description'] = $media->description_L10n;
2056

    
2057
  // Location.
2058
  $metadata_caption['location'] = array();
2059
  $metadata_caption['location']['sublocation'] = !empty($media_metadata->Sublocation) ? $media_metadata->Sublocation : FALSE;
2060
  $metadata_caption['location']['city'] = !empty($media_metadata->City) ? $media_metadata->City : FALSE;
2061
  $metadata_caption['location']['province'] = !empty($media_metadata->Province) ? $media_metadata->Province : FALSE;
2062
  $metadata_caption['location']['country'] = !empty($media_metadata->Country)? $media_metadata->Country : FALSE;
2063

    
2064
  /*
2065
   // Creation date.
2066
   if($media_metadata["Modify Date"])
2067
   $metadata_caption['mediacreated'] = $media_metadata["Modify Date"];
2068
   else
2069
   $metadata_caption['mediacreated'] = $media->created;
2070
   */
2071

    
2072
  // Returned value.
2073
  return $metadata_caption;
2074
}
2075

    
2076
/**
2077
 * Collects all the media from a list of description elements.
2078
 *
2079
 * @param array $descriptionElements
2080
 *   The description elements from which to collect the media.
2081
 *
2082
 * @return array
2083
 *   The output with all the collected media.
2084
 */
2085
function cdm_dataportal_media_from_descriptionElements($descriptionElements) {
2086

    
2087
  $outArrayOfMedia = array();
2088

    
2089
  // Avoiding a warning box in Drupal for Flora Malesiana.
2090
  if (isset($descriptionElements) && is_array($descriptionElements)) {
2091
    foreach ($descriptionElements as $descriptionElement) {
2092
      if (isset($descriptionElement->media) && is_array($descriptionElement->media)) {
2093
        foreach ($descriptionElement->media as $media) {
2094
          if (is_object($media)) {
2095
            $outArrayOfMedia[] = $media;
2096
          }
2097
        }
2098
      }
2099
    }
2100
  }
2101
  return $outArrayOfMedia;
2102
}
2103

    
2104
/**
2105
 * @todo Please document this function.
2106
 * @see http://drupal.org/node/1354
2107
 *
2108
 * @param array $cdmBase_list
2109
 *   An array of CdmBase instances or a single instance.
2110
 * @param string $footnote_list_key_suggestion
2111
 *
2112
 * @return unknown
2113
 */
2114
function cdm_annotations_as_footnotekeys($cdmBase_list, $footnote_list_key_suggestion = NULL) {
2115

    
2116
   static $annotations_types_filter = null;
2117
   if(!$annotations_types_filter) {
2118
     $annotations_types_filter = unserialize(ANNOTATIONS_TYPES_AS_FOOTNOTES_DEFAULT);
2119
   }
2120

    
2121
  $footNoteKeys = array();
2122

    
2123
  // Is argument cdmBase an array?
2124
  if (!is_array($cdmBase_list)) {
2125
    $cdmBase_array = array();
2126
    $cdmBase_array[] = $cdmBase_list;
2127
  }
2128
  else {
2129
    $cdmBase_array = $cdmBase_list;
2130
  }
2131

    
2132
  // Getting the key for the footnotemanager.
2133
  if (isset($footnote_list_key_suggestion)) {
2134
    $footnote_list_key = $footnote_list_key_suggestion;
2135
  }
2136
  else {
2137
    $footnote_list_key = RenderHints::getFootnoteListKey() . '-annotations';
2138
  }
2139

    
2140
  // Adding the footnotes keys.
2141
  foreach ($cdmBase_array as $cdmBase_element) {
2142
    $annotations = cdm_ws_getAnnotationsFor($cdmBase_element, variable_get('annotations_types_as_footnotes', $annotations_types_filter));
2143
    if (is_array($annotations)) {
2144
      foreach ($annotations as $annotation) {
2145
        $footNoteKeys[] = FootnoteManager::addNewFootnote($footnote_list_key, $annotation->text);
2146
      }
2147
    }
2148
  }
2149

    
2150
  return $footNoteKeys;
2151
}
2152

    
2153
// @WA Comment: should this not be a theme function?
2154
/**
2155
 *  Creates a CDM Dynabox.
2156
 * @param string $dynabox_id
2157
 *   a uninque name for tha dynabox, using a cdm entity uuid herefore is good pratice.
2158
 * @param string $label
2159
 *   The clickable text to show.
2160
 * @param string $content_url
2161
 *   The cdm REST service request url wich will deliver the content to be shown
2162
 *   once the dynabox toggles open.
2163
 * @param string $theme
2164
 *   The theme to be used for rendering the cdm REST service response with is
2165
 *   returned from the $content_url.
2166
 * @param string $link_alt_text
2167
 *   The value for the alt attribute of the dynabox link.
2168
 * @param array $enclosingtags
2169
 *   An array with two elements: $enclosingtags[0] will be used for the dynabox
2170
 *   element itself, $enclosingtags[1] is the tag to be used for the
2171
 *   dynabox_content (optional)
2172
 * @param string $open_callback
2173
 *   optional javascript call back function to be triggered after toggling the box to
2174
 *   the open state.
2175
 * @param string $close_callback
2176
 *   optional javascript call back function to be triggered after toggling the box to
2177
 *   the closed state.
2178
 *
2179
 * @return string
2180
 *   Returns HTML for a dynabox.
2181
 */
2182
function cdm_dynabox($dynabox_id, $label, $content_url, $theme, $link_alt_text, $enclosingtags = array('li', 'ul'), $attributes = array(), $open_callback = 'function(){}', $close_callback = 'function(){}') {
2183
  $out = '';
2184

    
2185
  // check for plain class attribute string
2186
  $dynabox_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $dynabox_id);
2187

    
2188
  if(!array_key_exists('class', $attributes)) {
2189
    $attributes['class'] = array();
2190
  }
2191
  $attributes['class'][] = 'dynabox-' . $dynabox_id;
2192
  $dynabox_attributes = drupal_attributes($attributes);
2193

    
2194

    
2195
  _add_js_domEvent(); // requires domEvent.js
2196
  drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cdm_dynabox.js');
2197
  drupal_add_js("
2198
  jQuery(document).ready(
2199
      function() {
2200
        dynabox('". $dynabox_id ."',
2201
          {
2202
            open_callback: " . $open_callback .",
2203
            close_callback: " . $close_callback ."
2204
          }
2205
        );
2206
      }
2207
   );",
2208
   array(
2209
    'type'=>'inline',
2210
    'scope'=>'footer'
2211
    )
2212
  );
2213

    
2214

    
2215
  $cdm_proxy_url = url('cdm_api/proxy/' . urlencode($content_url) . "/$theme");
2216
  $out .= '<!-- dynabox for ' . $content_url . ' -->';
2217
  $out .= '<' . $enclosingtags[0] . ' ' .  $dynabox_attributes. '><a href="' . $cdm_proxy_url . '" class="label" alt="' . t($link_alt_text) . '">' . $label . '</a>';
2218
  // TODO stop using the title attribute, the label href now contains the same url!
2219
  $out .= '<' . $enclosingtags[1] . ' class="dynabox-' . $dynabox_id . '-content" title="' . $cdm_proxy_url . '">';
2220
  $out .= '<' . $enclosingtags[0] . ' class="dynabox-content-inner">' . loading_image_html() . '</' . $enclosingtags[0] . '>';
2221
  $out .= '</' . $enclosingtags[1] . '>';
2222
  $out .= '</' . $enclosingtags[0] . '>';
2223
  $out .= '<!-- dynabox end -->';
2224
  return $out;
2225
}
2226

    
2227
/**
2228
 * Checks whether a feature has any description elements.
2229
 *
2230
 * @param mixed $featureNode
2231
 *   A feature node as produced by the function _mergeFeatureTreeDescriptions().
2232
 *
2233
 * @see _mergeFeatureTreeDescriptions()
2234
 *
2235
 * @return bool
2236
 *   Returns TRUE if the given $featureNode or any of its subordinate nodes
2237
 *   contains at least one non empty TextData or at least one DescriptionElement
2238
 *   of an other type. A TextData element holding a multilanguageText or a
2239
 *   source reference is considered to be not empty.
2240
 *
2241
 * @TODO this function may have become obsolete by the new method of detecting empty blocks,
2242
 *       see $block_content_is_not_empty in compose_cdm_feature_nodes() and
2243
 *       $feature_block_has_content in compose_cdm_descriptionElements
2244
 */
2245
function has_feature_node_description_elements($featureNode) {
2246

    
2247
  if (isset($featureNode->descriptionElements) && is_array($featureNode->descriptionElements) && count($featureNode->descriptionElements) > 0) {
2248
    if(!isset($featureNode->descriptionElements['#type'])){ // #type is used to identify e.g. DTO elements: '#type' => 'DTO'
2249
      foreach ($featureNode->descriptionElements as $descriptionElement) {
2250
        if ($descriptionElement->class != "TextData" || isset($descriptionElement->multilanguageText_L10n->text)
2251
          && $descriptionElement->multilanguageText_L10n->text != ''
2252
          || isset($descriptionElement->sources[0])
2253
          || isset($descriptionElement->media[0]) ) {
2254
          return TRUE;
2255
        }
2256
      }
2257
    }
2258
  }
2259
  else if (isset($featureNode->childNodes) && is_array($featureNode->childNodes)) {
2260
    foreach ($featureNode->childNodes as $child) {
2261
      if (has_feature_node_description_elements($child)) {
2262
        return TRUE;
2263
      }
2264
    }
2265
  }
2266
  return FALSE;
2267
}
2268

    
2269
/**
2270
 * Checks if the current page is a valid taxon portal page and responds with HTTP status 404 (not found) otherwise
2271
 *
2272
 * @param $chapter
2273
 *   The taxon page chapter or part
2274
 */
2275
function cdm_check_valid_taxon_page($chapter){
2276
  static $taxon_tabs = null;
2277

    
2278
  cdm_check_valid_portal_page();
2279

    
2280
  if($taxon_tabs == null){
2281
    $taxon_tabs = array('all', 'description');
2282
    foreach(get_taxon_tabs_list() as $tab){
2283
      $taxon_tabs[] = strtolower($tab);
2284
    }
2285
  }
2286

    
2287
  if(!in_array($chapter, $taxon_tabs)){
2288
    // oops this is not a valid chapter name
2289
    http_send_status(404); // 404 = Not Found
2290
  }
2291

    
2292
}
2293

    
2294
/**
2295
 * Checks if the current page is a valid portal page and responds with HTTP status 404 (not found) otherwise
2296
 *
2297
 * @param $chapter
2298
 *   The taxon page chapter or part
2299
 */
2300
function cdm_check_valid_portal_page(){
2301
  $ends_with_file_suffix_pattern = '/\/[^\.\/]*[\.][^\.\/]*$/';
2302
  if(preg_match($ends_with_file_suffix_pattern, $_GET['q'])){
2303
    // oops this urls ends with a file_suffix and thus does not refer to a portal page
2304
    http_send_status(404); // 404 = Not Found
2305
    exit('HTTP 404');
2306
  }
2307
}
(7-7/14)