Project

General

Profile

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