Project

General

Profile

Download (28.8 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
define(DEFAULT_TAXONTREE_RANKLIMIT, '');//TODO Genus UUID
22

    
23

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

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

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

    
46

    
47
/**
48
 * Implementation of hook_menu()
49
 */
50
function cdm_api_menu($may_cache) {
51
  $items = array();
52
  if ($may_cache) {
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
  return $items;
63
}
64

    
65
/**
66
 * Configures the settings forfm for the CDM-API module.
67
 *
68
 * @return Array Drupal settings form
69
 */
70
function cdm_api_settings_form(){
71
  
72
  $form['cdm_webservice'] = array(
73
      '#type' => 'fieldset',
74
      '#title' => t('CDM Web Service'),
75
      '#collapsible' => FALSE,
76
      '#collapsed' => FALSE,
77
  );
78

    
79
  $form['cdm_webservice']['cdm_webservice_url'] =  array(
80
    '#type' => 'textfield',
81
    '#title'         => t('CDM Web Service URL'),
82
    '#description'   => t('The URL of CDM Webservice which delivers the data to be published.'),
83
    '#default_value' => variable_get('cdm_webservice_url', NULL),
84
  );
85
  
86
  $form['cdm_webservice']['taxontree_ranklimit'] =  array(
87
    '#type'          => 'select',
88
    '#title'         => t('Rank of highest displayed taxon'),
89
    '#default_value' => variable_get('taxontree_ranklimit', DEFAULT_TAXONTREE_RANKLIMIT_UUID),
90
    '#options'       => cdm_rankVocabulary_as_option(),
91
    '#description'   => t('The rank of the highest displayed taxon in the taxontree.'),
92
  );
93
  
94
  /*
95
  $form['cdm_webservice']['cdm_webservice_isStub'] =  array(
96
    '#type' => 'checkbox',
97
    '#title'         => t('Use Web Service Stub'),
98
    '#default_value' => variable_get('cdm_webservice_isStub', 1),
99
    '#description'   => t('Use a static web service stub. Only for development. For further information please refer to the ')
100
  .l('ws_stub/README.txt', 'http://dev.e-taxonomy.eu/svn/trunk/drupal/modules/cdm_dataportal/cdm/ws_stub/README.txt', array('target'=>'_blank')),
101
  );
102
  
103

    
104
  $form['cdm_webservice']['cdm_webservice_type'] =  array(
105
    '#type'          => 'select',
106
    '#title'         => t('Web Service Type'),
107
    '#default_value' => variable_get('cdm_webservice_type', 'json'),
108
    '#options'       => array(
109
            'xml'  => t('XML'),
110
            'json' => t('JSON'),
111
        ),
112
    '#description'   => t('The response data type of the web service.'),
113
  );
114
  */
115

    
116
  $form['cdm_webservice']['cdm_webservice_cache'] =  array(
117
    '#type' => 'checkbox',
118
    '#title'         => t('Enable Caching'),
119
    '#default_value' => variable_get('cdm_webservice_cache', 1),
120
    '#description'   => t('Enable caching of webservice responses on simple requests, '
121
      .'that is requests which only have one parameter generally a UUID or a concatenation of UUIDs')
122
  );
123
  
124
  $form['cdm_webservice']['proxy'] = array(
125
      '#type' => 'fieldset',
126
      '#title' => t('Proxy'),
127
      '#collapsible' => TRUE,
128
      '#collapsed' => TRUE
129
  );
130
  
131
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_url'] =  array(
132
    '#type' => 'textfield',
133
    '#title'         => t('Proxy URL'),
134
    '#description'   => t('If this proxy url is set the cdm api tries
135
    to connect the web service over the given proxy server.
136
    Otherwise proxy usage is deactivated.'),
137
    '#default_value' => variable_get('cdm_webservice_proxy_url', false),
138
  );
139
  
140
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_port'] =  array(
141
    '#type' => 'textfield',
142
    '#title'         => t('Proxy Port'),
143
    '#default_value' => variable_get('cdm_webservice_proxy_port', '80'),
144
  );
145
  
146
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_usr'] =  array(
147
    '#type' => 'textfield',
148
    '#title'         => t('Login'),
149
    '#default_value' => variable_get('cdm_webservice_proxy_usr', false),
150
  );
151
  
152
  $form['cdm_webservice']['proxy']['cdm_webservice_proxy_pwd'] =  array(
153
    '#type' => 'textfield',
154
    '#title'         => t('Password'),
155
    '#default_value' => variable_get('cdm_webservice_proxy_pwd', false),
156
  );
157
  
158
  $form['cdm_webservice']['cdm_webservice_debug'] =  array(
159
    '#type' => 'checkbox',
160
    '#title'         => t('Debug CDM Web Service'),
161
    '#default_value' => variable_get('cdm_webservice_debug', 1),
162
    '#description'   => t('Enable CDM Web Service debugging messages. Only visible for administrators!')
163
  );
164
    
165
  return $form;
166
}
167

    
168
/**
169
 * Implementation of hook_cron().
170
 *
171
 * Expire outdated cache entries
172
 */
173
function cdm_api_cron() {
174
  cache_clear_all(NULL, 'cache_cdm_ws');
175
}
176

    
177

    
178
// ----------------------------------------------------------- //
179

    
180

    
181
/**
182
 * Converts an array of TagedText items into a sequence of corresponding html tags whereas
183
 * each item will provided with a class attribute which set to the key of the TaggedText item.
184
 *
185
 * @param array $taggedtxt
186
 * @param String $tag
187
 * @param String $glue the string by which the chained text tokens are concatenated together.
188
 *       Default is a blank character
189
 * @return String of HTML
190
 */
191
function cdm_taggedtext2html(array &$taggedtxt, $tag = 'span', $glue = ' ', $skiptags = array()){
192
   $out = '';
193
   $i = 0;
194
   foreach($taggedtxt as $tt){
195
     if(!in_array($tt->type, $skiptags) && strlen($tt->text) > 0){
196
      $out .= (strlen($out) > 0 && ++$i < count($taggedtxt)? $glue : '').'<'.$tag.' class="'.$tt->type.'">'.t($tt->text).'</'.$tag.'>';
197
     }
198
   }
199
   return $out;
200
}
201

    
202
/**
203
 * Finds the text tagged with $$tag_type in an array of taggedText instances
204
 *
205
 * @param array $taggedtxt
206
 * @param string $tag_type
207
 * @return the text mapped by $tag_type or an empty string
208
 */
209
function cdm_taggedtext_value(array &$taggedtxt = array(), $tag_type){
210
  foreach($taggedtxt as $tagtxt){
211
    if($tagtxt->type == $tag_type)
212
    return $tagtxt->text;
213
  }
214
  return '';
215
}
216

    
217
/**
218
 * media Array [4]
219
 *   representations Array [3]
220
 *       mimeType  image/jpeg
221
 *       representationParts Array [1]
222
 *           duration  0
223
 *           heigth  0
224
 *           size  0
225
 *           uri http://wp5.e-taxonomy.eu/dataportal/cichorieae/media/protolog/jpeg/Acanthocephalus_p1.jpg
226
 *           uuid  15c687f1-f79d-4b79-992f-7ba0f55e610b
227
 *           width 0
228
 *       suffix  jpg
229
 *       uuid  930b7d51-e7b6-4350-b21e-8124b14fe29b
230
 *   title
231
 *   uuid  17e514f1-7a8e-4daa-87ea-8f13f8742cf9
232
 *
233
 * @param unknown_type $media
234
 * @param array $mimeTypes
235
 * @param unknown_type $width
236
 * @param unknown_type $height
237
 * @return unknown
238
 */
239
function cdm_preferred_media_representations($media, array $mimeTypes, $width = 400, $height = 300){
240
    /**
241

    
242
     *
243
     */
244
  $prefRepr = array();
245
  if(!isset($media->representations[0])){
246
    return $prefRepr;
247
  }
248
  
249
  while(count($mimeTypes) > 0){
250
    // getRepresentationByMimeType
251
    $mimeType = array_shift($mimeTypes);
252
    foreach($media->representations as $representation){
253
      if($representation->mimeType == $mimeType){
254
        // preffered mimetype found -> erase all remaining mimetypes to end loop
255
        $mimeTypes = array();
256
        $dwa = 0;
257
        // look for part with the best matching size
258
        foreach($representation->parts as $part){
259
          $dw = $part->width * $part->height - $height * $width;
260
          if($dw < 0){
261
            $dw *= -1;
262
          }
263
          $dwa+= $dw;
264
        }
265
        $dwa = (count($representation->parts)>0) ? $dwa / count($representation->parts) : 0;
266
        $prefRepr[$dwa.'_'.$mimeTypeKey] = $representation;
267
      }
268
    }
269
  }
270
  // sort
271
  krsort($prefRepr);
272
  // return
273
  return $prefRepr;
274
}
275

    
276
/**
277
 * expects an ISO 8601 time representations of a org.joda.time.Partial
278
 * of the form yyyy-MM-dd and returns the year as String.
279
 * In case the year is unknown (= ????) null is returned.
280
 *
281
 * @param ISO 8601 time representations of a org.joda.time.Partial
282
 * @return String
283
 */
284
function partialToYear($partial){
285
  if(is_string($partial)){
286
    $year = substr($partial, 0, 4);
287
    if($year != '??'){
288
      return $year;
289
    }
290
  }
291
  return;
292
}
293
/**
294
 * expects an ISO 8601 time representations of a org.joda.time.Partial
295
 * of the form yyyy-MM-dd and returns the month as String.
296
 * In case the month is unknown (= ???) null is returned.
297
 *
298
 * @param ISO 8601 time representations of a org.joda.time.Partial
299
 * @return String
300
 */
301
function partialToMonth($partial){
302
  if(is_string($partial)){
303
    $month = substr($partial, 5, 2);
304
    if($month != '??'){
305
      return $month;
306
    }
307
  }
308
  return;
309
}
310
/**
311
 * expects an ISO 8601 time representations of a org.joda.time.Partial
312
 * of the form yyyy-MM-dd and returns the day as String.
313
 * In case the day is unknown (= ???) null is returned.
314
 *
315
 * @param ISO 8601 time representations of a org.joda.time.Partial
316
 * @return String
317
 */
318
function partialToDay($partial){
319
  if(is_string($partial)){
320
    $day = substr($partial, 7, 2);
321
    if($day != '??'){
322
      return $day;
323
    }
324
  }
325
  return;
326
}
327

    
328
/**
329
 *
330
 * @param $uri_pattern
331
 * @param $pathParameters an array of path elements, or a single element
332
 * @param $query  A query string to append to the URL.
333
 * @return unknown_type
334
 */
335
function cdm_compose_url($uri_pattern, $pathParameters = array(), $query = NULL ){
336
  
337
  $request_params = '';
338
  $path_params = '';
339
  
340
  /* (1)
341
   * substitute all place holders ($0, $1, ..) in the
342
   * $uri_pattern by the according element of the $pathParameters array
343
   */
344
  static $helperArray = array();
345
  if($pathParameters && !is_array($pathParameters)){
346
    $helperArray[0] = $pathParameters;
347
    $pathParameters = $helperArray;
348
  }
349
  
350
  $i = 0;
351
  while(strpos($uri_pattern, "$".$i) !== FALSE){
352
    if(count($pathParameters) <= $i){
353
      drupal_set_message('cdm_compose_url(): missing pathParameters', 'debug');
354
    }
355
    $uri_pattern = str_replace("$".$i, rawurlencode($pathParameters[$i]), $uri_pattern);
356
    ++$i;
357
  }
358
    
359
  /* (2)
360
   * Append all remaining element of the $pathParameters array as path elements
361
   */
362
  if(count($pathParameters) > $i){
363
    // strip trailing slashes
364
    if(strrchr($uri_pattern, '/') == strlen($uri_pattern)){
365
      $uri_pattern = substr($uri_pattern, 0, strlen($uri_pattern) - 1);
366
    }
367
    while(count($pathParameters) > $i){
368
      $uri_pattern .= '/' . $pathParameters[$i];
369
      ++$i;
370
    }
371
  }
372
  
373
  /* (3)
374
   * Append the query string supplied by $query
375
   */
376
  if (isset($query)) {
377
    $uri_pattern .= (strpos($uri_pattern, '?') !== FALSE ? '&' : '?') . $query;
378
  }
379
  
380
  $path = $ws_name.$uri_pattern;
381
  
382
  $uri = variable_get('cdm_webservice_url', '').$path;
383
  return $uri;
384
}
385

    
386

    
387
function proxy_content($uri, $theme = null){
388
  
389
  $args = func_get_args();
390
  
391
  $uriEncoded = array_shift($args);
392
  $uri = urldecode($uriEncoded);
393
  $theme = array_shift($args);
394
  
395
  $request_method = strtoupper($_SERVER["REQUEST_METHOD"]);
396
  
397
  if($request_method == "POST"){
398
    
399
    $parameters = $_POST;
400
    
401
    $post_data = array();
402
    foreach ($parameters as $k=>$v)
403
    {
404
        $post_data[] = "$k=".utf8_encode($v);
405
    }
406
    $post_data = implode(',', $post_data);
407
    
408
    // testing
409
    $data = cdm_http_request($uri, "POST", $post_data);
410
    print $data;
411
    
412
  }else if(strpos($theme, '/') > 0){ // must be a mimetype
413
    header('Content-Type: '.$theme);
414
    $data = _http_request_binary($uri);
415
    print $data;
416
    exit;
417
  } else {
418
    // in all other cases perform a simple get request
419
    //TODO reconsider caching logic in this function
420
    if(!$theme){
421
      // print out JSON, the cache cannot be used since it contains objects
422
      $data = cdm_http_request($uri);
423
      print $data;
424
      exit;
425
    } else {
426
      $obj = cdm_ws_get($uri, null, null, null, TRUE);
427
      array_unshift($args, $theme, $obj);
428
      print call_user_func_array('theme', $args);
429
    }
430
  }
431
}
432

    
433
function uri_uriByProxy($uri, $theme = false){
434
  // usage: url('cdm_api/proxy/'.urlencode($content_url)."/$theme");)
435
  return url('cdm_api/proxy/'.urlencode($uri).($theme?"/$theme":''));
436
}
437

    
438
/**
439
 * Enter description here...
440
 *
441
 * @param String $resourceURI
442
 * @param pageSize
443
 *            the maximum number of entities returned per page (can be null
444
 *            to return all entities in a single page)
445
 * @param pageNumber
446
 *            the number of the page to be returned, the first page has the
447
 *            pageNumber = 1
448
 * @return unknown
449
 */
450
function cdm_ws_page($resourceURI, $pageSize, $pageNumber){
451
  return cdm_ws_get($resourceURI, null, queryString(array("page" => $pageNumber, 'pageSize'=>$pageSize)));
452
}
453

    
454
function cdm_ws_taxonomy_find($uuid, $rank = null, $viewUuid = null){
455
 return cdm_ws_get(CDM_WS_TAXONOMY, null, queryString(array("uuid" => $uuid, 'rank'=>$rank)));
456
}
457

    
458
/**
459
 * Enter description here...
460
 *
461
 * @param unknown_type $secUuid
462
 * @param unknown_type $path
463
 * @return unknown
464
 */
465
function cdm_ws_taxonomy($path = null){
466
 return cdm_ws_get(cdm_ws_taxonomy_compose_resourcePath($path));
467
}
468

    
469
function cdm_ws_taxonomy_compose_resourcePath($path = null){
470
  $viewrank =  _cdm_taxonomy_compose_viewrank();
471
  return CDM_WS_TAXONOMY . '/' . ($viewrank ? $viewrank : '' ) . ($path ? '/' . $path : '') ;
472
}
473

    
474
/**
475
 * Enter description here...
476
 *
477
 * @param UUID $secUuid
478
 * @param String $path
479
 * @return unknown
480
 */
481
function cdm_ws_taxonomy_pathFromRoot($path){
482
 $viewrank =  _cdm_taxonomy_compose_viewrank();
483
 return cdm_ws_get(CDM_WS_TAXONOMY .  ($viewrank ? '/' .$viewrank : '' )  . '/' . $path . '/path' );
484
}
485

    
486
/**
487
 * Enter description here...
488
 *
489
 * @param UUID $viewUuid
490
 * @param String $rank
491
 * @return unknown
492
 */
493
function _cdm_taxonomy_compose_viewrank(){
494
  $viewUuid = variable_get('cdm_taxonomictree_uuid', false);
495
  if(!$viewUuid){
496
    return;
497
  }
498
  $rank = variable_get('taxontree_ranklimit', DEFAULT_TAXONTREE_RANKLIMIT);
499
  return $viewUuid . (empty($rank) ? '' : ','.$rank);
500
}
501

    
502

    
503
function cdm_rankVocabulary_as_option(){
504
  global $rankVocabularyOptions;
505
  if(!$rankVocabularyOptions){
506
    $vocab = cdm_ws_get(CDM_WS_TERMVOCABULARY, UUID_RANK);
507
    $rankVocabularyOptions = array();
508
    foreach($vocab->terms as $term){
509
      $rankVocabularyOptions[$term->uuid] = t($term->representation_L10n);
510
    }
511
    array_reverse($rankVocabularyOptions);
512
  }
513
  return $rankVocabularyOptions;
514
}
515

    
516

    
517
function cdm_ws_descriptions_by_featuretree($featureTree, $descriptions, $isDescriptionsSeparated = false){
518
  
519
  if(!$featureTree){
520
    drupal_set_message('cdm_ws_descriptions_by_featuretree() - No feature supplied', 'error');
521
    return false;
522
  }
523
  
524
  $mergedTrees = array();
525
  
526
  if($isDescriptionsSeparated){
527
    // merge any description into a sparate feature tree
528
    foreach($descriptions as $desc){
529
      $mergedNodes = _mergeFeatureTreeDesciptions($featureTree->root->children, $desc->elements);
530
      
531
      $mergedTree = clone $featureTree;
532
      $mergedTree->root->children = $mergedNodes;
533
      $mergedTrees[] = $mergedTree;
534
    }
535
  } else {
536
    // combine all descripions into one feature tree
537
    foreach($descriptions as $desc){
538
      $mergedNodes = _mergeFeatureTreeDesciptions($featureTree->root->children, $desc->elements);
539
      $featureTree->root->children = $mergedNodes;
540
    }
541
    $mergedTrees[] = $featureTree;
542
  }
543
  
544
 return $mergedTrees;
545
}
546

    
547
function _mergeFeatureTreeDesciptions($featureNodes, $descriptionElements){
548
  
549
  foreach($featureNodes as &$node){
550
    
551
    // append corresponding elements to an additional node field: $node->descriptionElements
552
    foreach($descriptionElements as $element){
553
      if($element->feature->uuid == $node->feature->uuid){
554
        if(!isset($node->descriptionElements)){
555
          $node->descriptionElements = array();
556
        }
557
        $node->descriptionElements[] = $element;
558
      }
559
    }
560
    
561
    // recurse into node children
562
    if(is_array($node->children)){
563
      foreach($node->children as $nodes){
564
        $mergedChildNodes = _mergeFeatureTreeDesciptions($nodes, $descriptionElements);
565
        $node->children = $mergedChildNodes;
566
      }
567
    }
568
    
569
  }
570
  return $featureNodes;
571
}
572

    
573

    
574
/**
575
 * Loads the XML or JSON response for the given url from the CDM Data Store Webservice.
576
 * The XML is turned into a object which is returned.
577
 *
578
 * @param String $uri the relative url of the web service call.
579
 *        Relative means relative to the web service base url which is stored in cdm_webservice_url
580
 * @param $is_multi_parameter_query parameter to indicate that the URI has queryparameters and should not be cached
581
 * @return An object or false
582
 */
583

    
584

    
585
/**
586
 * Send a HTTP GET request to the RESTService and deserializes
587
 * and returns the response as object
588
 *
589
 * @param $uri
590
 * @param $pathParameters
591
 * @param $query
592
 * @param $method the HTTP method to use, valuid values are "GET" or "POST";
593
 * @param $absoluteURI
594
 * @return unknown_type
595
 */
596
function cdm_ws_get($uri, $pathParameters = array(), $query = null, $method="GET", $absoluteURI = false){
597
  
598
  // transform the given uri path or patthern into a proper webservice uri
599
  if(!$absoluteURI){
600
    $uri = cdm_compose_url($uri, $pathParameters, $query);
601
  }
602
  
603
  $do_cache = variable_get('cdm_webservice_cache', 1); //strpos($uri, "?") !== FALSE; // if the url has a query parameter sting
604
  $cache_entry = false;
605
   
606
  if($do_cache){
607
    // try to get object from cache
608
    $cache_entry = cache_get($uri, 'cache_cdm_ws');
609
  }
610
  
611
  if(!$cache_entry){
612
    // load fresh data from webservice
613
    $time_get_start = microtime(true);
614
    // request data from webservice JSON or XML
615
    $datastr = cdm_http_request($uri, $method);
616
    $time_get = microtime(true) - $time_get_start;
617

    
618
    
619
    $time_parse_start = microtime(true);
620
    // parse data and create object
621
    $obj = cdm_load_obj($datastr);
622

    
623
    $time_parse = microtime(true) - $time_parse_start;
624
    if(variable_get('cdm_webservice_debug', 1) && user_access('administer')){
625
      $success_msg = $obj || $datastr == "[]" ? 'valid':'invalid';
626
      _add_debugMessage($uri, $time_get, $time_parse, strlen($datastr), $success_msg);
627
    }
628
    if($obj && $do_cache) {
629
      // store fresh data in cache
630
      cache_set($uri, 'cache_cdm_ws', serialize($obj), CACHE_TEMPORARY);
631
    }
632
  } else {
633
    $obj = unserialize($cache_entry->data);
634
    if(variable_get('cdm_webservice_debug', 1) && user_access('administer')){
635
      _add_status_message_toggler();
636
      drupal_set_message('Using cache for: '.$uri, 'debug');
637
    }
638
  }
639
  return $obj;
640
}
641

    
642
function _add_debugMessage($uri, $time_get, $time_parse, $datasize, $success_msg){
643
  
644
  static $cummulated_time_parse;
645
  static $cummulated_time_get;
646
  _add_status_message_toggler();
647
  
648
  $cummulated_time_get += $time_get;
649
  $cummulated_time_parse += $time_parse;
650
 
651
  $message = '<span class="uri">'.$uri.'</span><br />';
652
  $message .= '[fetched in: '.sprintf('%3.3f', $time_get).'s('.sprintf('%3.3f', $cummulated_time_get).'s); ';
653
  $message .= 'parsed in '.sprintf('%3.3f', $time_parse).' s('.sprintf('%3.3f', $cummulated_time_parse).'s); ';
654
  $message .= 'size:'.sprintf('%3.1f', ($datasize / 1024)).' kb of '.$success_msg.' data: ';
655
  $message .= '<a href="'.$uri.'.xml" target="data" class="'.$success_msg.'">xml</a>,';
656
  $message .= '<a href="'.$uri.'.json" target="data" class="'.$success_msg.'">json</a>';
657
  $message .= '] ';
658
  
659
  drupal_set_message($message, 'debug');
660

    
661
}
662

    
663

    
664
function cdm_load_obj($datastr){
665
     
666
  // if the web service delivers XML convert it into json
667
  if(variable_get('cdm_webservice_type', 'xml') == 'xml'){
668
    $datastr = xml2json::transformXmlStringToJson($datastr);
669
  }
670
  
671
  $obj = json_decode($datastr);
672
  
673
  
674
  if(!(is_object($obj) || is_array($obj)) ){
675
    ob_start();
676
    var_dump($obj);
677
    $obj_dump = ob_get_contents();
678
    ob_clean();
679
    return false;
680
  }
681

    
682
  return $obj;
683
}
684

    
685
/**
686
 *
687
 * @param $uri
688
 * @param $method the HTTP method to use, valuid values are "GET" or "POST"; efaults to "GET" even if null,
689
 *        false or any invalid value is supplied.
690
 * @param $parameters
691
 * @param $header
692
 * @return unknown_type
693
 */
694
function cdm_http_request($uri, $method="GET", $parameters = array(), $header = false){
695
  global $locale;  // drupal variable containing the current locale i.e. language
696
  static $header;
697
  
698
  if($method != "GET" && $method != "POST"){
699
    $method  = "GET";
700
  }
701
  
702
  if(!$header){
703
    $header = array();
704
    $header[] = 'Accept: '.(variable_get('cdm_webservice_type', 'json') == 'json' ? 'application/json' : 'text/xml');
705
    $header[] = 'Accept-Language: '.$locale;
706
    $header[] = 'Accept-Charset: UTF-8';
707
  }
708
  
709
  if(function_exists('curl_init')){
710

    
711
    // use the CURL lib if installed it is supposed to be 20x faster
712
    return _http_request_using_curl($uri, $header, $method, $parameters);
713
  } else {
714
    return _http_request_using_fsockopen($uri, $header, $method, $parameters);
715
  }
716
}
717

    
718
function _http_request_using_fsockopen($uri, $header = array(), $method = "GET"){
719
  //FIXME implement get_content_fsockopen($uri);
720
   watchdog('CDM_API', '_http_request_fsockopen - UNIMPLEMENTED', WATCHDOG_ERROR);
721
   return false;
722
}
723

    
724

    
725
/**
726
 * Return string content from a remote file
727
 *
728
 * @param string $uri
729
 * @return string
730
 *
731
 * @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
732
*/
733
function _http_request_using_curl($uri, $header = array(), $method = "GET", $parameters = array())
734
{
735
    $ch = curl_init();
736

    
737
    curl_setopt ($ch, CURLOPT_URL, $uri);
738
    // set proxy settings
739
    if(variable_get('cdm_webservice_proxy_url', false)){
740
      curl_setopt($ch, CURLOPT_PROXY, variable_get('cdm_webservice_proxy_url', ''));
741
      curl_setopt($ch, CURLOPT_PROXYPORT, variable_get('cdm_webservice_proxy_port', '80'));
742
      if(variable_get('cdm_webservice_proxy_usr', false)){
743
        curl_setopt ($ch, CURLOPT_PROXYUSERPWD, variable_get('cdm_webservice_proxy_usr', '').':'.variable_get('cdm_webservice_proxy_pwd', ''));
744
      }
745
    }
746
    // set headers
747
    curl_setopt ($ch, CURLOPT_HTTPHEADER, $header);
748
    // set method if not default
749
    if($method != "GET"){
750
      if($method == "POST"){
751
        
752
        curl_setopt ($ch, CURLOPT_POST, 1);
753
        curl_setopt ($ch, CURLOPT_POSTFIELDS, $parameters);
754
        
755
      }else{
756
        // other obscure http methods get passed to curl directly
757
        // TODO generic parameter/body handling
758
        curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $method);
759
      }
760
    }
761
    
762
    ob_start();
763
    curl_exec ($ch);
764
    if(curl_errno($ch)){
765
      watchdog('CDM_API', '_http_request_curl() - '.curl_error($ch).'; REQUEST-METHOD:'.$method.' URL: '.substr($uri.' ', 0, 150), WATCHDOG_ERROR);
766
        if(variable_get('cdm_webservice_debug', 1)  && user_access('administer') ){
767
          drupal_set_message('_http_request_curl() - '.curl_error($ch).'; REQUEST-METHOD:'.$method.' URL: '.substr($uri.' ', 0, 150), 'error');
768
        }
769
    }
770
    curl_close ($ch);
771
    $string = ob_get_contents();
772
    ob_end_clean();
773
 
774
    
775
    
776
    echo "Break for: ";
777
    print_r($string);
778
    exit;
779
    
780
    
781
    return $string;
782
}
783

    
784
function cdm_api_secref_cache_prefetch(&$secUuids){
785
  global $secref_cache;
786
  if(!is_array($secref_cache)){
787
    $secref_cache = array();
788
  }
789
  $uniqueUuids = array_unique($secUuids);
790
  $i = 0;
791
  $param = '';
792
  while($i++ < count($uniqueUuids)){
793
    $param .= $secUuids[$i].',';
794
    if(strlen($param) + 37 > 2000){
795
     _cdm_api_secref_cache_add($param);
796
      $param = '';
797
    }
798
  }
799
  if($param){
800
     _cdm_api_secref_cache_add($param);
801
  }
802
}
803

    
804
function cdm_api_secref_cache_get($secUuid){
805
  global $secref_cache;
806
  if(!is_array($secref_cache)){
807
    $secref_cache = array();
808
  }
809
  if(!array_key_exists($secUuid, $secref_cache)){
810
    _cdm_api_secref_cache_add($secUuid);
811
  }
812
  return $secref_cache[$secUuid];
813
}
814

    
815
function cdm_api_secref_cache_clear(){
816
  global $secref_cache;
817
  $secref_cache = array();
818
}
819

    
820
function _cdm_api_secref_cache_add($secUuidsStr){
821
  global $secref_cache;
822
  $ref = cdm_ws_get(CDM_WS_REFERENCE, $secUuidsStr);
823
  // batch fetching not jet reimplemented thus:
824
  /*$assocRefSTOs = array();
825
  if($refSTOs) {
826
    foreach($refSTOs as $ref){
827
      $assocRefSTOs[$ref->uuid] = $ref;
828
    }
829
    $secref_cache = array_merge($secref_cache, $assocRefSTOs);
830
  }*/
831
  $secref_cache[$ref->uuid] = $ref;
832
}
833

    
834
function queryString($elements) {
835
  $query = '';
836
  foreach($elements as $key=>$value){
837
    if(is_array($value)){
838
      foreach($value as $v){
839
        $query .= (strlen($query) > 0 ? '&' : '').$key.'='.urlencode($v);
840
      }
841
    } else{
842
      $query .= (strlen($query) > 0 ? '&' : '').$key.'='.urlencode($value);
843
    }
844
  }
845
  return $query;
846
}
847

    
848
/**
849
 * implementation of the magic method __clone to allow deep cloning of objects and arrays
850
 */
851
function __clone(){
852
    foreach($this as $name => $value){
853
        if(gettype($value)=='object' || gettype($value)=='array'){
854
            $this->$name= clone($this->$name);
855
        }
856
    }
857
}
858

    
859
/**
860
 * Make a complete deep copy of an array replacing
861
 * references with deep copies until a certain depth is reached
862
 * ($maxdepth) whereupon references are copied as-is...
863
 * [From http://us3.php.net/manual/en/ref.array.php]
864
 * @param $array
865
 * @param $copy
866
 * @param $maxdepth
867
 * @param $depth
868
 * @return unknown_type
869
 */
870
function array_deep_copy (&$array, &$copy, $maxdepth=50, $depth=0) {
871
    if($depth > $maxdepth) { $copy = $array; return; }
872
    if(!is_array($copy)) $copy = array();
873
    foreach($array as $k => &$v) {
874
        if(is_array($v)) {        array_deep_copy($v,$copy[$k],$maxdepth,++$depth);
875
        } else {
876
            $copy[$k] = $v;
877
        }
878
    }
879
}
880

    
881
/**
882
 * Implementation of theme_status_messages($display = NULL)
883
 * @see includes/theme.inc
884
 *
885
 * @param $display
886
 * @return unknown_type
887
 */
888
function _add_status_message_toggler() {
889
  static $isAdded;
890
  if(!$isAdded){
891
    
892
    drupal_add_js(
893
          '$(document).ready(function(){
894
          
895
            $(\'.messages.debug\').before( \'<h6 class="messages_toggler debug">Debug Messages (klick to toggle)</h6>\' );
896
            $(\'.messages_toggler\').click(function(){
897
              $(this).next().slideToggle(\'fast\');
898
                return false;
899
            }).next().hide();
900
            
901
          });'
902
          , 'inline');
903
    $isAdded = TRUE;
904
  }
905
}
906

    
907

    
908
define('CDM_WS_NAME', 'name');
909

    
910
define('CDM_WS_NAME_TYPEDESIGNATIONS', 'name/$0/typeDesignations');
911

    
912
define('CDM_WS_TAXON_NAMETYPEDESIGNATIONS', 'portal/taxon/$0/nameTypeDesignations');
913

    
914
define('CDM_WS_TAXON_DESCRIPTIONS', 'portal/taxon/$0/descriptions');
915

    
916
define('CDM_WS_NAME_DESCRIPTIONS', 'portal/name/$0/descriptions');
917

    
918
define('CDM_WS_REFERENCE', 'reference');
919

    
920

    
921
define('CDM_WS_NOMENCLATURAL_REFERENCE_CITATION', 'reference/$0/nomenclaturalCitation/$1');
922

    
923
define('CDM_WS_FIND_TAXA', 'portal/taxon/find');
924

    
925
define('CDM_WS_TAXON', 'portal/taxon');
926

    
927
/**
928
 * @parameters $0 : the taxon uuid
929
 *
930
 * @returns
931
 */
932
define('CDM_WS_TAXON_SYNONYMY', 'portal/taxon/$0/synonymy');
933

    
934
define('CDM_WS_TAXON_RELATIONS', 'portal/taxon/$0/taxonRelationships');
935

    
936
define('CDM_WS_TAXON_NAMERELATIONS', 'portal/taxon/$0/nameRelationships');
937

    
938

    
939
/**
940
 * @parameters $0 : the taxon uuid
941
 *
942
 * @returns the taxon which is the accepted synonym for the taxon given as
943
 * parameter taxonUuid. If the taxon specified by taxonUuid is itself the
944
 * accepted taxon, this one will be returned.
945
 */
946
define('CDM_WS_TAXON_ACCEPTED', 'portal/taxon/$0/accepted');
947

    
948
define('CDM_WS_TAXON_MEDIA', 'portal/taxon/$0/media/$1/$2');
949

    
950
/**
951
 *
952
 * Gets the root nodes of the taxonomic concept tree for the concept
953
 * reference specified by the secUuid parameter.
954
 *
955
 * stub: treenode_root
956
 */
957
define('CDM_WS_TAXONOMY', 'taxontree');
958

    
959
define('CDM_WS_TERMVOCABULARY', 'term/$0');
960

    
961
define('CDM_WS_TERM_COMPARE', 'term/$0/compareTo/$1');
962

    
963
define('CDM_WS_TDWG_LEVEL', 'term/tdwg/$0');
964

    
965
/**
966
 * returns FeatureTrees that are stored in this community store
967
 *
968
 */
969
define('CDM_WS_FEATURETREE', 'featuretree/$0');
970

    
971
define('CDM_WS_FEATURETREES', 'featuretree');
972

    
973
define('CDM_WS_GEOSERVICE_DISTRIBUTIONMAP', 'geo/map/distribution/$0');
(4-4/7)