Project

General

Profile

Download (19.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
// $Id$
3

    
4
/**
5
 * @file
6
 * Functions which are required or useful when accessing and processing CDM Data Store Webservices
7
 * 
8
 * Naming conventions:
9
 * ----------------------
10
 * 
11
 *  - all webservice access methods are prefixed with cdm_ws
12
 * 
13
 *
14
 * Copyright (C) 2007 EDIT
15
 * European Distributed Institute of Taxonomy 
16
 * http://www.e-taxonomy.eu
17
 */
18
require_once ('xml2json.php');
19
require_once ('uuids.php');
20

    
21

    
22

    
23
/**
24
 * Implementation of hook_requirements()
25
 */
26
function cdm_api_requirements() {
27

    
28
  $requirements['cdm_api'] = array(
29
    'title' => t('CDM API')
30
  );
31

    
32
  if( function_exists('curl_init') ){
33
    $requirements['cdm_api']['description'] = ''; // description below title is not jet in use 
34
    $requirements['cdm_api']['value'] =  'CURL php extension is available.';
35
  } else {
36
    $requirements['cdm_api']['value'] =  'CURL php extension is missing.';
37
  }
38
 
39
  //FIXME: once _get_content_fsockopen is implemented change  severity to  REQUIREMENT_WARNING,
40
  $requirements['cdm_api']['severity'] =  (function_exists('curl_init') ? REQUIREMENT_OK : REQUIREMENT_ERROR);
41
  
42
  return $requirements;
43
}
44

    
45

    
46
/**
47
 * Implementation of hook_menu()
48
 */
49
function cdm_api_menu($may_cache) {
50
  $items = array();
51
  if ($may_cache) {
52
    
53
   $items[] = array(
54
      // usage: url('cdm_api/proxy/'.urlencode($content_url)."/$theme");
55
      'path' => 'cdm_api/proxy',
56
      'callback' => 'proxy_content',
57
      'access' => true,
58
      'type' => MENU_CALLBACK,
59
      );
60
    
61
  }
62
  
63
  return $items;
64
}
65

    
66
function cdm_api_settings_form(){
67
  
68
   $form['cdm_webservice'] = array(
69
      '#type' => 'fieldset',
70
      '#title' => t('CDM Web Service'),
71
      '#collapsible' => FALSE,
72
      '#collapsed' => FALSE,
73
  );
74

    
75
  $form['cdm_webservice']['cdm_webservice_url'] =  array(
76
    '#type' => 'textfield',
77
    '#title'         => t('CDM Web Service URL'),
78
    '#description'   => t('The URL of CDM Webservice which delivers the data to be published.'),
79
    '#default_value' => variable_get('cdm_webservice_url', 'http://dev.e-taxonomy.eu/svn/trunk/drupal/modules/cdm_dataportal/cdm_api/ws_stub/'),
80
  );
81

    
82
  $form['cdm_webservice']['cdm_webservice_isStub'] =  array(
83
    '#type' => 'checkbox',
84
    '#title'         => t('Use Web Service Stub'),
85
    '#default_value' => variable_get('cdm_webservice_isStub', 1),
86
    '#description'   => t('Use a static web service stub. Only for development. For further information please refer to the ')
87
  .l('ws_stub/README.txt', 'http://dev.e-taxonomy.eu/svn/trunk/drupal/modules/cdm_dataportal/cdm/ws_stub/README.txt', array('target'=>'_blank')),
88
  );
89
  
90

    
91
  $form['cdm_webservice']['cdm_webservice_type'] =  array(
92
    '#type'          => 'select',
93
    '#title'         => t('Web Service Type'),
94
    '#default_value' => variable_get('cdm_webservice_type', 'json'),
95
    '#options'       => array(
96
            'xml'  => t('XML'),
97
            'json' => t('JSON'),
98
        ),
99
    '#description'   => t('The response data type of the web service.'),
100
  );
101

    
102
  $form['cdm_webservice']['cdm_webservice_cache'] =  array(
103
    '#type' => 'checkbox',
104
    '#title'         => t('Enable Caching'),
105
    '#default_value' => variable_get('cdm_webservice_cache', 1),
106
    '#description'   => t('Enable caching of webservice responses on simple requests, '
107
      .'that is requests which only have one parameter generally a UUID or a concatenation of UUIDs')
108
  );
109
  
110
  $form['cdm_webservice']['proxy'] = array(
111
      '#type' => 'fieldset',
112
      '#title' => t('Proxy'),
113
      '#collapsible' => TRUE,
114
      '#collapsed' => TRUE
115
  );
116
  
117
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_url'] =  array(
118
    '#type' => 'textfield',
119
    '#title'         => t('Proxy URL'),
120
    '#description'   => t('If this proxy url is set the cdm api tries 
121
    to connect the web service over the given proxy server. 
122
    Otherwise proxy usage is deactivated.'),
123
    '#default_value' => variable_get('cdm_webservice_proxy_url', false),
124
  );
125
  
126
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_port'] =  array(
127
    '#type' => 'textfield',
128
    '#title'         => t('Proxy Port'),
129
    '#default_value' => variable_get('cdm_webservice_proxy_port', '80'),
130
  );
131
  
132
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_usr'] =  array(
133
    '#type' => 'textfield',
134
    '#title'         => t('Login'),
135
    '#default_value' => variable_get('cdm_webservice_proxy_usr', false),
136
  );
137
  
138
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_pwd'] =  array(
139
    '#type' => 'textfield',
140
    '#title'         => t('Password'),
141
    '#default_value' => variable_get('cdm_webservice_proxy_pwd', false),
142
  );
143
  
144
  $form['cdm_webservice']['cdm_webservice_debug'] =  array(
145
    '#type' => 'checkbox',
146
    '#title'         => t('Debug CDM Web Service'),
147
    '#default_value' => variable_get('cdm_webservice_debug', 1),
148
    '#description'   => t('Enable CDM Web Service debugging messages')
149
  );
150
  return $form;
151
}
152

    
153
/**
154
 * Implementation of hook_cron().
155
 *
156
 * Expire outdated cache entries
157
 */
158
function cdm_api_cron() {
159
  cache_clear_all(NULL, 'cache_cdm_ws');
160
}
161

    
162

    
163
// ----------------------------------------------------------- //
164

    
165

    
166
/**
167
 * Converts an array of TagedText items into a sequence of corresponding html tags whereas 
168
 * each item will provided with a class attribute which set to the key of the TaggedText item.
169
 * 
170
 * @param array $taggedtxt
171
 * @param String $tag
172
 * @param String $glue the string by which the chained text tokens are concatenated together. 
173
 *       Default is a blak character
174
 * @return String of HTML 
175
 */
176
function cdm_taggedtext2html(array &$taggedtxt, $tag = 'span', $glue = ' ', $skiptags = array()){
177
   $out = '';
178
   $i = 0;
179
   foreach($taggedtxt as $tt){
180
     if(!in_array($tt->type, $skiptags) && strlen($tt->text) > 0){
181
      $out .= (strlen($out) > 0 && ++$i < count($taggedtxt)? $glue : '').'<'.$tag.' class="'.$tt->type.'">'.$tt->text.'</'.$tag.'>';
182
     }
183
   }
184
   return $out;
185
}
186

    
187
/**
188
 * Finds the text tagged with $$tag_type in an array of taggedText instances
189
 *
190
 * @param array $taggedtxt
191
 * @param string $tag_type
192
 * @return the text mapped by $tag_type or an empty string
193
 */
194
function cdm_taggedtext_value(array &$taggedtxt = array(), $tag_type){
195
  foreach($taggedtxt as $tagtxt){
196
    if($tagtxt->type == $tag_type)
197
    return $tagtxt->text;
198
  }
199
  return '';
200
}
201

    
202
function cdm_preferred_media_representations($mediaTO, array $mimeTypes, $width, $height){
203
    /*
204
media Array [4]  
205
    representations Array [3] 
206
        mimeType  image/jpeg  
207
        representationParts Array [1]   
208
            duration  0 
209
            heigth  0 
210
            size  0 
211
            uri http://wp5.e-taxonomy.eu/dataportal/cichorieae/media/protolog/jpeg/Acanthocephalus_p1.jpg 
212
            uuid  15c687f1-f79d-4b79-992f-7ba0f55e610b  
213
            width 0 
214
        suffix  jpg 
215
        uuid  930b7d51-e7b6-4350-b21e-8124b14fe29b   
216
    title 
217
    uuid  17e514f1-7a8e-4daa-87ea-8f13f8742cf9   
218
     * 
219
     */
220
  $prefRepr = array();
221
  if(!isset($mediaTO->representations[0])){
222
    return $prefRepr;
223
  }
224
  foreach($mediaTO->representations as $representationTO){
225
    $mimeTypeKey = array_search($representationTO->mimeType, $mimeTypes);
226
    if($mimeTypeKey !== false){
227
      $dwa = 0;
228
      foreach($representationTO->representationParts as $part){
229
        $dw = $part->width * $part->height - $height * $width;
230
        if($dw < 0){
231
          $dw *= -1;
232
        }
233
        $dwa+= $dw;
234
      }
235
      $dwa = $dwa / count($representationTO->representationParts);
236
      $prefRepr[$dwa.'_'.$mimeTypeKey] = $representationTO;
237
    }
238
  }
239
  // sort
240
  krsort($prefRepr);
241
  // return
242
  return $prefRepr;
243
}
244

    
245

    
246
/**
247
 * Produces a path to a static web service stub out of a cdm web service path. 
248
 * These stubs are object serialisations stored in files whereas the filename
249
 * consists of the service name and of a 
250
 * encoded version of the request query parameters
251
 *
252
 * @param string $path
253
 * @param string $fileExtension
254
 * @return string
255
 */
256
function cdm_encode_stub($path, $fileExtension, $hasParams = false){
257
  $path =  str_replace('/',',',$path);
258
  if($hasParams){
259
    $path =  str_replace('?',',',$path);
260
    $path =  str_replace('&',',',$path);
261
  }
262
  return variable_get('cdm_webservice_type', 'xml').'/'.$path.'.'.$fileExtension;
263
}
264

    
265

    
266
function cdm_compose_url($ws_name, $parameters = array()){
267
  
268
  $request_params = '';
269
  $path_params = '';
270
  if(!is_array($parameters)){
271
     // add to path
272
     $path_params .= '/'.( is_string($parameters) ? urlencode($parameters) : $parameters);
273
  }else{
274
    foreach($parameters as $key=>$value){
275
      if(is_numeric($key)){
276
        // add to path
277
        $path_params .= '/'.( is_string($value) ? urlencode($value) : $value);
278
      } else {
279
        // add to parameters
280
        $request_params .= ( strlen($request_params) == 0 ? '?' : '&').$key.'='.( is_string($value) ? urlencode($value) : $value);
281
      }
282
    }
283
  }
284
  $path = $ws_name.$path_params.$request_params;
285
  
286
  if(variable_get('cdm_webservice_isStub', 0)){
287
    $path = cdm_encode_stub($path, variable_get('cdm_webservice_type', 'json'), strlen($request_params) > 0);
288
  }
289
  
290
  $url = variable_get('cdm_webservice_url', '').$path; 
291
  return $url;
292
}
293

    
294

    
295
function proxy_content($url, $theme = null){
296
  $args = func_get_args();
297
  
298
  $url = array_shift($args);
299
  $theme = array_shift($args);
300
  
301
  //TODO reconsider caching logic in this function
302
  if(!$theme){
303
    // print out JSON, the cache cannot be used since it contains objetcs
304
    $data = get_content(urldecode($url));
305
    print $data;
306
  } else {
307
    $obj = cdm_ws_load(urldecode($url), false);
308
    array_unshift($args, $theme, $obj);
309
    print call_user_func_array('theme', $args);
310
  }
311
}
312

    
313

    
314
/**
315
 * Enter description here...
316
 *
317
 * @param unknown_type $method
318
 * @param $parameters may be an array or a single variable
319
 * @return unknown
320
 */
321
function cdm_ws_get($method, $parameters = array()){
322
  /*$args = func_get_args();
323
  $method = array_shift($args);
324
  */  
325
  /*if(isset($args[0]) && is_array($args[0])){
326
    $url = cdm_compose_url_parametrised($method, $args[0]);
327
  } else {
328
 */    
329
  $url = cdm_compose_url($method, $parameters);
330
  //}
331
  return cdm_ws_load($url, (is_array($parameters)));
332
}
333

    
334
/**
335
 * Loads the XML or JSON response for the given url from the CDM Data Store Webservice.
336
 * The XML is turned into a object which is returned.
337
 * 
338
 * @param String $url the relative url of the web service call. 
339
 *        Relative means relative to the web service base url which is stored in cdm_webservice_url
340
 * @return An object or false
341
 */
342
function cdm_ws_load($url, $is_multi_paramater_query){
343
  
344
  $do_cache = !$is_multi_paramater_query && variable_get('cdm_webservice_cache', 0);
345
  $cache_entry = false;
346
  
347
  if($do_cache){
348
    // try to get object from cache 
349
    $cache_entry = cache_get($url, 'cache_cdm_ws');
350
  }
351
  
352
  if(!$cache_entry){
353
    // load fresh data from webservice
354
    $time_get_start = microtime(true);
355
    // request data from webservice JSON or XML
356
    $datastr = get_content($url);
357
    $time_get = microtime(true) - $time_get_start;
358
    /*if(TRUE){
359
      $storef =  urlencode($url);
360
      drupal_set_message($storef);
361
      file_save_data($datastr, $storef, FILE_EXISTS_REPLACE);
362
    }*/
363
    
364
    $time_parse_start = microtime(true);
365
    // parse data and create object
366
    $obj = cdm_load_obj($datastr);
367
    $time_parse = microtime(true) - $time_parse_start;
368
    if(variable_get('cdm_webservice_debug', 1)){
369
      drupal_set_message($url.' [fetched in: '.sprintf('%3.3f', $time_get).'s; parsed in '.sprintf('%3.3f', $time_parse).' s; size:'.sprintf('%3.1f', (strlen($datastr) / 1024)).' kb of '.($obj ?  l('valid data', 'cdm_api/proxy/'.urlencode($url), array('target'=>'json-data')):'invalid data').'] '.$json_data_link, 'debug');
370
    }
371
    if( !$obj || !$datastr){
372
      watchdog('CDM', 'cdm_ws_load() - URL: '.$url, WATCHDOG_ERROR);
373
    } else if($do_cache) {
374
      // store fresh data in cache
375
      cache_set($url, 'cache_cdm_ws', serialize($obj), CACHE_TEMPORARY);
376
    }
377
  } else {
378
    $obj = unserialize($cache_entry->data);
379
    if(variable_get('cdm_webservice_debug', 1)){
380
      drupal_set_message('Using cache for: '.$url, 'debug');
381
    }
382
  }
383
  return $obj;
384
}
385

    
386

    
387
function cdm_load_obj($datastr){
388
     
389
  // if the web service delivers XML convert it into json
390
  if(variable_get('cdm_webservice_type', 'xml') == 'xml'){
391
    $datastr = xml2json::transformXmlStringToJson($datastr);  
392
  }
393
  $use_stub = variable_get('cdm_webservice_isStub', 0); 
394
  if($use_stub){
395
    // --- for STUBS use the more syntax tolerant PEAR json lib --- //
396
    $json_pear = new Services_JSON();
397
    $obj = $json_pear->decode($datastr);
398
  } else {
399
    // --- generally use the fast php json lib --- //
400
    $obj = json_decode($datastr);
401
  }
402
  
403
  if(!(is_object($obj) || is_array($obj)) || ($use_stub && !isset($obj->root)) ){
404
    ob_start();
405
    var_dump($obj);
406
    $obj_dump = ob_get_contents();
407
    ob_clean();
408
    watchdog('CDM', 'cdm_load_obj() - invalid object: '.$obj_dump, WATCHDOG_ERROR);
409
    return false;
410
  }
411

    
412
  if($use_stub){
413
    $arr = (array)$obj;
414
    $obj = array_pop($arr);
415
  }
416
  return $obj;
417
}
418

    
419
function get_content($url){
420
  global $locale;  // drupal variable containing the current locale i.e. language
421
  static $header;
422
  
423
  if(!$header){
424
    $header = array();
425
    $header[] = 'Accept: '.(variable_get('cdm_webservice_type', 'json') == 'json' ? 'application/json' : 'text/xml');    
426
    $header[] = 'Accept-Language: '.$locale;
427
    $header[] = 'Accept-Charset: UTF8';
428
  }
429
  
430
  if(function_exists('curl_init')){
431

    
432
    // use the CURL lib if installed it is supposed to be 20x faster
433
    return _get_content_curl($url, $header);
434
  } else {
435
    return _get_content_fsockopen($url, $header);
436
  }
437
}
438

    
439

    
440
function _get_content_fsockopen($url, $header = array()){
441
  //FIXME implement get_content_fsockopen($url);
442
   watchdog('CDM_API', '_get_content_fsockopen - UNIMPLEMENTED', WATCHDOG_ERROR);
443
   return false;
444
}
445

    
446

    
447
/**
448
 * Return string content from a remote file
449
 * 
450
 * @param string $url
451
 * @return string
452
 * 
453
 * @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
454
*/
455
function _get_content_curl($url, $header = array())
456
{
457
    $ch = curl_init();
458

    
459
    curl_setopt ($ch, CURLOPT_URL, $url);
460
    // set proxy settings
461
    if(variable_get('cdm_webservice_proxy_url', false)){
462
      curl_setopt($ch, CURLOPT_PROXY, variable_get('cdm_webservice_proxy_url', ''));
463
      curl_setopt($ch, CURLOPT_PROXYPORT, variable_get('cdm_webservice_proxy_port', '80'));
464
      if(variable_get('cdm_webservice_proxy_usr', false)){
465
        curl_setopt ($ch, CURLOPT_PROXYUSERPWD, variable_get('cdm_webservice_proxy_usr', '').':'.variable_get('cdm_webservice_proxy_pwd', '')); 
466
      }
467
    }
468
    // set headers
469
    curl_setopt ($ch, CURLOPT_HTTPHEADER, $header);
470

    
471
    ob_start();
472
    curl_exec ($ch);
473
    if(curl_errno($ch)){
474
      watchdog('CDM_API', '_get_content_curl() - '.curl_error($ch).' URL: '.$url, WATCHDOG_ERROR);
475
        if(variable_get('cdm_webservice_debug', 1)){
476
          drupal_set_message('_get_content_curl() - '.curl_error($ch).' URL: '.$url, 'error');
477
        }
478
    }
479
    curl_close ($ch);
480
    $string = ob_get_contents();
481
    ob_end_clean();
482
 
483
    return $string;    
484
}
485

    
486
function cdm_api_secref_cache_prefetch(&$secUuids){
487
  global $secref_cache;
488
  if(!is_array($secref_cache)){
489
    $secref_cache = array();
490
  }
491
  $uniqueUuids = array_unique($secUuids);
492
  $i = 0;
493
  $param = '';
494
  while($i++ < count($uniqueUuids)){
495
    $param .= $secUuids[$i].',';
496
    if(strlen($param) + 37 > 2000){
497
     _cdm_api_secref_cache_add($param);
498
      $param = '';
499
    }
500
  }
501
  if($param){
502
     _cdm_api_secref_cache_add($param);
503
  }
504
}
505

    
506
function cdm_api_secref_cache_get($secUuid){
507
  global $secref_cache;
508
  if(!is_array($secref_cache)){
509
    $secref_cache = array();
510
  }
511
  if(!array_key_exists($secUuid, $secref_cache)){
512
    _cdm_api_secref_cache_add($secUuid);
513
  }
514
  return $secref_cache[$secUuid]; 
515
}
516

    
517
function cdm_api_secref_cache_clear(){
518
  global $secref_cache;
519
  $secref_cache = array();
520
}
521

    
522
function _cdm_api_secref_cache_add($secUuidsStr){
523
  global $secref_cache;
524
  $refSTOs = cdm_ws_get(CDM_WS_SIMPLE_REFERENCE, $secUuidsStr);
525
  $assocRefSTOs = array();
526
  if($refSTOs) {
527
    foreach($refSTOs as $ref){
528
      $assocRefSTOs[$ref->uuid] = $ref;
529
    }
530
    $secref_cache = array_merge($secref_cache, $assocRefSTOs);
531
  }
532
}
533

    
534
/**
535
 * Web Service Arguments: {Uuid}
536
 * 
537
 * The whatis service returns the type 
538
 * i.e. DTO class name and simplename & cdm class name and simplename of the instance referenced by the $uuid parameter. 
539
 * 
540
 * return: false if the cdm store contains no matching instance. 
541
 * An associative array with the following key-value pairs:
542
 *   - 'cdmName':       name of the cdm class as returned by Class.getName(), e.g. eu.etaxonomy.cdm.model.taxon.Taxon
543
 *   - 'cdmSimpleName': simple name of the cdm class as returned by Class.getSimpleName(), e.g. Taxon
544
 *   - 'dtoName':       name of the DTO class as returned by Class.getName(), e.g. eu.etaxonomy.cdm.dto.TaxonTO
545
 *   - 'dtoSimpleName': simple name of the TDO class as returned by Class.getSimpleName(), e.g. TaxonTO
546
 */
547
define('CDM_WS_WHATIS', 'whatis');
548

    
549

    
550
/**
551
 * Web Service Arguments: {NameUuid}
552
 */
553
define('CDM_WS_NAME', 'name');
554

    
555
/**
556
 * Web Service url parameters:
557
 * -  [last path element]: querystring
558
 * -  sec : the uuid of the concept reference
559
 * -  higherTaxa : list of taxon uuid, if higherTaxa are defined only taxa which are includet in one these taxa are taken in to account 
560
 * -  matchAnywhere : false (default) match the querystring to the beginning of names, if set to true any matching substring is taken as a hit.
561
 * -  onlyAccepted : return only taxa which are accepted in the sence of the concept reference as given by parameter sec
562
 * -  pagesize : maximum number of iteme per result page
563
 * -  page: the number of page to be returned
564
 * 
565
 * returns ResultPageSTO
566
 */
567
define('CDM_WS_FIND_TAXA', 'find/taxon');
568

    
569
/**
570
 * Web Service Arguments: {referenceUuid}
571
 * 
572
 */
573
define('CDM_WS_REFERENCE', 'ref');
574

    
575
/**
576
 * Web Service Arguments: {referenceUuid} or array of {referenceUuid}
577
 * 
578
 * returns a list of ReferenceSTO
579
 */
580
define('CDM_WS_SIMPLE_REFERENCE', 'simple/ref');
581

    
582
/**
583
 * Web Service Arguments: {taxonUuid}
584
 */
585
define('CDM_WS_TAXON', 'taxon');
586

    
587

    
588
/**
589
 * Web Service Arguments: {taxonUuid} or array of {referenceUuid}
590
 * 
591
 * returns a list of TaxonSTO
592
 */
593
define('CDM_WS_SIMPLE_TAXON', 'simple/taxon');
594

    
595
/**
596
 * Web Service Arguments: {nameUuid}
597
 * 
598
 * returns a set of type designation which are assigned to the name given
599
 * as parameter. The Set may contain {@link NameTypeDesignationSTO}
600
 * and {@link SpecimenTypeDesignationSTO}
601
 */
602
define('CDM_WS_TYPE_DESIGNATIONS', 'types');
603

    
604
/**
605
 * Web Service Arguments: {taxonUuid}
606
 * 
607
 * returns the taxon which is the accepted synonym for the taxon given as
608
 * parameter taxonUuid. If the taxon specified by taxonUuid is itself the
609
 * accepted taxon, this one will be returned.
610
 */
611
define('CDM_WS_ACCEPTED_TAXON', 'simple/taxon/acceptedfor');
612

    
613
/**
614
 * Web Service Arguments: {secUuid}
615
 * 
616
 * Gets the root nodes of the taxonomic concept tree for the concept
617
 * reference specified by the secUuid parameter.
618
 * 
619
 * stub: treenode_root
620
 */
621
define('CDM_WS_TREENODE_ROOT', 'taxonomy/root');
622

    
623
/**
624
 * Web Service Arguments: {taxonUuid}
625
 * 
626
 * Searches the concept taxon tree for all parent taxa by walking the tree
627
 * from the taxon which is referenced by the parameter taxonUuid down to its
628
 * root. The reference taxon will also be included into the returned set of
629
 * TreeNode instances.
630
 * 
631
 * stub: treenode_parents
632
 */
633
define('CDM_WS_TREENODE_PARENTS', 'taxonomy/parents');
634

    
635
/**
636
 * Web Service Arguments: {taxonUuid}
637
 * 
638
 * returns the children of the taxon referenced by the parameter
639
 * taxonUuid.
640
 * 
641
 * stub: treenode_children
642
 */
643
define('CDM_WS_TREENODE_CHILDREN', 'taxonomy/children');
644

    
(4-4/7)