ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilBMFWSDL.php
Go to the documentation of this file.
1<?php
25require_once dirname(__FILE__).'/class.ilBMFBase.php';
26require_once dirname(__FILE__).'/class.ilBMFFault.php';
27require_once 'HTTP/Request.php';
28
29define('WSDL_CACHE_MAX_AGE', 43200);
30define('WSDL_CACHE_USE', 0); // set to zero to turn off caching
31
49class ilBMFWSDL extends ilBMFBase
50{
51 var $tns = null;
52 var $definition = array();
53 var $namespaces = array();
54 var $ns = array();
56 var $complexTypes = array();
57 var $elements = array();
58 var $messages = array();
59 var $portTypes = array();
60 var $bindings = array();
61 var $imports = array();
62 var $services = array();
63 var $service = '';
64 var $uri = '';
65 var $docs = false;
66
72 var $proxy = null;
73
74 var $trace = 0;
75
81 var $cacheUse = null;
82
88 var $cacheMaxAge = null;
89
96 var $wsdlParserClass = 'ilBMFWSDL_Parser';
97
111 function ilBMFWSDL($wsdl_uri = false,
112 $proxy = array(),
115 $docs = false)
116 {
117 parent::ilBMFBase('WSDL');
118 $this->uri = $wsdl_uri;
119 $this->proxy = $proxy;
120 $this->cacheUse = $cacheUse;
121 $this->cacheMaxAge = $cacheMaxAge;
122 $this->docs = $docs;
123
124 if ($wsdl_uri) {
125 if (!PEAR::isError($this->parseURL($wsdl_uri))) {
126 reset($this->services);
127 $this->service = key($this->services);
128 }
129 }
130 }
131
133 {
134 if (array_key_exists($service, $this->services)) {
135 $this->service = $service;
136 }
137 }
138
142 function parse($wsdl_uri, $proxy = array())
143 {
144 $this->parseURL($wsdl_uri, $proxy);
145 }
146
154 function parseURL($wsdl_uri, $proxy = array())
155 {
156 $parser =& new $this->wsdlParserClass($wsdl_uri, $this, $this->docs);
157
158 if ($parser->fault) {
159 $this->_raiseSoapFault($parser->fault);
160 }
161 }
162
174 function parseObject(&$wsdl_obj, $targetNamespace, $service_name,
175 $service_desc = '')
176 {
177 $parser =& new ilBMFWSDL_ObjectParser($wsdl_obj, $this,
178 $targetNamespace, $service_name,
179 $service_desc);
180
181 if ($parser->fault) {
182 $this->_raiseSoapFault($parser->fault);
183 }
184 }
185
186 function getEndpoint($portName)
187 {
188 if ($this->__isfault()) {
189 return $this->__getfault();
190 }
191
192 return (isset($this->services[$this->service]['ports'][$portName]['address']['location']))
193 ? $this->services[$this->service]['ports'][$portName]['address']['location']
194 : $this->_raiseSoapFault("No endpoint for port for $portName", $this->uri);
195 }
196
197 function _getPortName($operation, $service)
198 {
199 if (isset($this->services[$service]['ports'])) {
200 $ports = $this->services[$service]['ports'];
201 foreach ($ports as $port => $portAttrs) {
202 $type = $ports[$port]['type'];
203 if ($type == 'soap' &&
204 isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) {
205 return $port;
206 }
207 }
208 }
209 return null;
210 }
211
216 function getPortName($operation, $service = null)
217 {
218 if ($this->__isfault()) {
219 return $this->__getfault();
220 }
221
222 if (!$service) {
224 }
225 if (isset($this->services[$service]['ports'])) {
226 if ($portName = $this->_getPortName($operation, $service)) {
227 return $portName;
228 }
229 }
230 // Try any service in the WSDL.
231 foreach ($this->services as $serviceName => $service) {
232 if (isset($this->services[$serviceName]['ports'])) {
233 if ($portName = $this->_getPortName($operation, $serviceName)) {
234 $this->service = $serviceName;
235 return $portName;
236 }
237 }
238 }
239 return $this->_raiseSoapFault("No operation $operation in WSDL.", $this->uri);
240 }
241
242 function getOperationData($portName, $operation)
243 {
244 if ($this->__isfault()) {
245 return $this->__getfault();
246 }
247
248 if (!isset($this->services[$this->service]['ports'][$portName]['binding']) ||
249 !($binding = $this->services[$this->service]['ports'][$portName]['binding'])) {
250 return $this->_raiseSoapFault("No binding for port $portName in WSDL.", $this->uri);
251 }
252
253 // Get operation data from binding.
254 if (is_array($this->bindings[$binding]['operations'][$operation])) {
255 $opData = $this->bindings[$binding]['operations'][$operation];
256 }
257 // get operation data from porttype
258 $portType = $this->bindings[$binding]['type'];
259 if (!$portType) {
260 return $this->_raiseSoapFault("No port type for binding $binding in WSDL.", $this->uri);
261 }
262 if (is_array($type = $this->portTypes[$portType][$operation])) {
263 if (isset($type['parameterOrder'])) {
264 $opData['parameterOrder'] = $type['parameterOrder'];
265 }
266 $opData['input'] = array_merge($opData['input'], $type['input']);
267 $opData['output'] = array_merge($opData['output'], $type['output']);
268 }
269 if (!$opData)
270 return $this->_raiseSoapFault("No operation $operation for port $portName in WSDL.", $this->uri);
271 $opData['parameters'] = false;
272 if (isset($this->bindings[$binding]['operations'][$operation]['input']['namespace']))
273 $opData['namespace'] = $this->bindings[$binding]['operations'][$operation]['input']['namespace'];
274 // Message data from messages.
275 $inputMsg = $opData['input']['message'];
276 if (is_array($this->messages[$inputMsg])) {
277 foreach ($this->messages[$inputMsg] as $pname => $pattrs) {
278 if ($opData['style'] == 'document' &&
279 $opData['input']['use'] == 'literal' &&
280 $pname == 'parameters') {
281 $opData['parameters'] = true;
282 $opData['namespace'] = $this->namespaces[$pattrs['namespace']];
283 $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
284 if (isset($el['elements'])) {
285 foreach ($el['elements'] as $elname => $elattrs) {
286 $opData['input']['parts'][$elname] = $elattrs;
287 }
288 }
289 } else {
290 $opData['input']['parts'][$pname] = $pattrs;
291 }
292 }
293 }
294 $outputMsg = $opData['output']['message'];
295 if (is_array($this->messages[$outputMsg])) {
296 foreach ($this->messages[$outputMsg] as $pname => $pattrs) {
297 if ($opData['style'] == 'document' &&
298 $opData['output']['use'] == 'literal' &&
299 $pname == 'parameters') {
300
301 $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
302 if (isset($el['elements'])) {
303 foreach ($el['elements'] as $elname => $elattrs) {
304 $opData['output']['parts'][$elname] = $elattrs;
305 }
306 }
307 } else {
308 $opData['output']['parts'][$pname] = $pattrs;
309 }
310 }
311 }
312 return $opData;
313 }
314
315 function matchMethod(&$operation)
316 {
317 if ($this->__isfault()) {
318 return $this->__getfault();
319 }
320
321 // Overloading lowercases function names :(
322 foreach ($this->services[$this->service]['ports'] as $port => $portAttrs) {
323 foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) {
324 if (strcasecmp($op, $operation) == 0) {
325 $operation = $op;
326 }
327 }
328 }
329 }
330
342 function getDataHandler($datatype, $namespace)
343 {
344 // See if we have an element by this name.
345 if (isset($this->namespaces[$namespace])) {
346 $namespace = $this->namespaces[$namespace];
347 }
348
349 if (isset($this->ns[$namespace])) {
350 $nsp = $this->ns[$namespace];
351 //if (!isset($this->elements[$nsp]))
352 // $nsp = $this->namespaces[$nsp];
353 if (isset($this->elements[$nsp][$datatype])) {
354 $checkmessages = array();
355 // Find what messages use this datatype.
356 foreach ($this->messages as $messagename => $message) {
357 foreach ($message as $partname => $part) {
358 if ($part['type'] == $datatype) {
359 $checkmessages[] = $messagename;
360 break;
361 }
362 }
363 }
364 // Find the operation that uses this message.
365 $dataHandler = null;
366 foreach($this->portTypes as $portname => $porttype) {
367 foreach ($porttype as $opname => $opinfo) {
368 foreach ($checkmessages as $messagename) {
369 if ($opinfo['input']['message'] == $messagename) {
370 return $opname;
371 }
372 }
373 }
374 }
375 }
376 }
377
378 return null;
379 }
380
381 function getSoapAction($portName, $operation)
382 {
383 if ($this->__isfault()) {
384 return $this->__getfault();
385 }
386
387 if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'])) {
388 return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'];
389 }
390
391 return false;
392 }
393
394 function getNamespace($portName, $operation)
395 {
396 if ($this->__isfault()) {
397 return $this->__getfault();
398 }
399
400 if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'])) {
401 return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'];
402 }
403
404 return false;
405 }
406
408 {
409 /* If it doesn't exist at first, flip the array and check again. */
410 if (empty($this->ns[$namespace])) {
411 $this->ns = array_flip($this->namespaces);
412 }
413
414 /* If it doesn't exist now, add it. */
415 if (empty($this->ns[$namespace])) {
416 return $this->addNamespace($namespace);
417 }
418
419 return $this->ns[$namespace];
420 }
421
423 {
424 if (!empty($this->ns[$namespace])) {
425 return $this->ns[$namespace];
426 }
427
428 $n = count($this->ns);
429 $attr = 'ns' . $n;
430 $this->namespaces['ns' . $n] = $namespace;
431 $this->ns[$namespace] = $attr;
432
433 return $attr;
434 }
435
436 function _validateString($string)
437 {
438 return preg_match('/^[\w_:#\/]+$/', $string);
439 }
440
441 function _addArg(&$args, &$argarray, $argname)
442 {
443 if ($args) {
444 $args .= ', ';
445 }
446 $args .= '$' . $argname;
447 if (!$this->_validateString($argname)) {
448 return;
449 }
450 if ($argarray) {
451 $argarray .= ', ';
452 }
453 $argarray .= "'$argname' => $" . $argname;
454 }
455
456 function _elementArg(&$args, &$argarray, &$_argtype, $_argname)
457 {
458 $comments = '';
459 $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
460 $tns = isset($this->ns[$el['namespace']])
461 ? $this->ns[$el['namespace']]
462 : $_argtype['namespace'];
463
464 if (!empty($el['complex']) ||
465 (isset($el['type']) &&
466 isset($this->complexTypes[$tns][$el['type']]))) {
467 // The element is a complex type.
468 $comments .= " // {$_argtype['type']} is a ComplexType, refer to the WSDL for more info.\n";
469 $attrname = "{$_argtype['type']}_attr";
470 if (isset($el['type']) &&
471 isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
472 $comments .= " // {$_argtype['type']} may require attributes, refer to the WSDL for more info.\n";
473 }
474 $comments .= " \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n";
475 $comments .= " \${$_argtype['type']} =& new ilBMFValue('{$_argtype['type']}', false, \${$_argtype['type']}, \$$attrname);\n";
476 $this->_addArg($args, $argarray, $_argtype['type']);
477 if (isset($el['type']) &&
478 isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
479 if ($args) {
480 $args .= ', ';
481 }
482 $args .= '$' . $attrname;
483 }
484 } elseif (isset($el['elements'])) {
485 foreach ($el['elements'] as $ename => $element) {
486 $comments .= " \$$ename =& new ilBMFValue('{{$this->namespaces[$element['namespace']]}}$ename', '" .
487 (isset($element['type']) ? $element['type'] : false) .
488 "', \$$ename);\n";
489 $this->_addArg($args, $argarray, $ename);
490 }
491 } else {
492 $comments .= " \$$_argname =& new ilBMFValue('{{$this->namespaces[$tns]}}$_argname', '{$el['type']}', \$$_argname);\n";
493 $this->_addArg($args, $argarray, $_argname);
494 }
495
496 return $comments;
497 }
498
499 function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname)
500 {
501 $comments = '';
502 if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) {
503 $comments = " // $_argname is a ComplexType {$_argtype['type']},\n" .
504 " // refer to wsdl for more info\n";
505 if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) {
506 $comments .= " // $_argname may require attributes, refer to wsdl for more info\n";
507 }
508 $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $_argtype['type'];
509 $comments .= " \$$_argname =& new ilBMFValue('$_argname', '$wrapname', \$$_argname);\n";
510 }
511
512 $this->_addArg($args, $argarray, $_argname);
513
514 return $comments;
515 }
516
521 function generateProxyCode($port = '', $classname = '')
522 {
523 if ($this->__isfault()) {
524 return $this->__getfault();
525 }
526
527 $multiport = count($this->services[$this->service]['ports']) > 1;
528 if (!$port) {
529 reset($this->services[$this->service]['ports']);
530 $port = current($this->services[$this->service]['ports']);
531 }
532 // XXX currently do not support HTTP ports
533 if ($port['type'] != 'soap') {
534 return null;
535 }
536
537 // XXX currentPort is BAD
538 $clienturl = $port['address']['location'];
539 if (!$classname) {
540 if ($multiport || $port) {
541 $classname = 'WebService_' . $this->service . '_' . $port['name'];
542 } else {
543 $classname = 'WebService_' . $this->service;
544 }
545 $classname = preg_replace('/[ .\-\‍(\‍)]+/', '_', $classname);
546 }
547
548 if (!$this->_validateString($classname)) {
549 return null;
550 }
551
552 if (is_array($this->proxy) && count($this->proxy)) {
553 $class = "class $classname extends ilBMFClient\n{\n" .
554 " function $classname(\$path = '$clienturl')\n {\n" .
555 " \$this->ilBMFClient(\$path, 0, 0,\n" .
556 ' array(';
557
558 foreach ($this->proxy as $key => $val) {
559 if (is_array($val)) {
560 $class .= "'$key' => array(";
561 foreach ($val as $key2 => $val2) {
562 $class .= "'$key2' => '$val2', ";
563 }
564 $class .= ')';
565 } else {
566 $class .= "'$key' => '$val', ";
567 }
568 }
569 $class .= "));\n }\n";
570 $class = str_replace(', ))', '))', $class);
571 } else {
572 $class = "class $classname extends ilBMFClient\n{\n" .
573 " function $classname(\$path = '$clienturl')\n {\n" .
574 " \$this->ilBMFClient(\$path, 0);\n" .
575 " }\n";
576 }
577
578 // Get the binding, from that get the port type.
579 $primaryBinding = $port['binding'];
580 $primaryBinding = preg_replace("/^(.*:)/", '', $primaryBinding);
581 $portType = $this->bindings[$primaryBinding]['type'];
582 $portType = preg_replace("/^(.*:)/", '', $portType);
583 $style = $this->bindings[$primaryBinding]['style'];
584
585 // XXX currentPortType is BAD
586 foreach ($this->portTypes[$portType] as $opname => $operation) {
587 $binding = $this->bindings[$primaryBinding]['operations'][$opname];
588 if (isset($binding['soapAction'])) {
589 $soapaction = $binding['soapAction'];
590 } else {
591 $soapaction = null;
592 }
593 if (isset($binding['style'])) {
594 $opstyle = $binding['style'];
595 } else {
596 $opstyle = $style;
597 }
598 $use = $binding['input']['use'];
599 if ($use == 'encoded') {
600 $namespace = $binding['input']['namespace'];
601 } else {
602 $bindingType = $this->bindings[$primaryBinding]['type'];
603 $ns = $this->portTypes[$bindingType][$opname]['input']['namespace'];
604 $namespace = $this->namespaces[$ns];
605 }
606
607 $args = '';
608 $argarray = '';
609 $comments = '';
610 $wrappers = '';
611 foreach ($operation['input'] as $argname => $argtype) {
612 if ($argname == 'message') {
613 foreach ($this->messages[$argtype] as $_argname => $_argtype) {
614 if ($opstyle == 'document' && $use == 'literal' &&
615 $_argtype['name'] == 'parameters') {
616 // The type or element refered to is used for
617 // parameters.
618 $elattrs = null;
619 $element = $_argtype['element'];
620 $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
621
622 if ($el['complex']) {
623 $namespace = $this->namespaces[$_argtype['namespace']];
624 // XXX need to wrap the parameters in a
625 // ilBMFValue.
626 }
627 if (isset($el['elements'])) {
628 foreach ($el['elements'] as $elname => $elattrs) {
629 // Is the element a complex type?
630 if (isset($this->complexTypes[$elattrs['namespace']][$elname])) {
631 $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
632 } else {
633 $this->_addArg($args, $argarray, $elname);
634 }
635 }
636 }
637 if ($el['complex'] && $argarray) {
638 $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $el['name'];
639 $comments .= " \${$el['name']} =& new ilBMFValue('$wrapname', false, \$v = array($argarray));\n";
640 $argarray = "'{$el['name']}' => \${$el['name']}";
641 }
642 } else {
643 if (isset($_argtype['element'])) {
644 // Element argument.
645 $comments .= $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']);
646 } else {
647 // Complex type argument.
648 $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
649 }
650 }
651 }
652 }
653 }
654
655 // Validate entries.
656
657 // Operation names are function names, so try to make sure it's
658 // legal. This could potentially cause collisions, but let's try
659 // to make everything callable and see how many problems that
660 // causes.
661 $opname_php = preg_replace('/[ .\-\‍(\‍)]+/', '_', $opname);
662 if (!$this->_validateString($opname_php)) {
663 return null;
664 }
665
666 if ($argarray) {
667 $argarray = "array($argarray)";
668 } else {
669 $argarray = 'null';
670 }
671
672 $class .= " function &$opname_php($args)\n {\n$comments$wrappers" .
673 " \$result = \$this->call('$opname',\n" .
674 " \$v = $argarray,\n" .
675 " array('namespace' => '$namespace',\n" .
676 " 'soapaction' => '$soapaction',\n" .
677 " 'style' => '$opstyle',\n" .
678 " 'use' => '$use'" .
679 ($this->trace?",\n 'trace' => 1" : '') . "));\n" .
680 " return \$result;\n" .
681 " }\n";
682 }
683
684 $class .= "}\n";
685
686 return $class;
687 }
688
690 {
691 $proxycode = '';
692 foreach (array_keys($this->services[$this->service]['ports']) as $key) {
693 $port =& $this->services[$this->service]['ports'][$key];
694 $proxycode .= $this->generateProxyCode($port);
695 }
696 return $proxycode;
697 }
698
699 function &getProxy($port = '', $name = '')
700 {
701 if ($this->__isfault()) {
702 $fault =& $this->__getfault();
703 return $fault;
704 }
705
706 $multiport = count($this->services[$this->service]['ports']) > 1;
707
708 if (!$port) {
709 reset($this->services[$this->service]['ports']);
710 $port = current($this->services[$this->service]['ports']);
711 }
712
713 if ($multiport || $port) {
714 $classname = 'WebService_' . $this->service . '_' . $port['name'];
715 } else {
716 $classname = 'WebService_' . $this->service;
717 }
718
719 if ($name) {
720 $classname = $name . '_' . $classname;
721 }
722
723 $classname = preg_replace('/[ .\-\‍(\‍)]+/', '_', $classname);
724 if (!class_exists($classname)) {
725 $proxy = $this->generateProxyCode($port, $classname);
726 require_once 'SOAP/Client.php';
727 eval($proxy);
728 }
729 $proxy =& new $classname;
730
731 return $proxy;
732 }
733
735 {
736 $t = null;
737 if (isset($this->ns[$namespace]) &&
738 isset($this->elements[$this->ns[$namespace]][$name]['type'])) {
739
740 $type = $this->elements[$this->ns[$namespace]][$name]['type'];
741 $ns = $this->elements[$this->ns[$namespace]][$name]['namespace'];
742
743 if (isset($this->complexTypes[$ns][$type])) {
744 $t = $this->complexTypes[$ns][$type];
745 }
746 }
747 return $t;
748 }
749
751 {
752 $t = $this->_getComplexTypeForElement($name, $namespace);
753 if ($t) {
754 return $t['name'];
755 }
756 return null;
757 }
758
759 function getComplexTypeChildType($ns, $name, $child_ns, $child_name)
760 {
761 // is the type an element?
762 $t = $this->_getComplexTypeForElement($name, $ns);
763 if ($t) {
764 // no, get it from complex types directly
765 if (isset($t['elements'][$child_name]['type']))
766 return $t['elements'][$child_name]['type'];
767 }
768 return null;
769 }
770
771 function getSchemaType($type, $name, $type_namespace)
772 {
773 // see if it's a complex type so we can deal properly with
774 // SOAPENC:arrayType.
775 if ($name && $type) {
776 // XXX TODO:
777 // look up the name in the wsdl and validate the type.
778 foreach ($this->complexTypes as $ns => $types) {
779 if (array_key_exists($type, $types)) {
780 if (array_key_exists('type', $types[$type])) {
781 list($arraytype_ns, $arraytype, $array_depth) = isset($types[$type]['arrayType'])?
782 $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType'])
783 : array($this->namespaces[$types[$type]['namespace']], null, 0);
784 return array($types[$type]['type'], $arraytype, $arraytype_ns, $array_depth);
785 }
786 if (array_key_exists('arrayType', $types[$type])) {
787 list($arraytype_ns, $arraytype, $array_depth) =
788 $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType']);
789 return array('Array', $arraytype, $arraytype_ns, $array_depth);
790 }
791 if (array_key_exists('elements', $types[$type]) &&
792 array_key_exists($name, $types[$type]['elements'])) {
793 $type = $types[$type]['elements']['type'];
794 return array($type, null, $this->namespaces[$types[$type]['namespace']], null);
795 }
796 }
797 }
798 }
799 if ($type && $type_namespace) {
800 $arrayType = null;
801 // XXX TODO:
802 // this code currently handles only one way of encoding array types in wsdl
803 // need to do a generalized function to figure out complex types
804 $p = $this->ns[$type_namespace];
805 if ($p &&
806 array_key_exists($p, $this->complexTypes) &&
807 array_key_exists($type, $this->complexTypes[$p])) {
808 if ($arrayType = $this->complexTypes[$p][$type]['arrayType']) {
809 $type = 'Array';
810 } elseif ($this->complexTypes[$p][$type]['order']=='sequence' &&
811 array_key_exists('elements', $this->complexTypes[$p][$type])) {
812 reset($this->complexTypes[$p][$type]['elements']);
813 // assume an array
814 if (count($this->complexTypes[$p][$type]['elements']) == 1) {
815 $arg = current($this->complexTypes[$p][$type]['elements']);
816 $arrayType = $arg['type'];
817 $type = 'Array';
818 } else {
819 foreach ($this->complexTypes[$p][$type]['elements'] as $element) {
820 if ($element['name'] == $type) {
821 $arrayType = $element['type'];
822 $type = $element['type'];
823 }
824 }
825 }
826 } else {
827 $type = 'Struct';
828 }
829 return array($type, $arrayType, $type_namespace, null);
830 }
831 }
832 return array(null, null, null, null);
833 }
834
846 function _getDeepestArrayType($nsPrefix, $arrayType)
847 {
848 static $trail = array();
849
850 $arrayType = ereg_replace('\[\]$', '', $arrayType);
851
852 // Protect against circular references XXX We really need to remove
853 // trail from this altogether (it's very inefficient and in the wrong
854 // place!) and put circular reference checking in when the WSDL info
855 // is generated in the first place
856 if (array_search($nsPrefix . ':' . $arrayType, $trail)) {
857 return array(null, null, -count($trail));
858 }
859
860 if (array_key_exists($nsPrefix, $this->complexTypes) &&
861 array_key_exists($arrayType, $this->complexTypes[$nsPrefix]) &&
862 array_key_exists('arrayType', $this->complexTypes[$nsPrefix][$arrayType])) {
863 $trail[] = $nsPrefix . ':' . $arrayType;
864 $result = $this->_getDeepestArrayType($this->complexTypes[$nsPrefix][$arrayType]['namespace'],
865 $this->complexTypes[$nsPrefix][$arrayType]['arrayType']);
866 return array($result[0], $result[1], $result[2] + 1);
867 }
868 return array($this->namespaces[$nsPrefix], $arrayType, 0);
869 }
870
871}
872
874{
875 // Cache settings
876
882 var $_cacheUse = null;
883
889 var $_cacheMaxAge = null;
890
898 function ilBMFWSDL_Cache($cacheUse = WSDL_CACHE_USE,
899 $cacheMaxAge = WSDL_CACHE_MAX_AGE)
900 {
901 parent::ilBMFBase('WSDLCACHE');
902 $this->_cacheUse = $cacheUse;
903 $this->_cacheMaxAge = $cacheMaxAge;
904 }
905
910 function _cacheDir()
911 {
912 $dir = getenv("WSDLCACHE");
913 if (!$dir) $dir = " ./wsdlcache";
914 @mkdir($dir, 0700);
915 return $dir;
916 }
917
928 function get($wsdl_fname, $proxy_params = array(), $cache = 0)
929 {
930 $cachename = $md5_wsdl = $file_data = '';
931 if ($this->_cacheUse) {
932 // Try to retrieve WSDL from cache
933 $cachename = ilBMFWSDL_Cache::_cacheDir() . '/' . md5($wsdl_fname). ' .wsdl';
934 if (file_exists($cachename)) {
935 $wf = fopen($cachename, 'rb');
936 if ($wf) {
937 // Reading cached file
938 $file_data = fread($wf, filesize($cachename));
939 $md5_wsdl = md5($file_data);
940 fclose($wf);
941 }
942 if ($cache) {
943 if ($cache != $md5_wsdl) {
944 return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname);
945 }
946 } else {
947 $fi = stat($cachename);
948 $cache_mtime = $fi[8];
949 //print cache_mtime, time()
950 if ($cache_mtime + $this->_cacheMaxAge < time()) {
951 // expired
952 $md5_wsdl = ''; // refetch
953 }
954 }
955 }
956 }
957
958 if (!$md5_wsdl) {
959 // Not cached or not using cache. Retrieve WSDL from URL
960
961 // is it a local file?
962 // this section should be replace by curl at some point
963 if (!preg_match('/^(https?|file):\/\//', $wsdl_fname)) {
964 if (!file_exists($wsdl_fname)) {
965 return $this->_raiseSoapFault("Unable to read local WSDL $wsdl_fname", $wsdl_fname);
966 }
967 if (function_exists('file_get_contents')) {
968 $file_data = file_get_contents($wsdl_fname);
969 } else {
970 $file_data = implode('',file($wsdl_fname));
971 }
972 } else {
973 $uri = explode('?', $wsdl_fname);
974 $rq =& new HTTP_Request($uri[0], $proxy_params);
975 // the user agent HTTP_Request uses fouls things up
976 if (isset($uri[1])) {
977 $rq->addRawQueryString($uri[1]);
978 }
979
980 if (isset($proxy_params['proxy_host']) &&
981 isset($proxy_params['proxy_port']) &&
982 isset($proxy_params['proxy_user']) &&
983 isset($proxy_params['proxy_pass'])) {
984 $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port'],
985 $proxy_params['proxy_user'], $proxy_params['proxy_pass']);
986 } elseif (isset($proxy_params['proxy_host']) &&
987 isset($proxy_params['proxy_port'])) {
988 $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port']);
989 }
990
991 $result = $rq->sendRequest();
992 if (PEAR::isError($result)) {
993 return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname," . $rq->getResponseCode(), $wsdl_fname);
994 }
995 $file_data = $rq->getResponseBody();
996 if (!$file_data) {
997 return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, no http body", $wsdl_fname);
998 }
999 }
1000
1001 $md5_wsdl = md5($file_data);
1002
1003 if ($this->_cacheUse) {
1004 $fp = fopen($cachename, "wb");
1005 fwrite($fp, $file_data);
1006 fclose($fp);
1007 }
1008 }
1009 if ($this->_cacheUse && $cache && $cache != $md5_wsdl) {
1010 return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname);
1011 }
1012 return $file_data;
1013 }
1014
1015}
1016
1018{
1019
1029
1034
1035 var $tns = null;
1036 var $soapns = array('soap');
1037 var $uri = '';
1038 var $wsdl = null;
1039
1040 var $status = '';
1041 var $element_stack = array();
1043
1044 var $schema = '';
1046 var $schema_stack = array();
1050
1054 function ilBMFWSDL_Parser($uri, &$wsdl, $docs = false)
1055 {
1056 parent::ilBMFBase('WSDLPARSER');
1057 $this->cache =& new ilBMFWSDL_Cache($wsdl->cacheUse, $wsdl->cacheMaxAge);
1058 $this->uri = $uri;
1059 $this->wsdl = &$wsdl;
1060 $this->docs = $docs;
1061 $this->parse($uri);
1062 }
1063
1064 function parse($uri)
1065 {
1066 // Check whether content has been read.
1067 $fd = $this->cache->get($uri, $this->wsdl->proxy);
1068 if (PEAR::isError($fd)) {
1069 return $this->_raiseSoapFault($fd);
1070 }
1071
1072 // Create an XML parser.
1073 $parser = xml_parser_create();
1074 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
1075 xml_set_object($parser, $this);
1076 xml_set_element_handler($parser, 'startElement', 'endElement');
1077 if ($this->docs) {
1078 xml_set_character_data_handler($parser, 'characterData');
1079 }
1080
1081 if (!xml_parse($parser, $fd, true)) {
1082 $detail = sprintf('XML error on line %d: %s',
1083 xml_get_current_line_number($parser),
1084 xml_error_string(xml_get_error_code($parser)));
1085 return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail");
1086 }
1087 xml_parser_free($parser);
1088 return true;
1089 }
1090
1094 function startElement($parser, $name, $attrs)
1095 {
1096 // Get element prefix.
1097 $qname =& new QName($name);
1098 if ($qname->ns) {
1099 $ns = $qname->ns;
1100 if ($ns && ((!$this->tns && strcasecmp($qname->name, 'definitions') == 0) || $ns == $this->tns)) {
1101 $name = $qname->name;
1102 }
1103 }
1104 $this->currentTag = $qname->name;
1105 $this->parentElement = '';
1106 $stack_size = count($this->element_stack);
1107 if ($stack_size) {
1108 $this->parentElement = $this->element_stack[$stack_size - 1];
1109 }
1110 $this->element_stack[] = $this->currentTag;
1111
1112 // Find status, register data.
1113 switch ($this->status) {
1114 case 'types':
1115 // sect 2.2 wsdl:types
1116 // children: xsd:schema
1117 $parent_tag = '';
1118 $stack_size = count($this->schema_stack);
1119 if ($stack_size) {
1120 $parent_tag = $this->schema_stack[$stack_size - 1];
1121 }
1122
1123 switch ($qname->name) {
1124 case 'schema':
1125 // No parent should be in the stack.
1126 if (!$parent_tag || $parent_tag == 'types') {
1127 if (array_key_exists('targetNamespace', $attrs)) {
1128 $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
1129 } else {
1130 $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
1131 }
1132 $this->wsdl->complexTypes[$this->schema] = array();
1133 $this->wsdl->elements[$this->schema] = array();
1134 }
1135 break;
1136
1137 case 'complexType':
1138 if ($parent_tag == 'schema') {
1139 $this->currentComplexType = $attrs['name'];
1140 if (!isset($attrs['namespace'])) {
1141 $attrs['namespace'] = $this->schema;
1142 }
1143 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs;
1144 if (array_key_exists('base', $attrs)) {
1145 $qn =& new QName($attrs['base']);
1146 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
1147 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
1148 } else {
1149 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
1150 }
1151 $this->schemaStatus = 'complexType';
1152 } else {
1153 $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = true;
1154 }
1155 break;
1156
1157 case 'element':
1158 if (isset($attrs['type'])) {
1159 $qn =& new QName($attrs['type']);
1160 $attrs['type'] = $qn->name;
1161 if ($qn->ns && array_key_exists($qn->ns, $this->wsdl->namespaces)) {
1162 $attrs['namespace'] = $qn->ns;
1163 }
1164 }
1165
1166 $parentElement = '';
1167 $stack_size = count($this->schema_element_stack);
1168 if ($stack_size > 0) {
1169 $parentElement = $this->schema_element_stack[$stack_size - 1];
1170 }
1171
1172 if (isset($attrs['ref'])) {
1173 $qn =& new QName($attrs['ref']);
1174 $this->currentElement = $qn->name;
1175 } else {
1176 $this->currentElement = $attrs['name'];
1177 }
1178 $this->schema_element_stack[] = $this->currentElement;
1179 if (!isset($attrs['namespace'])) {
1180 $attrs['namespace'] = $this->schema;
1181 }
1182
1183 if ($parent_tag == 'schema') {
1184 $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs;
1185 $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = false;
1186 $this->schemaStatus = 'element';
1187 } elseif ($this->currentComplexType) {
1188 // we're inside a complexType
1189 if ((isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order']) &&
1190 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence')
1191 && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') {
1192 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = isset($attrs['type']) ? $attrs['type'] : null;
1193 }
1194 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs;
1195 } else {
1196 $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs;
1197 }
1198 break;
1199
1200 case 'complexContent':
1201 case 'simpleContent':
1202 break;
1203
1204 case 'extension':
1205 case 'restriction':
1206 if ($this->schemaStatus == 'complexType') {
1207 if (!empty($attrs['base'])) {
1208 $qn =& new QName($attrs['base']);
1209 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
1210
1211 // Types that extend from other types aren't
1212 // *of* those types. Reflect this by denoting
1213 // which type they extend. I'm leaving the
1214 // 'type' setting here since I'm not sure what
1215 // removing it might break at the moment.
1216 if ($qname->name == 'extension') {
1217 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['extends'] = $qn->name;
1218 }
1219 } else {
1220 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
1221 }
1222 }
1223 break;
1224
1225 case 'sequence':
1226 if ($this->schemaStatus == 'complexType') {
1227 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
1228 if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
1229 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
1230 }
1231 }
1232 break;
1233
1234 case 'all':
1235 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
1236 if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
1237 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
1238 }
1239 break;
1240
1241 case 'choice':
1242 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
1243 if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
1244 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
1245 }
1246
1247 case 'attribute':
1248 if ($this->schemaStatus == 'complexType') {
1249 if (isset($attrs['name'])) {
1250 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs;
1251 } else {
1252 if (isset($attrs['ref'])) {
1253 $q =& new QName($attrs['ref']);
1254 foreach ($attrs as $k => $v) {
1255 if ($k != 'ref' && strstr($k, $q->name)) {
1256 $vq =& new QName($v);
1257 if ($q->name == 'arrayType') {
1258 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name. $vq->arrayInfo;
1259 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
1260 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->ns;
1261 } else {
1262 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name;
1263 }
1264 }
1265 }
1266 }
1267 }
1268 }
1269 break;
1270 }
1271
1272 $this->schema_stack[] = $qname->name;
1273 break;
1274
1275 case 'message':
1276 // sect 2.3 wsdl:message child wsdl:part
1277 switch ($qname->name) {
1278 case 'part':
1279 $qn = null;
1280 if (isset($attrs['type'])) {
1281 $qn =& new QName($attrs['type']);
1282 } elseif (isset($attrs['element'])) {
1283 $qn =& new QName($attrs['element']);
1284 }
1285 if ($qn) {
1286 $attrs['type'] = $qn->name;
1287 $attrs['namespace'] = $qn->ns;
1288 }
1289 $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs;
1290 // error in wsdl
1291
1292 case 'documentation':
1293 break;
1294
1295 default:
1296 break;
1297 }
1298 break;
1299
1300 case 'portType':
1301 // sect 2.4
1302 switch ($qname->name) {
1303 case 'operation':
1304 // attributes: name
1305 // children: wsdl:input wsdl:output wsdl:fault
1306 $this->currentOperation = $attrs['name'];
1307 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs;
1308 break;
1309
1310 case 'input':
1311 case 'output':
1312 case 'fault':
1313 // wsdl:input wsdl:output wsdl:fault
1314 // attributes: name message parameterOrder(optional)
1315 if ($this->currentOperation) {
1316 if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) {
1317 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name], $attrs);
1318 } else {
1319 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs;
1320 }
1321 if (array_key_exists('message', $attrs)) {
1322 $qn =& new QName($attrs['message']);
1323 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name;
1324 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->ns;
1325 }
1326 }
1327 break;
1328
1329 case 'documentation':
1330 break;
1331
1332 default:
1333 break;
1334 }
1335 break;
1336
1337 case 'binding':
1338 $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
1339 switch ($ns) {
1340 case SCHEMA_SOAP:
1341 // this deals with wsdl section 3 soap binding
1342 switch ($qname->name) {
1343 case 'binding':
1344 // sect 3.3
1345 // soap:binding, attributes: transport(required), style(optional, default = document)
1346 // if style is missing, it is assumed to be 'document'
1347 if (!isset($attrs['style'])) {
1348 $attrs['style'] = 'document';
1349 }
1350 $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs);
1351 break;
1352
1353 case 'operation':
1354 // sect 3.4
1355 // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style)
1356 if (!isset($attrs['style'])) {
1357 $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style'];
1358 }
1359 if (isset($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation])) {
1360 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = array_merge($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation], $attrs);
1361 } else {
1362 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs;
1363 }
1364 break;
1365
1366 case 'body':
1367 // sect 3.5
1368 // soap:body attributes:
1369 // part - optional. listed parts must appear in body, missing means all parts appear in body
1370 // use - required. encoded|literal
1371 // encodingStyle - optional. space seperated list of encodings (uri's)
1372 $this->wsdl->bindings[$this->currentBinding]
1373 ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
1374 break;
1375
1376 case 'fault':
1377 // sect 3.6
1378 // soap:fault attributes: name use encodingStyle namespace
1379 $this->wsdl->bindings[$this->currentBinding]
1380 ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
1381 break;
1382
1383 case 'header':
1384 // sect 3.7
1385 // soap:header attributes: message part use encodingStyle namespace
1386 $this->wsdl->bindings[$this->currentBinding]
1387 ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
1388 break;
1389
1390 case 'headerfault':
1391 // sect 3.7
1392 // soap:header attributes: message part use encodingStyle namespace
1393 $header = count($this->wsdl->bindings[$this->currentBinding]
1394 ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1;
1395 $this->wsdl->bindings[$this->currentBinding]
1396 ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs;
1397 break;
1398
1399 case 'documentation':
1400 break;
1401
1402 default:
1403 // error! not a valid element inside binding
1404 break;
1405 }
1406 break;
1407
1408 case SCHEMA_WSDL:
1409 // XXX verify correct namespace
1410 // for now, default is the 'wsdl' namespace
1411 // other possible namespaces include smtp, http, etc. for alternate bindings
1412 switch ($qname->name) {
1413 case 'operation':
1414 // sect 2.5
1415 // wsdl:operation attributes: name
1416 $this->currentOperation = $attrs['name'];
1417 break;
1418
1419 case 'output':
1420 case 'input':
1421 case 'fault':
1422 // sect 2.5
1423 // wsdl:input attributes: name
1424 $this->opStatus = $qname->name;
1425 break;
1426
1427 case 'documentation':
1428 break;
1429
1430 default:
1431 break;
1432 }
1433 break;
1434
1435 case SCHEMA_WSDL_HTTP:
1436 switch ($qname->name) {
1437 case 'binding':
1438 // sect 4.4
1439 // http:binding attributes: verb
1440 // parent: wsdl:binding
1441 $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs);
1442 break;
1443
1444 case 'operation':
1445 // sect 4.5
1446 // http:operation attributes: location
1447 // parent: wsdl:operation
1448 $this->wsdl->bindings[$this->currentBinding]['operations']
1449 [$this->currentOperation] = $attrs;
1450 break;
1451
1452 case 'urlEncoded':
1453 // sect 4.6
1454 // http:urlEncoded attributes: location
1455 // parent: wsdl:input wsdl:output etc.
1456 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
1457 [$this->currentOperation]['uri'] = 'urlEncoded';
1458 break;
1459
1460 case 'urlReplacement':
1461 // sect 4.7
1462 // http:urlReplacement attributes: location
1463 // parent: wsdl:input wsdl:output etc.
1464 $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
1465 [$this->currentOperation]['uri'] = 'urlReplacement';
1466 break;
1467
1468 case 'documentation':
1469 break;
1470
1471 default:
1472 // error
1473 break;
1474 }
1475
1476 case SCHEMA_MIME:
1477 // sect 5
1478 // all mime parts are children of wsdl:input, wsdl:output, etc.
1479 // unsuported as of yet
1480 switch ($qname->name) {
1481 case 'content':
1482 // sect 5.3 mime:content
1483 // <mime:content part="nmtoken"? type="string"?/>
1484 // part attribute only required if content is child of multipart related,
1485 // it contains the name of the part
1486 // type attribute contains the mime type
1487 case 'multipartRelated':
1488 // sect 5.4 mime:multipartRelated
1489 case 'part':
1490 case 'mimeXml':
1491 // sect 5.6 mime:mimeXml
1492 // <mime:mimeXml part="nmtoken"?/>
1493 //
1494 case 'documentation':
1495 break;
1496
1497 default:
1498 // error
1499 break;
1500 }
1501
1502 case SCHEMA_DIME:
1503 // DIME is defined in:
1504 // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm
1505 // all DIME parts are children of wsdl:input, wsdl:output, etc.
1506 // unsuported as of yet
1507 switch ($qname->name) {
1508 case 'message':
1509 // sect 4.1 dime:message
1510 // appears in binding section
1511 $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs;
1512 break;
1513
1514 default:
1515 break;
1516 }
1517
1518 default:
1519 break;
1520 }
1521 break;
1522
1523 case 'service':
1524 $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
1525
1526 switch ($qname->name) {
1527 case 'port':
1528 // sect 2.6 wsdl:port attributes: name binding
1529 $this->currentPort = $attrs['name'];
1530 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs;
1531 // XXX hack to deal with binding namespaces
1532 $qn =& new QName($attrs['binding']);
1533 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name;
1534 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->ns;
1535 break;
1536
1537 case 'address':
1538 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs;
1539 // what TYPE of port is it? SOAP or HTTP?
1540 $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
1541 switch ($ns) {
1542 case SCHEMA_WSDL_HTTP:
1543 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http';
1544 break;
1545
1546 case SCHEMA_SOAP:
1547 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
1548 break;
1549
1550 default:
1551 // Shouldn't happen, we'll assume SOAP.
1552 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
1553 }
1554
1555 break;
1556
1557 case 'documentation':
1558 break;
1559
1560 default:
1561 break;
1562 }
1563 }
1564
1565 // Top level elements found under wsdl:definitions.
1566 switch ($qname->name) {
1567 case 'import':
1568 // sect 2.1.1 wsdl:import attributes: namespace location
1569 if ((isset($attrs['location']) || isset($attrs['schemaLocation'])) &&
1570 !isset($this->wsdl->imports[$attrs['namespace']])) {
1571 $uri = isset($attrs['location']) ? $attrs['location'] : $attrs['schemaLocation'];
1572 $location = @parse_url($uri);
1573 if (!isset($location['scheme'])) {
1574 $base = @parse_url($this->uri);
1575 $uri = $this->mergeUrl($base, $uri);
1576 }
1577
1578 $this->wsdl->imports[$attrs['namespace']] = $attrs;
1579 $import_parser_class = get_class($this);
1580 $import_parser =& new $import_parser_class($uri, $this->wsdl, $this->docs);
1581 if ($import_parser->fault) {
1582 unset($this->wsdl->imports[$attrs['namespace']]);
1583 return false;
1584 }
1585 $this->currentImport = $attrs['namespace'];
1586 }
1587 // Continue on to the 'types' case - lack of break; is
1588 // intentional.
1589
1590 case 'types':
1591 // sect 2.2 wsdl:types
1592 $this->status = 'types';
1593 break;
1594
1595 case 'schema':
1596 // We can hit this at the top level if we've been asked to
1597 // import an XSD file.
1598 if (!empty($attrs['targetNamespace'])) {
1599 $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
1600 } else {
1601 $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
1602 }
1603 $this->wsdl->complexTypes[$this->schema] = array();
1604 $this->wsdl->elements[$this->schema] = array();
1605 $this->schema_stack[] = $qname->name;
1606 $this->status = 'types';
1607 break;
1608
1609 case 'message':
1610 // sect 2.3 wsdl:message attributes: name children:wsdl:part
1611 $this->status = 'message';
1612 if (isset($attrs['name'])) {
1613 $this->currentMessage = $attrs['name'];
1614 $this->wsdl->messages[$this->currentMessage] = array();
1615 }
1616 break;
1617
1618 case 'portType':
1619 // sect 2.4 wsdl:portType
1620 // attributes: name
1621 // children: wsdl:operation
1622 $this->status = 'portType';
1623 $this->currentPortType = $attrs['name'];
1624 $this->wsdl->portTypes[$this->currentPortType] = array();
1625 break;
1626
1627 case 'binding':
1628 // sect 2.5 wsdl:binding attributes: name type
1629 // children: wsdl:operation soap:binding http:binding
1630 if ($qname->ns && $qname->ns != $this->tns) {
1631 break;
1632 }
1633 $this->status = 'binding';
1634 $this->currentBinding = $attrs['name'];
1635 $qn =& new QName($attrs['type']);
1636 $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name;
1637 $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->ns;
1638 break;
1639
1640 case 'service':
1641 // sect 2.7 wsdl:service attributes: name children: ports
1642 $this->currentService = $attrs['name'];
1643 $this->wsdl->services[$this->currentService]['ports'] = array();
1644 $this->status = 'service';
1645 break;
1646
1647 case 'definitions':
1648 // sec 2.1 wsdl:definitions
1649 // attributes: name targetNamespace xmlns:*
1650 // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service
1651 $this->wsdl->definition = $attrs;
1652 foreach ($attrs as $key => $value) {
1653 if (strstr($key, 'xmlns:') !== false) {
1654 $qn =& new QName($key);
1655 // XXX need to refactor ns handling.
1656 $this->wsdl->namespaces[$qn->name] = $value;
1657 $this->wsdl->ns[$value] = $qn->name;
1658 if ($key == 'targetNamespace' ||
1659 strcasecmp($value,SOAP_SCHEMA) == 0) {
1660 $this->soapns[] = $qn->name;
1661 } else {
1662 if (in_array($value, $this->_XMLSchema)) {
1663 $this->wsdl->xsd = $value;
1664 }
1665 }
1666 }
1667 }
1668 if (isset($ns) && $ns) {
1669 $namespace = 'xmlns:' . $ns;
1670 if (!$this->wsdl->definition[$namespace]) {
1671 return $this->_raiseSoapFault("parse error, no namespace for $namespace", $this->uri);
1672 }
1673 $this->tns = $ns;
1674 }
1675 break;
1676 }
1677 }
1678
1682 function endElement($parser, $name)
1683 {
1684 $stacksize = count($this->element_stack);
1685 if ($stacksize) {
1686 if ($this->element_stack[$stacksize - 1] == 'definitions') {
1687 $this->status = '';
1688 }
1689 array_pop($this->element_stack);
1690 }
1691
1692 if (stristr($name, 'schema')) {
1693 array_pop($this->schema_stack);
1694 $this->schema = '';
1695 }
1696
1697 if ($this->schema) {
1698 array_pop($this->schema_stack);
1699 if (count($this->schema_stack) <= 1) {
1700 /* Correct the type for sequences with multiple
1701 * elements. */
1702 if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])
1703 && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array'
1704 && array_key_exists('elements', $this->wsdl->complexTypes[$this->schema][$this->currentComplexType])
1705 && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) {
1706 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
1707 }
1708 }
1709 if (stristr($name, 'complexType')) {
1710 $this->currentComplexType = '';
1711 if (count($this->schema_element_stack)) {
1712 $this->currentElement = array_pop($this->schema_element_stack);
1713 } else {
1714 $this->currentElement = '';
1715 }
1716 } elseif (stristr($name, 'element')) {
1717 if (count($this->schema_element_stack)) {
1718 $this->currentElement = array_pop($this->schema_element_stack);
1719 } else {
1720 $this->currentElement = '';
1721 }
1722 }
1723 }
1724 }
1725
1729 function characterData($parser, $data)
1730 {
1731 // Store the documentation in the WSDL file.
1732 if ($this->currentTag == 'documentation') {
1733 $data = trim(preg_replace('/\s+/', ' ', $data));
1734 if (!strlen($data)) {
1735 return;
1736 }
1737
1738 switch ($this->status) {
1739 case 'service':
1740 $ptr =& $this->wsdl->services[$this->currentService];
1741 break;
1742
1743 case 'portType':
1744 $ptr =& $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation];
1745 break;
1746
1747 case 'binding':
1748 $ptr =& $this->wsdl->bindings[$this->currentBinding];
1749 break;
1750
1751 case 'message':
1752 $ptr =& $this->wsdl->messages[$this->currentMessage];
1753 break;
1754
1755 case 'operation':
1756 break;
1757
1758 case 'types':
1759 if (isset($this->currentComplexType) &&
1760 isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
1761 if ($this->currentElement) {
1762 $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement];
1763 } else {
1764 $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType];
1765 }
1766 }
1767 break;
1768 }
1769
1770 if (isset($ptr)) {
1771 if (!isset($ptr['documentation'])) {
1772 $ptr['documentation'] = '';
1773 } else {
1774 $ptr['documentation'] .= ' ';
1775 }
1776 $ptr['documentation'] .= $data;
1777 }
1778 }
1779 }
1780
1786 function mergeUrl($parsed, $path)
1787 {
1788 if (!is_array($parsed)) {
1789 return false;
1790 }
1791
1792 $uri = '';
1793 if (!empty($parsed['scheme'])) {
1794 $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://');
1795 $uri = $parsed['scheme'] . $sep;
1796 }
1797
1798 if (isset($parsed['pass'])) {
1799 $uri .= "$parsed[user]:$parsed[pass]@";
1800 } elseif (isset($parsed['user'])) {
1801 $uri .= "$parsed[user]@";
1802 }
1803
1804 if (isset($parsed['host'])) {
1805 $uri .= $parsed['host'];
1806 }
1807 if (isset($parsed['port'])) {
1808 $uri .= ":$parsed[port]";
1809 }
1810 if ($path[0] != '/' && isset($parsed['path'])) {
1811 if ($parsed['path'][strlen($parsed['path']) - 1] != '/') {
1812 $path = dirname($parsed['path']) . '/' . $path;
1813 } else {
1814 $path = $parsed['path'] . $path;
1815 }
1816 $path = $this->_normalize($path);
1817 }
1818 $sep = $path[0] == '/' ? '' : '/';
1819 $uri .= $sep . $path;
1820
1821 return $uri;
1822 }
1823
1824 function _normalize($path_str)
1825 {
1826 $pwd = '';
1827 $strArr = preg_split('/(\/)/', $path_str, -1, PREG_SPLIT_NO_EMPTY);
1828 $pwdArr = '';
1829 $j = 0;
1830 for ($i = 0; $i < count($strArr); $i++) {
1831 if ($strArr[$i] != ' ..') {
1832 if ($strArr[$i] != ' .') {
1833 $pwdArr[$j] = $strArr[$i];
1834 $j++;
1835 }
1836 } else {
1837 array_pop($pwdArr);
1838 $j--;
1839 }
1840 }
1841 $pStr = implode('/', $pwdArr);
1842 $pwd = (strlen($pStr) > 0) ? ('/' . $pStr) : '/';
1843 return $pwd;
1844 }
1845
1846}
1847
1857{
1862 var $tnsPrefix = 'tns';
1863
1867 var $wsdl = null;
1868
1877 function ilBMFWSDL_ObjectParser(&$objects, &$wsdl, $targetNamespace, $service_name, $service_desc = '')
1878 {
1879 parent::ilBMFBase('WSDLOBJECTPARSER');
1880
1881 $this->wsdl = &$wsdl;
1882
1883 // Set up the ilBMFWSDL object
1884 $this->_initialise($service_name);
1885
1886 // Parse each web service object
1887 $wsdl_ref = (is_array($objects)? $objects : array(&$objects));
1888
1889 foreach ($wsdl_ref as $ref_item) {
1890 if (!is_object($ref_item))
1891 return $this->_raiseSoapFault('Invalid web service object passed to object parser', 'urn:' . get_class($object));
1892
1893 if ($this->_parse($ref_item, $targetNamespace, $service_name) != true)
1894 break;
1895 }
1896
1897 // Build bindings from abstract data.
1898 if ($this->fault == null) {
1899 $this->_generateBindingsAndServices($targetNamespace, $service_name, $service_desc);
1900 }
1901 }
1902
1912 function _initialise($service_name)
1913 {
1914 // Set up the basic namespaces that all WSDL definitions use.
1915 $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL; // WSDL language
1916 $this->wsdl->namespaces['soap'] = SCHEMA_SOAP; // WSDL SOAP bindings
1917 $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name; // Target namespace
1918 $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces); // XML Schema
1919 $this->wsdl->namespaces['SOAP-ENC'] = array_search('SOAP-ENC', $this->_namespaces); // SOAP types
1920
1921 // XXX Refactor $namespace/$ns for Shane :-)
1922 unset($this->wsdl->ns['urn:' . $service_name]);
1923 $this->wsdl->ns += array_flip($this->wsdl->namespaces);
1924
1925 // Imports are not implemented in WSDL generation from classes.
1926 // *** <wsdl:import> ***
1927 }
1928
1937 function _parse(&$object, $schemaNamespace, $service_name)
1938 {
1939 // Create namespace prefix for the schema
1940 // XXX not very elegant :-(
1941
1942 list($schPrefix, $foo) = $this->_getTypeNs('{' . $schemaNamespace.'}');
1943 unset($foo);
1944
1945 // Parse all the types defined by the object in whatever
1946 // schema language we are using (currently __typedef arrays)
1947 // *** <wsdl:types> ***
1948
1949 foreach ($object->__typedef as $typeName => $typeValue) {
1950 // Get/create namespace definition
1951
1952 list($nsPrefix, $typeName) = $this->_getTypeNs($typeName);
1953
1954 // Create type definition
1955
1956 $this->wsdl->complexTypes[$schPrefix][$typeName] = array('name' => $typeName);
1957 $thisType =& $this->wsdl->complexTypes[$schPrefix][$typeName];
1958
1959 // According to Dmitri's documentation, __typedef comes in two
1960 // flavors:
1961 // Array = array(array("item" => "value"))
1962 // Struct = array("item1" => "value1", "item2" => "value2", ...)
1963
1964 if (is_array($typeValue)) {
1965 if (is_array(current($typeValue)) && count($typeValue) == 1
1966 && count(current($typeValue)) == 1) {
1967 // It's an array
1968
1969 $thisType['type'] = 'Array';
1970 list($nsPrefix, $typeName) = $this->_getTypeNs(current(current($typeValue)));
1971 $thisType['namespace'] = $nsPrefix;
1972 $thisType['arrayType'] = $typeName . '[]';
1973 } elseif (!is_array(current($typeValue))) {
1974 // It's a struct
1975
1976 $thisType['type'] = 'Struct';
1977 $thisType['order'] = 'all';
1978 $thisType['namespace'] = $nsPrefix;
1979 $thisType['elements'] = array();
1980
1981 foreach ($typeValue as $elementName => $elementType) {
1982 list($nsPrefix, $typeName) = $this->_getTypeNs($elementType);
1983 $thisType['elements'][$elementName]['name'] = $elementName;
1984 $thisType['elements'][$elementName]['type'] = $typeName;
1985 $thisType['elements'][$elementName]['namespace'] = $nsPrefix;
1986 }
1987 } else {
1988 // It's erroneous
1989 return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
1990 }
1991 } else {
1992 // It's erroneous
1993 return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
1994 }
1995 }
1996
1997 // Create an empty element array with the target namespace
1998 // prefix, to match the results of WSDL parsing.
1999
2000 $this->wsdl->elements[$schPrefix] = array();
2001
2002 // Populate tree with message information
2003 // *** <wsdl:message> ***
2004
2005 foreach ($object->__dispatch_map as $operationName => $messages) {
2006 foreach ($messages as $messageType => $messageParts) {
2007 unset($thisMessage);
2008
2009 switch ($messageType) {
2010 case 'in':
2011 $this->wsdl->messages[$operationName . 'Request'] = array();
2012 $thisMessage =& $this->wsdl->messages[$operationName . 'Request'];
2013 break;
2014
2015 case 'out':
2016 $this->wsdl->messages[$operationName . 'Response'] = array();
2017 $thisMessage =& $this->wsdl->messages[$operationName . 'Response'];
2018 break;
2019
2020 case 'alias':
2021 // Do nothing
2022 break;
2023
2024 default:
2025 // Error condition
2026 break;
2027 }
2028
2029 if (isset($thisMessage)) {
2030 foreach ($messageParts as $partName => $partType) {
2031 list ($nsPrefix, $typeName) = $this->_getTypeNs($partType);
2032
2033 $thisMessage[$partName] = array(
2034 'name' => $partName,
2035 'type' => $typeName,
2036 'namespace' => $nsPrefix
2037 );
2038 }
2039 }
2040 }
2041 }
2042
2043 // Populate tree with portType information
2044 // XXX Current implementation only supports one portType that
2045 // encompasses all of the operations available.
2046 // *** <wsdl:portType> ***
2047
2048 if (!isset($this->wsdl->portTypes[$service_name . 'Port'])) {
2049 $this->wsdl->portTypes[$service_name . 'Port'] = array();
2050 }
2051 $thisPortType =& $this->wsdl->portTypes[$service_name . 'Port'];
2052
2053 foreach ($object->__dispatch_map as $operationName => $messages) {
2054 $thisPortType[$operationName] = array('name' => $operationName);
2055
2056 foreach ($messages as $messageType => $messageParts) {
2057 switch ($messageType) {
2058 case 'in':
2059 $thisPortType[$operationName]['input'] = array(
2060 'message' => $operationName . 'Request',
2061 'namespace' => $this->tnsPrefix);
2062 break;
2063
2064 case 'out':
2065 $thisPortType[$operationName]['output'] = array(
2066 'message' => $operationName . 'Response',
2067 'namespace' => $this->tnsPrefix);
2068 break;
2069 }
2070 }
2071 }
2072
2073 return true;
2074 }
2075
2087 function _generateBindingsAndServices($schemaNamespace, $service_name, $service_desc = '')
2088 {
2089 // Populate tree with bindings information
2090 // XXX Current implementation only supports one binding that
2091 // matches the single portType and all of its operations.
2092 // XXX Is this the correct use of $schemaNamespace here?
2093 // *** <wsdl:binding> ***
2094
2095 $this->wsdl->bindings[$service_name . 'Binding'] = array(
2096 'type' => $service_name . 'Port',
2097 'namespace' => $this->tnsPrefix,
2098 'style' => 'rpc',
2099 'transport' => SCHEMA_SOAP_HTTP,
2100 'operations' => array());
2101 $thisBinding =& $this->wsdl->bindings[$service_name . 'Binding'];
2102
2103 foreach ($this->wsdl->portTypes[$service_name . 'Port'] as $operationName => $operationData) {
2104 $thisBinding['operations'][$operationName] = array(
2105 'soapAction' => $schemaNamespace . '#' . $operationName,
2106 'style' => $thisBinding['style']);
2107
2108 foreach (array('input', 'output') as $messageType)
2109 if (isset($operationData[$messageType])) {
2110 $thisBinding['operations'][$operationName][$messageType] = array(
2111 'use' => 'encoded',
2112 'namespace' => $schemaNamespace,
2113 'encodingStyle' => SOAP_SCHEMA_ENCODING);
2114 }
2115 }
2116
2117 // Populate tree with service information
2118 // XXX Current implementation supports one service which groups
2119 // all of the ports together, one port per binding
2120 // XXX What about https?
2121 // *** <wsdl:service> ***
2122
2123 $this->wsdl->services[$service_name . 'Service'] = array('ports' => array());
2124 $thisService =& $this->wsdl->services[$service_name . 'Service']['ports'];
2125
2126 foreach ($this->wsdl->bindings as $bindingName => $bindingData) {
2127 $thisService[$bindingData['type']] = array(
2128 'name' => $bindingData['type'],
2129 'binding' => $bindingName,
2130 'namespace' => $this->tnsPrefix,
2131 'address' => array('location' =>
2132 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] .
2133 (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')),
2134 'type' => 'soap');
2135 }
2136
2137 // Set service
2138 $this->wsdl->set_service($service_name . 'Service');
2139 $this->wsdl->uri = $this->wsdl->namespaces[$this->tnsPrefix];
2140
2141 // Create WSDL definition
2142 // *** <wsdl:definitions> ***
2143
2144 $this->wsdl->definition = array(
2145 'name' => $service_name,
2146 'targetNamespace' => $this->wsdl->namespaces[$this->tnsPrefix],
2147 'xmlns' => SCHEMA_WSDL);
2148
2149 foreach ($this->wsdl->namespaces as $nsPrefix => $namespace) {
2150 $this->wsdl->definition['xmlns:' . $nsPrefix] = $namespace;
2151 }
2152 }
2153
2165 function _getTypeNs($type)
2166 {
2167 preg_match_all("'\{(.*)\}'sm", $type, $m);
2168 if (isset($m[1][0]) && $m[1][0] != '') {
2169 if (!array_key_exists($m[1][0], $this->wsdl->ns)) {
2170 $ns_pref = 'ns' . count($this->wsdl->namespaces);
2171 $this->wsdl->ns[$m[1][0]] = $ns_pref;
2172 $this->wsdl->namespaces[$ns_pref] = $m[1][0];
2173 }
2174 $typens = $this->wsdl->ns[$m[1][0]];
2175 $type = ereg_replace($m[0][0], '', $type);
2176 } else {
2177 $typens = 'xsd';
2178 }
2179
2180 return array($typens, $type);
2181 }
2182
2183}
$result
$n
Definition: RandomTest.php:80
$location
Definition: buildRTE.php:44
isError($data, $code=null)
Tell whether a value is a PEAR error.
Definition: PEAR.php:279
const SCHEMA_MIME
const SOAP_SCHEMA
const SCHEMA_SOAP_HTTP
const SCHEMA_DIME
const SCHEMA_WSDL
const SOAP_XML_SCHEMA_VERSION
const SCHEMA_SOAP
const SOAP_SCHEMA_ENCODING
const SCHEMA_WSDL_HTTP
const WSDL_CACHE_USE
const WSDL_CACHE_MAX_AGE
$fault
Recent PEAR_Error object.
& _raiseSoapFault($str, $detail='', $actorURI='', $code=null, $mode=null, $options=null, $skipmsg=false)
Raises a SOAP error.
ilBMFWSDL_Cache($cacheUse=WSDL_CACHE_USE, $cacheMaxAge=WSDL_CACHE_MAX_AGE)
ilBMFWSDL_Cache constructor
_cacheDir()
_cacheDir return the path to the cache, if it doesn't exist, make it
Parses the types and methods used in web service objects into the internal data structures used by il...
ilBMFWSDL_ObjectParser(&$objects, &$wsdl, $targetNamespace, $service_name, $service_desc='')
Constructor.
$tnsPrefix
Target namespace for the WSDL document will have the following prefix.
_getTypeNs($type)
This function is adapted from Dmitri V's implementation of DISCO/WSDL generation.
$wsdl
Reference to the ilBMFWSDL object to populate.
_parse(&$object, $schemaNamespace, $service_name)
Parser - takes a single object to add to tree (non-destructive).
_generateBindingsAndServices($schemaNamespace, $service_name, $service_desc='')
Take all the abstract WSDL data and build concrete bindings and services (destructive).
_initialise($service_name)
Initialise the ilBMFWSDL tree (destructive).
startElement($parser, $name, $attrs)
start-element handler
mergeUrl($parsed, $path)
$parsed is an array returned by parse_url().
endElement($parser, $name)
end-element handler.
$currentMessage
Define internal arrays of bindings, ports, operations, messages, etc.
characterData($parser, $data)
Element content handler.
ilBMFWSDL_Parser($uri, &$wsdl, $docs=false)
constructor
_elementArg(&$args, &$argarray, &$_argtype, $_argname)
getNamespaceAttributeName($namespace)
getComplexTypeNameForElement($name, $namespace)
getNamespace($portName, $operation)
_validateString($string)
getEndpoint($portName)
generateProxyCode($port='', $classname='')
Generates stub code from the WSDL that can be saved to a file or eval'd into existence.
addNamespace($namespace)
getSoapAction($portName, $operation)
& _getComplexTypeForElement($name, $namespace)
parseURL($wsdl_uri, $proxy=array())
Fills the WSDL array tree with data from a WSDL file.
parse($wsdl_uri, $proxy=array())
getSchemaType($type, $name, $type_namespace)
_complexTypeArg(&$args, &$argarray, &$_argtype, $_argname)
getDataHandler($datatype, $namespace)
Given a datatype, what function handles the processing?
matchMethod(&$operation)
ilBMFWSDL($wsdl_uri=false, $proxy=array(), $cacheUse=WSDL_CACHE_USE, $cacheMaxAge=WSDL_CACHE_MAX_AGE, $docs=false)
ilBMFWSDL constructor.
getOperationData($portName, $operation)
getPortName($operation, $service=null)
Finds the name of the first port that contains an operation of name $operation.
_getDeepestArrayType($nsPrefix, $arrayType)
Recurse through the WSDL structure looking for the innermost array type of multi-dimensional arrays.
_getPortName($operation, $service)
& getProxy($port='', $name='')
parseObject(&$wsdl_obj, $targetNamespace, $service_name, $service_desc='')
Fills the WSDL array tree with data from one or more PHP class objects.
set_service($service)
getComplexTypeChildType($ns, $name, $child_ns, $child_name)
_addArg(&$args, &$argarray, $argname)
parses a WSDL file, allows access to it's data, other utility methods
Definition: nusoap.php:3133
if($err=$client->getError()) $namespace
$header
$data
$style
Definition: example_012.php:70
$messages
Definition: en-x-test.php:7
$path
Definition: index.php:22
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']