Project

General

Profile

Download (38.5 KB) Statistics
| Branch: | Tag: | Revision:
1 6657531f Andreas Kohlbecker
<?php
2
/**
3
 * @file
4
 * Displays a taxon tree in 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 8a4d078d Andreas Kohlbecker
const CDM_TAXONTREE_LINK_TYPE = 'cdm_taxontree_link_type';
21
22 6657531f Andreas Kohlbecker
/**
23 f555e0ec Andreas Kohlbecker
 * Implements hook_menu() 
24
 */
25 6657531f Andreas Kohlbecker
function cdm_taxontree_menu() {
26
27
  $items = array();
28
29
  $items['cdm_taxontree/set'] = array(
30
    'page callback' => 'cdm_taxontree_set',
31 c6fe437b Andreas Kohlbecker
    'access arguments' => array('access cdm content'),
32 6657531f Andreas Kohlbecker
    'type' => MENU_CALLBACK,
33
  );
34
35
  $items['cdm_taxontree/filter'] = array(
36
    'page callback' => 'cdm_taxontree_view_filter',
37 c6fe437b Andreas Kohlbecker
    'access arguments' => array('access cdm content'),
38 6657531f Andreas Kohlbecker
    'type' => MENU_CALLBACK,
39
  );
40
41
  $items['cdm_taxontree/taxonomy/children'] = array(
42
    'page callback' => 'cdm_taxontree_taxonomy_children',
43 c6fe437b Andreas Kohlbecker
    'access arguments' => array('access cdm content'),
44 6657531f Andreas Kohlbecker
    'type' => MENU_CALLBACK,
45
  );
46
47
48
  return $items;
49
}
50
51
/**
52
 * Implements hook_block_info().
53
 */
54
function cdm_taxontree_block_info() {
55 fc13aa30 Andreas Kohlbecker
  $block['cdm_tree'] = array(
56
        "info" => t('CDM taxon tree'),
57
        "cache" => DRUPAL_NO_CACHE
58
      );
59 6657531f Andreas Kohlbecker
60 0375638f Andreas Kohlbecker
  $block['cdm_tree_filters']['info'] = t('Active filters');
61
  $block['cdm_tree_drupal_taxonomy']['info'] = t('Drupal taxonomy tree');
62 6657531f Andreas Kohlbecker
  return $block;
63
}
64
65
/**
66
 * Implements hook_block_view().
67
 */
68
function cdm_taxontree_block_view($delta) {
69
70
  switch ($delta) {
71
    case 'cdm_tree':
72
      $block['subject'] = t('Classification');
73
      $taxonUuid_inFocus = _cdm_get_taxonuuid();
74
      $tree = cdm_taxontree_build_tree($taxonUuid_inFocus);
75 0375638f Andreas Kohlbecker
76
      // cdm_taxontree_magicbox_enable is not yet made available via the settings, so $magicbox_enable is always 0
77 6657531f Andreas Kohlbecker
      $magicbox_enable = variable_get('cdm_taxontree_magicbox_enable', 0);
78
79
      $block['content'] = '';
80 d7588d36 Andreas Kohlbecker
      $taxonomictree_selector_form = cdm_taxonomictree_selector();
81
      if (count($taxonomictree_selector_form['val']['#options']) > 1) {
82
        $block['content'] = drupal_render($taxonomictree_selector_form);
83 6657531f Andreas Kohlbecker
      }
84
      $block['content'] .= theme('cdm_taxontree_block', array(
85
        'tree' => $tree,
86
        'delta' => $delta,
87 0375638f Andreas Kohlbecker
        'magicbox' => $magicbox_enable == 1,
88 6657531f Andreas Kohlbecker
        'show_filter_switch' => FALSE,
89
        // 'cdm_taxontree_node_concept_switch'
90
       ));
91 0375638f Andreas Kohlbecker
      cdm_taxontree_add_js('#block-cdm-taxontree-cdm-tree', $magicbox_enable);
92 6657531f Andreas Kohlbecker
      return $block;
93
94 0375638f Andreas Kohlbecker
    case 'cdm_tree_filters':
95 6657531f Andreas Kohlbecker
      $block['subject'] = t('Active filters');
96
      $block['content'] = cdm_taxontree_view_filter('list');
97
      return $block;
98
99 0375638f Andreas Kohlbecker
    case 'cdm_tree_drupal_taxonomy':
100
      // cdm tree for a drupal taxonomy
101 6657531f Andreas Kohlbecker
      $block['subject'] = t('Taxonomy tree');
102
      $term_inFocus = arg(0) == 'taxonomy' && arg(1) == 'term' ? arg(2) : 0;
103 8a4d078d Andreas Kohlbecker
      $tree = cdm_taxontree_build_tree($term_inFocus, TRUE);
104 6657531f Andreas Kohlbecker
      $block['content'] = theme('cdm_taxontree_block', array(
105
        'tree' => $tree,
106
        'delta' => $delta,
107
        'magicbox' => FALSE,
108
      ));
109 0375638f Andreas Kohlbecker
      cdm_taxontree_add_js('#block-cdm-taxontree-cdm-tree-drupal-taxonomy');
110 6657531f Andreas Kohlbecker
      return $block;
111
112
  }
113
}
114
115
/**
116
 * Implements hook_block_configure().
117
 */
118
function cdm_taxontree_block_configure($delta) {
119 7ac8c744 Andreas Kohlbecker
120
  $form = array();
121 6657531f Andreas Kohlbecker
    switch ($delta) {
122 7ac8c744 Andreas Kohlbecker
      case 'cdm_tree':
123 8a4d078d Andreas Kohlbecker
124
        $form[CDM_TAXONTREE_LINK_TYPE] = array(
125
          '#type' => 'radios',
126
          '#title' => t('Link to '),
127
          '#default_value' => variable_get(CDM_TAXONTREE_LINK_TYPE,  'taxon_page'),
128
          '#options' => array('taxon_page' => 'Taxon pages', 'search_registrations' =>'Registration search page' ),
129
        );
130
131 7ac8c744 Andreas Kohlbecker
        /* TODO The option to use the cdm_taxontree for drupal vocabulaties also has been removed, the below code should be
132
           removed, see #7565
133 6657531f Andreas Kohlbecker
        $vocs = taxonomy_get_vocabularies();
134
        $options = array();
135
        foreach ($vocs as $voc) {
136
          $options[$voc->vid] = $voc->name;
137
        }
138
        $form['vid'] = array(
139
          '#type' => 'select',
140
          '#title' => t('Category'),
141
          '#default_value' => variable_get('cdm_taxontree_block_1_vid', 0),
142
          '#options' => $options,
143
        );
144 7ac8c744 Andreas Kohlbecker
        */
145 6657531f Andreas Kohlbecker
    }
146 7ac8c744 Andreas Kohlbecker
  return $form;
147 6657531f Andreas Kohlbecker
}
148
149
/**
150
 * Implements hook_block_save().
151
 */
152
function cdm_taxontree_block_save($delta, $edit) {
153 8a4d078d Andreas Kohlbecker
154 6657531f Andreas Kohlbecker
    switch ($delta) {
155 8a4d078d Andreas Kohlbecker
      case 'cdm_tree':
156
        variable_set(CDM_TAXONTREE_LINK_TYPE,  $edit[CDM_TAXONTREE_LINK_TYPE]);
157
        /* TODO The option to use the cdm_taxontree for drupal vocabulaties also has been removed, the below code should be
158
           removed, see #7565
159 6657531f Andreas Kohlbecker
        variable_set('cdm_taxontree_block_1_vid', $edit['vid']);
160
        return;
161 8a4d078d Andreas Kohlbecker
        */
162 6657531f Andreas Kohlbecker
    }
163 8a4d078d Andreas Kohlbecker
164 6657531f Andreas Kohlbecker
}
165
166
/**
167
 * Implements hook_help().
168
 */
169
function cdm_taxontree_help($path, $arg) {
170
  switch ($path) {
171
    case 'admin/modules#description':
172
      return t('Defines a selection widget for massive taxonomy structures.');
173
  }
174
}
175
176
/**
177
 * Implements hook_field_info().
178
 */
179
function cdm_taxontree_field_info() {
180
  return array(
181
    'cdm_taxontree' => array('label' => 'CDM Taxontree'),
182
  );
183
}
184
185
/**
186
 * @todo Please document this function.
187
 * @see http://drupal.org/node/1354
188
 */
189
function cdm_taxontree_field_formatter_info() {
190
  return array(
191
    'default' => array(
192
      'label' => t('Default'),
193
      'field types' => array('cdm_taxontree'),
194
    ),
195
    'link' => array(
196
      'label' => t('With link'),
197
      'field types' => array('cdm_taxontree'),
198
    ),
199
  );
200
}
201
202
/**
203
 * Formatters to prepare the correct links for taxa.
204
 */
205
function cdm_taxontree_field_formatter($field, $item, $formatter, $node) {
206
  switch ($formatter) {
207 7ac8c744 Andreas Kohlbecker
    // TODO remove case, see #7565
208 6657531f Andreas Kohlbecker
    case 'link':
209
      $term = taxonomy_term_load($item['tid']);
210
      $taxa = db_query('SELECT name FROM {taxonomy_vocabulary} WHERE vid = :vid', array(':vid' => $term->vid))->fetchField();
211
      switch ($taxa) {
212
        case 'Taxonomy':
213
          $link = 'interest_by_taxonomy/';
214
          break;
215
216
        case 'Georegion':
217
          $link = 'interest_by_georegion/';
218
          break;
219
220
        default:
221
          $link = 'taxonomy/term/';
222
      }
223
      return l($term->name, $link . $term->tid);
224
225
    default:
226
      $name = db_query('SELECT name FROM {taxonomy_term_data} WHERE tid = :tid', array(':tid' => $item['tid']))->fetchField();
227
      return $name;
228
  }
229
}
230
231
232
/**
233
 * Transforms an unpredictably and irregularly nested set of tids (as returned
234
 * from a taxonomy form) into a linear array of tids.
235
 * borrow from taxonomy_browser.module
236
 */
237
function _cdm_taxontree_get_all_children($tids = NULL, $include_children = FALSE) {
238
  static $tid_list = array();
239
240
  if (isset($tids) && is_array($tids)) {
241
242
    foreach ($tids as $key => $tid) {
243
      if (!empty($tid)) {
244
        if (is_array($tid)) {
245
          foreach ($tid as $key2 => $tid2) {
246
            if (!empty($tid2)) {
247
              $tid_list[$tid2] = $tid2;
248
            }
249
          }
250
        }
251
        else {
252
          $tid_list[$tid] = $tid;
253
        }
254
      } /* end !empty */
255
    } /* end foreach */
256
  }
257
258
  if ($include_children) {
259
    foreach ($tid_list as $tid) {
260
      _cdm_taxontree_get_children($tid_list, $tid);
261
    }
262
  }
263
264
  return $tid_list;
265
}
266
267
/**
268
 * @todo Please document this function.
269
 * @see http://drupal.org/node/1354
270
 */
271
function _cdm_taxontree_get_children(&$tid_list, $tid) {
272
  $child_nodes = taxonomy_get_children($tid);
273
  if (!empty($child_nodes)) {
274
    foreach ($child_nodes as $child_tid => $child_term) {
275
      $tid_list[$tid] = $tid;
276
      _cdm_taxontree_get_children($tid_list, $child_tid);
277
    }
278
  }
279
  else {
280
    $tid_list[$tid] = $tid;
281
  }
282
}
283
284
/**
285
 * @todo Please document this function.
286
 * @see http://drupal.org/node/1354
287
 */
288
function cdm_taxontree_set($key, $value) {
289
  if (is_string($key)) {
290
    $_SESSION['cdm']['taxontree'][$key] = $value;
291
  }
292
293
  if ($_GET['destination']) {
294
    $destination = $_GET['destination'];
295
    unset($_GET['destination']);
296
    drupal_goto($destination);
297
  }
298
}
299
300
/**
301
 * Enter description here...
302
 *
303
 * @param string $secUuid
304
 *
305
 * @return unknown
306
 */
307
function cdm_taxontree_secRefTitle_for($secUuid) {
308
309
  $reference = cdm_api_secref_cache_get($secUuid);
310
  if ($reference) {
311
    $cit = $reference->titleCache;
312
  }
313
  else {
314
    $cit = '[no title for:' . $secUuid . ']';
315
  }
316
  return $cit;
317
}
318
319
/**
320
 * Queries the Drupal db for location of a certain block with the given $delta.
321
 *
322
 * @param mixed $delta
323
 *   String or number identifying the block.
324
 *
325
 * @return string
326
 *   The location: left, right or <empty>.
327
 */
328
function _get_block_region($delta) {
329
  global $user, $theme_key;
330
  // Comment @WA you need to repace this with db_select if other modules
331
  // should be able to overrride this.
332
  $result = db_query("
333
    SELECT DISTINCT b.region
334
    FROM {block} b
335
    LEFT JOIN {block_role} r
336
    ON b.module = r.module
337
    AND b.delta = r.delta
338
    WHERE b.theme = :b.theme
339
    AND b.status = :b.status
340
    AND (r.rid IN (:r.rid) OR r.rid IS NULL)
341 50172c55 Andreas Kohlbecker
    AND b.module = :b.module
342 6657531f Andreas Kohlbecker
    AND b.delta = :b.delta
343
  ", array(
344
    ':b.theme' => $theme_key,
345
    ':b.status' => 1,
346
    ':r.rid' => implode(',', array_keys($user->roles)),
347
    ':b.module' => 'cdm_taxontree',
348
    ':b.delta' => $delta,
349
  ))->fetch();
350
  return $result['region'];
351
}
352
353
/**
354
 * Enter description here...
355
 *
356
 * @return unknown
357
 */
358
function _get_compact_mode() {
359
  if (!isset($_SESSION['cdm']['taxontree']['compact_mode'])) {
360
    $_SESSION['cdm']['taxontree']['compact_mode'] = 'expanded';
361
  }
362
  return $_SESSION['cdm']['taxontree']['compact_mode'];
363
}
364
365
/**
366
 * Converts Drupal taxonomy terms into preliminary cdm tree nodes.
367
 *
368
 * An array of drupal taxonomy terms are converted into an
369
 * array of partially instantiated cdm tree nodes by adding the fields
370
 * relevant for tree node processing in cdm_taxontree.
371
 *
372
 * term => cdm tree node
373
 * ------------------------------------
374
 * tid -> uuid
375
 * name -> titleCache
376
 * taggedName
377
 * secUuid
378
 * isAccepted
379
 * taxonomicChildrenCount
380
 * alternativeConceptRefs
381
 *
382
 * @param array $terms
383 7ac8c744 Andreas Kohlbecker
 *
384
 * TODO remove method, see #7565
385 6657531f Andreas Kohlbecker
 */
386
function cdm_taxontree_terms2treenodes(&$terms) {
387
  foreach ($terms as &$term) {
388
    $term->uuid = $term->tid;
389
    $term->titleCache = $term->name;
390
    $term->taxonomicChildrenCount = count(taxonomy_get_children($term->tid, $term->vid));
391
  }
392
  return $terms;
393
}
394
395
/**
396
 * Enter description here...
397
 *
398
 * @param unknown_type $tid
399
 * @param unknown_type $vid
400
 * @param unknown_type $theme
401 a3228c59 Andreas Kohlbecker
 *
402
 * * TODO remove method, see #7565
403 6657531f Andreas Kohlbecker
 */
404
function cdm_taxontree_taxonomy_children($tid, $vid, $theme) {
405
  $args = func_get_args();
406
  $tid = array_shift($args);
407
  $vid = array_shift($args);
408
  $theme = array_shift($args);
409
410
  $children = cdm_taxontree_get_children($tid, $vid);
411
  $children = cdm_taxontree_terms2treenodes($children);
412
  array_unshift($args, $theme, $children);
413
  print call_user_func_array('theme', $args);
414
}
415
416
/**
417 50172c55 Andreas Kohlbecker
 * Get the root level of the tree
418 6657531f Andreas Kohlbecker
 */
419
function cdm_taxontree_get_root($vid = NULL) {
420
  if (is_numeric($vid)) {
421 a3228c59 Andreas Kohlbecker
    //  TODO remove case, see #7565
422 6657531f Andreas Kohlbecker
    // vid, $parent = 0, $depth = -1, $max_depth = NULL) {
423
    $terms = taxonomy_get_tree($vid, 0, 1);
424
    return cdm_taxontree_terms2treenodes($terms);
425
  }
426
  else {
427 50172c55 Andreas Kohlbecker
    return cdm_ws_taxonomy_root_level();
428 6657531f Andreas Kohlbecker
  }
429
}
430
431
/**
432
 * @todo Enter description here...
433
 *
434
 * @param unknown_type $uuid
435
 * @param unknown_type $vid
436
 *
437
 * @return unknown
438
 */
439
function cdm_taxontree_get_children($uuid, $vid = NULL) {
440
441
  if (is_numeric($vid)) {
442 a3228c59 Andreas Kohlbecker
    //  TODO remove case, see #7565
443 6657531f Andreas Kohlbecker
    $terms = taxonomy_get_children($uuid, $vid);
444
    return cdm_taxontree_terms2treenodes($terms);
445
  }
446
  else {
447
    // FIXME Replace $uuid by path of parent $uuids.
448 50172c55 Andreas Kohlbecker
    return cdm_ws_taxonomy_root_level($uuid);
449 6657531f Andreas Kohlbecker
  }
450
}
451
452
/**
453
 * @todo Enter description here...
454
 *
455
 * @param unknown_type $uuid
456
 *
457
 * @return unknown
458
 */
459
function cdm_taxontree_get_parents($uuid) {
460
461
  if (!is_uuid($uuid)) {
462
    // Using Drupal taxonomy.
463 a3228c59 Andreas Kohlbecker
    //  TODO remove case, see #7565
464 6657531f Andreas Kohlbecker
    $terms = taxonomy_get_parents($uuid);
465
    array_push($terms, taxonomy_term_load($uuid));
466
    $terms = array_reverse($terms);
467
    return cdm_taxontree_terms2treenodes($terms);
468
  }
469
  else {
470
    // Using cdm.
471
    $terms = cdm_ws_taxonomy_pathFromRoot($uuid);
472
    if (!$terms) {
473
      return;
474
    }
475
    $terms = array_reverse($terms);
476
    return $terms;
477
  }
478
}
479
480
/**
481
 * Builds a tree of TaxonNode instances
482
 *
483
 * When building the tree, the instances are extended by some fields:
484
 *  - $node->filter: values ( 'on', 'excluded', 'included' )
485
 *  - $node->expanded: values ( 'expanded', 'collapsed' )
486
 *
487
 * @param string $taxonUuid
488
 *
489
 * @return unknown
490
 */
491
function cdm_taxontree_build_tree($taxonUuid = NULL, $hideOtherConcepts = TRUE, $vid = NULL) {
492
  // TODO Remove $hideOtherConcepts from method signature.
493
  if (is_null($vid)) {
494 a3228c59 Andreas Kohlbecker
    //  TODO remove case, see #7565
495 6657531f Andreas Kohlbecker
    if ($taxonUuid) {
496
      $taxon = cdm_ws_get(CDM_WS_PORTAL_TAXON, $taxonUuid);
497
    }
498
499
    $compact_tree = cdm_taxontree_filters_active() && _get_compact_mode() != 'expanded';
500
  }
501
  // Valid compact_modes: 'expanded', 'compact', 'flattened'.
502
  // Get the root level.
503 a3228c59 Andreas Kohlbecker
504
  $root_tree = cdm_taxontree_get_root($vid); //  TODO remove $vid, see #7565 ?
505 6657531f Andreas Kohlbecker
  /*
506
  if(!$root_tree || !is_array($root_tree)){
507
    return array();
508
  }
509
  */
510
  $root_tree = _cdm_resultset2nodelist($root_tree, cdm_taxontree_filters_active());
511
512
  if (cdm_taxontree_filters_active()) {
513
    // The paths up to active filters are inactive in the user interface and
514
    // thus cannot be browsed by expanding nodes.
515
    // Therefore we need to build up the branches for all nodes which are set
516
    // as filters. The branches are merged with the root.
517
    foreach (cdm_taxontree_filters_get() as $uuid => $filter) {
518
      $branch = cdm_taxontree_build_path($uuid, TRUE, ($compact_tree === FALSE ? TRUE : NULL));
519
      $root_tree = _cdm_taxontree_merge($root_tree, $branch);
520
    }
521
  }
522
523
  // Build the the branch for the focused node and merge it with the root.
524
  if ($taxonUuid) {
525 7663cd0b Andreas Kohlbecker
    $taxon_in_current_tree = taxon_in_current_classification($taxonUuid);
526 6657531f Andreas Kohlbecker
    if ($taxon_in_current_tree) {
527 0af3ce28 Andreas Kohlbecker
      $branch = cdm_taxontree_build_path($taxonUuid, NULL, (cdm_taxontree_filters_active() ? NULL : TRUE));
528 6657531f Andreas Kohlbecker
      $root_tree = _cdm_taxontree_merge($root_tree, $branch);
529
    }
530
  }
531
532
   // Reorder siblings & populate expanded nodes with children and propagate
533
   // the filter attribute.
534
   $root_tree = cdm_taxontree_populate($root_tree, $compact_tree === FALSE);
535
536
  // Flatten tree.
537
  if ($compact_tree) {
538
    if (_get_compact_mode() == 'flattened') {
539
      $root_tree = cdm_taxontree_flatten($root_tree);
540
    }
541
    elseif (_get_compact_mode() == 'compact') {
542
      foreach ($root_tree as $uuid => $node) {
543
        if ($node->filter == 'excluded' && !$node->children) {
544
          unset($root_tree[$uuid]);
545
        }
546
      }
547
    }
548
  }
549
550
  return $root_tree;
551
}
552
553
/**
554
 * Builds the specific branch path for $taxonUuid.
555
 *
556
 * The branch path reaches from the parent root node of
557
 * $taxonUuid up to $taxonUuid.
558
 *
559
 * @param string $taxonUuid
560
 *   The UUID of the taxon.
561
 * @param bool $is_filter_path
562
 *   Whether the upmost node of this path is mapped by an active filter.
563
 * @param bool $is_expanded
564
 *   Whether all nodes along the tree are expanded.
565
 *
566
 * @return mixed
567
 *   A subtree.
568
 */
569 0af3ce28 Andreas Kohlbecker
function cdm_taxontree_build_path($taxonUuid, $is_filter_path = NULL, $is_expanded = NULL) {
570 6657531f Andreas Kohlbecker
571
  $branch_path = array();
572
573
  $parents = cdm_taxontree_get_parents($taxonUuid);
574
  if (!$parents) {
575
    if ($is_filter_path) {
576
      // \remove invalid filter.
577
      cdm_taxontree_filters_remove($taxonUuid);
578
    }
579
    return FALSE;
580
  }
581
582
  $parents = _cdm_resultset2nodelist($parents, NULL);
583
  $lastParent = NULL;
584
585
  foreach ($parents as $pnode) {
586
    if ($lastParent) {
587
      $pnode->children = array($lastParent->taxonUuid => $lastParent);
588
      if (!is_null($is_filter_path)) {
589
        $pnode->filter = ($is_filter_path ? 'excludes' : 'included');
590
      }
591
      if (!is_null($is_expanded)) {
592
        $pnode->expanded = ($is_expanded ? 'expanded' : 'collapsed');
593
      }
594
    }
595
    else {
596
      // The uppermost node of branch.
597
      if (!is_null($is_filter_path)) {
598
        $pnode->filter = ($is_filter_path ? 'on' : 'includes');
599
      }
600
      $pnode->expanded = ($pnode->taxonomicChildrenCount ? 'expanded' : 'collapsed');
601
    }
602
    $lastParent = $pnode;
603
  }
604
  $branch_path[$pnode->taxonUuid] = $pnode;
605
  return $branch_path;
606
}
607
608
/**
609
 * Order a tree and populate expanded nodes.
610
 *
611
 * Performs two steps on each level of the tree:
612
 *  1. Reorder siblings except root (which is expected to be ordered already)
613
 *     alphabetically.
614
 *  2. Populate children of expanded nodes  & propagate the filter attribute
615
 *
616
 * @param array $tree
617
 * @param unknown $expand_excluded
618
 * @param unknown $filter_default
619
 *
620
 * @return unknown
621
 */
622
function cdm_taxontree_populate($tree, $expand_excluded, $filter_default = NULL) {
623
624
  if (!is_array($tree)) {
625
    return FALSE;
626
  }
627
  foreach (array_keys($tree) as $uuid) {
628
629 b5519d3a Andreas Kohlbecker
    if (!isset($tree[$uuid]->filter)) {
630 6657531f Andreas Kohlbecker
      $tree[$uuid]->filter = $filter_default;
631
    }
632
633
    if (isset($tree[$uuid]->expanded) && $tree[$uuid]->expanded == 'expanded' && ($expand_excluded || $tree[$uuid]->filter != 'excluded')) {
634
635
      if (isset($tree[$uuid]->vid)) {
636 7ac8c744 Andreas Kohlbecker
        //  TODO remove case, see #7565
637 6657531f Andreas Kohlbecker
        $children = cdm_taxontree_get_children($uuid, $tree[$uuid]->vid);
638
      }
639
      else {
640
        $children = cdm_taxontree_get_children($uuid);
641
      }
642
      $children = _cdm_resultset2nodelist($children, ($tree[$uuid]->filter == 'excludes'));
643
644
      // Store the children of the node for later processing.
645
      if (isset($tree[$uuid]->children) && is_array($tree[$uuid]->children)) {
646
        $pnode_children = $tree[$uuid]->children;
647
      }
648
      else {
649
        $pnode_children = FALSE;
650
      }
651
      // Replace the children by the newly retrieved child nodes.
652
      $tree[$uuid]->children = $children;
653
654
      if ($pnode_children) {
655
        // Recurse into the childtree which was stored before.
656
        $pnode_children = cdm_taxontree_populate($pnode_children, $expand_excluded, $tree[$uuid]->filter);
657
        // Recombine.
658
        foreach ($pnode_children as $childUuid => $cnode) {
659
          $tree[$uuid]->children[$childUuid] = $cnode;
660
        }
661
      }
662
    }
663
    else {
664
      // Reorder nodes which are not expanded, expanded nodes are reordered
665
      // implicitly above.
666
      if (isset($tree[$uuid]->children) && count($tree[$uuid]->children) > 1) {
667
        // Copy the children into an array which can be sorted by its keys.
668
        $ordered = array();
669
        foreach ($tree[$uuid]->children as $cnode) {
670
          // Concatenate full name and uid.
671
          $reordered[str_pad($cnode->titleCache, 255, '-') . $cnode->taxonUuid] = $cnode;
672
        }
673
674
        // Sort.
675
        ksort($reordered);
676
677
        // Move the children back into the parent node.
678
        $tree[$uuid]->children = array();
679
        foreach ($reordered as $cnode) {
680
          $tree[$uuid]->children[$cnode->taxonUuid] = $cnode;
681
        }
682
      }
683
      if (!isset($tree[$uuid]->children)) {
684
        $tree[$uuid]->children = FALSE;
685
      }
686
      $tree[$uuid]->children = cdm_taxontree_populate($tree[$uuid]->children, $expand_excluded, $tree[$uuid]->filter);
687
    }
688
  }
689
  return $tree;
690
}
691
692
/**
693
 * Enter description here...
694
 *
695
 * @param array $tree
696
 *   Tree to flatten.
697
 * @param array $new_root
698
 *
699
 * @return unknown
700
 */
701
function cdm_taxontree_flatten($tree, &$new_root = NULL) {
702
  if (empty($new_root)) {
703
    $new_root = array();
704
  }
705
  foreach ($tree as $node) {
706
    if ($node->filter == 'on') {
707
      $new_root[$node->taxonUuid] = $node;
708
    }
709
    elseif (is_array($node->children)) {
710
      cdm_taxontree_flatten($node->children, $new_root);
711
    }
712
  }
713
  return $new_root;
714
}
715
716
/**
717
 * Merge a branch into a tree.
718
 *
719
 * Merge a branch into a tree whereas the tree dominated the branch except
720
 * nodes having property filter set to "on". These always dominate
721
 * nevertheless if they are in tree or branch.
722
 *
723
 * @param array $tree
724
 *   The dominant tree.
725
 * @param array $branch
726
 *   The tree to be merged in.
727
 *
728
 * @return array
729
 *   The merged $tree.
730
 */
731
function _cdm_taxontree_merge($tree, $branch) {
732
733
  if (!$branch || !is_array($branch)) {
734
    return $tree;
735
  }
736
737
  if (!is_array($tree)) {
738
    return;
739
  }
740
741
  foreach (array_keys($tree) as $uuid) {
742
    // Check if node exists in $branch.
743
    if (!empty($branch[$uuid])) {
744
      // Preserve filter property.
745
      if (isset($tree[$uuid]->filter) && !(isset($branch[$uuid]->filter) && $branch[$uuid]->filter == 'on')) {
746
        $branch[$uuid]->filter = $tree[$uuid]->filter;
747
      }
748
      elseif (isset($branch[$uuid]->filter)) {
749
        $tree[$uuid]->filter = $branch[$uuid]->filter;
750
      }
751
      // Preserve expanded property.
752
      if (isset($tree[$uuid]->expanded)) {
753
        $branch[$uuid]->expanded = $tree[$uuid]->expanded;
754
      }
755
      elseif (isset($branch[$uuid]->expanded)) {
756
        $tree[$uuid]->expanded = $branch[$uuid]->expanded;
757
      }
758
      // $Uuid exists check if the node in tree1 or tree2 contains children.
759
      if (isset($branch[$uuid]->children) && is_array($branch[$uuid]->children) && isset($tree[$uuid]->children) && is_array($tree[$uuid]->children)) {
760
        // Merge recursive.
761
        $tree[$uuid]->children = _cdm_taxontree_merge($tree[$uuid]->children, $branch[$uuid]->children);
762
      }
763
      elseif (isset($branch[$uuid]->children) && is_array($branch[$uuid]->children)) {
764
        $tree[$uuid] = $branch[$uuid];
765
      }
766
      unset($branch[$uuid]);
767
    }
768
  }
769
  // Append remaining items from branch to tree.
770
  foreach (array_keys($branch) as $uuid) {
771
    $tree[$uuid] = $branch[$uuid];
772
  }
773
  return $tree;
774
}
775
776
777
/**
778 43251923 Andreas Kohlbecker
 * Alter a resultset into an array of TreeNode instances with taxonUuid as keys.
779 6657531f Andreas Kohlbecker
 *
780
 * Replaces the keys of an array of TreeNode instances
781
 * by the $treenode->taxonUuid of the single array elements and sets
782
 * additional fields.
783
 *
784
 * @param array $resultset
785
 *   Array of TreeNode instances as +returned by the cdm web service.
786
 * @param mixed $excluded
787
 *   Whether the $resultset is included by a active filter. Is ignored if NULL.
788
 * @param mixed $expanded
789
 *   Whether the children of the nodes in the $resultset are expanded or not.
790
 *   Is ignored if NULL.
791
 *
792
 * @return array
793
 *   A tree of TreeNode instances with altered keys.
794
 */
795
function _cdm_resultset2nodelist($resultset, $excluded = NULL, $expanded = NULL) {
796
797
  if (!is_array($resultset)) {
798
    return FALSE;
799
  }
800
801
  $tree = array();
802
  foreach ($resultset as $treeNode) {
803
    if (!is_null($excluded)) {
804
      $treeNode->filter = ($excluded ? 'excluded' : 'included');
805
    }
806
    if (!is_null($expanded)) {
807
      $treeNode->expanded = ($expanded ? 'expanded' : 'collapsed');
808
    }
809
    $tree[$treeNode->taxonUuid] = $treeNode;
810
  }
811
  return $tree;
812
}
813
814
/**
815 0375638f Andreas Kohlbecker
 * Adds all java script files and also initializes the cdm_taxontree java script behaviours
816
 *
817
 * @param string $parent_element_selector
818
 *    jQuery selector of a parent element of the cdm_taxontree, This is usually a drupal block id
819
 *    selector: #block-cdm-taxontree-cdm-tree or #block-cdm-taxontree-cdm-tree-drupal-taxonomy
820
 *
821
 * @param bool $magicbox_enable
822
 *    If set to TRUE the cdm_taxontree will get the magic box behavoir, which means that it
823
 *    will extend on mouse over events in order to
824
 *    show the entrys without truncation through cropping
825 6657531f Andreas Kohlbecker
 */
826 0375638f Andreas Kohlbecker
function cdm_taxontree_add_js($parent_element_selector, $magicbox_enable = FALSE) {
827
828 6657531f Andreas Kohlbecker
  $path_cdm_taxontree = drupal_get_path('module', 'cdm_taxontree');
829
  $path_preferred_module = drupal_get_path('module', 'cdm_dataportal') ? drupal_get_path('module', 'cdm_dataportal') : $path_cdm_taxontree;
830
  drupal_add_css($path_cdm_taxontree . '/cdm_taxontree.css');
831
  drupal_add_js($path_cdm_taxontree . '/js/cdm_taxontree.js');
832 b0adfd32 Andreas Kohlbecker
833 0375638f Andreas Kohlbecker
  drupal_add_js('
834
      jQuery(document).ready(function()
835
      {
836 b7b43dc2 Andreas Kohlbecker
        jQuery(\'' . $parent_element_selector . '\').cdm_taxontree();
837 0375638f Andreas Kohlbecker
      });
838
      ', array('type' => 'inline'));
839 6657531f Andreas Kohlbecker
}
840
841 0375638f Andreas Kohlbecker
// ------------------------ THEME --------------------------- //
842 6657531f Andreas Kohlbecker
843
/**
844
 *  Returns HTML for a Taxontree block.
845
 *
846
 * @param array $variables
847
 *   An associative array containing:
848
 *   - tree: The tree of TreeNode to be displayed.
849
 *   - magicbox: Boolean. If TRUE, the tree will be embedded into a set of
850
 *       div tags which allow the tree to expand and overlap other content.
851
 *       This is useful if the node titles are quite long or if the tree is
852
 *       nested deeply. If $magicbox ist set to the delta of the containing
853
 *       block the direction into which the box expands is dependent on the
854
 *       region in which the block is located. See also $left_expand_region
855
 *       in this function!
856
 *   - show_filter_switch: The tree can offer buttons to add a node to a set of
857
 *       filters which can then be applied to the tree to limit the visible
858
 *       subtrees and thus to compact the tree. Three different compact modes
859
 *       are available.
860
 *   - tree_node_callback: Name of a callback method which will be called
861
 *       for each node in theme_cdm_taxontree_node(). The output of this
862
 *       callback, which takes the $node object as single arument, is appended
863
 *       to the end of the rendered node.
864
 *
865
 * @ingroup themeable
866
 */
867
function theme_cdm_taxontree_block($variables) {
868
  $tree = $variables['tree'];
869
  $delta = $variables['delta'];
870
  $magicbox = $variables['magicbox'];
871
  $show_filter_switch = $variables['show_filter_switch'];
872
  $tree_node_callback = $variables['tree_node_callback'];
873
874
  // THEMERS: change the line below according to the
875
  // specific regions of your theme.
876
  $left_expand_region = 'right';
877
878
  $out = '';
879
  if (cdm_taxontree_filters_active()) {
880
    $out .= theme('cdm_taxontree_controller', array('compact_mode' => _get_compact_mode()));
881
  }
882 0375638f Andreas Kohlbecker
  $region = null;
883 6657531f Andreas Kohlbecker
  if (!empty($magicbox)) {
884
    if (is_numeric($magicbox) || is_string($magicbox)) {
885
      $region = _get_block_region($magicbox);
886
    }
887
    // The magicbox expands to the right by default,
888
    // if the class 'expand-left' to  the cdm_taxontree_scroller_x the box will
889
    // expand to the left.
890 0375638f Andreas Kohlbecker
    $expand_direction = ($region == 'right' ? 'expand-left' : '');
891 6657531f Andreas Kohlbecker
    $out .= '<div class="cdm_taxontree_scroller_x ' . $expand_direction . '"><div class="cdm_taxontree_container"><div class="cdm_taxontree_scroller_y">';
892
  }
893
  else {
894
    $out .= '<div class="cdm_taxontree_scroller_xy">';
895
  }
896
897
  $out .= theme('cdm_taxontree', array(
898
    'tree' => $tree,
899
    'filterIncludes' => !cdm_taxontree_filters_active(),
900
    'show_filter_switch' => $show_filter_switch,
901
    'tree_node_callback' => $tree_node_callback,
902
    ));
903
904
  if ($magicbox) {
905
    $out .= '</div></div></div>';
906
  }
907
  else {
908
    $out .= '</div>';
909
  }
910
  return $out;
911
}
912
913
/**
914
 * @todo Please document this function.
915
 * @see http://drupal.org/node/1354
916
 */
917
function theme_cdm_taxontree_controller($variables) {
918
  $compact_mode = $variables['compact_mode'];
919
920
  static $modes = array('expanded', 'compact', 'flattened');
921
922
  $out = '<div class="settings">';
923
  foreach ($modes as $mode) {
924
    if ($compact_mode == $mode) {
925 7cc085da Andreas Kohlbecker
      $out .= t('@mode', array('@mode' => $mode));
926 6657531f Andreas Kohlbecker
    }
927
    else {
928 7cc085da Andreas Kohlbecker
      $out .= l(t('@mode', array('@mode' => $mode)), 'cdm_taxontree/set/compact_mode/' . $mode, array('query' => drupal_get_destination()));
929 6657531f Andreas Kohlbecker
    }
930
    $out .= ' ';
931
  }
932
933
  return $out . '</div>';
934
}
935
936
/**
937
 * @todo Please document this function.
938
 * @see http://drupal.org/node/1354
939
 */
940
function theme_cdm_taxontree($variables) {
941
  $tree = $variables['tree'];
942
  $filterIncludes = $variables['filterIncludes'];
943
  $show_filter_switch = $variables['show_filter_switch'];
944
  $tree_node_callback = $variables['tree_node_callback'];
945
  $element_name = $variables['element_name'];
946
947 38da4e54 Andreas Kohlbecker
  if(isset($tree->records)){
948
    // unwrap from pager object
949
    $tree = $tree->records;
950
  }
951
952 6657531f Andreas Kohlbecker
  if (!is_array($tree)) {
953
    return FALSE;
954
  }
955
956
  if (is_null($filterIncludes)) {
957
    // Set $filterIncludes TRUE if no filters are set.
958
    $filterIncludes = !cdm_taxontree_filters_active();
959
  }
960
961
  // Append element name to get multiple taxontrees on one page working.
962 b0adfd32 Andreas Kohlbecker
  $out = '<ul class="taxon-nodes ' . (($element_name) ? ' ' . $element_name : '') . '">';
963 6657531f Andreas Kohlbecker
  foreach ($tree as $node) {
964 38da4e54 Andreas Kohlbecker
    if($node == null){
965
      continue;
966
    }
967 6657531f Andreas Kohlbecker
    $out .= theme('cdm_taxontree_node', array(
968
      'node' => $node,
969
      'filterIncludes' => $filterIncludes,
970
      'show_filter_switch' => $show_filter_switch,
971 0af3ce28 Andreas Kohlbecker
      'tree_node_callback' => $tree_node_callback
972 6657531f Andreas Kohlbecker
      ));
973
  }
974
  $out .= '</ul>';
975
  return $out;
976
}
977
978
/**
979
 * @todo Please document this function.
980
 * @see http://drupal.org/node/1354
981
 */
982
function theme_cdm_taxontree_node($variables) {
983
  $node = $variables['node'];
984
  $filterIncludes = $variables['filterIncludes'];
985
  $show_filter_switch = $variables['show_filter_switch'];
986
  $tree_node_callback = $variables['tree_node_callback'];
987 0af3ce28 Andreas Kohlbecker
988 6657531f Andreas Kohlbecker
  $is_leaf = !$node->taxonomicChildrenCount || $node->taxonomicChildrenCount == 0;
989
  $is_expanded = isset($node->expanded) && $node->expanded = 'expanded';
990
991 0af3ce28 Andreas Kohlbecker
  $focused_taxon_uuid = get_current_taxon_uuid();
992
993 8a4d078d Andreas Kohlbecker
  $path = '';
994
  $query = array();
995 6657531f Andreas Kohlbecker
  if (isset($node->tid)) {
996 8a4d078d Andreas Kohlbecker
    //  TODO remove case, see #7565
997 6657531f Andreas Kohlbecker
    $node_name = $node->name;
998
    $path = "taxonomy/term/" . $node->tid;
999
    // disable filterswitch
1000
1001
    $show_filter_switch = FALSE;
1002
1003
  }
1004
  elseif (module_exists('cdm_dataportal')) {
1005
    $node_name = cdm_dataportal_shortname_of($node);
1006 8a4d078d Andreas Kohlbecker
    $link_type = variable_get(CDM_TAXONTREE_LINK_TYPE,  'taxon_page');
1007
    switch($link_type){
1008
      case 'taxon_page':
1009
        $path = path_to_taxon($node->taxonUuid);
1010
        break;
1011
      case 'search_registrations':
1012
        $path = "cdm_dataportal/search/registration";
1013
        $query['taxon_name'] = $node->titleCache;
1014
        break;
1015
      default:
1016
        $path = "invalid_cdm_taxontree_linktype";
1017
    }
1018 6657531f Andreas Kohlbecker
  }
1019
  else {
1020
    $node_name = "module cdm_dataportal missing";
1021
    $path = "";
1022
  }
1023
1024
  if ($filterIncludes) {
1025 8a4d078d Andreas Kohlbecker
    $name = l($node_name, $path, array('query' => $query));
1026 6657531f Andreas Kohlbecker
    // No names for terms in filter widget; as discussed with A. Müller.
1027
    // $name = '';
1028
    $filter_class = 'filter_included';
1029
  }
1030
  else {
1031
    if ($node->filter == 'on') {
1032 8a4d078d Andreas Kohlbecker
      $name = l($node_name, $path, array('query' => $query));
1033 6657531f Andreas Kohlbecker
      $filter_class = 'filter_on';
1034
    }
1035
    else {
1036 0af3ce28 Andreas Kohlbecker
      $name = $node_name;
1037 6657531f Andreas Kohlbecker
      $filter_class = 'filter_excluded';
1038
    }
1039
  }
1040
  $nextLevelIncluded = isset($node->filter) && $node->filter == 'on' || $filterIncludes;
1041
1042
  $ahah_url = FALSE;
1043
  if (!$is_leaf && !$is_expanded && $filter_class != 'filter_excluded') {
1044
    if (isset($node->tid)) {
1045 7ac8c744 Andreas Kohlbecker
      //  TODO remove case, see #7565
1046 6657531f Andreas Kohlbecker
      $ahah_url = url('cdm_taxontree/taxonomy/children/' . $node->tid . '/' . $node->vid . '/cdm_taxontree/' . ($nextLevelIncluded ? 1 : 0) . '/' . ($show_filter_switch ? 1 : 0) . '/' . $tree_node_callback);
1047
    }
1048
    elseif (module_exists('cdm_dataportal')) {
1049 50172c55 Andreas Kohlbecker
      $ws_url = cdm_compose_taxonomy_root_level_path($node->taxonUuid);
1050 6657531f Andreas Kohlbecker
      $ahah_url = url('cdm_api/proxy/' . urlencode($ws_url) . '/cdm_taxontree/' . ($nextLevelIncluded ? 1 : 0) . '/' . ($show_filter_switch ? 1 : 0) . '/' . $tree_node_callback);
1051
    }
1052
  }
1053
1054
  // List item.
1055
  $out = '<li class="'
1056 0af3ce28 Andreas Kohlbecker
    . ($node->taxonUuid == $focused_taxon_uuid ? 'focused ' : '')
1057 6657531f Andreas Kohlbecker
    . ($is_leaf ? 'leaf ' : ($is_expanded ? 'expanded ' : 'collapsed '))
1058
    . $filter_class . '"'
1059 cbc77aa9 Andreas Kohlbecker
    . ($ahah_url ? ' data-cdm-ahah-url="' . $ahah_url . '"' : '')
1060 6657531f Andreas Kohlbecker
    . '>';
1061
1062
  if ($show_filter_switch) {
1063
    // Filter icon.
1064
    $out .= theme('cdm_taxontree_node_filter_switch', array('node' => $node, 'filter_class' => $filter_class));
1065
  }
1066
1067
  // Taxon name.
1068 4b3be949 Andreas Kohlbecker
  $out .= '<span class="' . html_class_attribute_ref($node) . '">' . $name . '</span>';
1069 6657531f Andreas Kohlbecker
1070
  // Concept_switch or other theme callbacks.
1071
  if ($tree_node_callback) {
1072
     $out .= theme($tree_node_callback, array('node' => $node));
1073
  }
1074
1075
  if (isset($node->children) && is_array($node->children)) {
1076
    $out .= theme('cdm_taxontree', array(
1077
      'tree' => $node->children,
1078
      'filterIncludes' => $nextLevelIncluded,
1079
      'show_filter_switch' => $show_filter_switch,
1080
      'tree_node_callback' => $tree_node_callback,
1081
    ));
1082
  }
1083
  $out .= '</li>';
1084
1085
  return $out;
1086
}
1087
1088
/**
1089
 * @todo Please document this function.
1090
 * @see http://drupal.org/node/1354
1091
 */
1092
function theme_cdm_taxontree_node_filter_switch($variables) {
1093
  $node = $variables['node'];
1094
  $filter_class = $variables['filter_class'];
1095
  if (!module_exists('cdm_dataportal')) {
1096
    return '';
1097
  }
1098
1099
  $out = '';
1100
  switch ($filter_class) {
1101
    case 'filter_included':
1102
      $filter_icon = 'visible_implicit_small.gif';
1103
      break;
1104
1105
    case 'filter_excluded':
1106
      $filter_icon = 'invisible_small.gif';
1107
      break;
1108
1109
    case 'filter_on':
1110
      $filter_icon = 'visible_small.gif';
1111
      break;
1112
1113
  }
1114
1115
  $filter_op = $node->filter == 'on' ? 'remove' : 'add';
1116
1117
  $out .= '&nbsp;'
1118 d5f0e39e Andreas Kohlbecker
    . l('<img src="' . base_path() . drupal_get_path('module', 'cdm_taxontree') . '/' . $filter_icon . '" alt="[f]" />',
1119 6657531f Andreas Kohlbecker
        'cdm_taxontree/filter/' . $filter_op . '/' . $node->taxonUuid, array(
1120
          'attributes' => array('class' => 'filter_' . $filter_op),
1121
          'query' => 'destination=' . path_to_taxon($node->taxonUuid),
1122
          'fragment' => NULL,
1123
          'absolute' => TRUE,
1124
          'html' => TRUE,
1125
        ));
1126
1127
  return $out;
1128
}
1129
1130
/**
1131
 * Returns HTML for a Taxontree-node concept switch.
1132
 *
1133
 * @param array $variables
1134
 *   An associative array containing:
1135
 *   - node: The node object.
1136
 *
1137
 * @ingroup themeable
1138
 */
1139
function theme_cdm_taxontree_node_concept_switch($variables) {
1140
  $node = $variables['node'];
1141
  $out = '';
1142
1143
  if (isset($node->alternativeConceptRefs[0])) {
1144
    $out = l(
1145 d5f0e39e Andreas Kohlbecker
      '<img src="' . base_path() . drupal_get_path('module', 'cdm_taxontree') . '/concept_switch.gif" alt="[-&gt;]" />',
1146 6657531f Andreas Kohlbecker
      'cdm_dataportal/taxon/alternative/' . $node->taxonUuid, array(
1147
        'attributes' => array('rel' => 'cdm_dataportal/taxon/alternative/' . $node->taxonUuid, 'class' => 'concept_switch'),
1148
        'query' => NULL,
1149
        'fragment' => NULL,
1150
        'absolute' => TRUE,
1151
        'html' => TRUE,
1152
      ));
1153
  }
1154
  return $out;
1155
}
1156
1157
/**
1158
 * @todo Please document this function.
1159
 * @see http://drupal.org/node/1354
1160
 */
1161
function cdm_taxontree_theme() {
1162
  return array(
1163
    'cdm_taxontree' => array('variables' => array(
1164
      'tree' => NULL,
1165
      'filterIncludes' => NULL,
1166
      'show_filter_switch' => FALSE,
1167
      'tree_node_callback' => FALSE,
1168 0af3ce28 Andreas Kohlbecker
      'element_name' => FALSE
1169 6657531f Andreas Kohlbecker
      )),
1170
    'cdm_taxontree_block' => array('variables' => array(
1171
      'tree' => NULL,
1172
      'delta' => NULL,
1173
      'magicbox' => FALSE,
1174
      'show_filter_switch' => FALSE,
1175
      'tree_node_callback' => FALSE,
1176
      )),
1177
    'cdm_taxontree_controller' => array('variables' => array('compact_mode' => NULL)),
1178
    'cdm_taxontree_node' => array('variables' => array(
1179
      'node' => NULL,
1180
      'filterIncludes' => NULL,
1181
      'show_filter_switch' => FALSE,
1182 0af3ce28 Andreas Kohlbecker
      'tree_node_callback' => FALSE
1183 6657531f Andreas Kohlbecker
      )),
1184
    'cdm_taxontree_node_concept_switch' => array('variables' => array('node' => NULL)),
1185
    'cdm_taxontree_node_filter_switch' => array('variables' => array('node' => NULL, 'filter_class' => NULL)),
1186
  );
1187
}
1188
1189
// ----------------- FILTERS -------------------------- //
1190
/**
1191
 * Filters on children, overrides already set parent filters and vice versa.
1192
 *
1193
 * @param string $op
1194
 *   [add | remove] a taxon from the filtered taxa.
1195
 *   TODO at the moment there is also a 'list' operation that displays all
1196
 *   set filters and provides the ability to delete them.
1197
 *   This option depends on function is defined in cdm_dataportal.
1198
 *   Problem is, that the dependency is the other way round.
1199
 * @param string $taxonUuid
1200
 *
1201 a0e3ae5c Andreas Kohlbecker
 * @return string
1202 6657531f Andreas Kohlbecker
 */
1203
function cdm_taxontree_view_filter($op, $taxonUuid = NULL) {
1204
1205
  if (!isset($_SESSION['cdm']['filters'])) {
1206
    $_SESSION['cdm']['filters'] = array();
1207
  }
1208
  if ($taxonUuid || $op == 'list') {
1209
    switch ($op) {
1210
      case 'add':
1211
        cdm_taxontree_filters_add($taxonUuid);
1212
        break;
1213
1214
      case 'remove':
1215
        cdm_taxontree_filters_remove($taxonUuid);
1216
        break;
1217
1218
      case 'list':
1219
        // TODO put in cdm_dataportal_theme to decouple both modules by this!!!
1220
        $out = '<ul>';
1221
        foreach ($_SESSION['cdm']['filters'] as $uuid => $node) {
1222
          $out .= '<li>' . cdm_dataportal_shortname_of($node) . ' ' . l(t('[x]'), 'cdm_dataportal/filter/remove/' . $uuid, array('query' => drupal_get_destination())) . '</li>';
1223
        }
1224
        $out .= '</ul>';
1225
        return $out;
1226
    }
1227
  }
1228
  if ($_GET['destination']) {
1229
    $destination = $_GET['destination'];
1230
    unset($_GET['destination']);
1231
    drupal_goto($destination);
1232
  }
1233
}
1234
1235
/**
1236
 * Checks if there are active filters.
1237
 *
1238
 * Filters are set in cdm_dataportal_view_filter().
1239
 * functions using filters should remove invalid filters.
1240
 *
1241
 * @return bool
1242
 *   TRUE if any filter is active.
1243
 */
1244
function cdm_taxontree_filters_active() {
1245
  return isset($_SESSION['cdm']['filters']) && count($_SESSION['cdm']['filters']) > 0;
1246
}
1247
1248
/**
1249
 * Filters are set in cdm_dataportal_view_filter().
1250
 *
1251
 * @return mixed
1252
 *   A reference on the filters array stored in the SESSION.
1253
 */
1254
function &cdm_taxontree_filters_get() {
1255
  if (!isset($_SESSION['cdm']['filters'])) {
1256
    $_SESSION['cdm']['filters'] = array();
1257
  }
1258
  return $_SESSION['cdm']['filters'];
1259
}
1260
1261
/**
1262
 * Adds a taxon to the filtered taxa array
1263
 *
1264
 * @param UUID $taxonUuid
1265
 */
1266
function cdm_taxontree_filters_add($taxonUuid) {
1267
1268
  $parents = cdm_ws_taxonomy_pathFromRoot($taxonUuid);
1269
1270
  $parents = array_reverse($parents);
1271
1272
  // Pop off last element since this is the TreeNode object for $taxonUuid!
1273
  $this_node = array_pop($parents);
1274
1275
  // Will contain the uuid of the parent nodes excluding the
1276
  // $taxonUuid node itself.
1277
  $parent_uuids = array();
1278
1279
  // Children override parents rule: remove all parent filters.
1280
  foreach ($parents as $pnode) {
1281
    unset($_SESSION['cdm']['filters'][$pnode->taxonUuid]);
1282
    $parent_uuids[] = $pnode->taxonUuid;
1283
  }
1284
1285
  // Search for potential children of this $taxonUuid.
1286
  foreach ($_SESSION['cdm']['filters'] as $uuid => $node) {
1287
    if (in_array($taxonUuid, $node->parentUuids)) {
1288
      unset($_SESSION['cdm']['filters'][$node->taxonUuid]);
1289
    }
1290
  }
1291
  // Finally add this $taxonUuid as new filter.
1292
  $this_node->parentUuids = $parent_uuids;
1293
  $_SESSION['cdm']['filters'][$taxonUuid] = $this_node;
1294
}
1295
1296
/**
1297
 * Unsets a taxon from the filtered taxa array.
1298
 *
1299
 * @param string $taxonUuid
1300
 */
1301
function cdm_taxontree_filters_remove($taxonUuid) {
1302
  unset($_SESSION['cdm']['filters'][$taxonUuid]);
1303
}
1304
1305
// ------------------------ PRIVATE --------------------------- //
1306
/**
1307
 * Analyses the current Drupal path to get the taxon UUID.
1308
 *
1309
 * If a certain taxon was requested in the request, returns the UUID
1310
 * of that taxon. Returns a stored UUID if no taxon was requested.
1311
 * TODO where does the stored UUID come from?
1312
 *
1313
 * @return string
1314
 *   The taxon id found, or FALSE.
1315 0af3ce28 Andreas Kohlbecker
 *
1316
 * @deprecated use get_current_taxon_uuid() instead
1317 6657531f Andreas Kohlbecker
 */
1318
function _cdm_get_taxonuuid() {
1319 0af3ce28 Andreas Kohlbecker
1320 6657531f Andreas Kohlbecker
  if (arg(0) == "cdm_dataportal" && arg(1) == "taxon" && arg(2) !== 0) {
1321
    $taxon_uuid = arg(2);
1322
  }
1323
  else {
1324
    $taxon_uuid = FALSE;
1325 0af3ce28 Andreas Kohlbecker
    // TODO is this SESSION variable ['cdm_dataportal']['tree']['taxon_uuid'] use at all?
1326 6657531f Andreas Kohlbecker
    if (isset($_SESSION['cdm_dataportal']['tree']['taxon_uuid'])) {
1327
      $taxon_uuid = $_SESSION['cdm_dataportal']['tree']['taxon_uuid'];
1328
    }
1329
1330
  }
1331
  return $taxon_uuid;
1332
}