Project

General

Profile

Download (32.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/**
3
 * @file
4
 * Search related functions.
5
 */
6

    
7
define("SESSION_KEY_SEARCH_REGISTRATION_FILTER", "SESSION_KEY_SEARCH_REGISTRATION_FILTER");
8
define('SESSION_KEY_SEARCH_TAXONGRAPH_FOR_REGISTRATION_FILTER', 'SESSION_KEY_SEARCH_TAXONGRAPH_FOR_REGISTRATION_FILTER');
9

    
10
/**
11
 * Returns a Drupal path to a search form for a CDM webservice.
12
 *
13
 * For a given CDM webservice end-point, the drupal page path to the
14
 * according search form is returned.
15
 * cdm webservice end points are defined in constant variables like:
16
 * <code>CDM_WS_PORTAL_TAXON_FIND</code> and
17
 * <code>CDM_WS_PORTAL_TAXON_FINDBY_DESCRIPTIONELEMENT_FULLTEXT</code>
18
 *
19
 * @param string $ws_endpoint
20
 *   The cdm webservice endpoint for which to find the search form path.
21
 *
22
 * @return string
23
 *   The Drupal path found.
24
 */
25
function cdm_dataportal_search_form_path_for_ws($ws_endpoint) {
26
  static $form_ws_map = array(
27
    CDM_WS_PORTAL_TAXON_FIND => "cdm_dataportal/search",
28
    CDM_WS_PORTAL_TAXON_SEARCH => "cdm_dataportal/search",
29
    CDM_WS_PORTAL_TAXON_FINDBY_DESCRIPTIONELEMENT_FULLTEXT => "cdm_dataportal/search/taxon_by_description",
30
  );
31
  return $form_ws_map[$ws_endpoint];
32
}
33

    
34
/**
35
 * Prepares a form array for a general purpose search form.
36
 *
37
 * The form is used for general purpose search functionality in the
38
 * dataportal. The form returned is populated with all necessary fields
39
 * for internal processing and has the textfield element $form['query']
40
 * which holds the query term.
41
 *
42
 * @param string $action_path
43
 *   The Drupal path to be put into the action url to which the form will
44
 *   be submitted.
45
 * @param string $search_webservice
46
 *   The cdm-remote webservice to be used, valid values are defined by
47
 *   the constants: FIXME.
48
 * @param string $query_field_default_value
49
 *   A default text for the query field
50
 * @param string $query_field_description
51
 *   The description text for the query field
52
 *
53
 * @return array
54
 *   The prepared form array.
55
 */
56
function cdm_dataportal_search_form_prepare($action_path, $search_webservice, $query_field_default_value, $query_field_description) {
57

    
58

    
59
  $form['#method'] = 'get';
60
  $form['#action'] = url($action_path, array(
61
    'absolute' => TRUE,
62
  ));
63

    
64
  $form['ws'] = array(
65
    '#type' => 'hidden',
66
    '#value' => $search_webservice,
67
    '#name' => 'ws',
68
  );
69

    
70
  $form['query'] = array(
71
    '#weight' => 0,
72
    '#type' => 'textfield',
73
    '#size' => 68,
74
    // This causes the description to display also when hovering over
75
    // the textfield.
76
    // This is wanted behaviour for the simple seach but could
77
    // be disabled for the advances search.
78
    '#attributes' => array(
79
      'title' => $query_field_description,
80
    ),
81
    '#description' => $query_field_description,
82
    '#value' => $query_field_default_value,
83
    // '#description' => $query_field_description,
84
  );
85
  if(variable_get(SIMPLE_SEARCH_AUTO_SUGGEST)){
86
      $form['query']['#autocomplete_path'] = 'cdm_dataportal/taxon/autosuggest////';
87
  }
88

    
89
    $form['search'] = array(
90
    '#weight' => 3,
91
    '#tree' => TRUE,
92
    // '#type' => $advanced_form ? 'fieldset': 'hidden',
93
    '#title' => t('Options'),
94
  );
95

    
96
  // Clean URL get forms breaks if we don't give it a 'q'.
97
  if (!(bool) variable_get('clean_url', '0')) {
98
    $form['search']['q'] = array(
99
      '#type' => 'hidden',
100
      '#value' => $action_path,
101
      '#name' => 'q',
102
    );
103
  }
104

    
105
  $form['submit'] = array(
106
    '#weight' => 5,
107
    '#type' => 'submit',
108
    '#name' => '',
109
    '#value' => t('Search'),
110
  );
111

    
112
  return $form;
113
}
114

    
115
function cdm_dataportal_taxon_autosuggest($classificationUuid = NULL, $areaUuid = NULL, $status = NULL, $string) {
116
  $matches = array();
117

    
118
  $queryParams = array();
119
  $queryParams['query'] = $string.'*';
120
  if((is_null($classificationUuid) || $classificationUuid=='') && isset($_SESSION['cdm']['taxonomictree_uuid'])){
121
    $classificationUuid = $_SESSION['cdm']['taxonomictree_uuid'];// if no classification uuid is set use the current one
122
  }
123
  if($classificationUuid){
124
    $queryParams['classificationUuid'] = $classificationUuid;
125
  }
126
  if($areaUuid){
127
    $queryParams['area'] = $areaUuid;
128
  }
129
  if($status){
130
    $queryParams['status'] = $status ;
131
  }
132
  $queryParams['pageNumber'] = '0';
133
  $queryParams['pageSize'] = '10';
134
  $queryParams['doTaxa'] = true;
135
  $queryParams['doSynonyms'] = true;
136
  $queryParams['doMisappliedNames'] = true;
137
  $queryParams['doTaxaByCommonNames'] = true;
138

    
139
  $search_results = cdm_ws_get(CDM_WS_TAXON_SEARCH, NULL, queryString($queryParams));
140
  foreach($search_results->records as $record){
141
      $titleCache = $record->entity->titleCache;
142
      preg_match('/(.*) sec.*/', $titleCache, $trimmedTitle); //remove sec reference
143
      $trimmedTitle = trim($trimmedTitle[1]);
144
      $matches[$trimmedTitle] = check_plain($trimmedTitle);
145
  }
146
  drupal_json_output($matches);
147
}
148

    
149

    
150
  /**
151
 * Creates a search form for searching on taxa.
152
 *
153
 * If advanced $advanced_form id TRUE the form will offer additional choices
154
 *
155
 * @param array $form
156
 *   A drupal form array
157
 * @param array $form_state
158
 *   The drupal form state passed as reference
159
 * @param bool $advanced_form
160
 *   default is FALSE
161
 * @param bool $classification_select
162
 *   set TRUE to offer a classification selector in the form - default is FALSE
163
 *   if only available in the advanced mode
164
 *
165
 * @return array
166
 *   the form array
167
 */
168
function cdm_dataportal_search_taxon_form($form, &$form_state, $advanced_form = FALSE, $classification_select = TRUE) {
169

    
170
  $query_field_default_value = (isset($_SESSION['cdm']['search']['query']) ? $_SESSION['cdm']['search']['query'] : '');
171

    
172
  if ($advanced_form || variable_get(SIMPLE_SEARCH_USE_LUCENE_BACKEND, FALSE)) {
173
    $search_service_endpoint = CDM_WS_PORTAL_TAXON_SEARCH;
174
  }
175
  else {
176
    $search_service_endpoint = CDM_WS_PORTAL_TAXON_FIND;
177
  }
178

    
179
  $form = cdm_dataportal_search_form_prepare(
180
    'cdm_dataportal/search/results/taxon',
181
    $search_service_endpoint,
182
    $query_field_default_value,
183
    t('Enter the name or part of a name you wish to search for.
184
      The asterisk  character * can be used as wildcard, but must not be used as first character.')
185
  );
186

    
187
  if (!$advanced_form) {
188
    $form['query']['#size'] = 20;
189
  }
190

    
191
  $form['search']['pageSize'] = array(
192
    '#weight' => -1,
193
    '#type' => 'hidden',
194
    '#value' => variable_get('cdm_dataportal_search_items_on_page', 25),
195
  );
196

    
197
  $form['search']['pageNumber'] = array(
198
    '#weight' => -1,
199
    '#type' => 'hidden',
200
    '#value' => 0,
201
  );
202

    
203
  $search_taxa_mode_settings = get_array_variable_merged(
204
    CDM_SEARCH_TAXA_MODE,
205
    CDM_SEARCH_TAXA_MODE_DEFAULT
206
  );
207
  $preset_do_taxa = $search_taxa_mode_settings['doTaxa'] !== 0;
208
  $preset_do_synonyms = $search_taxa_mode_settings['doSynonyms'] !== 0;
209
  $preset_do_taxa_by_common_names = $search_taxa_mode_settings['doTaxaByCommonNames'] !== 0;
210
  $preset_do_misapplied_names = $search_taxa_mode_settings['doMisappliedNames'] !== 0;
211

    
212
  if ($advanced_form) {
213

    
214
    // --- ADVANCED SEARCH FORM ---
215
    //
216

    
217
    // Get presets from settings.
218
    $preset_classification_uuid = get_current_classification_uuid();
219

    
220
    // Overwrite presets by user choice stored in session.
221
    if (isset($_SESSION['cdm']['search'])) {
222
      $preset_do_taxa = (isset($_SESSION['cdm']['search']['doTaxa']) ? 1 : 0);
223
      $preset_do_synonyms = (isset($_SESSION['cdm']['search']['doSynonyms']) ? 1 : 0);
224
      $preset_do_misapplied_names = (isset($_SESSION['cdm']['search']['doMisappliedNames']) ? 1 : 0);
225
      $preset_do_taxa_by_common_names = (isset($_SESSION['cdm']['search']['doTaxaByCommonNames']) ? 1 : 0);
226
      if (isset($_SESSION['cdm']['search']['tree'])) {
227
        $preset_classification_uuid = $_SESSION['cdm']['search']['tree'];
228
      }
229
    }
230

    
231
    if ($classification_select === TRUE) {
232
      $form['search']['tree'] = array(
233
        '#title' => t('Classification'),
234
        '#weight' => 1,
235
        '#type' => 'select',
236
        '#default_value' => $preset_classification_uuid,
237
        '#options' => cdm_get_taxontrees_as_options(TRUE),
238
        '#description' => t('A filter to limit the search to a specific classification. Choosing <em>--- ALL ---</em> will disable this filter.'),
239
      );
240
    }
241

    
242
    // General search parameters.
243
    $form['search']['doTaxa'] = array(
244
      '#weight' => 2,
245
      '#type' => 'checkbox',
246
      '#title' => t('Include') . ' ' . t('accepted taxa'),
247
      '#value' => $preset_do_taxa,
248
    );
249
    $form['search']['doSynonyms'] = array(
250
      '#weight' => 3,
251
      '#type' => 'checkbox',
252
      '#title' => t('Include') . ' ' . t('synonyms'),
253
      '#value' => $preset_do_synonyms,
254
    );
255
    $form['search']['doMisappliedNames'] = array(
256
      '#weight' => 4,
257
      '#type' => 'checkbox',
258
      '#title' => t('Include') . ' ' . t('misapplied names'),
259
      '#value' => $preset_do_misapplied_names,
260
    );
261
    $form['search']['doTaxaByCommonNames'] = array(
262
      '#weight' => 5,
263
      '#type' => 'checkbox',
264
      '#title' => t('Include') . ' ' . t('common names'),
265
      '#value' => $preset_do_taxa_by_common_names,
266
    );
267

    
268
    $area_term_dtos = cdm_ws_fetch_all(
269
      CDM_WS_DESCRIPTION_NAMEDAREAS_IN_USE,
270
      array('includeAllParents' => 'true')
271
    );
272

    
273
    // create map: term_uuid => term
274
    $term_map = array();
275
    foreach ($area_term_dtos as $term_dto) {
276
      $term_map[$term_dto->uuid] = $term_dto;
277
    }
278

    
279
    $term_tree = array();
280
    // mixed_vocabularies will contain the uuid vocabularies which
281
    // also contain terms of foreign vocabularies due to the term
282
    // hierarchy
283
    $mixed_vocabularies = array();
284

    
285
    // Build hierarchy of the terms regardless of the vocabulary.
286
    foreach ($term_map as $term_dto) {
287
      if (!empty($term_dto->partOfUuid)) {
288
        // Children.
289
        $parent =& $term_map[$term_dto->partOfUuid];
290
        if ($parent) {
291
          if (!isset($parent->children)) {
292
            $parent->children = array();
293
          }
294
          $parent->children[$term_dto->uuid] = $term_dto;
295
          if ($parent->vocabularyUuid != $term_dto->vocabularyUuid) {
296
            $mixed_vocabularies[$parent->vocabularyUuid] = $parent->vocabularyUuid;
297
          }
298
        }
299
      }
300
      else {
301
        // group root nodes by vocabulary
302
        if (!isset($term_tree[$term_dto->vocabularyUuid])) {
303
          $term_tree[$term_dto->vocabularyUuid] = array();
304
        }
305
        $term_tree[$term_dto->vocabularyUuid][$term_dto->uuid] = $term_dto;
306
      }
307
    }
308

    
309
    $show_area_filter = ! variable_get(CDM_SEARCH_AREA_FILTER_PRESET, '');
310

    
311
    if($show_area_filter){
312
      drupal_add_js(drupal_get_path('module', 'cdm_dataportal') . '/js/search_area_filter.js');
313

    
314
      drupal_add_js('jQuery(document).ready(function() {
315
        jQuery(\'#edit-search-areas\').search_area_filter(\'#edit-search-areas-areas-filter\');
316
      });
317
      ', array('type' => 'inline'));
318

    
319
      $form['search']['areas'] = array(
320
        '#type' => 'fieldset',
321
        '#title' => t('Filter by distribution areas'),
322
        '#description' => t('The search will return taxa having distribution
323
        information for at least one of the selected areas.') . ' '
324
          .(count($term_tree) > 1 ? t('The areas are grouped
325
        by the vocabularies to which the highest level areas belong.') : ''),
326
      );
327
      $form['search']['areas']['areas_filter'] = array(
328
        '#type' => 'textfield',
329
        '#description' => t('Type to filter the areas listed below.'),
330
      );
331
      $vocab_cnt = 0;
332
      $areas_defaults = array();
333
      if (isset($_SESSION['cdm']['search']['area'])) {
334
        $areas_defaults = explode(',', $_SESSION['cdm']['search']['area']);
335
      }
336
      _add_js_resizable_element('.resizable-box', true);
337
      foreach ($term_tree as $vocab_uuid => $term_dto_tree) {
338
        $vocabulary = cdm_ws_get(CDM_WS_TERMVOCABULARY, array($vocab_uuid));
339
        $areas_options = term_tree_as_options($term_dto_tree);
340
        $form['search']['areas']['area'][$vocab_cnt++] = array(
341
          '#prefix' => '<strong>' . $vocabulary->representation_L10n
342
            . (isset($mixed_vocabularies[$vocab_uuid]) ? ' <span title="Contains terms of at least one other area vocabulary.">(' . t('mixed') . ')</span>': '')
343
            . '</strong><div class="resizable-container"><div class="resizable-box">',
344
          '#type' => 'checkboxes',
345
          '#default_value' => $areas_defaults,
346
          '#options' => $areas_options,
347
          '#suffix' => '</div></div>'
348
        );
349
      }
350
    }
351

    
352
  }
353
  else {
354
    // --- SIMPLE SEARCH FORM ---
355
    //
356

    
357
    // Overwrite presets by user choice stored in session.
358
    if (isset($_SESSION['cdm']['search'])) {
359
      $preset_do_misapplied_names = (isset($_SESSION['cdm']['search']['doMisappliedNames']) ? 1 : 0);
360
    }
361

    
362
    $form['search']['doTaxa'] = array(
363
      '#weight' => -2,
364
      '#type' => 'hidden',
365
      '#value' => $preset_do_taxa,
366
    );
367
    $form['search']['doSynonyms'] = array(
368
      '#weight' => -3,
369
      '#type' => 'hidden',
370
      '#value' => $preset_do_synonyms,
371
    );
372
    $form['search']['doMisappliedNames'] = array(
373
      '#weight' => -4,
374
      '#type' => 'checkbox',
375
      '#title' => t('Misapplied names'),
376
      '#value' => $preset_do_misapplied_names,
377
    );
378
    $form['search']['doTaxaByCommonNames'] = array(
379
      '#weight' => -5,
380
      '#type' => 'hidden',
381
      '#value' => $preset_do_taxa_by_common_names,
382
    );
383
  }
384

    
385
  return $form;
386
}
387

    
388
/**
389
 * Wrapper function for cdm_dataportal_search_taxon_form().
390
 *
391
 * This function makes ot possible possible to just pass the
392
 * correct $form_id 'cdm_dataportal_search_taxon_form_advanced' to
393
 * drupal_get_form like:
394
 * drupal_get_form('cdm_dataportal_search_taxon_form_advanced');
395
 *
396
 * @param array $form
397
 *   A drupal form array
398
 * @param array $form_state
399
 *   The drupal form state passed as reference
400
 *
401
 * @return array
402
 *   The form array
403
 */
404
function cdm_dataportal_search_taxon_form_advanced($form, &$form_state) {
405
  return cdm_dataportal_search_taxon_form($form, $form_state, TRUE);
406
}
407

    
408
/**
409
 * Form for searching taxa by the findByDescriptionElementFullText rest service.
410
 */
411
function cdm_dataportal_search_taxon_by_description_form() {
412
  $query_field_default_value = (isset($_SESSION['cdm']['search']['query']) ? $_SESSION['cdm']['search']['query'] : '');
413

    
414
  $form = cdm_dataportal_search_form_prepare(
415
    'cdm_dataportal/search/results/taxon',
416
    CDM_WS_PORTAL_TAXON_FINDBY_DESCRIPTIONELEMENT_FULLTEXT,
417
    $query_field_default_value,
418
    t("Enter the text you wish to search for. The asterisk character * can be
419
        used as wildcard, but must not be used as first character. Terms can be combined with 'AND'. To search for a
420
        full phrase enclose the terms in parentheses. For more syntactical
421
        options please refer to the !link.",
422
      array(
423
        '!link' => l(
424
          t('Apache Lucene - Query Parser Syntax'),
425
          'http://lucene.apache.org/core/old_versioned_docs/versions/2_9_1/queryparsersyntax.html', array(
426
            'attributes' => array(
427
              'absolute' => TRUE,
428
              'html' => TRUE),
429
          )
430
        ),
431
      )
432
    )
433
  );
434

    
435
  $form['search']['tree'] = array(
436
    '#weight' => -1,
437
    '#type' => 'hidden',
438
    '#value' => get_current_classification_uuid(),
439
  );
440

    
441
  $form['search']['hl'] = array(
442
    '#weight' => -1,
443
    '#type' => 'hidden',
444
    '#value' => 1,
445
  );
446

    
447
  // Only available to admins:
448
  if (!isset($_SESSION['cdm']['search']['clazz'])) {
449
    $_SESSION['cdm']['search']['clazz'] = '';
450
  }
451
  if (module_exists("user") && user_access('administer')) {
452
    $form['search']['clazz'] = array(
453
      '#type' => 'select',
454
      '#title' => t('Limit to description item type'),
455
      '#default_value' => $_SESSION['cdm']['search']['clazz'],
456
      '#options' => cdm_descriptionElementTypes_as_option(TRUE),
457
    );
458
  }
459

    
460
  $profile_feature_tree = get_profile_feature_tree();
461
  $feature_options = _featureTree_nodes_as_feature_options($profile_feature_tree->root);
462
  if (isset($_SESSION['cdm']['search']['features'])) {
463
    $form['search']['features'] = array(
464
      '#type' => 'checkboxes',
465
      '#title' => t('Limit to selected features'),
466
      '#default_value' => $_SESSION['cdm']['search']['features'],
467
      '#options' => $feature_options,
468
    );
469
  }
470
  else {
471
    $form['search']['features'] = array(
472
      '#type' => 'checkboxes',
473
      '#title' => t('Limit to selected features'),
474
      '#options' => $feature_options,
475
    );
476
  }
477
  return $form;
478
}
479

    
480
/**
481
 * Processes the query parameters of the search form.
482
 *
483
 * Reads the query parameters from $_REQUEST and modifies and adds additional
484
 * query parameters if necessary.
485
 *
486
 *  - Filters $_REQUEST by a list of valid request parameters
487
 *  - modifies geographic_range parameters
488
 *  - adds taxon tree uuid if it is missing and if it should not be
489
 *    ignored (parameter value = 'IGNORE')
490
 *  - and more
491
 *
492
 * @param $search_endpoint string
493
 *    The web service endpoint which will be used for executing the search.
494
 *    Usually one of CDM_WS_PORTAL_TAXON_SEARCH, CDM_WS_PORTAL_TAXON_FIND,
495
 *    CDM_WS_PORTAL_TAXON_FINDBY_DESCRIPTIONELEMENT_FULLTEXT.
496
 * @return array
497
 *   the processed request parameters submitted by the search form and
498
 *   also stores them in $_SESSION['cdm']['search']
499
 */
500
function cdm_dataportal_search_request($search_endpoint)
501
{
502

    
503
  $form_params = array();
504

    
505
  if (isset($_REQUEST['search']) && is_array($_REQUEST['search'])) {
506
    array_deep_copy($_REQUEST['search'], $form_params);
507
  }
508

    
509
  if (isset($_REQUEST['pager']) && is_array($_REQUEST['pager'])) {
510
    $form_params = array_merge($form_params, $_REQUEST['pager']);
511
  }
512

    
513
  $form_params['query'] = trim($_REQUEST['query']);
514

    
515

    
516
  // --- handle geographic range
517
  // Split of geographic range.
518
  unset($form_params['areas']);
519

    
520
  $area_filter_preset = null;
521
  if (variable_get(CDM_SEARCH_AREA_FILTER_PRESET, '')) {
522
    $area_filter_preset = explode(',', variable_get(CDM_SEARCH_AREA_FILTER_PRESET, ''));
523
  }
524

    
525
  $area_uuids = array();
526
  if($area_filter_preset){
527
    $area_uuids = $area_filter_preset;
528
  }
529
  elseif (isset($_REQUEST['search']['areas']['area']) && is_array($_REQUEST['search']['areas']['area'])) {
530
    foreach ($_REQUEST['search']['areas']['area'] as $areas) {
531
      $area_uuids = array_merge($area_uuids, $areas);
532
    }
533
    // The area filter is limited to areas with non absent distribution status
534
    $presence_terms_options = cdm_vocabulary_as_option(UUID_PRESENCE_ABSENCE_TERM, null, FALSE, array('absenceTerm' => '/false/'));
535
    $presence_term_uuids = array_keys($presence_terms_options);
536
    $form_params['status'] = $presence_term_uuids;
537
  }
538
  if(count($area_uuids) > 0){
539
    $form_params['area'] = implode(',', $area_uuids);
540
  }
541

    
542
  // Simple search will not submit a 'tree' query parameter,
543
  // so we add it here from what is stored in the session unless
544
  // SIMPLE_SEARCH_IGNORE_CLASSIFICATION is checked in the settings.
545
  if (!isset($form_params['tree']) && !variable_get(SIMPLE_SEARCH_IGNORE_CLASSIFICATION, 0)) {
546
    $form_params['tree'] = get_current_classification_uuid();
547
  }
548
  // Store in session.
549
  $_SESSION['cdm']['search'] = $form_params;
550

    
551
  // ----------- further processing that must not be store in the session --------- //
552

    
553
  if($search_endpoint == CDM_WS_PORTAL_TAXON_SEARCH){
554
    // HACK to allow using dot characters
555
    $form_params['query'] = str_replace('.', '*', $form_params['query']);
556
    // lucene based taxon search always as phrase search if the query string contains a whitespace --> enclose it in "
557
    if(preg_match("/\s+/", $form_params['query'])){
558
      if(!str_beginsWith($form_params['query'], '"')){
559
        $form_params['query'] = '"' . $form_params['query'];
560
      }
561
      if(!str_endsWith($form_params['query'], '"')){
562
        $form_params['query'] = $form_params['query'] . '"' ;
563
      }
564
    }
565
  }
566

    
567
  // If the 'NONE' classification has been chosen (advanced search)
568
  // delete the tree information to avoid unknown uuid exceptions in the
569
  // cdm service.
570
  if (isset($form_params['tree'])
571
    && ($form_params['tree'] == 'NONE' || !is_uuid($form_params['tree']))
572
  ) {
573
    // $form_params['ignore_classification'] =  TRUE;
574
    unset($form_params['tree']);
575
  }
576
  // else {
577
  //   $form_params['ignore_classification'] =  NULL;
578
  // }
579

    
580

    
581
  return $form_params;
582
}
583

    
584
/**
585
 * Provides the classification to which the last search has been limited to..
586
 *
587
 * This function should only be used after the cdm_dataportal_search_taxon_execute()
588
 * handler has been run, otherwise it will return the information from the last
589
 * search executed. The information is retrieved from
590
 * the $_SESSION variable:  $_SESSION['cdm']['search']['tree']
591
 *
592
 * @return object
593
 *   the CDM classification instance which has been used a filter for the
594
 *   last processed search
595
 *   or NULL, it it was on all classifications
596
 */
597
function cdm_dataportal_searched_in_classification() {
598

    
599
  $classification = &drupal_static(__FUNCTION__);
600

    
601
  if (!isset($classification)) {
602
    if (isset($_SESSION['cdm']['search']['tree'])) {
603
      $classification = cdm_ws_get(CDM_WS_PORTAL_TAXONOMY, ($_SESSION['cdm']['search']['tree']));
604
    }
605
    else {
606
      $classification = FALSE;
607
    }
608
  }
609

    
610
  return $classification !== FALSE ? $classification : NULL;
611
}
612

    
613
/**
614
 * Removed the drupal internal form parameters 'form_id', 'form_token', 'form_build_id' from the request array.
615
 *
616
 * @param $request array
617
 *   Pass $_REQUEST as paramter
618
 * @return array
619
 *  The $request array without drupal internal form parameters
620
 */
621
function remove_drupal_form_params($request) {
622

    
623
  static $exclude_keys = array('form_id', 'form_token', 'form_build_id');
624
  $request_sanitized = array();
625
  foreach ($request as $key => $value) {
626
    if(!array_search($key, $exclude_keys)){
627
      $request_sanitized[$key] = $value;
628
    }
629
  }
630

    
631
  return $request_sanitized;
632
}
633

    
634
/**
635
 * Sends a search request to the cdm server.
636
 *
637
 * The parameters to build the query are taken obtained by calling
638
 * cdm_dataportal_search_request() which reads the query parameters
639
 * from $_REQUEST and add additional query parameters if nessecary.
640
 *
641
 * @see cdm_dataportal_search_request()
642
 */
643
function cdm_dataportal_search_taxon_execute() {
644

    
645
  // Store as last search in session.
646
  $_SESSION['cdm']['last_search'] = $_SERVER['REQUEST_URI'];
647

    
648
  // Validate the search webservice parameter:
649
  if (!isset($_REQUEST['ws'])) {
650
    drupal_set_message(
651
      t("Invalid search, webservice parameter 'ws' is missing"), 'warning'
652
    );
653
    return NULL;
654
  }
655
  if (!cdm_dataportal_search_form_path_for_ws($_REQUEST['ws'])) {
656
    // Endpoint is unknown.
657
    drupal_set_message(
658
      t("Invalid search webservice parameter 'ws' given"), 'warning'
659
    );
660
    return NULL;
661
  }
662

    
663
  // Read the query parameters from $_REQUEST and add additional query
664
  // parameters if necessary.
665
  $request_params = cdm_dataportal_search_request($_REQUEST['ws']);
666

    
667
  $taxon_pager = cdm_ws_get($_REQUEST['ws'], NULL, queryString($request_params));
668

    
669
  return $taxon_pager;
670
}
671

    
672

    
673
/**
674
 * Sends a request for a registrations filter search to the cdm server.
675
 */
676
function cdm_dataportal_search_registrations_filter_execute()
677
{
678

    
679
  static $query_param_map = array(
680
    'identifier' => 'identifierFilterPattern',
681
    'taxon_name'=> 'taxonNameFilterPattern',
682
    'type_designation_status' => 'typeDesignationStatusUuids',
683
  );
684

    
685
  $session_key = SESSION_KEY_SEARCH_REGISTRATION_FILTER;
686
  $request_params = cdm_dataportal_search_request_params($session_key, $query_param_map);
687

    
688
  // cleanup
689
  if(isset($request_params['typeDesignationStatusUuids'])){
690
    if(!$request_params['typeDesignationStatusUuids']
691
      || $request_params['typeDesignationStatusUuids'] == "0"
692
      || (isset($request_params['typeDesignationStatusUuids'][0]) && !$request_params['typeDesignationStatusUuids'][0])){
693
      unset($request_params['typeDesignationStatusUuids']);
694
    }
695
  }
696
  if(isset($request_params['taxonNameFilterPattern'])){
697
    // trim and remove empty taxon name query strings
698
    $request_params['taxonNameFilterPattern'] = trim($request_params['taxonNameFilterPattern']);
699
    if(!$request_params['taxonNameFilterPattern']){
700
      unset($request_params['taxonNameFilterPattern']);
701
    }
702
  }
703

    
704
  $registration_pager = cdm_ws_get('registrationDTO/find', NULL, queryString($request_params));
705

    
706
  return $registration_pager;
707
}
708

    
709
/**
710
 * Sends a request for a registrations taxongraph search to the cdm server.
711
 */
712
function cdm_dataportal_search_registrations_taxongraph_execute()
713
{
714

    
715
  static $query_param_map = array(
716
    'taxon_name'=> 'taxonNameFilter'
717
  );
718

    
719
  $session_key = SESSION_KEY_SEARCH_TAXONGRAPH_FOR_REGISTRATION_FILTER;
720
  $request_params = cdm_dataportal_search_request_params($session_key, $query_param_map);
721

    
722
  // cleanup
723
  if(isset($request_params['taxonNameFilter'])){
724
    // trim and remove empty taxon name query strings
725
    $request_params['taxonNameFilter'] = trim($request_params['taxonNameFilter']);
726
    if(!$request_params['taxonNameFilter']){
727
      unset($request_params['taxonNameFilter']);
728
    }
729
  }
730

    
731
  $registration_pager = cdm_ws_get('registrationDTO/findInTaxonGraph', NULL, queryString($request_params));
732

    
733
  return $registration_pager;
734
}
735

    
736
/**
737
 * @param $session_key
738
 * @param $query_param_map
739
 * @return array
740
 */
741
function cdm_dataportal_search_request_params($session_key, $query_param_map)
742
{
743
  // Read the query parameters from $_REQUEST and add additional query
744
  // parameters if necessary.
745
  $request_params = array();
746

    
747
  $request = remove_drupal_form_params($_REQUEST);
748

    
749
  if (count($request) > 0) {
750
    $_SESSION['cdm'][$session_key] = $request;
751
    foreach ($query_param_map as $filter_key => $query_param) {
752
      if (isset($request[$filter_key])) {
753
        $request_params[$query_param] = $request[$filter_key];
754
      }
755
    }
756
    if (isset($request['pager']['pageNumber'])) {
757
      $request_params['pageNumber'] = $request['pager']['pageNumber'];
758
    }
759
  }
760

    
761
  if (count($request_params) == 0 && isset($_SESSION['cdm'][$session_key])) {
762
    foreach ($query_param_map as $filter_key => $query_param) {
763
      if (isset($_SESSION['cdm'][$session_key][$filter_key])) {
764
        $request_params[$query_param] = $_SESSION['cdm'][$session_key][$filter_key];
765
      }
766
    }
767
    if (isset($_SESSION['cdm'][$session_key]['pager']['pageNumber'])) {
768
      $request_params['pageNumber'] = $_SESSION['cdm'][$session_key]['pager']['pageNumber'];
769
    }
770
  }
771
  return $request_params;
772
}
773

    
774
/**
775
 * Transforms the termDTO tree into options array.
776
 *
777
 *   TermDto:
778
 *      - partOfUuid:
779
 *      - representation_L10n:
780
 *      - representation_L10n_abbreviatedLabel:
781
 *      - uuid:
782
 *      - vocabularyUuid:
783
 *      - children: array of TermDto
784
 *
785
 * The options array is suitable for drupal form API elements that
786
 * allow multiple choices.
787
 * @see http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#options
788
 *
789
 * @param array $term_dto_tree
790
 *   a hierarchic array of CDM TermDto instances, with additional
791
 * 'children' field:
792
 * @param array $options
793
 *   Internally used for recursive calls
794
 * @param string $prefix
795
 *   Internally used for recursive calls
796
 *
797
 * @return array
798
 *   the terms in an array as options for a form element that allows
799
 *   multiple choices.
800
 */
801
function term_tree_as_options($term_dto_tree, &$options = array(), $prefix = '') {
802

    
803
  uasort($term_dto_tree, 'compare_terms_by_order_index');
804
  foreach ($term_dto_tree as $uuid => $dto) {
805
    $label = $prefix . '<span class="child-label">'
806
      .  $dto->representation_L10n
807
      . '</span><span class="child-label-abbreviated"> (' . $dto->representation_L10n_abbreviatedLabel . ')</span>';
808
    $options[$uuid] = $label;
809
    if (isset($dto->children) && is_array($dto->children)) {
810
      term_tree_as_options(
811
        $dto->children,
812
        $options, $prefix
813
          . '<span data-cdm-parent="' . $uuid . '" class="parent"></span>'
814
      );
815
    }
816
  }
817

    
818
  return $options;
819
}
820

    
821

    
822
function cdm_dataportal_search_registration_filter_form($form, &$form_state) {
823

    
824
  static $filter_presets_empty = array(
825
    'identifier'=> null,
826
    'taxon_name'=> null,
827
    'type_designation_status' => null
828
  );
829

    
830
  _add_font_awesome_font();
831

    
832
  if(isset($_REQUEST['q']) && ($_REQUEST['q'] == 'cdm_dataportal/registration-search/filter' || $_REQUEST['q'] == 'cdm_dataportal/registration-search')){
833
    // read the $request_params only if it was send from this form
834
    $request_params = remove_drupal_form_params($_REQUEST);
835
  } else {
836
    $request_params = array();
837
  }
838
  $filter_presets = (isset($_SESSION['cdm'][SESSION_KEY_SEARCH_REGISTRATION_FILTER]) ? $_SESSION['cdm'][SESSION_KEY_SEARCH_REGISTRATION_FILTER] : array());
839
  $filter_presets = array_merge($filter_presets_empty, $filter_presets, $request_params);
840
  $form['#action'] =  url('/cdm_dataportal/registration-search/filter');
841
  $form['#method'] = 'get';
842
  $form['#attributes'] = array('class' => array('search-filter'));
843
  $form['identifier'] = array(
844
    '#type' => 'textfield',
845
    '#title' => t('Identifier'),
846
    '#default_value' => $filter_presets['identifier'],
847
    '#size' => 20,
848
    '#maxlength' => 128
849
  );
850
  $form['taxon_name'] = array(
851
    '#type' => 'textfield',
852
    '#title' => t('Scientific name'),
853
    '#default_value' => $filter_presets['taxon_name'],
854
    '#size' => 20,
855
    '#maxlength' => 128
856
  );
857
  $form['type_designation_status'] = array(
858
    '#type' => 'select',
859
    '#title' => t('Type designation status'),
860
    '#multiple' => true,
861
    '#options' => cdm_terms_by_type_as_option('TypeDesignationStatusBase', null, null, TRUE),
862
    '#default_value' => $filter_presets['type_designation_status']
863
  );
864

    
865
  $form['submit'] = array(
866
    '#type' => 'submit',
867
    '#attributes' => array('class' => array('fa-icon'), 'title' => t('Search')),
868
    '#value' => decode_entities('&#xf002;'), // fontawesome search icon
869
//    '#prefix' => "<div class=\"form-item\"><label>&nbsp</label>",
870
//    '#suffix' => "</div>"
871

    
872
  );
873
  return $form;
874
}
875

    
876

    
877
function cdm_dataportal_search_registration_taxongraph_form($form, &$form_state) {
878

    
879
  static $filter_presets_empty = array(
880
    'taxon_name'=> null
881
  );
882

    
883
  _add_font_awesome_font();
884

    
885
  if(isset($_REQUEST['q']) && $_REQUEST['q']  == 'cdm_dataportal/registration-search/taxongraph'){
886
    // read the $request_params only if it was send from this form
887
    $request_params = remove_drupal_form_params($_REQUEST);
888
  } else {
889
    $request_params = array();
890
  }
891
  $filter_presets = (isset($_SESSION['cdm'][SESSION_KEY_SEARCH_TAXONGRAPH_FOR_REGISTRATION_FILTER]) ? $_SESSION['cdm'][SESSION_KEY_SEARCH_TAXONGRAPH_FOR_REGISTRATION_FILTER] : array());
892
  $filter_presets = array_merge($filter_presets_empty, $filter_presets, $request_params);
893

    
894
  $form['#action'] =  url('/cdm_dataportal/registration-search/taxongraph');
895
  $form['#method'] = 'get';
896
  $form['#attributes'] = array('class' => array('search-filter'));
897
  $form['taxon_name'] = array(
898
    '#type' => 'textfield',
899
    '#title' => t('Scientific name'),
900
    '#default_value' => $filter_presets['taxon_name'],
901
    '#size' => 20,
902
    '#maxlength' => 128
903
  );
904

    
905
  $form['submit'] = array(
906
    '#type' => 'submit',
907
    '#attributes' => array('class' => array('fa-icon'), 'title' => t('Search')),
908
    '#value' => decode_entities('&#xf002;'), // fontawesome search icon
909
//    '#prefix' => "<div class=\"form-item\"><label>&nbsp</label>",
910
//    '#suffix' => "</div>"
911

    
912
  );
913
  return $form;
914
}
915

    
916
/**
917
 * Compose the result set of a registration search from a pager object
918
 *
919
 * @param $registration_pager
920
 *    The pager containing registration objects
921
 *
922
 * @return
923
 *   A drupal render array.
924
 *
925
 * @ingroup compose
926
 *
927
 * TODO compose function into search.inc ?
928
 */
929
function compose_registrations_search_results($registration_pager){
930

    
931
  $render_array = array();
932
  $render_array['pre'] = markup_to_render_array("<div class=\"cdm-item-list\">");
933

    
934
  if($registration_pager != null && count($registration_pager->records) > 0){
935
    $items_render_array = array();
936
    foreach($registration_pager->records as $registration_dto) {
937

    
938
      $items_render_array[]  = array(
939
        '#prefix' => "<div class=\"item\"><div class=\"" . html_class_attribute_ref(new TypedEntityReference("Registration", $registration_dto->uuid)) . "\">",
940
         'item_data' => compose_registration_dto_compact($registration_dto, 'item-style'),
941
        '#suffix' => "</div></div>"
942
        );
943
      ;
944
    }
945

    
946
    $render_array['items'] = $items_render_array;
947
    $render_array['pager'] =  markup_to_render_array(theme('cdm_pager', array(
948
          'pager' => $registration_pager,
949
          'path' => $_REQUEST['q'], // stay on same page
950
          'parameters' => $_REQUEST,
951
        )));
952

    
953
  } else {
954
    if($registration_pager != null && $registration_pager->count > 0 && count($registration_pager->records) == 0){
955
      $render_array['items'] = markup_to_render_array("<div id=\"no_results\">Result page out of range.</div>");
956
    } else {
957
      $render_array['items'] = markup_to_render_array("<div id=\"no_results\">No results found.</div>");
958
    }
959
  }
960
  $render_array['post'] = markup_to_render_array("</div>");
961

    
962
  return $render_array;
963

    
964
}
(11-11/18)