Project

General

Profile

Download (97.5 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/symbols');
26
  module_load_include('inc', 'cdm_dataportal', 'includes/common');
27
  module_load_include('inc', 'cdm_dataportal', 'includes/footnotes');
28
  module_load_include('inc', 'cdm_dataportal', 'includes/agent');
29
  module_load_include('inc', 'cdm_dataportal', 'includes/name');
30
  module_load_include('inc', 'cdm_dataportal', 'includes/taxon');
31
  module_load_include('inc', 'cdm_dataportal', 'includes/taxon-node');
32
  module_load_include('inc', 'cdm_dataportal', 'includes/references');
33
  module_load_include('inc', 'cdm_dataportal', 'includes/pages');
34
  module_load_include('inc', 'cdm_dataportal', 'includes/media');
35
  module_load_include('inc', 'cdm_dataportal', 'includes/maps');
36
  module_load_include('inc', 'cdm_dataportal', 'includes/occurrences');
37
  module_load_include('inc', 'cdm_dataportal', 'includes/occurrences_new'); // tmp file, shoud be merged later with occurrences.inc
38
  module_load_include('inc', 'cdm_dataportal', 'includes/descriptions');
39
  module_load_include('inc', 'cdm_dataportal', 'includes/pre-drupal8');
40

    
41
  module_load_include('inc', 'cdm_dataportal', 'theme/theme_registry');
42
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.common');
43
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.descriptions');
44
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.media');
45
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.page');
46
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.taxon');
47
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.name');
48
  module_load_include('theme', 'cdm_dataportal', 'theme/cdm_dataportal.references');
49

    
50
  module_load_include('php', 'cdm_dataportal', 'classes/footnotemanager');
51
  module_load_include('php', 'cdm_dataportal', 'classes/footnote');
52
  module_load_include('php', 'cdm_dataportal', 'classes/footnotekey');
53
  module_load_include('php', 'cdm_dataportal', 'classes/renderhints');
54

    
55

    
56
  /* ============================ java script functions ============================= */
57

    
58

    
59
  /**
60
  * loads external java script files asynchronously.
61
  *
62
  * @param unknown_type $script_url
63
  */
64
  function drupal_add_js_async($script_url, $callback){
65

    
66
    drupal_add_js("
67
          jQuery(document).ready(function() {
68
            jQuery.ajax({
69
              url: '" . $script_url . "',
70
              dataType: 'script',
71
              cache: true, // otherwise will get fresh copy every page load
72
              success: function() {
73
                    " . $callback . "
74
              }
75
            });
76
          });"
77
    , 'inline');
78
  }
79

    
80
  /**
81
   */
82
  function drupal_add_js_rowToggle($tableId){
83

    
84
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/table_modification.js');
85
      drupal_add_js('jQuery(document).ready(function(){
86
          addRowToggle("' . $tableId . '");
87
      });
88
      ', array('type' => 'inline'));
89
  }
90

    
91
  /**
92
   * @param unknown_type $link_element_selector
93
   * @param unknown_type $progress_element_selector
94
   */
95
  function _add_js_cdm_ws_progressbar($link_element_selector, $progress_element_selector){
96

    
97
    $callback = "jQuery('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');";
98

    
99
    drupal_add_js_async(variable_get('cdm_webservice_url', '').'js/cdm_ws_progress.js', $callback);
100

    
101
    //   drupal_add_js("
102
    //   	  if (Drupal.jsEnabled) {
103
    //         $(document).ready(function() {
104
    //       		$('" . $link_element_selector . "').cdm_ws_progress('" . $progress_element_selector . "');
105
    //         });
106
    //       }", 'inline');
107
    }
108

    
109
  /**
110
   * @todo Please document this function.
111
   * @see http://drupal.org/node/1354
112
   */
113
  function _add_js_treeselector() {
114
    // drupal_add_js(drupal_get_path('module', 'cdm_dataportal').'/js/treeselector.js');
115
    drupal_add_js("
116
        jQuery(document).ready(function() {
117
           jQuery('#cdm-taxonomictree-selector-form #edit-val').change(function () {
118
                jQuery('#cdm-taxonomictree-selector-form').submit();
119
            });
120

    
121
        });
122
      ",
123
      array(
124
        'type' => 'inline',
125
        'scope' => 'footer'
126
      )
127
    );
128
  }
129

    
130
  function _add_js_resizable_element($selector, $y_axis_only) {
131

    
132
    _add_jquery_ui();
133
    $options = "";
134
    if($y_axis_only) {
135
      $options = "resize: function(event, ui) {
136
        ui.size.width = ui.originalSize.width;
137
        },
138
        handles: \"s\"";
139

    
140
    }
141
    drupal_add_js("
142
          jQuery(document).ready(function() {
143
             jQuery('" . $selector . "').resizable({". $options ."});
144
          });
145
        ",
146
      array(
147
        'type' => 'inline',
148
        'scope' => 'footer'
149
      )
150
    );
151
  }
152

    
153
  function _add_js_openlayers() {
154

    
155
    $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.js';
156
    $proj4js = '/js/map/proj4js-1.1.0/proj4js-compressed.js';
157

    
158
    if(variable_get('cdm_js_devel_mode', FALSE)){
159
      // develooper mode libs
160
  //     $openlayers = '/js/map/OpenLayers-2.13.1/lib/OpenLayers.js';
161
      $openlayers = '/js/map/OpenLayers-2.13.1/OpenLayers.debug.js';
162
      $proj4js = '/js/map/proj4js-1.1.0/proj4js-combined.js';
163
    }
164

    
165
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $openlayers,
166
      array(
167
        'type' => 'file',
168
        'group' => JS_LIBRARY,
169
        'weight' => 0,
170
        'cache' => TRUE,
171
        'preprocess' => FALSE
172
      )
173
    );
174

    
175

    
176
    // see https://github.com/proj4js/proj4js
177
    // http://openlayers.org/dev/examples/using-proj4js.html
178
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . $proj4js,
179
      array(
180
        'type' => 'file',
181
        'group' => JS_LIBRARY,
182
        'weight' => -1, // before open layers
183
        'cache' => TRUE,
184
      )
185
    );
186

    
187
    // configure the theme
188
    $openlayers_theme_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/OpenLayers-2.13.1/theme/default/';
189
    $openlayers_imp_path = drupal_get_path('module', 'cdm_dataportal') . '/js/map/img/dark/';
190
    drupal_add_js('OpenLayers.ImgPath="' . base_path() . $openlayers_imp_path . '";', array(
191
        'type' => 'inline',
192
        'group' => JS_LIBRARY,
193
        'weight' => 1, // after openlayers
194
        'cache' => TRUE,
195
        'preprocess' => FALSE
196
      ));
197

    
198
    drupal_add_css($openlayers_theme_path . 'style.tidy.css',
199
      array(
200
        'type' => 'file',
201
        'cache' => TRUE,
202
        'preprocess' => FALSE
203
      )
204
    );
205

    
206
  }
207

    
208
  /**
209
   * @todo Please document this function.
210
   * @see http://drupal.org/node/1354
211
   */
212
  function _add_js_thickbox() {
213
    // ---- jQuery thickbox:
214
    /*
215
    * bug: compat-1.0.js && thickbox.js line 237 .trigger("unload") -> event is
216
    * not triggered because of problems with compat-1.0.js' see INSTALL.txt
217
    */
218
    // drupal_add_js(drupal_get_path('module',
219
    // 'cdm_dataportal').'/js/jquery.imagetool.min.js');
220
    //
221
    // Add a setting for the path to cdm_dataportal module, used to find the path
222
    // for the loading animation image in thickbox.
223
    drupal_add_js(array(
224
    'cdm_dataportal' => array(
225
    'cdm_dataportal_path' => base_path() . drupal_get_path('module', 'cdm_dataportal'),
226
    )
227
    ),
228
    'setting'
229
        );
230
        drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/thickbox.js');
231
        drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/js/thickbox/cdm_thickbox.css');
232
  }
233

    
234
  /**
235
   * @todo Please document this function.
236
   * @see http://drupal.org/node/1354
237
   */
238
  function _add_js_lightbox($galleryID) {
239
    /*
240
     * Important Notice: The jquery.lightbox-0.5.js has been modified in order to
241
     * allow using the "alt" attribute for captions instead of the "title"
242
     * attribute
243
     */
244
    $lightbox_base_path =  drupal_get_path('module', 'cdm_dataportal') . '/js/jquery-lightbox-0.5';
245
    $lightbox_image_path = base_path() . $lightbox_base_path . '/images/';
246
    drupal_add_js($lightbox_base_path . '/js/jquery.lightbox-0.5.js');
247
    drupal_add_css($lightbox_base_path . '/css/jquery.lightbox-0.5.css');
248
    drupal_add_js('jQuery(document).ready(function() {
249
        jQuery(\'#' . $galleryID . ' a.lightbox\').lightBox({
250
          fixedNavigation:  true,
251
          imageLoading:     \'' . $lightbox_image_path . 'lightbox-ico-loading.gif\',
252
          imageBtnPrev:     \'' . $lightbox_image_path . 'lightbox-btn-prev.gif\',
253
          imageBtnNext:     \'' . $lightbox_image_path . 'lightbox-btn-next.gif\',
254
          imageBtnClose:    \'' . $lightbox_image_path . 'lightbox-btn-close.gif\',
255
          imageBlank:       \'' . $lightbox_image_path . 'lightbox-blank.gif\',
256
          adjustToWindow: true
257
        });
258
      });
259
      ', array('type' => 'inline'));
260
  }
261

    
262
  /**
263
   * @todo Please document this function.
264
   * @see http://drupal.org/node/1354
265
   */
266
  function _add_js_footnotes() {
267
    _add_js_domEvent();
268
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/footnotes.js');
269
  }
270

    
271
  /**
272
   * @todo Please document this function.
273
   * @see http://drupal.org/node/1354
274
   */
275
  function _add_js_ahah() {
276

    
277
    _add_js_domEvent(); // requires domEvent.js
278
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/ahah-content.js');
279
  }
280

    
281
/**
282
 * @todo Please document this function.
283
 * @see http://drupal.org/node/1354
284
 */
285
function _add_js_taxonomic_children($jquery_selector) {
286

    
287
  global $base_url;
288

    
289

    
290
  drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/jquery.cdm.taxonomic_children.js');
291
  
292
  drupal_add_js('jQuery(document).ready(function() {
293
        jQuery(\'' . $jquery_selector . '\').taxonomic_children({
294
          // hoverClass: "fa-rotate-90",
295
          // activeClass: "fa-rotate-90",
296
          classificationUuid: "' . get_current_classification_uuid() . '",
297
          taxonUuid: "' . get_current_taxon_uuid() . '",
298
          cdmWebappBaseUri: "' . variable_get('cdm_webservice_url', '') . '",
299
          proxyBaseUri: "' . $base_url . '",
300
          
301
        });
302
      });
303
      ', array('type' => 'inline'));
304
}
305

    
306
  /**
307
   * Adds the external javascript file for domEvent.js.
308
   *
309
   * @see drupal_add_js()
310
   */
311
  function _add_js_domEvent() {
312
    drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/domEvent.js');
313
  }
314

    
315
  function _add_jquery_ui()
316
  {
317
    drupal_add_css(drupal_get_path('module',
318
        'cdm_dataportal') . '/js/jquery-ui-1.8.24/themes/base/jquery.ui.all.css');
319
    drupal_add_js(drupal_get_path('module',
320
        'cdm_dataportal') . '/js/jquery-ui-1.8.24/ui/jquery-ui.js',
321
      array(
322
        'type' => 'file',
323
        'weight' => JS_LIBRARY,
324
        'cache' => TRUE,
325
        'preprocess' => FALSE
326
      )
327
    );
328
  }
329

    
330
function _add_js_ui_accordion(){
331
  _add_jquery_ui();
332
  drupal_add_js('jQuery(document).ready(function() {
333
      jQuery( "#accordion" ).accordion();
334
    });',
335
    array('type' => 'inline')
336
  );
337
}
338

    
339

    
340
function _add_js_utis_client($jquery_selector){
341

    
342
  drupal_add_js(drupal_get_path('module',
343
      'cdm_dataportal') . '/js/utis-client/utis-client.js',
344
    array(
345
      'type' => 'file',
346
      'weight' => JS_LIBRARY,
347
      'cache' => TRUE,
348
      'preprocess' => FALSE
349
    )
350
  );
351

    
352
  drupal_add_js('jQuery(document).ready(function() {
353
        jQuery( "' . $jquery_selector . '" ).utis_client(
354
        {
355
          spinnerIcon: \'' . font_awesome_icon_markup('fa-sync', array('class' => array('fa-3x',  'fa-spin'), 'style' => array('opacity: 0.3;'))) . '\',
356
          externalLinkIcon: \'' . font_awesome_icon_markup('fa-external-link-alt') . '\'
357
        });
358
      });',
359
    array('type' => 'inline')
360
  );
361
}
362

    
363
function _add_js_universalviewer($jquery_selector, $manifest_uri){
364

    
365
  $universalviewer_path  = drupal_get_path('module',    'cdm_dataportal') . '/js/universalviewer';
366

    
367
  drupal_add_css($universalviewer_path . '/uv/uv.css');
368
  drupal_add_css($universalviewer_path . '/uv-fix.css');
369

    
370
  // offline.js is all of these dependencies concatenated (jQuery, CoreJS, and JSViews)
371
  drupal_add_js($universalviewer_path . '/uv/lib/offline.js',
372
      array(
373
      'type' => 'file',
374
      'group' => JS_LIBRARY,
375
      'cache' => TRUE,
376
      'preprocess' => FALSE
377
    )
378
  );
379
  drupal_add_js($universalviewer_path . '/uv/helpers.js',
380
    array(
381
      'type' => 'file',
382
      'group' => JS_LIBRARY,
383
      'cache' => TRUE,
384
      'preprocess' => FALSE
385
    )
386
  );
387
  // from UV 3.x documentation:
388
  // "root:
389
  // The path to the uv directory. Use a relative path e.g. root: '../../uv'
390
  // Don't start your path with a / otherwise requirejs will not append .js to
391
  // dependencies and they won't load."
392
  //
393
  // universalviewerPath will be used to build the root config variable.
394
  $iCleanUrlRequest = strpos($_SERVER['REQUEST_URI'], 'q=cdm_dataportal/') === false;
395
  if($iCleanUrlRequest){
396
    $folders_up = preg_replace('/[^\/]+/', '..', $_GET['q']);
397
    $folders_up = preg_replace('/\.\.$/', '', $folders_up);
398
  } else {
399
    $folders_up = '';
400
  }
401
  $basePath = base_path();
402
  $config_file = 'uv-config.json';
403
  drupal_add_js('
404
      console.log(\'jQuery inline: \' + jQuery.fn.jquery);
405
      jQuery(window).on(\'uvLoaded\', function() {
406
        jQuery( "' . $jquery_selector . '" ).jqUniversalviewer(
407
        {
408
          root: \'' . $folders_up . $universalviewer_path . '/uv\',
409
          configUri: \'' . $basePath . $universalviewer_path . '/'. $config_file . '\',
410
          manifestUri: \'' . $manifest_uri . '\'
411
        }
412
        );
413
      });',
414
    array(
415
      'type' => 'inline',
416
      'scope' => 'footer',
417
      'group' => JS_DEFAULT,
418
      'weight' => 0,
419
    )
420
  );
421
  drupal_add_js($universalviewer_path . '/jq-universalviewer.js',
422
    array(
423
      'type' => 'file',
424
      'scope' => 'footer',
425
      'group' => JS_DEFAULT,
426
      'weight' => 10,
427
      'cache' => TRUE,
428
      'preprocess' => FALSE
429
    )
430
  );
431
  // ui.js must be last
432
  drupal_add_js($universalviewer_path . '/uv/uv.js',
433
    array(
434
      'type' => 'file',
435
      'scope' => 'footer',
436
      'group' => 300, // IMPORTANT!
437
      'cache' => TRUE,
438
      'preprocess' => FALSE
439
    )
440
  );
441
}
442

    
443
function _add_js_derivation_tree($jquery_selector){
444
  drupal_add_js(drupal_get_path('module','cdm_dataportal') . '/js/derivation-tree.js');
445
  drupal_add_js('jQuery(document).ready(function() {
446
      jQuery( "' . $jquery_selector . '" ).derivationTree();
447
    });',
448
    array('type' => 'inline')
449
  );
450
}
451

    
452
  /**
453
   * Provides the markup for an font awesome icon.
454
   *
455
   * The icons is created in default size without any extra features.
456
   *
457
   * The available icons are listed here http://fontawesome.io/cheatsheet/
458
   * fontawesome icons have much more features than implemented here in this function,
459
   * for spinning icons, fixed width icons, rotation, etc please checkout the
460
   * examples at http://fontawesome.io/examples/
461
   *
462
   * @parameter $icon_name
463
   *  The name of the icon which starts with 'fa-'
464
   *
465
   * @return String
466
   *    the markup for the icon in an <i> tag
467
   *
468
   */
469
  function font_awesome_icon_markup($icon_name = NULL, $attributes = array()){
470
    _add_font_awesome_font();
471

    
472
    if($icon_name){
473
      if(!isset($attributes['class'])){
474
        $attributes['class'] = array();
475
      }
476
      $attributes['class'][] = 'fa';
477
      $attributes['class'][] = $icon_name;
478

    
479
      return '<i ' . drupal_attributes($attributes) . '></i>';
480
    }
481

    
482
    return '';
483
  }
484

    
485
/**
486
 * see https://fontawesome.com/how-to-use/on-the-web/styling/stacking-icons
487
 * @param array $fa_icons_markup
488
 *  Array of font awesome icon markup preferably created by font_awesome_icon_markup()
489
 *
490
 * @return string
491
 *  The markup
492
 */
493
function font_awesome_icon_stack($fa_icons_markup, $attributes = array(), $no_resize = TRUE){
494

    
495

    
496
    if(!isset($attributes['class'])){
497
      $attributes['class'] = array();
498
    }
499
    if($no_resize){
500
      $attributes['class'][] = 'fa-stack-no-resize';
501
    } else {
502
      $attributes['class'][] = 'fa-stack';
503
    }
504

    
505
    return '<span ' . drupal_attributes($attributes) . '>' . join('', $fa_icons_markup) . '</span>';
506
}
507

    
508
/**
509
 * @param string $glyph_name
510
 *   The name of the gloyph (e.g. 'icon-interal-link-alt-solid') for the foll list please
511
 *   refer to modules/cdm_dataportal/fonts/custom-icon-font
512
 * @param array $attributes
513
 * @return string
514
 */
515
  function custom_icon_font_markup($glyph_name = NULL, $attributes = array()){
516
    _add_font_custom_icon_font();
517

    
518

    
519
    if($glyph_name){
520
      if(!isset($attributes['class'])){
521
        $attributes['class'] = array();
522
      }
523
      $attributes['class'][] = $glyph_name;
524

    
525
      return '<i ' . drupal_attributes($attributes) . '></i>';
526
    }
527

    
528
    return '';
529
  }
530

    
531
/**
532
 * Adds the css  containing the font awesome icons to the html header.
533
 */
534
function _add_font_awesome_font()
535
{
536
  // $fa_font_version = 'font-awesome-4.6.3/css/font-awesome.min.css';
537
  $fa_font_version = 'fontawesome-free-5.9.0-web/css/all.css';
538
  $font_awesome_css_uri = base_path() . drupal_get_path('module', 'cdm_dataportal') . '/fonts/' . $fa_font_version;
539

    
540
  drupal_add_html_head_link(
541
    array(
542
      'href' => $font_awesome_css_uri,
543
      'rel' => 'stylesheet'
544
    )
545
  );
546
}
547

    
548
/**
549
 * Adds the css  containing the font awesome icons to the html header.
550
 */
551
function _add_font_custom_icon_font()
552
{
553

    
554
  $custom_icon_font_css_uri = base_path() . drupal_get_path('module', 'cdm_dataportal') . '/fonts/custom-icon-font/style.css';
555

    
556
  drupal_add_html_head_link(
557
    array(
558
      'href' => $custom_icon_font_css_uri,
559
      'rel' => 'stylesheet'
560
    )
561
  );
562
}
563

    
564
/* ====================== hook implementations ====================== */
565
  /**
566
   * Implements hook_permission().
567
   *
568
   * Valid permissions for this module.
569
   *
570
   * @return array
571
   *   An array of valid permissions for the cdm_dataportal module.
572
   */
573
  function cdm_dataportal_permission() {
574
    return array(
575
      'administer cdm_dataportal' => array(
576
        'title' => t('Administer CDM DataPortal settings'),
577
        'description' => t("Access the settings pages specific for the cdm_dataportal module"),
578
      ),
579
      'access cdm content' => array(
580
        'title' => t('Access CDM content'),
581
        'description' => t("Access content (taxa, names, specimens, etc.) served by the CDM web service."),
582
      ),
583
    );
584
  }
585

    
586
/**
587
 * Implements hook_menu().
588
 */
589
function cdm_dataportal_menu() {
590
  $items = array();
591

    
592
  // @see settings.php.
593
  cdm_dataportal_menu_admin($items);
594
  cdm_dataportal_menu_help($items);
595

    
596
  $items['cdm_dataportal/names'] = array(
597
    'page callback' => 'cdm_dataportal_view_names',
598
    'access arguments' => array('access cdm content'),
599
    'type' => MENU_CALLBACK,
600
  );
601

    
602
  // Optional callback arguments: page.
603
  $items['cdm_dataportal/taxon'] = array(
604
    'page callback' => 'cdm_dataportal_taxon_page_view',
605
    'access arguments' => array('access cdm content'),
606
    'type' => MENU_CALLBACK,
607
    // Expected callback arguments: uuid.
608
  );
609

    
610
  $items['cdm_dataportal/occurrence'] = array(
611
        'page callback' => 'cdm_dataportal_specimen_page_view',
612
        'access arguments' => array('access cdm content'),
613
        'type' => MENU_CALLBACK,
614
        // Expected callback arguments: uuid.
615
    );
616

    
617
  $items['cdm_dataportal/description'] = array(
618
        'page callback' => 'cdm_dataportal_description_page_view',
619
        'access arguments' => array('access cdm content'),
620
        'type' => MENU_CALLBACK,
621
        // Expected callback arguments: uuid.
622
    );
623

    
624
   $items['cdm_dataportal/specimen/accession_number'] = array(
625
        'page callback' => 'cdm_dataportal_specimen_by_accession_number_page_view',
626
        'access arguments' => array('access cdm content'),
627
        'type' => MENU_CALLBACK,
628
        // Expected callback arguments: accession number.
629
    );
630
  $items['cdm_dataportal/named_area'] = array(
631
    'page callback' => 'cdm_dataportal_named_area_page_view',
632
    'access arguments' => array('access cdm content'),
633
    'type' => MENU_CALLBACK,
634
    // Expected callback arguments: uuid.
635
  );
636

    
637
  $items['cdm_dataportal/name'] = array(
638
    'page callback' => 'cdm_dataportal_name_page_view',
639
      /*
640
    'page arguments' => array(
641
       'taxon_name_uuid',
642
       'taxon_to_hide_uuid',
643
       'synonym_uuid' => NULL
644
      ),
645
      */
646
    'access arguments' => array('access cdm content'),
647
    'type' => MENU_CALLBACK,
648
    // Expected callback arguments: uuid.
649
  );
650

    
651
  $items['cdm_dataportal/reference'] = array(
652
    'page callback' => 'cdm_dataportal_view_reference',
653
    'access arguments' => array('access cdm content'),
654
    'type' => MENU_CALLBACK,
655
    // Expected callback arguments: uuid.
656
  );
657

    
658
  $items['cdm_dataportal/reference/list'] = array(
659
    'page callback' => 'cdm_dataportal_view_reference_list',
660
    'access arguments' => array('access cdm content'),
661
    'type' => MENU_CALLBACK,
662
    // Expected callback arguments: uuid.
663
  );
664

    
665
  $items['cdm_dataportal/media'] = array(
666
    'page callback' => 'cdm_dataportal_view_media',
667
    'access arguments' => array('access cdm content'),
668
    'type' => MENU_CALLBACK,
669
    // Expected callback arguments:
670
    // uuid, mediarepresentation_uuid, part_uuid or part#.
671
  );
672

    
673
  $items['cdm_dataportal/polytomousKey'] = array(
674
    'page callback' => 'cdm_dataportal_view_polytomousKey',
675
    'access arguments' => array('access cdm content'),
676
    'type' => MENU_CALLBACK,
677
    // Expected callback arguments: polytomousKey->uuid.
678
  );
679

    
680
  $items['cdm_dataportal/search'] = array(
681
    'page callback' => 'cdm_dataportal_view_search_advanced',
682
    'access arguments' => array('access cdm content'),
683
    'type' => MENU_CALLBACK,
684
  );
685

    
686
  // Optional callback arguments: page.
687
  $items['cdm_dataportal/registration'] = array(
688
    'page callback' => 'cdm_dataportal_registration_page_view',
689
    'access arguments' => array('access cdm content'),
690
    'type' => MENU_CALLBACK,
691
    // Expected callback arguments: uuid.
692
  );
693

    
694
  // ------------ SEARCH -----------
695
  $items['cdm_dataportal/search/advanced'] = array(
696
    'title' => 'Advanced', // will be passed through t()
697
    'page callback' => 'cdm_dataportal_view_search_advanced',
698
    'access arguments' => array('access cdm content'),
699
    'type' => MENU_DEFAULT_LOCAL_TASK,
700
  );
701
  $items['cdm_dataportal/search/blast'] = array(
702
    'title' => 'Blast', // will be passed through t()
703
    'page callback' => 'cdm_dataportal_view_search_blast',
704
    'access arguments' => array('access cdm content'),
705
    'type' => MENU_LOCAL_TASK,
706
  );
707

    
708
  $items['cdm_dataportal/search/taxon_by_description'] = array(
709
    'title' => 'By content category', // will be passed through t()
710
    'page callback' => 'cdm_dataportal_view_search_taxon_by_description',
711
    'access arguments' => array('access cdm content'),
712
    'type' => MENU_LOCAL_TASK,
713
  );
714
  $items['cdm_dataportal/search/results/taxon'] = array(
715
    'page callback' => 'cdm_dataportal_view_search_results_taxon',
716
    'access arguments' => array('access cdm content'),
717
    'type' => MENU_CALLBACK,
718
  );
719

    
720
  $items['cdm_dataportal/search/results/specimen'] = array(
721
      'page callback' => 'cdm_dataportal_view_search_results_specimen',
722
      'access arguments' => array('access cdm content'),
723
      'type' => MENU_CALLBACK,
724
  );
725

    
726
  /*
727
   * MENU_CALLBACK at cdm_dataportal/registration-search is needed to make the
728
   * tabs in the subordinate paths work, accessing this 'page' will cause the
729
   * MENU_DEFAULT_LOCAL_TASK being displayed
730
   */
731
  $items['cdm_dataportal/registration-search'] = array(
732
    'title' => 'Search', // will be passed through t()
733
    'page callback' => 'cdm_dataportal_view_search_registrations_results',
734
    'page arguments' => array("filter"),
735
    'access arguments' => array('access cdm content'),
736
    'type' => MENU_CALLBACK,
737
  );
738
  /*
739
   * the MENU_DEFAULT_LOCAL_TASK creates a tab for the MENU_CALLBACK
740
   * defined at a higher level of the path (cdm_dataportal/registration-search)
741
   */
742
  $items['cdm_dataportal/registration-search/filter'] = array(
743
    'title' => 'Search', // will be passed through t()
744
    'page callback' => 'cdm_dataportal_view_search_registrations_results',
745
    'page arguments' => array("filter"),
746
    'access arguments' => array('access cdm content'),
747
    'type' => MENU_DEFAULT_LOCAL_TASK,
748
  );
749
  /*
750
   * the MENU_LOCAL_TASK creates another tab
751
   */
752
  $items['cdm_dataportal/registration-search/taxongraph'] = array(
753
    'title' => 'Taxon graph search', // will be passed through t()
754
    'page callback' => 'cdm_dataportal_view_search_registrations_results',
755
    'page arguments' => array("taxongraph"),
756
    'access arguments' => array('access cdm content'),
757
    'type' => MENU_LOCAL_TASK,
758
  );
759

    
760
  // Optional callback arguments: page.
761
  $items['cdm_dataportal/search/agent'] = array(
762
    'page callback' => 'cdm_dataportal_view_search_agent',
763
    'access arguments' => array('access cdm content'),
764
    'type' => MENU_CALLBACK,
765
    // Expected callback arguments: uuid.
766
  );
767

    
768
  // ------------ menu items with variable path elements -----------
769

    
770
  // 'May not cache' in D5.
771
  $items['cdm_dataportal/name/%'] = array(
772
    // 'page callback' => 'cdm_dataportal_view_name',
773
    'page callback' => 'cdm_dataportal_name_page_view',
774
    'page arguments' => array(2, 3, 4, 5),
775
    'access arguments' => array('access cdm content'),
776
    'type' => MENU_CALLBACK,
777
  );
778

    
779
  // --- Local tasks for Taxon.
780
  // --- tabbed taxon page
781
  if (variable_get('cdm_dataportal_taxonpage_tabs', 1)) {
782
    $items['cdm_dataportal/taxon/%'] = array(
783
      'title' => cdm_taxonpage_tab_label('General'),
784
      'page callback' => 'cdm_dataportal_taxon_page_view',
785
      'access arguments' => array('access cdm content'),
786
      'type' => MENU_CALLBACK,
787
      'weight' => 1,
788
      'page arguments' => array(2, "description")
789
      , // Expected callback arguments: taxon_uuid.
790
    );
791

    
792
    $items['cdm_dataportal/taxon/%/all'] = array(
793
      'title' => cdm_taxonpage_tab_label('General'),
794
      'page callback' => 'cdm_dataportal_taxon_page_view',
795
      'access arguments' => array('access cdm content'),
796
      'type' => MENU_CALLBACK,
797
      'weight' => 2,
798
      'page arguments' => array(2, "all")
799
      , // Expected callback arguments: taxon_uuid.
800
    );
801

    
802
    $items['cdm_dataportal/taxon/%/description'] = array(
803
      'title' => cdm_taxonpage_tab_label('General'),
804
      'page callback' => 'cdm_dataportal_taxon_page_view',
805
      'access arguments' => array('access cdm content'),
806
      'type' => MENU_DEFAULT_LOCAL_TASK,
807
      'weight' => 2,
808
      'page arguments' => array(2, "description")
809
      , // Expected callback arguments: taxon_uuid.
810
    );
811

    
812
    $items['cdm_dataportal/taxon/%/synonymy'] = array(
813
      'title' => cdm_taxonpage_tab_label('Synonymy'),
814
      'page callback' => 'cdm_dataportal_taxon_page_view',
815
      'access arguments' => array('access cdm content'),
816
      'type' => MENU_LOCAL_TASK,
817
      'weight' => 4,
818
      'page arguments' => array(2, "synonymy", 4)
819
      , // Expected callback arguments: taxon_uuid and ...
820
    );
821
    $items['cdm_dataportal/taxon/%/images'] = array( // Images
822
      'title' => cdm_taxonpage_tab_label('Images'),
823
      'page callback' => 'cdm_dataportal_taxon_page_view',
824
      'access arguments' => array('access cdm content'),
825
      'type' => MENU_LOCAL_TASK,
826
      'weight' => 5,
827
      'page arguments' => array(2, "images")
828
      , // Expected callback arguments: taxon_uuid.
829
    );
830

    
831
    $items['cdm_dataportal/taxon/%/specimens'] = array( // Specimens
832
      'title' => cdm_taxonpage_tab_label('Specimens'),
833
      'page callback' => 'cdm_dataportal_taxon_page_view',
834
      'access arguments' => array('access cdm content'),
835
      'type' => MENU_LOCAL_TASK,
836
      'weight' => 6,
837
      'page arguments' => array(2, "specimens")
838
      , // Expected callback arguments: taxon_uuid.
839
    );
840

    
841
    $items['cdm_dataportal/taxon/%/keys'] = array( // Keys
842
      'title' => cdm_taxonpage_tab_label('Keys'),
843
      'page callback' => 'cdm_dataportal_taxon_page_view',
844
      'access arguments' => array('access cdm content'),
845
      'type' => MENU_LOCAL_TASK,
846
      'weight' => 6,
847
      'page arguments' => array(2, "keys")
848
      , // Expected callback arguments: taxon_uuid.
849
    );
850

    
851
    $items['cdm_dataportal/taxon/%/experts'] = array( // Experts
852
      'title' => cdm_taxonpage_tab_label('Experts'),
853
        'page callback' => 'cdm_dataportal_taxon_page_view',
854
        'access arguments' => array('access cdm content'),
855
        'type' => MENU_LOCAL_TASK,
856
        'weight' => 6,
857
        'page arguments' => array(2, "experts")
858
    , // Expected callback arguments: taxon_uuid.
859
    );
860

    
861
    $items['cdm_dataportal/taxon/autosuggest/%/%/%/'] = array(
862
        'page callback' => 'cdm_dataportal_taxon_autosuggest',
863
        'access arguments' => array('access cdm content'),
864
        'page arguments' => array(3,4,5),
865
        'type' => MENU_CALLBACK
866
    );
867
  }
868

    
869
  // --- refresh link for all cdmnode types
870
  foreach (cdm_get_nodetypes() as $type=>$name) {
871
    $items['cdm_dataportal/' . $name . '/%/refresh'] = array(
872
        'title' => 'Refresh',
873
        'page callback' => 'cdm_dataportal_refresh_node',
874
        'access arguments' => array('administer cdm_dataportal'),
875
        'type' => MENU_LOCAL_TASK,
876
        'weight' => 100,
877
        'page arguments' => array($name, 2)
878
    );
879
  }
880

    
881
  return $items;
882
}
883

    
884
/**
885
 * Implements hook_init().
886
 *
887
 */
888
function cdm_dataportal_init() {
889
  if (!path_is_admin(current_path())) {
890
    //FIXME To add CSS or JS that should be present on all pages, modules
891
    //      should not implement this hook, but declare these files in their .info file.
892
    drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal.css');
893
    // drupal_add_css(drupal_get_path('module', 'cdm_dataportal').'/cdm_dataportal_print.css', 'print');
894
    drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal_screen.css', array('type' => 'screen'));
895
  } else {
896
    drupal_add_css(drupal_get_path('module', 'cdm_dataportal') . '/cdm_dataportal_settings.css');
897
  }
898

    
899
  if(variable_get('cdm_debug_mode', FALSE)){
900
    $file = 'temporary://drupal_debug.txt';
901
    file_put_contents($file, 'CDM DEBUG LOG for ' . $_GET['q']. "\n"); // will overwrite the file
902
  }
903

    
904
  $bibliography_settings = get_bibliography_settings();
905
  $enclosing_tag = $bibliography_settings['enabled'] == 1 ? 'div' : 'span';
906
  FootnoteManager::registerFootnoteSet('BIBLIOGRAPHY', $enclosing_tag, $bibliography_settings['key_format']);
907
}
908

    
909
function cdm_dataportal_refresh_node($cdm_node_name, $uuid, $parameters = array()){
910

    
911
  $base_path = 'cdm_dataportal/' . $cdm_node_name . '/' . $uuid;
912

    
913
  if($cdm_node_name == 'taxon' && variable_get('cdm_dataportal_taxonpage_tabs', 1)){
914
    // force reloading of all and notify user about this special loading
915
    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: ')
916
        . l('Back to tabbed taxon page', $base_path));
917
    $base_path .= '/all';
918
  } else {
919
    drupal_set_message(t('The level 2 cache has been cleared for this page'));
920
  }
921

    
922
  $parameters['cacheL2_refresh'] ='1';
923

    
924

    
925
  drupal_goto($base_path, array('query' => $parameters));
926
}
927

    
928
/**
929
 * Implements hook_requirements($phase)
930
 */
931
function cdm_dataportal_requirements($phase) {
932
    $requirements = array();
933
    if($phase == 'runtime'){
934

    
935
    }
936
    return $requirements;
937
}
938

    
939
/**
940
 * Implements hook_block_info().
941
 */
942
function cdm_dataportal_block_info() {
943

    
944
    // $block[0]["info"] = t("CDM DataPortal DevLinks");
945
    // $block[1]["info"] = t("CDM DataPortal Credits");
946
    $block["2"] = array(
947
        "info" => t("CDM - Search Taxa"),
948
        "cache" => DRUPAL_NO_CACHE
949
      );
950
    // $block[3]["info"] = t("CDM Filters");
951
    $block["4"]["info"] = t("CDM  - Dataportal Print");
952
    $block["keys"]["info"] = t("CDM - Identification keys");
953
    $block["fundedByEDIT"]["info"] = t('CDM - Powered by EDIT');
954
    $block["classification_breadcrumbs"] =  array(
955
        'info' => t('CDM - Classification breadcrumbs'),
956
        'cache' => DRUPAL_CACHE_PER_PAGE
957
      );
958
    $block["taxonomic_children"] =  array(
959
      'info' => t('CDM - Taxonomic children'),
960
      'cache' => DRUPAL_CACHE_PER_PAGE
961
    );
962
    $block["back_to_search_results"] =  array(
963
      'title' => '<none>',
964
      'info' => t('CDM - Back to search Results'),
965
      'cache' => DRUPAL_CACHE_PER_PAGE,
966
      'visibility' => BLOCK_VISIBILITY_LISTED,
967
      'pages' => "cdm_dataportal/taxon/*", // multiple page paths separated by "\n"!!!
968
    );
969
  $block['registrations_search_filter'] =  array(
970
    'title' => 'Filter registrations',
971
    'info' => t('CDM - Registrations search filter'),
972
    'cache' => DRUPAL_CACHE_PER_PAGE,
973
    'visibility' => BLOCK_VISIBILITY_NOTLISTED,
974
    'pages' => "cdm_dataportal/registration-search\ncdm_dataportal/registration-search/*", // multiple page paths separated by "\n"!!!
975
  );
976
  $block['registrations_search_taxongraph'] =  array(
977
    'title' => 'Taxonomic registration search',
978
    'info' => t('CDM - Registrations search by taxon graph'),
979
    'cache' => DRUPAL_CACHE_PER_PAGE,
980
    'visibility' => BLOCK_VISIBILITY_NOTLISTED,
981
    'pages' => "cdm_dataportal/registration-search\ncdm_dataportal/registration-search/*", // multiple page paths separated by "\n"!!!
982
  );
983
  $block['registrations_search'] =  array(
984
    'title' => 'Search',
985
    'info' => t('CDM - Registrations search combining filter and taxon graph search' ),
986
    'cache' => DRUPAL_CACHE_PER_PAGE,
987
    'visibility' => BLOCK_VISIBILITY_NOTLISTED,
988
    'pages' => "cdm_dataportal/registration-search\ncdm_dataportal/registration-search/*", // multiple page paths separated by "\n"!!!
989
  );
990
  $block['utis_search'] =  array(
991
    'title' => 'UTIS Search',
992
    'info' => t('Query the Unified Taxonomic Information Service (UTIS)' ),
993
    'cache' => DRUPAL_CACHE_PER_PAGE,
994
    'visibility' => BLOCK_VISIBILITY_NOTLISTED
995
  );
996
  return $block;
997
}
998

    
999
/**
1000
 * Implements hook_block_view().
1001
 */
1002
function cdm_dataportal_block_view($delta) {
1003
  // TODO Rename block deltas (e.g. '2') to readable strings.
1004
  switch ($delta) {
1005
    // case 'delta-1':
1006
    // $block['subject'] = t('Credits');
1007
    // $block['content'] = theme('cdm_credits');
1008
    // return $block;
1009
    case '2':
1010
      $block['subject'] = t('Search taxa');
1011
      $form = drupal_get_form('cdm_dataportal_search_taxon_form');
1012
      $block['content'] = drupal_render($form);
1013

    
1014
      if (variable_get('cdm_dataportal_show_advanced_search', 1)) {
1015
        $block['content'] .= '<div>' . l(t('Advanced Search'), 'cdm_dataportal/search') . '</div>';
1016
      }
1017
      if (variable_get(CDM_SEARCH_BLAST_ENABLED)){
1018
          $block['content'] .= '<div>' . l(t('Blast Search'), 'cdm_dataportal/search/blast') . '</div>';
1019
      }
1020
      return $block;
1021
    case '4':
1022
      $block['subject'] = '';
1023
      $block['content'] = theme('cdm_print_button');
1024
      return $block;
1025
    case "keys":
1026
      $block['subject'] = t('Identification Keys');
1027
      $block['content'] = theme('cdm_block_IdentificationKeys', array('taxonUuid' => NULL));
1028
      return $block;
1029
    case "fundedByEDIT":
1030
      // t('Funded by EDIT');
1031
      $text = '<none>';
1032
      $block['subject'] = $text;
1033
      $img_tag = '<img src="' . base_path() . drupal_get_path('module', 'cdm_dataportal') . '/images/powered_by_edit.png' . '" alt="' . $text . '"/>';
1034
      $block['content'] = l($img_tag, "http://cybertaxonomy.org/", array(
1035
        'attributes' => array("target" => "EDIT"),
1036
        'absolute' => TRUE,
1037
        'html' => TRUE,
1038
      ));
1039
      return $block;
1040
    case 'classification_breadcrumbs':
1041
      $taxon_uuid = get_current_taxon_uuid();
1042
      $block['subject'] = '<none>';
1043
      $block['content'] = compose_classification_breadcrumbs($taxon_uuid);
1044
      return $block;
1045
    case 'taxonomic_children':
1046
      $taxon_uuid = get_current_taxon_uuid();
1047
      $block['subject'] = '<none>';
1048
      $block['content'] = compose_taxonomic_children($taxon_uuid);
1049
      return $block;
1050
    case 'back_to_search_results':
1051
      $block['subject'] = '<none>';
1052
      if (isset($_SESSION['cdm']['search'])) {
1053
        $block['content'] = l(t('Back to search result'), "http://" . $_SERVER['SERVER_NAME'] . $_SESSION['cdm']['last_search']);
1054
      }
1055
      return $block;
1056
    case 'registrations_search_filter':
1057
      $block['subject'] = '<none>';
1058
      $block['content'] = drupal_get_form('cdm_dataportal_search_registration_filter_form'); // see cdm_dataportal_search_registration_filter_form($form, &$form_state)
1059
      return $block;
1060
    case 'registrations_search_taxongraph':
1061
      $block['subject'] = '<none>';
1062
      $block['content'] = drupal_get_form('cdm_dataportal_search_registration_taxongraph_form'); // see cdm_dataportal_search_registration_taxongraph_form($form, &$form_state)
1063
      return $block;
1064
    case 'registrations_search':
1065
      _add_js_ui_accordion();
1066
      _add_font_awesome_font();
1067
      $block['subject'] = '<none>';
1068
      $filter_form = drupal_get_form('cdm_dataportal_search_registration_filter_form');
1069
      $filter_form['#prefix'] = '<div>';
1070
      $filter_form['#suffix'] = '</div>';
1071
      $taxongraph_form = drupal_get_form('cdm_dataportal_search_registration_taxongraph_form');
1072
      $taxongraph_form['#prefix'] = '<div>';
1073
      $taxongraph_form['#suffix'] = '</div>';
1074
      $block['content'] = array(
1075
        'accordion' => array(
1076
          '#markup' => '',
1077
          '#prefix' => '<div id="accordion">',
1078
          '#suffix' => '</div>',
1079
          'content' => array(
1080
            array('#markup' => '<h3>Filter</h3>'),
1081
            $filter_form,
1082
            array('#markup' => '<h3>Taxon graph</h3>'),
1083
            $taxongraph_form,
1084
          )
1085
        )
1086
    );
1087
       return $block;
1088
    case 'utis_search':
1089
      _add_js_utis_client('.utis_client');
1090
      $block['subject'] = '<none>';
1091
      $block['content'] = '<div class="utis_client"></div>';
1092
      return $block;
1093
    default:
1094
      return null;
1095
  }
1096
}
1097

    
1098

    
1099
/**
1100
 * Provides the uuid of the taxon for pages with the path ./taxon/{taxon_uuid}
1101
 *
1102
 * @return string
1103
 *   the taxon uuid or NULL
1104
 */
1105
function get_current_taxon_uuid()
1106
{
1107
  static $taxon_uuid;
1108

    
1109
  if(!isset($taxon_uuid)){
1110
    if(isset($_REQUEST['currentTaxon']) && is_uuid($_REQUEST['currentTaxon'])) {
1111
      $taxon_uuid = $_REQUEST['currentTaxon'];
1112
    } else if (arg(1) == 'taxon' && is_uuid(arg(2))) {
1113
      $taxon_uuid = arg(2);
1114
    } else {
1115
      $taxon_uuid = null;
1116
    }
1117
  }
1118

    
1119
  return $taxon_uuid;
1120
}
1121

    
1122
/**
1123
 * Returns the currently classification tree in use.
1124
 *
1125
 * @return string
1126
 *   The uuid of the currently focused classification
1127
 */
1128
function get_current_classification_uuid() {
1129
  if (isset($_SESSION['cdm']['taxonomictree_uuid']) && is_uuid($_SESSION['cdm']['taxonomictree_uuid'])) {
1130
    return $_SESSION['cdm']['taxonomictree_uuid'];
1131
  }
1132
  else {
1133
    return variable_get(CDM_TAXONOMICTREE_UUID, FALSE);
1134
  }
1135
}
1136

    
1137
/*
1138
 function cdm_dataportal_session_clear($cdm_ws_uri_update = FALSE){
1139
 $_SESSION['cdm'] = NULL;
1140
 if(is_string($cdm_ws_uri_update)){
1141
 $_SESSION['cdm'] = array('ws_uri'=>$cdm_ws_uri_update);
1142
 }
1143
 }
1144

    
1145
 function cdm_dataportal_session_validate(){
1146
 if(!isset($_SESSION['cdm']['ws_uri'])){
1147
 $_SESSION['cdm'] = array('ws_uri'=>variable_get('cdm_webservice_url', FALSE));
1148
 } else if($_SESSION['cdm']['ws_uri'] != variable_get('cdm_webservice_url', FALSE)){
1149
 cdm_dataportal_session_clear(variable_get('cdm_webservice_url', FALSE));
1150
 }
1151
 }
1152
 */
1153

    
1154
/**
1155
 * creates a  selector form for taxonomic trees.
1156
 *
1157
 * @return array
1158
 *  a drupal form array
1159
 */
1160
function cdm_taxonomictree_selector() {
1161
  _add_js_treeselector();
1162

    
1163
  $form = drupal_get_form('cdm_taxonomictree_selector_form');
1164
  return $form;
1165
}
1166

    
1167
/**
1168
 * @todo Please document this function.
1169
 * @see http://drupal.org/node/1354
1170
 *
1171
 * used by cdm_taxonomictree_selector()
1172
 *
1173
 * @deprecated use compose_classification_selector instead
1174
 */
1175
function cdm_taxonomictree_selector_form($form, &$form_state) {
1176

    
1177
  $url = url('cdm_api/setvalue/session', array('query' => NULL));
1178
  $form['#action'] = $url;
1179

    
1180
  $form['var'] = array(
1181
    '#weight' => -3,
1182
    '#type' => 'hidden',
1183
    '#value' => '[cdm][taxonomictree_uuid]',
1184
  );
1185

    
1186
  $destination_array = drupal_get_destination();
1187
  $destination = $destination_array['destination'];
1188

    
1189
  $form['destination'] = array(
1190
    '#weight' => -3,
1191
    '#type' => 'hidden',
1192
    '#value' =>  $destination,
1193
  );
1194
  $options = cdm_get_taxontrees_as_options(
1195
    FALSE,
1196
    variable_get(CDM_TAXONTREE_INCLUDES, [])
1197
  );
1198
  $form['val'] = array(
1199
    '#type' => 'select',
1200
    '#title' => t('Available classifications'),
1201
    '#default_value' => get_current_classification_uuid(),
1202
    '#options' => $options,
1203
    '#attributes' => array('class' => array('highlite-first-child')),
1204
  );
1205

    
1206
  return $form;
1207

    
1208
}
1209

    
1210
/**
1211
 *
1212
 * @ingroup compose
1213
 */
1214
function compose_classification_selector() {
1215

    
1216
  $destination_array = drupal_get_destination();
1217
  $destination = $destination_array['destination'];
1218

    
1219
  $options = cdm_get_taxontrees_as_options(
1220
    FALSE,
1221
    variable_get(CDM_TAXONTREE_INCLUDES, [])
1222
  );
1223
  $items = array();
1224

    
1225
  $current_classification_uuid = get_current_classification_uuid();
1226

    
1227

    
1228
  foreach($options as $uuid=>$label){
1229
    $class_attributes = '';
1230
    if($current_classification_uuid == $uuid){
1231
      $class_attributes  = array('focused');
1232
    }
1233
    $items[] = array(
1234
      'data' => l($label,
1235
        'cdm_api/setvalue/session',
1236
        array(
1237
          'query' => array(
1238
            'destination' => $destination,
1239
            'val' => $uuid,
1240
            'var' => '[cdm][taxonomictree_uuid]'
1241
          ),
1242
        )
1243
      ),
1244
      'class' => $class_attributes
1245
    );
1246
  }
1247

    
1248
  $render_array = array(
1249
    '#theme' => 'item_list',
1250
    '#type' => 'ul',
1251
    '#items' => $items
1252
  );
1253

    
1254
  return $render_array;
1255
}
1256

    
1257

    
1258
/* ====================== menu callback functions ====================== */
1259
/**
1260
 * @todo Please document this function.
1261
 * @see http://drupal.org/node/1354
1262
 */
1263
/*
1264
function cdm_dataportal_form_alter(&$form, &$form_state, $form_id) {
1265
  static $comment_node_disabled =  0;
1266
  static $comment_node_read_only =  1;
1267
  static $comment_node_read_write =  2;
1268

    
1269
  if ($form_id == 'node_type_form'
1270
   && isset($form['identity']['type'])
1271
   && array_key_exists($form['#node_type']->type, cdm_get_nodetypes())
1272
  ) {
1273
    $form['workflow']['comment'] = array(
1274
      '#type' => 'radios',
1275
      '#title' => t('Default comment setting'),
1276
      '#default_value' => variable_get('comment__' . $node->type . $form['#node_type']->type, $comment_node_disabled),
1277
      '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
1278
      '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'),
1279
    );
1280
  }
1281
}
1282
*/
1283

    
1284
/**
1285
 * Displays a list of the known taxonomic names.
1286
 *
1287
 * When the list of taxonomic names is displayed, long lists are split up into
1288
 * multiple pages.
1289
 *
1290
 * TODO: Parameters are still preliminary.
1291
 *
1292
 * @param string $beginsWith
1293
 * @param string $page
1294
 *   Page number to diplay defaults to page 1.
1295
 * @param bool $onlyAccepted
1296
 */
1297
function cdm_dataportal_view_names($beginsWith = 'A', $page = 1, $onlyAccepted = FALSE) {
1298

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

    
1301
  /*
1302
  // FIXME the filter for accepted names will be a form element, thus this
1303
  // widget should be generated via form api preferably as block.
1304
  $out  = theme('cdm_dataportal_widget_filter_accepted', $onlyAccepted);
1305
  $out .= theme('cdm_dataportal_widget_names_list', $names, $page);
1306
  $out .= theme('cdm_listof_taxa', $taxonPager);
1307
  return $out;
1308
  */
1309
}
1310

    
1311
/**
1312
 * @todo Please document this function.
1313
 * @see http://drupal.org/node/1354
1314
 * @throws Exception
1315
 */
1316
function cdm_dataportal_view_reference($uuid, $arg2 = NULL) {
1317

    
1318
  cdm_check_valid_portal_page();
1319

    
1320
  return compose_cdm_reference_page($uuid);
1321
}
1322

    
1323
/**
1324
 * Creates a view on a all references contained in the portal.
1325
 *
1326
 * This function is used at the path cdm_dataportal/reference/list
1327
 */
1328
function cdm_dataportal_view_reference_list($pageNumber) {
1329
  $referencePager = cdm_ws_page(CDM_WS_REFERENCE, variable_get(CDM_SEARCH_RESULT_PAGE_SIZE, CDM_SEARCH_RESULT_PAGE_SIZE_DEFAULT), $pageNumber);
1330
  cdm_reference_pager($referencePager, 'cdm_dataportal/reference/list/');
1331
}
1332

    
1333
/**
1334
 * @todo Please document this function.
1335
 * @see http://drupal.org/node/1354
1336
 */
1337
function cdm_dataportal_view_media($mediaUuid, $mediarepresentation_uuid = FALSE, $part = 0) {
1338

    
1339
  cdm_check_valid_portal_page();
1340

    
1341
  $media = cdm_ws_get(CDM_WS_PORTAL_MEDIA, $mediaUuid);
1342
  if (!$media) {
1343
    drupal_set_title(t('Media does not exist'), PASS_THROUGH);
1344
    return "";
1345
  }
1346
  return theme('cdm_media_page', array(
1347
    'media' => $media,
1348
    'mediarepresentation_uuid' => $mediarepresentation_uuid,
1349
    'partId' => $part,
1350
    ));
1351
}
1352

    
1353
/**
1354
 * Loads the media associated to the given taxon from the cdm server.
1355
 * The aggregation settings regarding taxon relathionships and
1356
 * taxonnomic childen are taken into account.
1357
 *
1358
 * The media lists are cached in a static variable.
1359
 *
1360
 * @param Taxon $taxon
1361
 *   A CDM Taxon entity
1362
 *
1363
 * @return array
1364
 *   An array of CDM Media entities
1365
 *
1366
 */
1367
  function _load_media_for_taxon($taxon) {
1368

    
1369
  static $media = NULL;
1370

    
1371
  if(!isset($media)) {
1372
    $media = array();
1373
  }
1374
  if (!isset($media[$taxon->uuid])) {
1375

    
1376

    
1377
    $mediaQueryParameters = taxon_media_query_parameters();
1378

    
1379
    $ws_endpoint = NULL;
1380
    if ( $mediaQueryParameters['includeTaxonomicChildren']) {
1381
      $ws_endpoint = CDM_WS_PORTAL_TAXON_SUBTREE_MEDIA;
1382
    } else {
1383
      $ws_endpoint = CDM_WS_PORTAL_TAXON_MEDIA;
1384
    }
1385
    // this parameter is not yet used by the CDM_WS_PORTAL_TAXON_*MEDIA
1386
    // services
1387
    unset($mediaQueryParameters['includeTaxonomicChildren']);
1388

    
1389
    $media[$taxon->uuid] = cdm_ws_get($ws_endpoint,
1390
        array(
1391
            $taxon->uuid,
1392
        ),
1393
        queryString($mediaQueryParameters)
1394
       );
1395
  }
1396

    
1397
  return $media[$taxon->uuid];
1398
}
1399

    
1400
/**
1401
 *
1402
 * @param Taxon $taxon
1403
 *   A CDM Taxon entitiy
1404
 *
1405
 * @return array
1406
 *   An array of CDM SpecimenOrObservation entities
1407
 *
1408
function _load_occurences_for_taxon($taxon){
1409

    
1410
  static $occurences = NULL;
1411

    
1412
  if(!isset($occurences)) {
1413
    $occurences = array();
1414
  }
1415

    
1416
  if (!isset($occurences[$taxon->uuid])){
1417

    
1418
    $relationship_choice = variable_get(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS, unserialize(CDM_AGGREGATE_BY_TAXON_RELATIONSHIPS_DEFAULT));
1419
    $relationship_choice['direct'] = get_selection($relationship_choice['direct']);
1420
    $relationship_choice['invers'] = get_selection($relationship_choice['invers']);
1421

    
1422
    $by_associatedtaxon_query = http_build_query(array(
1423
        'relationshipsInvers' => implode(',', $relationship_choice['invers']),
1424
        'relationships' => implode(',', $relationship_choice['direct']),
1425
        'pageSize' => null // all hits in one page
1426
    )
1427
    );
1428

    
1429
    $pager = cdm_ws_get(CDM_WS_OCCURRENCE_BY_ASSOCIATEDTAXON,
1430
        null,
1431
        $by_associatedtaxon_query . '&taxonUuid=' . $taxon->uuid
1432
    );
1433

    
1434

    
1435
    if(isset($pager->records[0])){
1436
      $occurences[$taxon->uuid] =  $pager->records;
1437
    }
1438
  }
1439
  return $occurences[$taxon->uuid];
1440
}
1441
 */
1442

    
1443
/**
1444
 * Gets a Drupal variable, string or array and returns it.
1445
 *
1446
 * Similar to the variable_get() function of Drupal, except that this function
1447
 * is able to handle arrays correctly. This function is especially useful
1448
 * when dealing with collections of settings form elements (#tree = TRUE).
1449
 *
1450
 * @param string $variableKey
1451
 *   The Unique key of the Drupal variable in the Drupal variables table.
1452
 * @param string $defaultValueString
1453
 *   A string as for example derived from a CONSTANT.
1454
 *
1455
 * @return mixed
1456
 *   usually an array, depending on the nature of the variable.
1457
 *
1458
 * TODO compare with get_array_variable_merged() duplicate functions?
1459
 * @deprecated rather use get_array_variable_merged() since this function
1460
 * used an array as second parameter
1461
 */
1462
function mixed_variable_get($variableKey, $defaultValueString) {
1463
  $systemDefaults = unserialize($defaultValueString);
1464
  $storedSettings = variable_get($variableKey, array());
1465
  if (is_array($storedSettings)) {
1466
    // TODO better use drupal_array_merge_deep() ?
1467
    $settings = array_merge($systemDefaults, $storedSettings);
1468
  }
1469
  else {
1470
    $settings = $systemDefaults;
1471
  }
1472
  return $settings;
1473
}
1474

    
1475
/**
1476
 * Recursive function to convert an object into an array.
1477
 * also subordinate objects will be converted.
1478
 *
1479
 * @param object $object
1480
 *  the object to be converted
1481
 * @return array
1482
 *  The array
1483
 */
1484
function object_to_array($object) {
1485
  if(is_object($object) || is_array($object)) {
1486
    $array = (array)$object;
1487
    foreach ($array as $key=>$value){
1488
      $array[$key] = object_to_array($value);
1489
    }
1490
    return $array;
1491
  } else {
1492
    return $object;
1493
  }
1494
}
1495

    
1496
/**
1497
 * Searches the $collection for the cdm entitiy given as $element.
1498
 *
1499
 * The elements are compared by their UUID.
1500
 *
1501
 * @param $element
1502
 *  the CDM entitiy to search for
1503
 * @param $collection
1504
 *  the list of CDM entities to search in
1505
 *
1506
 * @return boolean TRUE if the $collection contains the $element, otheriwse FALSE
1507
 *
1508
 */
1509
function contains_cdm_entitiy($element, $collection) {
1510
  $result = FALSE;
1511
  foreach ($collection as $a) {
1512
    if ($a->uuid == $element->uuid) {
1513
      $result = TRUE;
1514
    }
1515
  }
1516
  return $result;
1517
}
1518

    
1519
/**
1520
 * Filters the array $entity_list of CDM entities by the list
1521
 * of $excludes. Any element contained in the $excludes will be removed
1522
 * from included int the returned list.
1523
 *
1524
 * If the $entity_list is not an array the $excludes will be returned.
1525
 */
1526
function filter_cdm_entity_list($entity_list, $excludes) {
1527
  if (is_array($entity_list)) {
1528
    $result = $entity_list;
1529
    if ($excludes) {
1530
      foreach ($excludes as $exclude) {
1531
        if (!contains_cdm_entitiy($exclude, $entity_list)) {
1532
          $result[] = $exclude;
1533
        }
1534
      }
1535
    }
1536
  }
1537
  else {
1538
    $result = $excludes;
1539
  }
1540
  return $result;
1541
}
1542

    
1543
/**
1544
 * Wraps the given $html string into a render array suitable for drupal_render()
1545
 *
1546
 * @param $html
1547
 *   the html string, see
1548
 *   http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#markup
1549
 * @param $weight
1550
 *   A positive or negative number (integer or decimal).
1551
 *   see http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#weightval
1552
 * @param $prefix
1553
 *   Optional markup for the '#prefix' element of the render array
1554
 * @param $suffix
1555
 *   Optional markup for the '#suffix' element of the render array
1556
 *
1557
 * @return array
1558
 *   A render array
1559
 *
1560
 */
1561
function markup_to_render_array($html, $weight = FALSE, $prefix = NULL, $suffix = NULL) {
1562
  $render_array = array(
1563
    '#markup' => $html
1564
      );
1565
  if (is_numeric($weight)) {
1566
    $render_array['#weight'] = $weight;
1567
  }
1568
  if($prefix){
1569
    $render_array['#prefix'] = $prefix;
1570
  }
1571
  if($suffix) {
1572
    $render_array['#suffix'] = $suffix;
1573
  }
1574
  return $render_array;
1575
}
1576

    
1577
/**
1578
 * Loads the subgraph of a given PolytomousKeyNode.
1579
 *
1580
 * Loads the subgraph of the given PolytomousKeyNode recursively from
1581
 * the CDM REST service.
1582
 *
1583
 * @param mixed $polytomousKeyNode
1584
 *   PolytomousKeyNode passed by reference.
1585
 *
1586
 * @return void
1587
 */
1588
function _load_polytomousKeySubGraph(&$polytomousKeyNode) {
1589

    
1590
  if (!$polytomousKeyNode) {
1591
    return;
1592
  }
1593
  if ($polytomousKeyNode->class != "PolytomousKeyNode") {
1594
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1595
    return;
1596
  }
1597
  if (!is_uuid($polytomousKeyNode->uuid)) {
1598
    drupal_set_message('_load_polytomousKeySubGraph(): ' . t('invalid type given.'), 'error');
1599
    return;
1600
  }
1601

    
1602
  $polytomousKeyNode = cdm_ws_get(CDM_WS_PORTAL_POLYTOMOUSKEY_NODE, $polytomousKeyNode->uuid);
1603

    
1604
  if (!$polytomousKeyNode) {
1605
    // drupal_set_message("_load_polytomousKeyChildNodes() : could not load polytomousKeyNode", "error");
1606
    return;
1607
  }
1608

    
1609
  // Load children.
1610
  foreach ($polytomousKeyNode->children as &$childNode) {
1611
    _load_polytomousKeySubGraph($childNode);
1612
  }
1613
  return;
1614
}
1615

    
1616
/**
1617
 * @todo Please document this function.
1618
 * @see http://drupal.org/node/1354
1619
 */
1620
function cdm_dataportal_view_polytomousKey($polytomousKeyUuid) {
1621

    
1622
  cdm_check_valid_portal_page();
1623

    
1624
  $polytomousKey = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, $polytomousKeyUuid);
1625
  if (!$polytomousKey) {
1626
    drupal_set_title(t('Polytomous key does not exist'), PASS_THROUGH);
1627
    return "";
1628
  }
1629

    
1630
  $sourcePager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1631
  if (is_array($sourcePager->records)) {
1632
    $polytomousKey->sources = $sourcePager->records;
1633
    // $polytomousKey->sources->citation = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'sources'));
1634
  }
1635

    
1636
  $annotationPager = cdm_ws_get(CDM_WS_POLYTOMOUSKEY, array($polytomousKeyUuid, 'annotations'));
1637
  if (is_array($annotationPager->records)) {
1638
    $polytomousKey->annotations = $annotationPager->records;
1639
  }
1640

    
1641
  _load_polytomousKeySubGraph($polytomousKey->root);
1642
  return theme('cdm_polytomousKey_page', array('polytomousKey' => $polytomousKey));
1643
}
1644

    
1645
/**
1646
 * Creates a taxon page view or a chapter of it.
1647
 *
1648
 * The taxon page gives detailed information on a taxon, it shows:
1649
 *  - Taxon name.
1650
 *  - Full list of synonyms homotypic synonyms on top, followed by the
1651
 *    heterotypic and finally followed by misapplied names.
1652
 *    The list is ordered historically.
1653
 *  - All description associated with the taxon.
1654
 *
1655
 * @param string $uuid
1656
 * @param string $chapter
1657
 *   Name of the part to display, valid values are:
1658
 *   'description', 'images', 'synonymy', 'specimens', 'all'.
1659
 *
1660
 * @return string
1661
 */
1662
function cdm_dataportal_taxon_page_view($uuid, $chapter = 'all') {
1663

    
1664
  cdm_check_valid_taxon_page($chapter);
1665
  cdm_dd("START OF TAXON PAGE [" . $chapter . "] " . $uuid . ' for ' . $_GET['q']);
1666

    
1667

    
1668
  // Display the page for the taxon defined by $uuid.
1669
  // set_last_taxon_page_tab(arg(3));
1670
  $taxonpage = cdm_dataportal_taxon_view($uuid, $chapter);
1671
  if (!empty($taxonpage)) {
1672
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid);
1673
    return cdm_node_show(NODETYPE_TAXON, $uuid, $taxonpage->title, $taxonpage->content);
1674
  }
1675
  else {
1676
    cdm_dd("END OF TAXON PAGE [" . $chapter . "] " . $uuid . ' !!! PAGE IS EMPTY !!!');
1677
    return '';
1678
  }
1679
}
1680

    
1681
/**
1682
 * This function will generate the taxon page part ($chapter) and returns a taxonpage object
1683
 * which has two fields, one for the page title and one for the content. Later on in the
1684
 * process chain the value contained in these fields will be passed to the cdm_node_show()
1685
 * function as the function parameters $title and $content.
1686
 *
1687
 * @param string $uuid
1688
 *   the uuid of the taxon to show
1689
 * @param string $chapter
1690
 *   Name of the part to display, valid values are:
1691
 *   'description', 'images', 'synonymy', 'all'.
1692
 *
1693
 * @return object with the following fields:
1694
 *   - title : the title of the page
1695
 *   - content: the content of the page
1696
 *
1697
 * @throws Exception
1698
 *
1699
 */
1700
function cdm_dataportal_taxon_view($uuid, $chapter = 'all') {
1701
  // Taxon object.
1702
  $taxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $uuid);
1703
  if (empty($taxon)) {
1704
    drupal_set_title(t('Taxon does not exist'), PASS_THROUGH);
1705
    return null;
1706
  }
1707
  $taxonpage = new stdClass();
1708

    
1709
  $taxonpage->title = theme('cdm_taxon_page_title', array(
1710
    'taxon' => $taxon
1711
  ));
1712

    
1713
  // Check if the taxon id contained in the currently selected tree.
1714
  $taxon_in_current_classification = taxon_in_current_classification($uuid);
1715

    
1716
  if (!$taxon_in_current_classification) {
1717
    $classifications = get_classifications_for_taxon($taxon);
1718
    RenderHints::pushToRenderStack('not_in_current_classification');
1719
    RenderHints::setFootnoteListKey('not_in_current_classification');
1720
    FootnoteManager::blockFootnotesFor('not_in_current_classification');
1721
    $taxon_name_markup = render_taxon_or_name($taxon);
1722
    FootnoteManager::unblockFootnotesFor('not_in_current_classification');
1723
    RenderHints::clearFootnoteListKey();
1724

    
1725
    if (count($classifications) == 0) {
1726
      drupal_set_message(t('This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification.',
1727
        array(
1728
        '!taxonname' => $taxon_name_markup,
1729
        )
1730
      ), 'warning');
1731
    }
1732
    else {
1733
      $trees = [];
1734
      foreach ($classifications as $classification) {
1735
        if (isset($classification->titleCache)) {
1736
          $trees[] = '<strong>' . $classification->titleCache . '</strong>';
1737
        }
1738
      }
1739

    
1740
      drupal_set_message(format_plural(count($trees),
1741
          'This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification, but in this one: !trees',
1742
          'This concept of the taxon !taxonname is not contained as an accepted taxon in the currently chosen classification, but in one of these: !trees',
1743
          array('!taxonname' => $taxon_name_markup, '!trees' => join(', ', $trees))
1744
        ) ,
1745
        'warning');
1746
    }
1747
    RenderHints::popFromRenderStack();
1748
  }
1749

    
1750
  // Render the taxon page.
1751
  $render_array = compose_cdm_taxon_page($taxon, $chapter);
1752
  $taxonpage->content = drupal_render($render_array);
1753

    
1754
  return $taxonpage;
1755
}
1756

    
1757

    
1758
function cdm_dataportal_specimen_by_accession_number_page_view($accession_number)
1759
{
1760
  cdm_check_valid_portal_page();
1761

    
1762
  $specimenpage = specimen_by_accession_number_view($accession_number);
1763

    
1764
  if (!empty($specimenpage)) {
1765
    return cdm_node_show_simulate($specimenpage->content);
1766
  }
1767
  else {
1768
    return '';
1769
  }
1770

    
1771

    
1772
}
1773

    
1774
/**
1775
 * Creates a specimen page view.
1776
 * @param string $uuid the UUID of the specimen
1777
 * @return array|string
1778
 */
1779
function cdm_dataportal_specimen_page_view($uuid) {
1780

    
1781
    cdm_check_valid_portal_page();
1782
    $specimenpage = cdm_dataportal_specimen_view($uuid);
1783
    if (!empty($specimenpage)) {
1784
        return cdm_node_show_simulate($specimenpage->content);
1785
    }
1786
    else {
1787
        return '';
1788
    }
1789
}
1790

    
1791

    
1792
/**
1793
 * Creates a specimen page view.
1794
 * @param string $uuid the UUID of the specimen
1795
 * @return object
1796
 *  The page object with the following fields:
1797
 *   - 'title': the page title
1798
 *   - 'content' : the page content rendered as markup
1799
 */
1800
function specimen_by_accession_number_view($accession_number = null) {
1801

    
1802
  $field_unit_dto = cdm_ws_get(CDM_WS_OCCURRENCE_ACCESSION_NUMBER, null, 'accessionNumber=' . $accession_number);
1803

    
1804
  // Display the page for the specimen defined by $uuid.
1805
  if (isset($field_unit_dto)){
1806
    $dto_array = array($field_unit_dto);
1807
    $specimen_array = specimen_render_array_items($dto_array);
1808
    $specimen_table = array(
1809
      '#theme' => 'table',
1810
      '#weight' => 2,
1811
      // prefix attributes and rows with '#' to let it pass toF the theme function,
1812
      // otherwise it is handled as child render array
1813
      '#attributes' => array('class' => 'specimens'),
1814
      '#rows' => array(),
1815
      '#prefix' => '<div id="specimens">',
1816
      '#suffix' => '</div>',
1817
    );
1818
    foreach($specimen_array as $value){
1819
      $renderArray = array(
1820
        '#theme' => 'item_list',
1821
        '#items' => array($value),
1822
        '#type' => 'ul');
1823
      $output = drupal_render($renderArray);
1824
      $specimen_table['#rows'][] = array(
1825
        // An array of table rows. Every row is an array of cells, or an associative array
1826
        'data' => array($output),
1827
        'class' =>  array(
1828
          'descriptionElement',
1829
          'descriptionElement_IndividualsAssociation'
1830
        ),
1831
      );
1832

    
1833

    
1834
    }
1835
    $specimenpage = new stdClass();
1836

    
1837
    $specimenpage->title = render_cdm_specimen_dto_page_title($field_unit_dto);
1838

    
1839
     $render_array['markup'] = $specimen_table;
1840
     $specimenpage->content = drupal_render($render_array);
1841
  }
1842

    
1843
  return $specimenpage;
1844
}
1845

    
1846

    
1847
/**
1848
 *
1849
 * Creates a specimen view.
1850
 * @param string $uuid the UUID of the specimen
1851
 * @return object
1852
 *    Page object with the fields
1853
 *    - title
1854
 *    - content
1855
 */
1856
function cdm_dataportal_specimen_view($uuid) {
1857

    
1858
    $sob_dto = cdm_ws_get(CDM_WS_PORTAL_OCCURRENCE_AS_DTO, $uuid);
1859
    if (empty($sob_dto)) {
1860
        drupal_set_title(t('Specimen does not exist'), PASS_THROUGH);
1861
        return FALSE;
1862
    }
1863
    $specimenpage = new stdClass();
1864
    $specimenpage->title = render_specimen_page_title($sob_dto);
1865

    
1866
    // Render the specimen page.
1867
    $render_array = compose_cdm_specimen_page($sob_dto);
1868
    $specimenpage->content = drupal_render($render_array);
1869

    
1870
    return $specimenpage;
1871
}
1872

    
1873
/**
1874
 *
1875
 * Creates a description view.
1876
 *
1877
 * @param string $uuid the UUID of the description
1878
 * @param null $descriptive_dataset_uuid the uuid of the data set which defines
1879
 * the display of the description detail page
1880
 *
1881
 * @return object Page object with the fields
1882
 * Page object with the fields
1883
 * - title
1884
 * - content
1885
 */
1886
function cdm_dataportal_description_view($uuid, $descriptive_dataset_uuid = NULL) {
1887
    $description = cdm_ws_get(CDM_WS_PORTAL_DESCRIPTION, $uuid);
1888
    $description_page = new stdClass();
1889
    if (empty($description)) {
1890
      $description_page->title = t('Description does not exist');
1891
      drupal_set_title($description_page->title, PASS_THROUGH); // not necessary if correctly implemented as drupal node
1892
      $description_page->content = "";
1893

    
1894
    } else {
1895
      $description_page->title = $description->titleCache;
1896
      drupal_set_title($description_page->title); // not necessary if correctly implemented as drupal node
1897

    
1898
      // Render the description page.
1899
      $render_array = compose_description_table($description->uuid, $descriptive_dataset_uuid);
1900
      if($render_array['title']){
1901
        $page_title = strip_tags($render_array['title']['#markup']);
1902
        drupal_set_title($page_title);
1903
        unset($render_array['title']);
1904
      }
1905
      $description_page->content = drupal_render($render_array);
1906
    }
1907

    
1908
    return $description_page;
1909
}
1910

    
1911
function cdm_dataportal_description_page_view($uuid, $descriptive_dataset_uuid = NULL) {
1912

    
1913
  cdm_check_valid_portal_page();
1914
  $descriptionpage = cdm_dataportal_description_view($uuid, $descriptive_dataset_uuid);
1915
  if (!empty($descriptionpage)) {
1916
    return cdm_node_show_simulate($descriptionpage->content);
1917
  }
1918
  else {
1919
    return NULL;
1920
  }
1921
}
1922

    
1923
/**
1924
 *
1925
 * Creates a named area view.
1926
 * @param string $uuid the UUID of the specimen
1927
 *  * @return object
1928
 *   An object with two fields:
1929
 *     - title: the page title
1930
 *     - content: the page content
1931
 */
1932

    
1933
function cdm_dataportal_named_area_view($uuid) {
1934
  $named_area = cdm_ws_get(CDM_WS_PORTAL_TERM, $uuid);
1935
  if (empty($named_area) || $named_area->class !== 'NamedArea') {
1936
    drupal_set_title(t('Named area does not exist'), PASS_THROUGH);
1937
    return null;
1938
  }
1939
  $named_area_page = new stdClass();
1940

    
1941
  $named_area_page->title = $named_area->representation_L10n;
1942

    
1943
  // Render the specimen page.
1944
  $render_array = compose_cdm_named_area_page($uuid);
1945
  $named_area_page->content = drupal_render($render_array);
1946

    
1947
  return $named_area_page;
1948
}
1949

    
1950
function cdm_dataportal_named_area_page_view($uuid) {
1951

    
1952
  cdm_check_valid_portal_page();
1953

    
1954
  $named_area_page = cdm_dataportal_named_area_view($uuid);
1955
  if (!empty($named_area_page)) {
1956
    return cdm_node_show(NODETYPE_NAME, $uuid, $named_area_page->title, $named_area_page->content);
1957
  }
1958
  else {
1959
    return '';
1960
  }
1961

    
1962

    
1963
}
1964

    
1965
/**
1966
 * Returns a name page as a Drupal node ready to be renderized by Drupal.
1967
 *
1968
 * The node page shows the taxon name title and the list of taxon related
1969
 * with such taxon. Name on the tree already in use.
1970
 *
1971
 * @param string $taxon_name_uuid
1972
 *   The uuid of the CDM TaxonName to show a name page for
1973
 * @param string $taxon_to_hide_uuid
1974
 *   A taxon which should not be displayed in the taxon list
1975
 * @param $redirect_to_taxon
1976
 *   Automatically redirect to the related taxon if there is only one
1977
 *   accepted taxon for this name.
1978
 * @param string $highlite_synonym_uuid
1979
 *   Optinal parameter wich takes another taxon uuid, if given the
1980
 *   target taxon pages will show the syonymy tab where the taxon
1981
 *   refenrenced by the $highlite_synonym_uuid will be highlighted
1982
 *   in case it is found on this page.
1983
 *
1984
 * @return mixed
1985
 *   The formatted name page as node.
1986
 */
1987
function cdm_dataportal_name_page_view($taxon_name_uuid, $taxon_to_hide_uuid, $synonym_uuid = NULL, $redirect_to_taxon = false) {
1988

    
1989
  cdm_check_valid_portal_page();
1990

    
1991
  $taxonname_page = cdm_dataportal_name_view(
1992
    is_uuid($taxon_name_uuid) ? $taxon_name_uuid : null,
1993
    is_uuid($taxon_to_hide_uuid) ? $taxon_to_hide_uuid : null,
1994
    $redirect_to_taxon == 'redirect_to_taxon',
1995
    is_uuid($synonym_uuid) ? $synonym_uuid : null);
1996
  if (!empty($taxonname_page)) {
1997
    return cdm_node_show(NODETYPE_NAME, $taxon_name_uuid, $taxonname_page->title, $taxonname_page->content);
1998
  }
1999
  else {
2000
    return '';
2001
  }
2002
}
2003

    
2004
/**
2005
 * View function for a TaxonName page.
2006
 *
2007
 * The name page lists all taxa for which the name specified by the
2008
 * $taxon_name_uuid is being used. I case there is only one name the
2009
 * page automatically redirects ti the according taxon page. Otherwise
2010
 * the list of names is displayed.
2011
 *
2012
 * The parameter $taxon_to_hide_uuid allows to exclude a taxon from the
2013
 * list of taxa. This is useful for example when referencing from a taxon
2014
 * to the name page and the referring taxon should not be repeaded in the
2015
 * name page.
2016
 *
2017
 *
2018
 * @param string $taxon_name_uuid
2019
 *   The uuid of the CDM TaxonName to show a name page for
2020
 * @param string $taxon_to_hide_uuid
2021
 *   A taxon which should not be displayed in the taxon list
2022
 * @param $redirect_to_taxon
2023
 *   Automatically redirect to the related taxon if there is only one
2024
 *   accepted taxon for this name.
2025
 * @param string $highlite_synonym_uuid
2026
 *   Optional parameter which takes another taxon uuid, if given the
2027
 *   target taxon pages will show the synonymy tab where the taxon
2028
 *   referenced by the $highlite_synonym_uuid will be highlighted
2029
 *   in case it is found on this page.
2030
 *
2031
 * @return object|boolean
2032
 *   An object with two fields:
2033
 *     - title: the page title
2034
 *     - content: the page content
2035
 *   or FALSE
2036
 *
2037
 */
2038
function cdm_dataportal_name_view($taxon_name_uuid, $taxon_to_hide_uuid, $redirect_to_taxon, $highlite_synonym_uuid = NULL) {
2039
  // Getting the full taxonname object from the server.
2040
  $taxon_name = cdm_ws_get(CDM_WS_PORTAL_NAME, array($taxon_name_uuid));
2041
  if (!$taxon_name) {
2042
    drupal_set_title(t('Taxon name does not exist'), PASS_THROUGH);
2043
    return FALSE;
2044
  }
2045
  cdm_load_tagged_full_title($taxon_name);
2046
  // Searching for all the taxa connected with the taxon name on the tree
2047
  // in use.
2048
  $name = cdm_ws_get(CDM_WS_NAME, array($taxon_name_uuid));
2049
  $restrictions = array(new Restriction("name.titleCache","EXACT", array($name->titleCache), 'AND'));
2050
  $init_strategy = array(
2051
    "name.titleCache",
2052
    "name.nomenclaturalReference.authorship",
2053
    "name.nomenclaturalReference.inReference.authorship",
2054
    "name.nomenclaturalReference.inReference.inReference.authorship",
2055
    "name.nomenclaturalReference.inReference.inReference.inReference.authorship"
2056
  );
2057
  $taxa = cdm_ws_fetch_all_by_restriction("Taxon", NULL, $restrictions, $init_strategy);
2058

    
2059
  // Removing the name where we came from.
2060
  foreach ($taxa as $k => &$taxon) {
2061
    if ($taxon->uuid == $taxon_to_hide_uuid) {
2062
      unset($taxa[$k]);
2063
    }
2064
  }
2065
  // Show the taxa list or go to the singular taxon.
2066
  if (sizeof($taxa) == 1 && $redirect_to_taxon) {
2067
    // redirect to the taxon if there is only one.
2068
    $singleTaxon = array_pop($taxa);
2069
    if ($singleTaxon->class != "Taxon") {
2070
      // It is a Synonym -> look for the accepted.
2071
      $accepted_taxon = cdm_ws_get(CDM_WS_PORTAL_TAXON_ACCEPTED, array($singleTaxon->uuid), 'classificationFilter=' . get_current_classification_uuid());
2072
      if (!empty($highlite_synonym_uuid)) {
2073
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxon->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
2074
      }
2075
      else {
2076
        drupal_goto('cdm_dataportal/taxon/' . $accepted_taxon->uuid . '/synonymy', array('query' => array('highlite' => $singleTaxon->uuid)));
2077
      }
2078
    }
2079
    else {
2080
      // It is an accepted taxon.
2081
      if (!empty($highlite_synonym_uuid)) {
2082
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid . '/synonymy', array('query' => array('highlite' => $highlite_synonym_uuid)));
2083
      }
2084
      else {
2085
        drupal_goto('cdm_dataportal/taxon/' . $singleTaxon->uuid);
2086
      }
2087
    }
2088
  }
2089
  else {
2090
    // display the name page content
2091
    $taxon_name_page = new stdClass();
2092
    $taxon_name_page->title = theme('cdm_name_page_title', array('taxon_name' => $taxon_name));
2093
    $content = array();
2094

    
2095
    RenderHints::pushToRenderStack('name_page');
2096
    RenderHints::setFootnoteListKey('name_page');
2097
    $content['taxon_name'] = markup_to_render_array(render_taxon_or_name($taxon_name), null, '<div class="name-page-name">', '</div>');
2098

    
2099

    
2100
    // name relationships
2101
    $name_relations = cdm_ws_fetch_all(str_replace("$0", $taxon_name->uuid, CDM_WS_PORTAL_NAME_NAME_RELATIONS));
2102
    if(count($name_relations) > 0){
2103
      $content['name_relationships'] = compose_name_relationships_list($name_relations, $taxon_name->uuid, null);
2104
    }
2105

    
2106
    // type designations
2107
    $type_designations_render_array = compose_type_designations($taxon_name->uuid);
2108
    $content = array_merge($content, $type_designations_render_array);
2109
    // registrations
2110
    $registrationDTOs= cdm_ws_fetch_all(CDM_WS_REGISTRATION_DTO,  array('nameUuid' => $taxon_name_uuid));
2111
    if(isset($registrationDTOs) && count($registrationDTOs ) > 0 ){
2112
      $content['registrations'][] = markup_to_render_array('<h2>' . t("Registrations") . '</h2>') ;
2113
      foreach ($registrationDTOs as $regDTO){
2114
        $content['registrations'][] = compose_registration_dto_compact($regDTO);
2115
      }
2116
    }
2117

    
2118

    
2119
    // related taxa
2120
    $show_taxa_section = variable_get(CDM_NAME_PAGE_SECTION_TAXA, CDM_NAME_PAGE_SECTION_TAXA_DEFAULT);
2121
    if($show_taxa_section){
2122
      if ($taxa) {
2123
        $content['related_taxa_header'] = markup_to_render_array("<h2>" . count($taxa) > 1 ? t("Taxa for this name") :  t("Taxon for this name") . "</h2>");
2124
        $content['related_taxa'] = compose_list_of_taxa($taxa);
2125
      }
2126
      else {
2127
        $content['related_taxa'] = markup_to_render_array('This name is not assigned to any taxon.', null, '<div class="no-taxon-message">', '</div>');
2128
      }
2129
    }
2130

    
2131
    $content['footnotes'] = markup_to_render_array(render_footnotes());
2132

    
2133
    $taxon_name_page->content = $content;
2134
    RenderHints::popFromRenderStack();
2135
    RenderHints::clearFootnoteListKey();
2136
    return $taxon_name_page;
2137
  }
2138
}
2139

    
2140

    
2141
/**
2142
 * Returns a registration page as a Drupal node to be rendered by Drupal.
2143
 *
2144
 * @param string  $registration_identifie
2145
 *   The persistent identifier of the registration urlencoded.
2146
 * @return mixed
2147
 *   The formatted registration page as node.
2148
 */
2149
function cdm_dataportal_registration_page_view() {
2150

    
2151
  cdm_check_valid_portal_page("/\/cdm_dataportal\/registration/");
2152
  $registration_identifier = $_REQUEST['identifier'];
2153
  $registration_page = cdm_dataportal_registration_view($registration_identifier);
2154
  return cdm_node_show_simulate($registration_page);
2155
}
2156

    
2157
/**
2158
 * @param $registration_identifier
2159
 * @return array
2160
 *   The drupal render array for the registration view.
2161
 */
2162
function cdm_dataportal_registration_view($registration_identifier) {
2163

    
2164
  RenderHints::pushToRenderStack('registration_page');
2165
  RenderHints::setFootnoteListKey('registration_page');
2166

    
2167
  $render_array = array();
2168
  $registration_dto = cdm_ws_get(CDM_WS_REGISTRATION_DTO, null, 'identifier=' . $registration_identifier);
2169
  if($registration_dto){
2170

    
2171
    drupal_set_title(t('Registration Id:') . ' ' . $registration_identifier, PASS_THROUGH);
2172
    $render_array = compose_registration_dto_full($registration_dto, true);
2173

    
2174
  } else {
2175
    $status_text = cdm_ws_get(CDM_WS_REGISTRATION_STATUS, null, 'identifier=' . $registration_identifier);
2176
    if(isset($status_text->String)) {
2177
      $status_text = strtolower($status_text->String);
2178
      if($status_text == 'preparation' || $status_text == 'curation'){
2179
        $status_text = 'in ' . $status_text;
2180
      }
2181
      drupal_set_title(t('Registration ' . $status_text), PASS_THROUGH);
2182
      //$status_message;
2183
      drupal_set_message("A registration with the identifier  " . $registration_identifier . " is " . $status_text, "status");
2184
    } else {
2185
      drupal_set_title(t('Registration not found'), PASS_THROUGH);
2186
      drupal_set_message("A registration with the identifier  " . $registration_identifier . " does not exist", "warning");
2187
    }
2188
  }
2189

    
2190
  $render_array = array(
2191
    '#prefix' => '<div id="registration">',
2192
    'registration' => $render_array,
2193
    '#suffix' => '</div>',
2194
  );
2195

    
2196
  RenderHints::popFromRenderStack();
2197
  RenderHints::clearFootnoteListKey();
2198

    
2199
  return $render_array ;
2200
}
2201

    
2202

    
2203
/**
2204
 * Creates a page with the advance search form.
2205
 *
2206
 * NOTE: The advance search form allows searching for taxa.
2207
 */
2208
function cdm_dataportal_view_search_advanced() {
2209
  drupal_set_title(t('Advanced search'), PASS_THROUGH);
2210
  return drupal_get_form('cdm_dataportal_search_taxon_form_advanced');
2211
}
2212

    
2213
/**
2214
 * Creates a page with the blast search form.
2215
 *
2216
 * NOTE: The advance search form allows searching for specimen in blast DB.
2217
 */
2218
function cdm_dataportal_view_search_blast() {
2219
    drupal_set_title(t('Blast search'), PASS_THROUGH);
2220
    return drupal_get_form('cdm_dataportal_search_blast_form');
2221
}
2222

    
2223
/**
2224
 * Creates a page with the search form for searching by taxon descriptions.
2225
 */
2226
function cdm_dataportal_view_search_taxon_by_description() {
2227
  drupal_set_title(t('Search by factual data'), PASS_THROUGH);
2228
  return drupal_get_form('cdm_dataportal_search_taxon_by_description_form');
2229
}
2230

    
2231
/**
2232
 * Executes the search and generates the result list of taxa.
2233
 */
2234
function cdm_dataportal_view_search_results_taxon() {
2235

    
2236
  $taxonPager = cdm_dataportal_search_taxon_execute();
2237

    
2238
  $showThumbnails = do_showThumbnails();
2239

    
2240
  $setSessionUri = url('cdm_api/setvalue/session', array(
2241
      'query' => array('var' => '[pageoption][searchtaxa][showThumbnails]', 'val' => ''),
2242
  ));
2243

    
2244
  drupal_add_js('jQuery(document).ready(function() {
2245

    
2246
      // init
2247
      if(' . $showThumbnails . ' == 1){
2248
          jQuery(\'.media_gallery\').show(20);
2249
      } else {
2250
          jQuery(\'.media_gallery\').hide(20);
2251
      }
2252

    
2253
      // add change handler
2254
      jQuery(\'#showThumbnails input.showThumbnails\').change(
2255
      function(event){
2256
        var state = 0;
2257
        if(jQuery(this).is(\':checked\')){
2258
          jQuery(\'.media_gallery\').show(20);
2259
          state = 1;
2260
        } else {
2261
          jQuery(\'.media_gallery\').hide(20);
2262
        }
2263
        // store state in session variable
2264
        var uri = \'' . $setSessionUri . '\' + state;
2265
        jQuery.get(uri);
2266
      });
2267
  });',
2268
  array('type' => "inline", 'scope' => JS_DEFAULT));
2269

    
2270
  drupal_set_title(t('Search results'), PASS_THROUGH);
2271

    
2272
  return theme('cdm_search_taxa_results', array(
2273
    'pager' => $taxonPager,
2274
    'path' => 'cdm_dataportal/search/results/taxon',
2275
    ));
2276
}
2277

    
2278
/**
2279
 * Executes the blast search and generates the result list of specimen.
2280
 */
2281
function cdm_dataportal_view_search_results_specimen() {
2282

    
2283
    $specimenPager = cdm_dataportal_search_blast_execute();
2284

    
2285
    return theme('cdm_search_specimen_results', array(
2286
        'pager' => $specimenPager,
2287
        'path' => 'cdm_dataportal/search/results/specimen',
2288
    ));
2289
}
2290

    
2291

    
2292
/**
2293
 * Executes the search for registrations and generates the result list..
2294
 */
2295
function cdm_dataportal_view_search_registrations_results($mode = 'filter') {
2296

    
2297
  switch($mode ){
2298
    case 'taxongraph':
2299
      $block = block_load('cdm_dataportal', 'registrations_search_taxongraph');
2300
      $registration_pager = cdm_dataportal_search_registrations_taxongraph_execute();
2301
      break;
2302
    case 'filter':
2303
    default:
2304
      $block = block_load('cdm_dataportal', 'registrations_search_filter');
2305
      $registration_pager = cdm_dataportal_search_registrations_filter_execute();
2306
  }
2307
  $block->title = null;
2308

    
2309
  drupal_set_title(t('Search registrations'), PASS_THROUGH);
2310

    
2311
  $render_array = _block_get_renderable_array(_block_render_blocks(array($block)));
2312
  $registrations_pager_array = compose_search_results($registration_pager, new RegistrationDTOComposeHandler());
2313
  $render_array = array_merge($render_array, $registrations_pager_array);
2314

    
2315
  return $render_array;
2316
}
2317

    
2318
/**
2319
 * Executes the search for registrations and generates the result list..
2320
 */
2321
function cdm_dataportal_view_search_agent() {
2322

    
2323
  $render_array = [];
2324
  $title = isset($_REQUEST['class']) && $_REQUEST['class'] ? $_REQUEST['class'] : 'Persons & Teams';
2325
  drupal_set_title(t($title), PASS_THROUGH);
2326
  // TODO $block = block_load('cdm_dataportal', 'search_agent_filter');
2327
  // $block->title = null;
2328
  // $render_array = _block_get_renderable_array(_block_render_blocks(array($block)));
2329
  $pager = cdm_dataportal_search_agent_execute();
2330
  $pager_render_array = compose_search_results($pager, new AgentComposeHandler());
2331
  $render_array = array_merge($render_array, $pager_render_array);
2332
  return $render_array;
2333
}
2334

    
2335

    
2336
/**
2337
 * Provides the standard image which indicated a loading process
2338
 *
2339
 * @return string
2340
 *  The img html tag
2341
 */
2342
function loading_image_html() {
2343
  return '<img class="loading" src="' . base_path() . drupal_get_path('module', 'cdm_dataportal')
2344
    . '/images/loading_circle_grey_16.gif" style="display:none;">';
2345
}
2346

    
2347
/**
2348
 * Returns the state of the the showThumbnails flag set in the
2349
 * users session ($_SESSION['pageoption']['searchtaxa']['showThumbnails']).
2350
 *
2351
 * @return boolean
2352
 *    returns 1 if the flag is set
2353
 */
2354
function do_showThumbnails() {
2355
  static $showThumbnails = null;
2356

    
2357
  if($showThumbnails == null) {
2358
    $showThumbnails = 0;
2359
    if (!isset($_SESSION['pageoption']['searchtaxa']['showThumbnails'])) {
2360
      $showThumbnails = 0;
2361
      $search_gallery_settings = variable_get(CDM_DATAPORTAL_SEARCH_GALLERY_NAME, null);
2362
      $showThumbnails = is_array($search_gallery_settings)
2363
        && isset($search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'])
2364
        && (
2365
            $search_gallery_settings['cdm_dataportal_show_taxon_thumbnails'] +
2366
            $search_gallery_settings['cdm_dataportal_show_synonym_thumbnails'] +
2367
            $search_gallery_settings['cdm_dataportal_show_thumbnail_captions'] > 0
2368
            )
2369
         ? 1 : 0;
2370

    
2371
       drupal_array_set_nested_value($_SESSION, array('pageoption', 'searchtaxa', 'showThumbnails'), $showThumbnails);
2372
    }
2373
    $showThumbnails = $_SESSION['pageoption']['searchtaxa']['showThumbnails'];
2374
    if (!is_numeric($showThumbnails)) {
2375
      $showThumbnails = 1;
2376
    }
2377
  }
2378

    
2379
  return $showThumbnails;
2380
}
2381

    
2382

    
2383

    
2384
/* ====================== other functions ====================== */
2385
/**
2386
 * Creates a URL to the taxon page specified by the $uuid parameter.
2387
 *
2388
 * The URL will be prepended with a path element to a specific taxon page tab.
2389
 *
2390
 * This tab is either taken from the CDM_DATAPORTAL_DEFAULT_TAXON_TAB which can
2391
 * be set globally in the administrative settings or individually in the user
2392
 * profile. If the CDM_DATAPORTAL_DEFAULT_TAXON_TAB value is set to LAST_VISITED_TAB
2393
 * the last portal will stay on this last tab.
2394
 *
2395
 * A third option is offerered by the $page_tab parameter which allows overwriting this
2396
 * internal mechanism by a specific value.
2397
 *
2398
 * @param string $uuid
2399
 *   The UUID of the taxon.
2400
 * @param string $page_tab
2401
 *   Overwriting the preset mechanism by defining specific value for the
2402
 *   taxon page tab.
2403
 * @return string
2404
 *   The created URL.
2405
 */
2406
function path_to_taxon($uuid, $page_tab = FALSE) {
2407

    
2408
  $tab = get_default_taxon_tab();
2409
  $values = unserialize(CDM_DATAPORTAL_DEFAULT_TAXON_TAB);
2410

    
2411
  if (!$uuid) {
2412
    return FALSE;
2413
  }
2414

    
2415
  if ($page_tab) {
2416
    $url = 'cdm_dataportal/taxon/' . $uuid . '/' . $page_tab;
2417
  }
2418
  elseif (!$tab || strtolower($tab) == 'general') {
2419
    $url = 'cdm_dataportal/taxon/' . $uuid;
2420
  }
2421
  elseif (get_last_taxon_page_tab() &&   $tab == $values[CDM_DATAPORTAL_LAST_VISITED_TAB_ARRAY_INDEX]) {
2422
    $url = 'cdm_dataportal/taxon/' . $uuid . '/' . get_last_taxon_page_tab();
2423
  }
2424
  else {
2425
    $url = 'cdm_dataportal/taxon/' . $uuid . '/' . strtolower($tab);
2426
  }
2427
  return $url;
2428
}
2429

    
2430
function path_to_description($uuid, $descriptive_dataset_uuid = NULL) {
2431

    
2432
    if (!$uuid) {
2433
        return FALSE;
2434
    }
2435
    else {
2436
      return 'cdm_dataportal/description/' . $uuid
2437
        . (is_uuid($descriptive_dataset_uuid) ? '/' . $descriptive_dataset_uuid : '');
2438
    }
2439
}
2440

    
2441
function path_to_specimen($uuid) {
2442

    
2443
    if (!$uuid) {
2444
        return FALSE;
2445
    }
2446
    else {
2447
        return 'cdm_dataportal/occurrence/' . $uuid;
2448
    }
2449
}
2450

    
2451
function path_to_specimen_by_accession_number($accession_number) {
2452

    
2453
    if (!$accession_number) {
2454
        return FALSE;
2455
    }
2456
    else {
2457
        return 'cdm_dataportal/specimen/accession_number/' . $accession_number;
2458
    }
2459
}
2460

    
2461
function path_to_named_area($uuid) {
2462

    
2463
  if (!$uuid) {
2464
    return FALSE;
2465
  }
2466
  else {
2467
    return 'cdm_dataportal/named_area/' . $uuid;
2468
  }
2469
}
2470

    
2471
/**
2472
 * @param $uuid
2473
 *
2474
 * @return string
2475
 */
2476
function path_to_collection($uuid) {
2477
  if (!$uuid) {
2478
    return '';
2479
  }
2480
  else {
2481
    return 'cdm_dataportal/collection/' . $uuid;
2482
  }
2483
}
2484

    
2485
/**
2486
 * Creates a URL to show a synonmy in the according taxon page.
2487
 *
2488
 * The URL will point to the synonymy tab of the taxon page of the accepted taxon given as parameter $acceptedUuid.
2489
 * The resulting URI will include query parameters to highlight the synonym, and to optionally display
2490
 * the accepted taxons name in aform like "Foo bar is accepted taxon for Ree doo". The URI will also
2491
 * include the sysnonym uuid as fragment in order to let the browser scroll to the according location
2492
 * in the page
2493
 *
2494
 * @param string $synonymUuid
2495
 *    The uuid of the synonym
2496
 * @param string $acceptedUuid
2497
 *    The uuid of the according accepted taxon
2498
 * @return string
2499
 *    The URL to show a synonmy in the according taxon page
2500
 */
2501
function uri_to_synonym($synonymUuid, $acceptedUuid) {
2502
  $acceptedPath = path_to_taxon($acceptedUuid, "synonymy");
2503
  return url($acceptedPath, array(
2504
      'query' => array(
2505
        // highlite the synony in the synonymy
2506
        'highlite' => $synonymUuid,
2507
        // the taxon page is refered from a synonym and the synonym can optionally be named in the page title
2508
        // see theme_taxon_page_title()
2509
        'acceptedFor' => $synonymUuid
2510
      ),
2511
      'fragment' => $synonymUuid
2512
  ));
2513

    
2514
}
2515

    
2516
/**
2517
 * Composes the drupal path to the key identified by the uuid.
2518
 *
2519
 * @param string $keyType
2520
 *    the key typer corresponds to the specific class of the CDM
2521
 *    IdentificationKey. Possible values are
2522
 *      -PolytomousKey
2523
 *      -MultimediaKey
2524
 *      - ...
2525
 * @param string $keyUuid
2526
 *   The UUID of the key
2527
 */
2528
function path_to_key($keyType, $keyUuid) {
2529
  if (!$keyUuid || !$keyType) {
2530
    return FALSE;
2531
  }
2532
  $keyType[0] = strtolower($keyType[0]);
2533
  return "cdm_dataportal/" . $keyType . "/$keyUuid";
2534
}
2535

    
2536
/**
2537
 * Composes the drupal path to the reference identified by the uuid.
2538
 *
2539
 * @param $uuid string String representation of the registration entity uuid.
2540
 *
2541
 * @return string
2542
 *  The drupal path
2543
 *
2544
 */
2545
function path_to_reference($uuid) {
2546
  if (!$uuid) {
2547
    return FALSE;
2548
  }
2549
  return 'cdm_dataportal/reference/' . $uuid;
2550
}
2551

    
2552
/**
2553
 * @param string $registration_identifier
2554
 *  The persistent identifier of the registration entity (Registration.identifier).
2555
 *
2556
 * @return string
2557
 *  the markup for a HTML link
2558
 */
2559
function render_link_to_registration($registration_identifier) {
2560

    
2561
  if(variable_get(CDM_REGISTRATION_PRESISTENT_IDENTIFIER_AS_LINK)){
2562
    $path = $registration_identifier;
2563
    $query = [];
2564
  } else {
2565
    $path = 'cdm_dataportal/registration';
2566
    $query = ['identifier' => $registration_identifier];
2567
  }
2568
  return l($registration_identifier, $path, array('attributes' => array('class' => array('identifier')), 'query' => $query));
2569
}
2570

    
2571

    
2572
/**
2573
 * Creates the path to a cdm_dataportal taxon name page.
2574
 *
2575
 * @param string $taxon_name_uuid
2576
 *   The uuid as string of the CDM TaxonName to show a name page for
2577
 * @param string $taxon_to_hide_uuid
2578
 *   The uuid as string of a taxon which should not be displayed in the taxon list
2579
 * @param string $highlited_synonym_uuid
2580
 *   Optional parameter which takes another taxon uuid, if given the
2581
 *   target taxon pages will show the synonymy tab where the taxon
2582
 *   referenced by the $highlite_synonym_uuid will be highlighted
2583
 *   in case it is found on this page.
2584
 * @param $redirect_to_taxon
2585
 *   If true, the name page will redirect to the related taxon if there is a single one
2586
 *   for this name only.
2587
 *
2588
 * @return string
2589
 *  URI path element as string
2590
 */
2591
function path_to_name($name_uuid, $taxon_to_hide_uuid = NULL, $highlited_synonym_uuid  = NULL, $redirect_to_taxon = false) {
2592
  $res = FALSE;
2593
  if ($name_uuid) {
2594
    $res = 'cdm_dataportal/name/' . $name_uuid .
2595
    '/' . (is_uuid($taxon_to_hide_uuid) ? $taxon_to_hide_uuid : "null") .
2596
    '/' . (is_uuid($highlited_synonym_uuid) ? $highlited_synonym_uuid : "null") .
2597
    '/' . ($redirect_to_taxon || variable_get(CDM_NAME_PAGE_AUTOREDIRECT, 0) ? "redirect_to_taxon" : "");
2598
  }
2599

    
2600
  return $res;
2601
}
2602

    
2603
/**
2604
 * Composes the drupal path to the media entity identified by the uuid.
2605
 *
2606
 * @param string $uuid
2607
 *  The persistent identifier of the entity entity
2608
 * @return string
2609
 *  The drupal path
2610
 */
2611
function path_to_media($uuid, $representaion_uuid = FALSE, $partId = FALSE) {
2612
  if (!$uuid) {
2613
    return FALSE;
2614
  }
2615
  $out = 'cdm_dataportal/media/' . $uuid;
2616
  if ($representaion_uuid) {
2617
    $out .= '/' . $representaion_uuid;
2618
    if (is_numeric($partId)) {
2619
      $out .= '/' . $partId;
2620
    }
2621
  }
2622
  return $out;
2623
}
2624

    
2625
/**
2626
 * Compares thisRank with thatRank.
2627
 *
2628
 * Returns a negative integer, zero, or a positive integer
2629
 * as the of thisRank is higher than, equal to, or lower than thatRank.
2630
 * e.g:
2631
 * <ul>
2632
 * <li>rank_compare({species_uuid}, {genus_uuid}) = -1</li>
2633
 * <li>rank_compare({genus_uuid}, {genus_uuid}) = 0</li>
2634
 * <li>rank_compare({genus_uuid}, {tribus_uuid}) = 1</li>
2635
 * </ul>
2636
 * <p>
2637
 * This compare logic of the underlying webservice is the
2638
 * <b>inverse logic</b> of the the one implemented in
2639
 * java.lang.Comparable#compareTo(java.lang.Object)
2640
 *
2641
 * @param $thisRankUuid
2642
 * @param $thatRankUuid
2643
 *
2644
 * @return int
2645
 *   A negative integer, zero, or a positive integer
2646
 *   as the thisRank is lower than, equal to, or higher than thatRank.
2647
 */
2648
function rank_compare($thisRankUuid, $thatRankUuid) {
2649
  $result = cdm_ws_get(CDM_WS_TERM_COMPARE, array($thisRankUuid, $thatRankUuid));
2650
  return $result->Integer;
2651
}
2652

    
2653
/**
2654
 * Creates a short version of a taxonname.
2655
 *
2656
 * The short name is created by using the taggedTitle field of
2657
 * TaxonNodeDTO instances.
2658
 * If the taggedTitle if empty the fullname will be returned.
2659
 *
2660
 * @param object $taxonNodeDTO
2661
 *   A TaxonNodeDTO object
2662
 *
2663
 * @return string
2664
 */
2665
function cdm_dataportal_shortname_of($taxonNodeDTO) {
2666

    
2667
  $nameStr = '';
2668

    
2669
  normalize_tagged_text($taxonNodeDTO->taggedTitle);
2670

    
2671
  // Get all tagged text tokens of the scientific name.
2672
  foreach ($taxonNodeDTO->taggedTitle as $tagtxt) {
2673
    if ($tagtxt->type == 'name' || $tagtxt->type == 'rank') {
2674
      $nameStr .= ($nameStr ? ' ' : '') . $tagtxt->text;
2675
    }
2676
  }
2677
  $nameStr = trim($nameStr);
2678

    
2679
  if ($nameStr) {
2680
    if(isset($taxonNodeDTO->status->symbol)){
2681
      $nameStr = $taxonNodeDTO->status->symbol . ' ' . $nameStr;
2682
    }
2683
    // Do not return short names for these.
2684
    if ($taxonNodeDTO->unplaced || $taxonNodeDTO->excluded) {
2685
      return $nameStr;
2686
    }
2687

    
2688
    /*
2689
    1st capture group (^[a-zA-Z]): First letter of uninomial.
2690
    Second capture group ([\p{L}]+): remaining letters of uninomial ([\p{L} = an UTF-8 letter).
2691
    Third capture group (\s+[^(\x2E]+\s+.+$|\s+[a-zA-Z]+$): letters of name,
2692
    but only matching if no '(' or '.' in second word of name,        ( \x2E = '.')
2693
    OR only one specific epithet \s+[\p{L}\x22\x2D\xD7]+$             (\x22= '"', \x2D='-', \xD7='×' )
2694
    */
2695
    $pattern = '/(^[a-zA-Z])([\p{L}]+)(\s+[^(\x2E]+\s+.+$|\s+[\p{L}\x22\x2D\xD7]+$)/u';
2696
    if (preg_match($pattern, $nameStr, $matches, PREG_OFFSET_CAPTURE)) {
2697
      return $matches[1][0] . "." . $matches[3][0];
2698
    }
2699
    else {
2700
      return $nameStr;
2701
    }
2702
  }
2703
  else {
2704
    return $taxonNodeDTO->titleCache;
2705
  }
2706
}
2707

    
2708
/**
2709
 * Check if a taxon is accepted by the current taxonomic tree.
2710
 *
2711
 * @param mixed $taxon
2712
 *   The Taxon obkect to check.
2713
 *
2714
 * @return bool
2715
 *   Returns TRUE if $taxon is accepted, FALSE otherwise.
2716
 */
2717
function _cdm_dataportal_acceptedByCurrentView($taxon) {
2718

    
2719
  $default_classification_uuid = get_current_classification_uuid();
2720

    
2721
  if (isset($taxon->taxonNodes)) {
2722
    $taxon_nodes = $taxon->taxonNodes;
2723
  }
2724
  else {
2725
    $taxon_nodes = cdm_ws_get(CDM_WS_PORTAL_TAXON_TAXONNODES, $taxon->uuid);
2726
  }
2727

    
2728
  if ($taxon->class == "Taxon" && isset($taxon_nodes)) {
2729
    foreach ($taxon_nodes as $node) {
2730
      if($node->class == 'TaxonNodeDto' && isset($node->classificationUUID)){
2731
        // case of TaxonNodeDto
2732
        return $node->classificationUUID == $default_classification_uuid;
2733
      } else if($node->class == 'TaxonNode' && isset($node->classification->uuid)) {
2734
         return $node->classification->uuid == $default_classification_uuid;
2735
      }
2736
    }
2737
  }
2738
  return FALSE;
2739
}
2740

    
2741
/**
2742
 * Checks is the source has one of the given types.
2743
 *
2744
 * @param object $source
2745
 *   The original source entity
2746
 * @param array $types
2747
 *   An array of element of the OriginalSourceType enumeration
2748
 *   If not set the default will be used which is:
2749
 *    - Lineage
2750
 *    - PrimaryMediaSource
2751
 *    - PrimaryTaxonomicSource
2752
 *    - Unknown
2753
 *    - Other
2754
 * @return boolean
2755
 */
2756
  function _is_original_source_type($source, $types = null) {
2757
    // this is the default
2758
    // maybe this should also be put into the settings
2759
    static $default = array(
2760
      OriginalSourceType::Lineage,
2761
      OriginalSourceType::PrimaryMediaSource,
2762
      OriginalSourceType::PrimaryTaxonomicSource,
2763
      OriginalSourceType::Unknown,
2764
      OriginalSourceType::Other,
2765
      OriginalSourceType::Aggregation
2766
    );
2767

    
2768
    if(!$types){
2769
      $types = $default;
2770
    }
2771
    return isset($source->type) && in_array($source->type, $types);
2772
  }
2773

    
2774
/**
2775
 * Collects all the media from a list of description elements.
2776
 *
2777
 * @param array $descriptionElements
2778
 *   The description elements from which to collect the media.
2779
 *
2780
 * @return array
2781
 *   The output with all the collected media.
2782
 */
2783
function cdm_dataportal_media_from_descriptionElements($descriptionElements) {
2784

    
2785
  $outArrayOfMedia = array();
2786

    
2787
  // Avoiding a warning box in Drupal for Flora Malesiana.
2788
  if (isset($descriptionElements) && is_array($descriptionElements)) {
2789
    foreach ($descriptionElements as $descriptionElement) {
2790
      if (isset($descriptionElement->media) && is_array($descriptionElement->media)) {
2791
        foreach ($descriptionElement->media as $media) {
2792
          if (is_object($media)) {
2793
            $outArrayOfMedia[] = $media;
2794
          }
2795
        }
2796
      }
2797
    }
2798
  }
2799
  return $outArrayOfMedia;
2800
}
2801

    
2802

    
2803

    
2804

    
2805
/**
2806
 * Creates a CDM Dynabox.
2807
 *
2808
 * @param string $dynabox_id
2809
 *   a uninque name for tha dynabox, using a cdm entity uuid as id is good practice.
2810
 * @param string $label
2811
 *   The clickable text to show.
2812
 * @param string $content_url
2813
 *   The cdm REST service request url wich will deliver the content to be shown
2814
 *   once the dynabox toggles open.
2815
 * @param string $theme
2816
 *   The theme to be used for rendering the cdm REST service response with is
2817
 *   returned from the $content_url.
2818
 * @param string $link_alt_text
2819
 *   The value for the alt attribute of the dynabox link.
2820
 * @param array $enclosingtags
2821
 *   An array with two elements: $enclosingtags[0] will be used for the dynabox
2822
 *   element itself, $enclosingtags[1] is the tag to be used for the
2823
 *   dynabox_content (optional)
2824
 * @param array $attributes
2825
 * @param $content_element_selector
2826
 *   Optional jQuery selector which can be used to reference a dom element which should
2827
 *   be used as container for the content to be shown. The dynabox-<dynabox id>-content
2828
 *  element will be placed in this container.
2829
 *
2830
 * @param string $open_callback
2831
 *   optional javascript call back function to be triggered after toggling the box to
2832
 *   the open state.
2833
 * @param string $close_callback
2834
 *   optional javascript call back function to be triggered after toggling the box to
2835
 *   the closed state.
2836
 * @return string Returns HTML for a dynabox.
2837
 * Returns HTML for a dynabox.
2838
 */
2839
function cdm_dynabox($dynabox_id, $label, $content_url, $theme, $link_alt_text,
2840
                     $enclosingtags = array('li', 'ul'), $attributes = array(),
2841
                     $content_element_selector = null,
2842
                     $open_callback = 'function(){}', $close_callback = 'function(){}' ) {
2843
  $out = '';
2844

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

    
2848
  if(!array_key_exists('class', $attributes)) {
2849
    $attributes['class'] = ["dynabox"];
2850
  } else {
2851
    $attributes['class'] = array_merge($attributes['class'], ["dynabox"]);
2852
  }
2853
  $attributes['id'][] = 'dynabox-' . $dynabox_id;
2854
  $dynabox_attributes = drupal_attributes($attributes);
2855

    
2856

    
2857
  _add_js_domEvent(); // requires domEvent.js
2858
  drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/cdm_dynabox.js');
2859
  drupal_add_js("
2860
  jQuery(document).ready(
2861
      function() {
2862
        dynabox('". $dynabox_id ."',
2863
          {
2864
            open_callback: " . $open_callback .",
2865
            close_callback: " . $close_callback .
2866
            ($content_element_selector ? ",\n content_container_selector: '" . $content_element_selector . "'" : "") . "
2867
          }
2868
        );
2869
      }
2870
   );",
2871
   array(
2872
    'type'=>'inline',
2873
    'scope'=>'footer'
2874
    )
2875
  );
2876

    
2877

    
2878
  $cdm_proxy_url = url('cdm_api/proxy/' . urlencode($content_url) . "/$theme");
2879
  $out .= '<!-- dynabox for ' . $content_url . ' -->';
2880
  $out .= '<' . $enclosingtags[0] . ' ' .  $dynabox_attributes. '><a href="' . $cdm_proxy_url . '" class="label" alt="' . t('@link-alt-text', array('@link-alt-text' => $link_alt_text)) . '">' . $label . '</a>';
2881
  $out .= '  <' . $enclosingtags[1] . ' id="dynabox-' . $dynabox_id . '-content">';
2882
  $out .= '    <' . $enclosingtags[0] . ' class="dynabox-content-inner">' . loading_image_html() . '</' . $enclosingtags[0] . '>';
2883
  $out .= '    </' . $enclosingtags[1] . '>';
2884
  $out .= '  </' . $enclosingtags[0] . '>';
2885
  $out .= '<!-- dynabox end -->';
2886
  return $out;
2887
}
2888

    
2889
/**
2890
 * Checks whether a feature has any description elements.
2891
 *
2892
 * @param mixed $featureNode
2893
 *   A feature node as produced by the function _mergeFeatureTreeDescriptions().
2894
 *
2895
 * @see _mergeFeatureTreeDescriptions()
2896
 *
2897
 * @return bool
2898
 *   Returns TRUE if the given $featureNode or any of its subordinate nodes
2899
 *   contains at least one non empty TextData or at least one DescriptionElement
2900
 *   of an other type. A TextData element holding a multilanguageText or a
2901
 *   source reference is considered to be not empty.
2902
 *
2903
 * @TODO this function may have become obsolete by the new method of detecting empty blocks,
2904
 *       see $block_content_is_not_empty in make_feature_block_list() and
2905
 *       $feature_block_has_content in compose_feature_block_items_generic
2906
 */
2907
function has_feature_node_description_elements($featureNode) {
2908

    
2909
  if (isset($featureNode->descriptionElements) && is_array($featureNode->descriptionElements) && count($featureNode->descriptionElements) > 0) {
2910
    if(!isset($featureNode->descriptionElements['#type'])){ // #type is used to identify e.g. DTO elements: '#type' => 'DTO'
2911
      foreach ($featureNode->descriptionElements as $descriptionElement) {
2912
        if ($descriptionElement->class != "TextData" || isset($descriptionElement->multilanguageText_L10n->text)
2913
          && $descriptionElement->multilanguageText_L10n->text != ''
2914
          || isset($descriptionElement->sources[0])
2915
          || isset($descriptionElement->media[0]) ) {
2916
          return TRUE;
2917
        }
2918
      }
2919
    }
2920
  }
2921
  else if (isset($featureNode->childNodes) && is_array($featureNode->childNodes)) {
2922
    foreach ($featureNode->childNodes as $child) {
2923
      if (has_feature_node_description_elements($child)) {
2924
        return TRUE;
2925
      }
2926
    }
2927
  }
2928
  return FALSE;
2929
}
2930

    
2931
/**
2932
 * Checks if the current page is a valid taxon portal page and responds with HTTP status 404 (not found) otherwise
2933
 *
2934
 * @param $chapter
2935
 *   The taxon page chapter or part
2936
 */
2937
function cdm_check_valid_taxon_page($chapter){
2938
  static $taxon_tabs = null;
2939

    
2940
  cdm_check_valid_portal_page();
2941

    
2942
  if($taxon_tabs == null){
2943
    $taxon_tabs = array('all', 'description');
2944
    foreach(get_taxon_tabs_list() as $tab){
2945
      $taxon_tabs[] = strtolower($tab);
2946
    }
2947
  }
2948

    
2949
  if(!in_array($chapter, $taxon_tabs)){
2950
    // oops this is not a valid chapter name
2951
    http_response_code(404); // 404 = Not Found
2952
  }
2953

    
2954
}
2955

    
2956
function check_js_devel_mode_disabled() {
2957
  if(variable_get('cdm_js_devel_mode', FALSE)) {
2958
    drupal_set_message(t('The !url1 is enabled.
2959
        WARNING: this is a performance penalty and must be turned off on production websites.', array(
2960
      '!url1' => l('java-script development mode', 'admin/config/cdm_dataportal/settings', array('fragment' => 'edit-cdm-js-devel-mode'))
2961
    )),
2962
      'warning'
2963
    );
2964
  }
2965
}
2966

    
2967
/**
2968
 * Checks if the current page is a valid portal page and responds with HTTP status 404 (not found) otherwise.
2969
 * The test applied by default it a check for the query parameter 'q' ending with a file suffix like '*.*'
2970
 *
2971
 * @param $preg_pattern
2972
 *   Optional regular expression pattern to be used in preg_match().
2973
 */
2974
function cdm_check_valid_portal_page($preg_pattern = null){
2975
  $ends_with_file_suffix_pattern = '/\/[^\.\/]*[\.][^\.\/]*$/';
2976
  if($preg_pattern === null){
2977
    $preg_pattern = $ends_with_file_suffix_pattern;
2978
  }
2979
  if(preg_match($preg_pattern, $_GET['q'])){
2980
    // oops this urls ends with a file_suffix and thus does not refer to a portal page
2981
    http_response_code(404); // 404 = Not Found
2982
    exit('HTTP 404');
2983
  }
2984
  check_js_devel_mode_disabled();
2985
}
2986

    
2987
/**
2988
 * Generates the diff of the texts and presents it in a HTML diff viewer.
2989
 *
2990
 * @param $text_a
2991
 * @param $text_b
2992
 * @return string
2993
 */
2994
function diff_viewer($text_a, $text_b) {
2995

    
2996
  static $diff_viewer_count = 0;
2997

    
2998
  $element_id = 'part_definitions_diff_' . $diff_viewer_count++;
2999

    
3000
  // http://code.stephenmorley.org/php/diff-implementation/
3001
  module_load_include('php', 'cdm_dataportal', 'lib/class.Diff');
3002
  drupal_add_css(drupal_get_path('module',
3003
      'cdm_dataportal') . '/css/diff.css');
3004
  _add_jquery_ui();
3005
  drupal_add_js(
3006
    'jQuery(document).ready( function(){
3007
        jQuery(\'#' . $element_id . '\').accordion({
3008
        collapsible: true,
3009
        active: false,
3010
        fillSpace: true,
3011
        }).children(\'div\').css({ \'height\': \'auto\' });
3012
        jQuery(\'#' . $element_id . ' table.diff\').prepend(\'<thead><tr><th>Default</th><th>User defined<th></th><tr></thead>\');
3013
     });'
3014
    , array(
3015
    'type' => 'inline',
3016
    'scope' => 'footer'
3017
  ));
3018

    
3019
  $diff = Diff::compare($text_a,
3020
    $text_b);
3021
  $diff_viewer_markup = '<div id="' . $element_id . '"><h3>View Diff</h3><div>'
3022
    . Diff::toTable($diff, '', '')
3023
    . '</div></div>';
3024
  return $diff_viewer_markup;
3025
}
3026

    
3027
/**
3028
 * ====== EXPERIMENTAL only used by Euro+Med ===============
3029
 */
3030

    
3031

    
3032
/**
3033
 * See
3034
 *  - https://dev.e-taxonomy.eu/redmine/issues/9233
3035
 *  - https://www.drupal.org/project/feedback_simple
3036
 *  - https://www.drupal.org/node/1299158
3037
 * Implements hook_preprocess_feedback_simple().
3038
 *
3039
 * TODO: move into separate module
3040
 */
3041
function cdm_dataportal_preprocess_feedback_simple(&$variables) {
3042
  // Add modal_forms classes.
3043
  $variables['class'][] = 'ctools-use-modal';
3044
  // Uncomment either small, medium or large.
3045
  $variables['class'][] = 'ctools-modal-modal-popup-small';
3046
  // $variables['class'][] = 'ctools-modal-modal-popup-medium';
3047
  // $variables['class'][] = 'ctools-modal-modal-popup-large';
3048
}
3049

    
3050

    
(10-10/19)