• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

payment/bmf/lib/SOAP/class.ilBMFWSDL.php

Go to the documentation of this file.
00001 <?php
00002 //
00003 // +----------------------------------------------------------------------+
00004 // | PHP Version 4                                                        |
00005 // +----------------------------------------------------------------------+
00006 // | Copyright (c) 1997-2003 The PHP Group                                |
00007 // +----------------------------------------------------------------------+
00008 // | This source file is subject to version 2.02 of the PHP license,      |
00009 // | that is bundled with this package in the file LICENSE, and is        |
00010 // | available at through the world-wide-web at                           |
00011 // | http://www.php.net/license/2_02.txt.                                 |
00012 // | If you did not receive a copy of the PHP license and are unable to   |
00013 // | obtain it through the world-wide-web, please send a note to          |
00014 // | license@php.net so we can mail you a copy immediately.               |
00015 // +----------------------------------------------------------------------+
00016 // | Authors: Shane Caraveo <Shane@Caraveo.com>   Port to PEAR and more   |
00017 // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author         |
00018 // +----------------------------------------------------------------------+
00019 //
00020 // $Id: class.ilBMFWSDL.php 11401 2006-07-12 10:40:54Z jconze $
00021 //
00022 require_once dirname(__FILE__).'/class.ilBMFBase.php';
00023 require_once dirname(__FILE__).'/class.ilBMFFault.php';
00024 require_once 'HTTP/Request.php';
00025 
00026 define('WSDL_CACHE_MAX_AGE', 43200);
00027 define('WSDL_CACHE_USE',     0); // set to zero to turn off caching
00028 
00047 class ilBMFWSDL extends ilBMFBase
00048 {
00049     var $tns = null;
00050     var $definition = array();
00051     var $namespaces = array();
00052     var $ns = array();
00053     var $xsd = SOAP_XML_SCHEMA_VERSION;
00054     var $complexTypes = array();
00055     var $elements = array();
00056     var $messages = array();
00057     var $portTypes = array();
00058     var $bindings = array();
00059     var $imports = array();
00060     var $services = array();
00061     var $service = '';
00062     var $uri = '';
00063 
00069     var $proxy = null;
00070 
00071     var $trace = 0;
00072 
00078     var $cacheUse = null;
00079 
00085     var $cacheMaxAge = null;
00086 
00096     function ilBMFWSDL($wsdl_uri = false, $proxy = array(),
00097                        $cacheUse    = WSDL_CACHE_USE,
00098                        $cacheMaxAge = WSDL_CACHE_MAX_AGE) {
00099         parent::ilBMFBase('WSDL');
00100         $this->uri         = $wsdl_uri;
00101         $this->proxy       = $proxy;
00102         $this->cacheUse    = $cacheUse;
00103         $this->cacheMaxAge = $cacheMaxAge;
00104         if ($wsdl_uri) {
00105             $this->parseURL($wsdl_uri);
00106             reset($this->services);
00107             $this->service = key($this->services);
00108         }
00109     }
00110 
00111     function set_service($service) {
00112         if (array_key_exists($service, $this->services)) {
00113             $this->service = $service;
00114         }
00115     }
00116 
00120     function parse($wsdl_uri, $proxy = array()) {
00121         $this->parseURL($wsdl_uri, $proxy);
00122     }
00123 
00131     function parseURL($wsdl_uri, $proxy = array()) {
00132         $parser =& new ilBMFWSDL_Parser($wsdl_uri, $this);
00133 
00134         if ($parser->fault) {
00135             $this->_raiseSoapFault($parser->fault);
00136         }
00137     }
00138 
00147     function parseObject(&$wsdl_obj, $targetNamespace, $service_name, $service_desc = '')
00148     {
00149         $parser =& new ilBMFWSDL_ObjectParser($wsdl_obj, $this, $targetNamespace, $service_name, $service_desc);
00150 
00151          if ($parser->fault) {
00152              $this->_raiseSoapFault($parser->fault);
00153          }
00154     }
00155 
00156     function getEndpoint($portName)
00157     {
00158         return (isset($this->services[$this->service]['ports'][$portName]['address']['location']))
00159                 ? $this->services[$this->service]['ports'][$portName]['address']['location']
00160                 : $this->_raiseSoapFault("no endpoint for port for $portName", $this->uri);
00161     }
00162 
00163     function _getPortName($operation,$service) {
00164         if (isset($this->services[$service]['ports'])) {
00165             foreach ($this->services[$service]['ports'] as $port => $portAttrs) {
00166                 $type = $this->services[$service]['ports'][$port]['type'];
00167                 if ($type == 'soap' &&
00168                     isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) {
00169                         return $port;
00170                 }
00171             }
00172         }
00173         return null;
00174     }
00175 
00176     // find the name of the first port that contains an operation of name $operation
00177     // always returns a the soap portName
00178     function getPortName($operation, $service = null)
00179     {
00180         if (!$service) $service = $this->service;
00181         if (isset($this->services[$service]['ports'])) {
00182             $portName = $this->_getPortName($operation,$service);
00183             if ($portName) return $portName;
00184         }
00185         // try any service in the wsdl
00186         foreach ($this->services as $serviceName=>$service) {
00187             if (isset($this->services[$serviceName]['ports'])) {
00188                 $portName = $this->_getPortName($operation,$serviceName);
00189                 if ($portName) {
00190                     $this->service = $serviceName;
00191                     return $portName;
00192                 }
00193             }
00194         }
00195         return $this->_raiseSoapFault("no operation $operation in wsdl", $this->uri);
00196     }
00197 
00198     function getOperationData($portName,$operation)
00199     {
00200         if (isset($this->services[$this->service]['ports'][$portName]['binding'])
00201             && $binding = $this->services[$this->service]['ports'][$portName]['binding']) {
00202             // get operation data from binding
00203             if (is_array($this->bindings[$binding]['operations'][$operation])) {
00204                 $opData = $this->bindings[$binding]['operations'][$operation];
00205             }
00206             // get operation data from porttype
00207             $portType = $this->bindings[$binding]['type'];
00208             if (!$portType) {
00209                 return $this->_raiseSoapFault("no port type for binding $binding in wsdl " . $this->uri);
00210             }
00211             if (is_array($this->portTypes[$portType][$operation])) {
00212                 if (isset($this->portTypes[$portType][$operation]['parameterOrder']))
00213                     $opData['parameterOrder'] = $this->portTypes[$portType][$operation]['parameterOrder'];
00214                 $opData['input'] = array_merge($opData['input'], $this->portTypes[$portType][$operation]['input']);
00215                 $opData['output'] = array_merge($opData['output'], $this->portTypes[$portType][$operation]['output']);
00216             }
00217             if (!$opData)
00218                 return $this->_raiseSoapFault("no operation $operation for port $portName, in wsdl", $this->uri);
00219             $opData['parameters'] = false;
00220             if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']))
00221                 $opData['namespace'] = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'];
00222             // message data from messages
00223             $inputMsg = $opData['input']['message'];
00224             if (is_array($this->messages[$inputMsg])) {
00225             foreach ($this->messages[$inputMsg] as $pname => $pattrs) {
00226                 if ($opData['style'] == 'document' && $opData['input']['use'] == 'literal'
00227                     && $pname == 'parameters') {
00228                         $opData['parameters'] = true;
00229                         $opData['namespace'] = $this->namespaces[$pattrs['namespace']];
00230                         $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00231                         if (isset($el['elements'])) {
00232                             foreach ($el['elements'] as $elname => $elattrs) {
00233                                 $opData['input']['parts'][$elname] = $elattrs;
00234                             }
00235                         }
00236                 } else {
00237                     $opData['input']['parts'][$pname] = $pattrs;
00238                 }
00239             }
00240             }
00241             $outputMsg = $opData['output']['message'];
00242             if (is_array($this->messages[$outputMsg])) {
00243             foreach ($this->messages[$outputMsg] as $pname => $pattrs) {
00244                 if ($opData['style'] == 'document' && $opData['output']['use'] == 'literal'
00245                     && $pname == 'parameters') {
00246 
00247                         $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00248                         if (isset($el['elements'])) {
00249                             foreach ($el['elements'] as $elname => $elattrs) {
00250                                 $opData['output']['parts'][$elname] = $elattrs;
00251                             }
00252                         }
00253 
00254                 } else {
00255                     $opData['output']['parts'][$pname] = $pattrs;
00256                 }
00257             }
00258             }
00259             return $opData;
00260         }
00261         return $this->_raiseSoapFault("no binding for port $portName in wsdl", $this->uri);
00262     }
00263 
00264     function matchMethod(&$operation) {
00265         // Overloading lowercases function names :(
00266         foreach ($this->services[$this->service]['ports'] as $port => $portAttrs) {
00267             foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) {
00268                 if (strcasecmp($op, $operation) == 0) {
00269                     $operation = $op;
00270                 }
00271             }
00272         }
00273     }
00274 
00288     function getDataHandler($datatype, $namespace) {
00289         // see if we have an element by this name
00290         if (isset($this->namespaces[$namespace]))
00291             $namespace = $this->namespaces[$namespace];
00292         if (isset($this->ns[$namespace])) {
00293             $nsp = $this->ns[$namespace];
00294             #if (!isset($this->elements[$nsp]))
00295             #    $nsp = $this->namespaces[$nsp];
00296             if (isset($this->elements[$nsp][$datatype])) {
00297                 $checkmessages = array();
00298                 // find what messages use this datatype
00299                 foreach ($this->messages as $messagename=>$message) {
00300                     foreach ($message as $partname=>$part) {
00301                         if ($part['type']==$datatype) {
00302                             $checkmessages[] = $messagename;
00303                             break;
00304                         }
00305                     }
00306                 }
00307                 // find the operation that uses this message
00308                 $dataHandler = NULL;
00309                 foreach($this->portTypes as $portname=>$porttype) {
00310                     foreach ($porttype as $opname=>$opinfo) {
00311                         foreach ($checkmessages as $messagename) {
00312                             if ($opinfo['input']['message'] == $messagename) {
00313                                 return $opname;
00314                             }
00315                         }
00316                     }
00317                 }
00318             }
00319         }
00320         return null;
00321     }
00322 
00323     function getSoapAction($portName, $operation)
00324     {
00325         if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']) &&
00326             $soapAction = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']) {
00327             return $soapAction;
00328         }
00329         return false;
00330     }
00331 
00332     function getNamespace($portName, $operation)
00333     {
00334         if (isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]) &&
00335             isset($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']) &&
00336             $namespace = $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']) {
00337             return $namespace;
00338         }
00339         return false;
00340     }
00341 
00342     function getNamespaceAttributeName($namespace) {
00343         /* if it doesn't exist at first, flip the array and check again */
00344         if (!array_key_exists($namespace, $this->ns)) {
00345             $this->ns = array_flip($this->namespaces);
00346         }
00347         /* if it doesn't exist now, add it */
00348         if (!array_key_exists($namespace, $this->ns)) {
00349             return $this->addNamespace($namespace);
00350         }
00351         return $this->ns[$namespace];
00352     }
00353 
00354     function addNamespace($namespace) {
00355         if (array_key_exists($namespace, $this->ns)) {
00356             return $this->ns[$namespace];
00357         }
00358         $n = count($this->ns);
00359         $attr = 'ns'.$n;
00360         $this->namespaces['ns'.$n] = $namespace;
00361         $this->ns[$namespace] = $attr;
00362         return $attr;
00363     }
00364 
00365     function _validateString($string) {
00366         // XXX this should be done sooner or later
00367         return true;
00368         #if (preg_match("/^[\w_:#\/]+$/",$string)) return true;
00369         #return false;
00370     }
00371 
00372     function _addArg(&$args, &$argarray, $argname)
00373     {
00374         if ($args) $args .= ", ";
00375         $args .= "\$".$argname;
00376         if (!$this->_validateString($argname)) return NULL;
00377         if ($argarray) $argarray .= ", ";
00378         $argarray .= "\"$argname\"=>\$".$argname;
00379     }
00380 
00381     function _elementArg(&$args, &$argarray, &$_argtype, $_argname)
00382     {
00383         $comments = '';
00384         $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00385         $tns = isset($this->ns[$el['namespace']])?$this->ns[$el['namespace']]:$_argtype['namespace'];
00386         if (isset($this->complexTypes[$tns][$el['type']])) {
00387             // the element is actually a complex type!
00388             $comments = "        // {$el['type']} is a ComplexType, refer to wsdl for more info\n";
00389             $attrname = "{$_argtype['type']}_attr";
00390             if (isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00391                 $comments .= "        // {$el['type']} may require attributes, refer to wsdl for more info\n";
00392             }
00393             $comments .= "        \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n";
00394             $comments .= "        \${$_argtype['type']} =& new ilBMFValue('{$_argtype['type']}',false,\${$_argtype['type']},\$$attrname);\n";
00395             $this->_addArg($args,$argarray,$_argtype['type']);
00396             if (isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00397                 if ($args) $args .= ", ";
00398                 $args .= "\$".$attrname;
00399             }
00400             #$comments = $this->_complexTypeArg($args,$argarray,$el,$_argtype['type']);
00401         } else if (isset($el['elements'])) {
00402             foreach ($el['elements'] as $ename => $element) {
00403                 $comments .= "        \$$ename =& new ilBMFValue('{{$this->namespaces[$element['namespace']]}}$ename','{$element['type']}',\$$ename);\n";
00404                 $this->_addArg($args,$argarray,$ename);
00405             }
00406         } else {
00407             #$echoStringParam =& new ilBMFValue('{http://soapinterop.org/xsd}echoStringParam',false,$echoStringParam);
00408             $comments .= "        \$$_argname =& new ilBMFValue('{{$this->namespaces[$tns]}}$_argname','{$el['type']}',\$$_argname);\n";
00409             $this->_addArg($args,$argarray,$_argname);
00410         }
00411         return $comments;
00412     }
00413 
00414     function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname)
00415     {
00416         $comments = '';
00417         if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) {
00418             $comments  = "        // $_argname is a ComplexType {$_argtype['type']},\n";
00419             $comments .= "        //refer to wsdl for more info\n";
00420             if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) {
00421                 $comments .= "        // $_argname may require attributes, refer to wsdl for more info\n";
00422             }
00423             $wrapname = '{'.$this->namespaces[$_argtype['namespace']].'}'.$_argtype['type'];
00424             $comments .= "        \$$_argname =& new ilBMFValue('$_argname','$wrapname',\$$_argname);\n";
00425 
00426         }
00427         $this->_addArg($args,$argarray,$_argname);
00428         return $comments;
00429     }
00430 
00435     function generateProxyCode($port = '', $classname='')
00436     {
00437         $multiport = count($this->services[$this->service]['ports']) > 1;
00438         if (!$port) {
00439             reset($this->services[$this->service]['ports']);
00440             $port = current($this->services[$this->service]['ports']);
00441         }
00442         // XXX currently do not support HTTP ports
00443         if ($port['type'] != 'soap') return NULL;
00444 
00445         // XXX currentPort is BAD
00446         $clienturl = $port['address']['location'];
00447         if (!$classname) {
00448             if ($multiport || $port) {
00449                 $classname = 'WebService_'.$this->service.'_'.$port['name'];
00450             } else {
00451                 $classname = 'WebService_'.$this->service;
00452             }
00453             $classname = str_replace('-','_',$classname);
00454         }
00455 
00456         if (!$this->_validateString($classname)) return NULL;
00457 
00458         if (is_array($this->proxy) && count($this->proxy) > 0) {
00459             $class = "class $classname extends ilBMFClient\n{\n".
00460             "    function $classname()\n{\n".
00461             "        \$this->ilBMFClient(\"$clienturl\", 0, 0,
00462                     array(";
00463 
00464             foreach($this->proxy as $key => $val) {
00465                 if (is_array($val)) {
00466                     $class .= "\"$key\" => array(";
00467                     foreach ($val as $key2 => $val2) {
00468                         $class .= "\"$key2\" => \"$val2\",";
00469                     }
00470                     $class .= ')';
00471                 } else {
00472                     $class .= "\"$key\"=>\"$val\",";
00473                 }
00474             }
00475             $class .= "));\n }\n";
00476             $class = str_replace(',))', '))', $class);
00477         } else {
00478             $class = "class $classname extends ilBMFClient\n{\n".
00479             "    function $classname()\n{\n".
00480             "        \$this->ilBMFClient(\"$clienturl\", 0);\n".
00481             "    }\n";
00482         }
00483 
00484         // get the binding, from that get the port type
00485         $primaryBinding = $port['binding']; //$this->services[$this->service]['ports'][$port['name']]["binding"];
00486         $primaryBinding = preg_replace("/^(.*:)/","",$primaryBinding);
00487         $portType = $this->bindings[$primaryBinding]['type'];
00488         $portType = preg_replace("/^(.*:)/","",$portType);
00489         $style = $this->bindings[$primaryBinding]['style'];
00490 
00491         // XXX currentPortType is BAD
00492         foreach ($this->portTypes[$portType] as $opname => $operation) {
00493             $soapaction = $this->bindings[$primaryBinding]['operations'][$opname]['soapAction'];
00494             if (isset($this->bindings[$primaryBinding]['operations'][$opname]['style'])) {
00495                 $opstyle = $this->bindings[$primaryBinding]['operations'][$opname]['style'];
00496             } else {
00497                 $opstyle = $style;
00498             }
00499             $use = $this->bindings[$primaryBinding]['operations'][$opname]['input']['use'];
00500             if ($use == 'encoded') {
00501                 $namespace = $this->bindings[$primaryBinding]['operations'][$opname]['input']['namespace'];
00502             } else {
00503                 $bindingType = $this->bindings[$primaryBinding]['type'];
00504                 $ns = $this->portTypes[$bindingType][$opname]['input']['namespace'];
00505                 $namespace = $this->namespaces[$ns];
00506             }
00507 
00508             $args = '';
00509             $argarray = '';
00510             $comments = '';
00511             $wrappers = '';
00512             foreach ($operation['input'] as $argname => $argtype) {
00513                 if ($argname == "message") {
00514                     foreach ($this->messages[$argtype] as $_argname => $_argtype) {
00515                         $comments = '';
00516                         if ($opstyle == 'document' && $use == 'literal' &&
00517                             $_argtype['name'] == 'parameters') {
00518                                 // the type or element refered to is used for parameters!
00519                                 $elattrs = null;
00520                                 $element = $_argtype['element'];
00521                                 $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00522 
00523                                 if($el['complex']) {
00524                                     $namespace = $this->namespaces[$_argtype['namespace']];
00525                                     // XXX need to wrap the parameters in a soap_value
00526                                 }
00527                                 if (isset($el['elements'])) {
00528                                     foreach ($el['elements'] as $elname => $elattrs) {
00529                                         // is the element a complex type?
00530                                         if (isset($this->complexTypes[$elattrs['namespace']][$elname])) {
00531                                             $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00532                                         } else {
00533                                             $this->_addArg($args, $argarray, $elname);
00534                                         }
00535                                     }
00536                                 }/* else {
00537                                     $comments = $this->_complexTypeArg($args, $argarray, $elattrs, $elattrs['name']);
00538                                 }*/
00539                                 if($el['complex'] && $argarray) {
00540                                     $wrapname = '{'.$this->namespaces[$_argtype['namespace']].'}'.$el['name'];
00541                                     $comments .= "        \${$el['name']} =& new ilBMFValue('$wrapname',false,\$v=array($argarray));\n";
00542                                     $argarray = "'{$el['name']}'=>\${$el['name']}";
00543                                 }
00544                         } else
00545                         if (isset($_argtype['element'])) {
00546                             // element argument
00547                             $comments = $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']);
00548                         } else {
00549                             // complex type argument
00550                             $comments = $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00551                         }
00552                     }
00553                 }
00554             }
00555 
00556             // validate entries
00557             if (!$this->_validateString($opname)) return NULL;
00558             if (!$this->_validateString($namespace)) return NULL;
00559             if (!$this->_validateString($soapaction)) return NULL;
00560 
00561             if ($argarray) {
00562                 $argarray = "array($argarray)";
00563             } else {
00564                 $argarray = 'null';
00565             }
00566 
00567             $class .= "    function &$opname($args) {\n$comments$wrappers".
00568             "        return \$this->call(\"$opname\", \n".
00569             "                        \$v = $argarray, \n".
00570             "                        array('namespace'=>'$namespace',\n".
00571             "                            'soapaction'=>'$soapaction',\n".
00572             "                            'style'=>'$opstyle',\n".
00573             "                            'use'=>'$use'".
00574             ($this->trace?",'trace'=>1":"")." ));\n".
00575             "    }\n";
00576         }
00577         $class .= "}\n";
00578         return $class;
00579     }
00580 
00581     function generateAllProxies()
00582     {
00583         $proxycode = '';
00584         foreach (array_keys($this->services[$this->service]['ports']) as $key) {
00585             $port =& $this->services[$this->service]['ports'][$key];
00586             $proxycode .= $this->generateProxyCode($port);
00587         }
00588         return $proxycode;
00589     }
00590 
00591     function &getProxy($port = '', $name = '')
00592     {
00593         $multiport = count($this->services[$this->service]['ports']) > 1;
00594 
00595         if (!$port) {
00596             reset($this->services[$this->service]['ports']);
00597             $port = current($this->services[$this->service]['ports']);
00598         }
00599 
00600         if ($multiport || $port) {
00601             $classname = 'WebService_' . $this->service . '_' . $port['name'];
00602         } else {
00603             $classname = 'WebService_' . $this->service;
00604         }
00605 
00606         if ($name) {
00607             $classname = $name . '_' . $classname;
00608         }
00609 
00610         $classname = preg_replace('/[ .\-\(\)]+/', '_', $classname);
00611 
00612         if (!class_exists($classname)) {
00613             $proxy = $this->generateProxyCode($port, $classname);
00614             eval($proxy);
00615         }
00616 
00617         return new $classname;
00618     }
00619 
00620     function &_getComplexTypeForElement($name, $namespace)
00621     {
00622         $t = NULL;
00623         if (isset($this->ns[$namespace]) &&
00624             isset($this->elements[$this->ns[$namespace]][$name]['type'])) {
00625 
00626             $type = $this->elements[$this->ns[$namespace]][$name]['type'];
00627             $ns = $this->elements[$this->ns[$namespace]][$name]['namespace'];
00628 
00629             if (isset($this->complexTypes[$ns][$type])) {
00630                 $t = $this->complexTypes[$ns][$type];
00631             }
00632         }
00633         return $t;
00634     }
00635 
00636     function getComplexTypeNameForElement($name, $namespace)
00637     {
00638         $t = $this->_getComplexTypeForElement($name, $namespace);
00639         if ($t) {
00640             return $t['name'];
00641         }
00642         return NULL;
00643     }
00644 
00645     function getComplexTypeChildType($ns, $name, $child_ns, $child_name) {
00646         // is the type an element?
00647         $t = $this->_getComplexTypeForElement($name, $ns);
00648         if ($t) {
00649             // no, get it from complex types directly
00650             if (isset($t['elements'][$child_name]['type']))
00651                 return $t['elements'][$child_name]['type'];
00652         }
00653         return NULL;
00654     }
00655 
00656     function getSchemaType($type, $name, $type_namespace)
00657     {
00658         # see if it's a complex type so we can deal properly with SOAPENC:arrayType
00659         if ($name && $type) {
00660             # XXX TODO:
00661             # look up the name in the wsdl and validate the type
00662             foreach ($this->complexTypes as $ns=> $types) {
00663                 if (array_key_exists($type, $types)) {
00664                     if (array_key_exists('type', $types[$type])) {
00665                         list($arraytype_ns, $arraytype, $array_depth) = isset($types[$type]['arrayType'])?
00666                             $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType'])
00667                             : array($this->namespaces[$types[$type]['namespace']], NULL, 0);
00668                         return array($types[$type]['type'], $arraytype, $arraytype_ns, $array_depth);
00669                     }
00670                     if (array_key_exists('arrayType', $types[$type])) {
00671                         list($arraytype_ns, $arraytype, $array_depth) =
00672                                 $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType']);
00673                         return array('Array', $arraytype, $arraytype_ns, $array_depth);
00674                     }
00675                     if (array_key_exists('elements', $types[$type]) &&
00676                         array_key_exists($name, $types[$type]['elements'])) {
00677                         $type = $types[$type]['elements']['type'];
00678                         return array($type, NULL, $this->namespaces[$types[$type]['namespace']], NULL);
00679                     }
00680                 }
00681             }
00682         }
00683         if ($type && $type_namespace) {
00684             $arrayType = NULL;
00685             # XXX TODO:
00686             # this code currently handles only one way of encoding array types in wsdl
00687             # need to do a generalized function to figure out complex types
00688             $p = $this->ns[$type_namespace];
00689             if ($p &&
00690                 array_key_exists($p, $this->complexTypes) &&
00691                 array_key_exists($type, $this->complexTypes[$p])) {
00692                 if ($arrayType = $this->complexTypes[$p][$type]['arrayType']) {
00693                     $type = 'Array';
00694                 } else if ($this->complexTypes[$p][$type]['order']=='sequence' &&
00695                            array_key_exists('elements', $this->complexTypes[$p][$type])) {
00696                     reset($this->complexTypes[$p][$type]['elements']);
00697                     # assume an array
00698                     if (count($this->complexTypes[$p][$type]['elements']) == 1) {
00699                         $arg = current($this->complexTypes[$p][$type]['elements']);
00700                         $arrayType = $arg['type'];
00701                         $type = 'Array';
00702                     } else {
00703                         foreach($this->complexTypes[$p][$type]['elements'] as $element) {
00704                             if ($element['name'] == $type) {
00705                                 $arrayType = $element['type'];
00706                                 $type = $element['type'];
00707                             }
00708                         }
00709                     }
00710                 } else {
00711                     $type = 'Struct';
00712                 }
00713                 return array($type, $arrayType, $type_namespace, null);
00714             }
00715         }
00716         return array(null, null, null, null);
00717     }
00718 
00728     function _getDeepestArrayType($nsPrefix, $arrayType)
00729     {
00730         static $trail = array();
00731 
00732         $arrayType = ereg_replace('\[\]$', '', $arrayType);
00733 
00734         // Protect against circular references
00735         // XXX We really need to remove trail from this altogether (it's very inefficient and
00736         // in the wrong place!) and put circular reference checking in when the WSDL info
00737         // is generated in the first place
00738         if (array_search($nsPrefix . ':' . $arrayType, $trail)) {
00739             return array(NULL, NULL, -count($trail));
00740         }
00741 
00742         if (array_key_exists($nsPrefix, $this->complexTypes) &&
00743             array_key_exists($arrayType, $this->complexTypes[$nsPrefix]) &&
00744             array_key_exists('arrayType', $this->complexTypes[$nsPrefix][$arrayType])) {
00745             $trail[] = $nsPrefix . ':' . $arrayType;
00746             $result = $this->_getDeepestArrayType( $this->complexTypes[$nsPrefix][$arrayType]['namespace'],
00747                                                    $this->complexTypes[$nsPrefix][$arrayType]['arrayType']);
00748             return array($result[0], $result[1], $result[2] + 1);
00749         }
00750         return array($this->namespaces[$nsPrefix], $arrayType, 0);
00751     }
00752 }
00753 
00754 class ilBMFWSDL_Cache extends ilBMFBase
00755 {
00756     // Cache settings
00757 
00763     var $_cacheUse = null;
00764 
00770     var $_cacheMaxAge = null;
00771 
00779     function ilBMFWSDL_Cache($cacheUse = WSDL_CACHE_USE,
00780                              $cacheMaxAge = WSDL_CACHE_MAX_AGE) {
00781         parent::ilBMFBase('WSDLCACHE');
00782         $this->_cacheUse = $cacheUse;
00783         $this->_cacheMaxAge = $cacheMaxAge;
00784     }
00785 
00790     function _cacheDir() {
00791         $dir = getenv("WSDLCACHE");
00792         if (!$dir) $dir = "./wsdlcache";
00793         @mkdir($dir, 0700);
00794         return $dir;
00795     }
00796 
00807     function get($wsdl_fname, $proxy_params = array(), $cache = 0) {
00808         $cachename = $md5_wsdl = $file_data = '';
00809         if ($this->_cacheUse) {
00810             // Try to retrieve WSDL from cache
00811             $cachename = ilBMFWSDL_Cache::_cacheDir() . '/' . md5($wsdl_fname). '.wsdl';
00812             if (file_exists($cachename)) {
00813                 $wf = fopen($cachename,'rb');
00814                 if ($wf) {
00815                     // Reading cached file
00816                     $file_data = fread($wf, filesize($cachename));
00817                     $md5_wsdl = md5($file_data);
00818                     fclose($wf);
00819                 }
00820                 if ($cache) {
00821                     if ($cache != $md5_wsdl) {
00822                         return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname);
00823                     }
00824                 } else {
00825                     $fi = stat($cachename);
00826                     $cache_mtime = $fi[8];
00827                     #print cache_mtime, time()
00828                     if ($cache_mtime + $this->_cacheMaxAge < time()) {
00829                         # expired
00830                         $md5_wsdl = ''; # refetch
00831                     }
00832                 }
00833             }
00834         }
00835 
00836         if (!$md5_wsdl) {
00837             // Not cached or not using cache. Retrieve WSDL from URL
00838 
00839             // is it a local file?
00840             // this section should be replace by curl at some point
00841             if (!preg_match('/^(https?|file):\/\//',$wsdl_fname)) {
00842                 if (!file_exists($wsdl_fname)) {
00843                     return $this->_raiseSoapFault("Unable to read local WSDL $wsdl_fname", $wsdl_fname);
00844                 }
00845                 if (function_exists('file_get_contents')) {
00846                     $file_data = file_get_contents($wsdl_fname);
00847                 } else {
00848                     $file_data = implode('',file($wsdl_fname));
00849                 }
00850             } else {
00851                 $uri = explode('?',$wsdl_fname);
00852                 $rq =& new HTTP_Request($uri[0], $proxy_params);
00853                 // the user agent HTTP_Request uses fouls things up
00854                 if (isset($uri[1])) {
00855                     $rq->addRawQueryString($uri[1]);
00856                 }
00857 
00858                 if (isset($proxy_params['proxy_host']) &&
00859                     isset($proxy_params['proxy_port']) &&
00860                     isset($proxy_params['proxy_user']) &&
00861                     isset($proxy_params['proxy_pass'])) {
00862                     $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port'],
00863                                   $proxy_params['proxy_user'], $proxy_params['proxy_pass']);
00864                 } elseif (isset($proxy_params['proxy_host']) &&
00865                           isset($proxy_params['proxy_port'])) {
00866                     $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port']);
00867                 }
00868 
00869                 $result = $rq->sendRequest();
00870                 if (PEAR::isError($result)) {
00871                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname," . $rq->getResponseCode(), $wsdl_fname);
00872             }
00873                $file_data = $rq->getResponseBody();
00874                 if (!$file_data) {
00875                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, no http body", $wsdl_fname);
00876                 }
00877             }
00878 
00879             $md5_wsdl = md5($file_data);
00880 
00881             if ($this->_cacheUse) {
00882                 $fp = fopen($cachename, "wb");
00883                 fwrite($fp, $file_data);
00884                 fclose($fp);
00885             }
00886         }
00887         if ($this->_cacheUse && $cache && $cache != $md5_wsdl) {
00888             return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname);
00889         }
00890         return $file_data;
00891     }
00892 }
00893 
00894 class ilBMFWSDL_Parser extends ilBMFBase
00895 {
00896     // define internal arrays of bindings, ports, operations, messages, etc.
00897     var $currentMessage;
00898     var $currentOperation;
00899     var $currentPortType;
00900     var $currentBinding;
00901     var $currentPort;
00902 
00903     // parser vars
00904     var $cache;
00905 
00906     var $tns = null;
00907     var $soapns = array('soap');
00908     var $uri = '';
00909     var $wsdl = null;
00910 
00911     var $status = '';
00912     var $element_stack = array();
00913     var $parentElement = '';
00914 
00915     var $schema = '';
00916     var $schemaStatus = '';
00917     var $schema_stack = array();
00918     var $currentComplexType;
00919     var $schema_element_stack = array();
00920     var $currentElement;
00921 
00922     // constructor
00923     function ilBMFWSDL_Parser($uri, &$wsdl, $docs = false) {
00924         parent::ilBMFBase('WSDLPARSER');
00925         $this->cache =& new ilBMFWSDL_Cache($wsdl->cacheUse, $wsdl->cacheMaxAge);
00926         $this->uri = $uri;
00927         $this->wsdl = &$wsdl;
00928         $this->docs = $docs;
00929         $this->parse($uri);
00930     }
00931 
00932     function parse($uri) {
00933         // Check whether content has been read.
00934         $fd = $this->cache->get($uri, $this->wsdl->proxy);
00935         if (PEAR::isError($fd)) {
00936             return $this->_raiseSoapFault($fd);
00937         }
00938 
00939         // Create an XML parser.
00940         $parser = xml_parser_create();
00941         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00942         xml_set_object($parser, $this);
00943         xml_set_element_handler($parser, 'startElement', 'endElement');
00944         if ($this->docs) {
00945             xml_set_character_data_handler($parser, 'characterData');
00946         }
00947 
00948         if (!xml_parse($parser,$fd, true)) {
00949             $detail = sprintf('XML error on line %d: %s',
00950                                     xml_get_current_line_number($parser),
00951                                     xml_error_string(xml_get_error_code($parser)));
00952             //print $fd;
00953             return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail");
00954         }
00955         xml_parser_free($parser);
00956         return true;
00957     }
00958 
00959     // start-element handler
00960     function startElement($parser, $name, $attrs) {
00961         // get element prefix
00962         $qname =& new ilBMFQName($name);
00963         if ($qname->ns) {
00964             $ns = $qname->ns;
00965             if ($ns && ((!$this->tns && strcasecmp($qname->name,'definitions') == 0) || $ns == $this->tns)) {
00966                 $name = $qname->name;
00967             }
00968         }
00969         $this->currentTag = $qname->name;
00970         $this->parentElement = '';
00971         $stack_size = count($this->element_stack);
00972         if ($stack_size > 0) {
00973             $this->parentElement = $this->element_stack[$stack_size-1];
00974         }
00975         $this->element_stack[] = $this->currentTag;
00976 
00977         // find status, register data
00978         switch($this->status) {
00979         case 'types':
00980             // sect 2.2 wsdl:types
00981             // children: xsd:schema
00982             $parent_tag = '';
00983             $stack_size = count($this->schema_stack);
00984             if ($stack_size > 0) {
00985                 $parent_tag = $this->schema_stack[$stack_size-1];
00986             }
00987 
00988             switch($qname->name) {
00989             case 'schema':
00990                 // no parent should be in the stack
00991                 if (!$parent_tag || $parent_tag == 'types') {
00992                     if (array_key_exists('targetNamespace', $attrs)) {
00993                         $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
00994                     } else {
00995                         $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
00996                     }
00997                     $this->wsdl->complexTypes[$this->schema] = array();
00998                     $this->wsdl->elements[$this->schema] = array();
00999                 }
01000             break;
01001             case 'complexType':
01002                 if ($parent_tag == 'schema') {
01003                     $this->currentComplexType = $attrs['name'];
01004                     if (!isset($attrs['namespace'])) $attrs['namespace'] = $this->schema;
01005                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs;
01006                     if (array_key_exists('base',$attrs)) {
01007                         $qn =& new ilBMFQName($attrs['base']);
01008                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
01009                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
01010                     } else {
01011                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01012                     }
01013                     $this->schemaStatus = 'complexType';
01014                 } else {
01015                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = TRUE;
01016                 }
01017             break;
01018             case 'element':
01019                 if (isset($attrs['type'])) {
01020                     $qn =& new ilBMFQName($attrs['type']);
01021                     $attrs['type'] = $qn->name;
01022                     #$this->wsdl->getNamespaceAttributeName
01023                     if ($qn->ns && array_key_exists($qn->ns, $this->wsdl->namespaces)) {
01024                         $attrs['namespace'] = $qn->ns;
01025                     }
01026                 }
01027 
01028                 $parentElement = '';
01029                 $stack_size = count($this->schema_element_stack);
01030                 if ($stack_size > 0) {
01031                     $parentElement = $this->schema_element_stack[$stack_size-1];
01032                 }
01033 
01034                 if (isset($attrs['ref'])) {
01035                     $this->currentElement = $attrs['ref'];
01036                 } else {
01037                     $this->currentElement = $attrs['name'];
01038                 }
01039                 $this->schema_element_stack[] = $this->currentElement;
01040                 if (!isset($attrs['namespace'])) $attrs['namespace'] = $this->schema;
01041 
01042                 if ($parent_tag == 'schema') {
01043                     $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs;
01044                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = FALSE;
01045                     $this->schemaStatus = 'element';
01046                 } else if ($this->currentComplexType) {
01047                     // we're inside a complexType
01048                     if ((isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order']) &&
01049                          $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence')
01050                         && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') {
01051                             $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = $attrs['type'];
01052                     }
01053                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs;
01054                 } else {
01055                     $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs;
01056                 }
01057             break;
01058             case 'complexContent':
01059             case 'simpleContent':
01060             break;
01061             case 'extension':
01062             case 'restriction':
01063                 if ($this->schemaStatus == 'complexType') {
01064                     if ($attrs['base']) {
01065                         $qn =& new ilBMFQName($attrs['base']);
01066                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
01067                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
01068                     } else {
01069                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01070                     }
01071                 }
01072             break;
01073             case 'sequence':
01074                 if ($this->schemaStatus == 'complexType') {
01075                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01076                     #if (!array_key_exists('type',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
01077                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01078                     #}
01079                 }
01080             break;
01081             case 'all':
01082                 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01083                 if (!array_key_exists('type',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
01084                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01085                 }
01086             break;
01087             case 'choice':
01088                 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01089                 if (!array_key_exists('type',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
01090                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01091                 }
01092             case 'attribute':
01093                 if ($this->schemaStatus == 'complexType') {
01094                     if (isset($attrs['name'])) {
01095                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs;
01096                     } else
01097                     if (isset($attrs['ref'])) {
01098                         $q =& new ilBMFQName($attrs['ref']);
01099                         foreach ($attrs as $k => $v) {
01100                             if ($k != 'ref' && strstr($k, $q->name)) {
01101                                 $vq =& new ilBMFQName($v);
01102                                 if ($q->name == 'arrayType') {
01103                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name.$vq->arrayInfo;
01104                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01105                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->ns;
01106                                 } else {
01107                                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name;
01108                                 }
01109                             }
01110                         }
01111                     }
01112                 }
01113             break;
01114             }
01115 
01116             $this->schema_stack[] = $qname->name;
01117 
01118         break;
01119         case 'message':
01120             // sect 2.3 wsdl:message child wsdl:part
01121             switch($qname->name) {
01122             case 'part':
01123                 $qn = NULL;
01124                 if (isset($attrs['type'])) {
01125                     $qn =& new ilBMFQName($attrs['type']);
01126                 } else if (isset($attrs['element'])) {
01127                     $qn =& new ilBMFQName($attrs['element']);
01128                 }
01129                 if ($qn) {
01130                     $attrs['type'] = $qn->name;
01131                     $attrs['namespace'] = $qn->ns;
01132                 }
01133                 $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs;
01134                 // error in wsdl
01135             case 'documentation':
01136                 break;
01137             default:
01138                 break;
01139             }
01140         break;
01141         case 'portType':
01142             // sect 2.4
01143             switch($qname->name) {
01144             case 'operation':
01145                 // attributes: name
01146                 // children: wsdl:input wsdl:output wsdl:fault
01147                 $this->currentOperation = $attrs['name'];
01148                 #$this->wsdl->portTypes[$this->currentPortType][$this->currentOperation]['parameterOrder'] = $attrs['parameterOrder'];
01149                 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs;
01150                 break;
01151             case 'input':
01152             case 'output':
01153             case 'fault':
01154                 // wsdl:input wsdl:output wsdl:fault
01155                 // attributes: name message parameterOrder(optional)
01156                 if ($this->currentOperation) {
01157                     if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) {
01158                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name],$attrs);
01159                     } else {
01160                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs;
01161                     }
01162                     if (array_key_exists('message',$attrs)) {
01163                         $qn =& new ilBMFQName($attrs['message']);
01164                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name;
01165                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->ns;
01166                     }
01167                 }
01168                 break;
01169             case 'documentation':
01170                 break;
01171             default:
01172                 break;
01173             }
01174         break;
01175         case 'binding':
01176             $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01177             switch($ns) {
01178             case SCHEMA_SOAP:
01179                 // this deals with wsdl section 3 soap binding
01180                 switch($qname->name) {
01181                 case 'binding':
01182                     // sect 3.3
01183                     // soap:binding, attributes: transport(required), style(optional, default = document)
01184                     // if style is missing, it is assumed to be 'document'
01185                     if (!isset($attrs['style'])) $attrs['style'] = 'document';
01186                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs);
01187                     break;
01188                 case 'operation':
01189                     // sect 3.4
01190                     // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style)
01191                     if (!isset($attrs['style'])) $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style'];
01192                     if (isset($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation])) {
01193                         $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = array_merge($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation],$attrs);
01194                     } else {
01195                         $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs;
01196                     }
01197                     break;
01198                 case 'body':
01199                     // sect 3.5
01200                     // soap:body attributes:
01201                     // part - optional.  listed parts must appear in body, missing means all parts appear in body
01202                     // use - required. encoded|literal
01203                     // encodingStyle - optional.  space seperated list of encodings (uri's)
01204                     $this->wsdl->bindings[$this->currentBinding]
01205                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
01206                     break;
01207                 case 'fault':
01208                     // sect 3.6
01209                     // soap:fault attributes: name use  encodingStyle namespace
01210                     $this->wsdl->bindings[$this->currentBinding]
01211                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
01212                     break;
01213                 case 'header':
01214                     // sect 3.7
01215                     // soap:header attributes: message part use encodingStyle namespace
01216                     $this->wsdl->bindings[$this->currentBinding]
01217                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
01218                     break;
01219                 case 'headerfault':
01220                     // sect 3.7
01221                     // soap:header attributes: message part use encodingStyle namespace
01222                     $header = count($this->wsdl->bindings[$this->currentBinding]
01223                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1;
01224                     $this->wsdl->bindings[$this->currentBinding]
01225                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs;
01226                     break;
01227                 case 'documentation':
01228                     break;
01229                 default:
01230                     // error!  not a valid element inside binding
01231                     break;
01232                 }
01233                 break;
01234             case SCHEMA_WSDL:
01235                 // XXX verify correct namespace
01236                 // for now, default is the 'wsdl' namespace
01237                 // other possible namespaces include smtp, http, etc. for alternate bindings
01238                 switch($qname->name) {
01239                 case 'operation':
01240                     // sect 2.5
01241                     // wsdl:operation attributes: name
01242                     $this->currentOperation = $attrs['name'];
01243                     break;
01244                 case 'output':
01245                 case 'input':
01246                 case 'fault':
01247                     // sect 2.5
01248                     // wsdl:input attributes: name
01249                     $this->opStatus = $qname->name;
01250                     break;
01251                 case 'documentation':
01252                     break;
01253                 default:
01254                     break;
01255                 }
01256                 break;
01257             case SCHEMA_WSDL_HTTP:
01258                 switch($qname->name) {
01259                 case 'binding':
01260                     // sect 4.4
01261                     // http:binding attributes: verb
01262                     // parent: wsdl:binding
01263                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs);
01264                     break;
01265                 case 'operation':
01266                     // sect 4.5
01267                     // http:operation attributes: location
01268                     // parent: wsdl:operation
01269                     $this->wsdl->bindings[$this->currentBinding]['operations']
01270                                                         [$this->currentOperation] = $attrs;
01271                     break;
01272                 case 'urlEncoded':
01273                     // sect 4.6
01274                     // http:urlEncoded attributes: location
01275                     // parent: wsdl:input wsdl:output etc.
01276                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01277                                                         [$this->currentOperation]['uri'] = 'urlEncoded';
01278                     break;
01279                 case 'urlReplacement':
01280                     // sect 4.7
01281                     // http:urlReplacement attributes: location
01282                     // parent: wsdl:input wsdl:output etc.
01283                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01284                                                         [$this->currentOperation]['uri'] = 'urlReplacement';
01285                     break;
01286                 case 'documentation':
01287                     break;
01288                 default:
01289                     // error
01290                     break;
01291                 }
01292             case SCHEMA_MIME:
01293                 // sect 5
01294                 // all mime parts are children of wsdl:input, wsdl:output, etc.
01295                 // unsuported as of yet
01296                 switch($qname->name) {
01297                 case 'content':
01298                     // sect 5.3 mime:content
01299                     // <mime:content part="nmtoken"? type="string"?/>
01300                     // part attribute only required if content is child of multipart related,
01301                     //        it contains the name of the part
01302                     // type attribute contains the mime type
01303                 case 'multipartRelated':
01304                     // sect 5.4 mime:multipartRelated
01305                 case 'part':
01306                 case 'mimeXml':
01307                     // sect 5.6 mime:mimeXml
01308                     // <mime:mimeXml part="nmtoken"?/>
01309                     //
01310                 case 'documentation':
01311                     break;
01312                 default:
01313                     // error
01314                     break;
01315                 }
01316             case SCHEMA_DIME:
01317                 // DIME is defined in:
01318                 // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm
01319                 // all DIME parts are children of wsdl:input, wsdl:output, etc.
01320                 // unsuported as of yet
01321                 switch($qname->name) {
01322                 case 'message':
01323                     // sect 4.1 dime:message
01324                     // appears in binding section
01325                     $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs;
01326                     break;
01327                 default:
01328                     break;
01329                 }
01330             default:
01331                 break;
01332             }
01333         break;
01334         case 'service':
01335             $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01336 
01337             switch($qname->name) {
01338             case 'port':
01339                 // sect 2.6 wsdl:port attributes: name binding
01340                 $this->currentPort = $attrs['name'];
01341                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs;
01342                 // XXX hack to deal with binding namespaces
01343                 $qn =& new ilBMFQName($attrs['binding']);
01344                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name;
01345                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->ns;
01346             break;
01347             case 'address':
01348                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs;
01349                 // what TYPE of port is it?  SOAP or HTTP?
01350                 $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01351                 switch($ns) {
01352                 case SCHEMA_WSDL_HTTP:
01353                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http';
01354                     break;
01355                 case SCHEMA_SOAP:
01356                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01357                     break;
01358                 default:
01359                     // shouldn't happen, we'll assume soap
01360                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01361                 }
01362 
01363             break;
01364             case 'documentation':
01365                 break;
01366             default:
01367                 break;
01368             }
01369         }
01370 
01371         // top level elements found under wsdl:definitions
01372         // set status
01373         switch($qname->name) {
01374         case 'import':
01375             // sect 2.1.1 wsdl:import attributes: namespace location
01376             if (array_key_exists('location',$attrs) &&
01377                 !isset($this->wsdl->imports[$attrs['namespace']])) {
01378                 $uri = $attrs['location'];
01379                 $location = parse_url($uri);
01380                 if (!isset($location['scheme'])) {
01381                     $base = parse_url($this->uri);
01382                     $uri = $this->merge_url($base,$uri);
01383                 }
01384                 $import_parser =& new ilBMFWSDL_Parser($uri, $this->wsdl);
01385                 if ($import_parser->fault) {
01386                     return FALSE;
01387                 }
01388                 $this->currentImport = $attrs['namespace'];
01389                 $this->wsdl->imports[$this->currentImport] = $attrs;
01390             }
01391             $this->status = '';
01392         case 'types':
01393             // sect 2.2 wsdl:types
01394             $this->status = 'types';
01395         break;
01396         case 'message':
01397             // sect 2.3 wsdl:message attributes: name children:wsdl:part
01398             $this->status = 'message';
01399             if (isset($attrs['name'])) {
01400                 $this->currentMessage = $attrs['name'];
01401                 $this->wsdl->messages[$this->currentMessage] = array();
01402             }
01403         break;
01404         case 'portType':
01405             // sect 2.4 wsdl:portType
01406             // attributes: name
01407             // children: wsdl:operation
01408             $this->status = 'portType';
01409             $this->currentPortType = $attrs['name'];
01410             $this->wsdl->portTypes[$this->currentPortType] = array();
01411         break;
01412         case 'binding':
01413             // sect 2.5 wsdl:binding attributes: name type
01414             // children: wsdl:operation soap:binding http:binding
01415             if ($qname->ns && $qname->ns != $this->tns) break;
01416             $this->status = 'binding';
01417             $this->currentBinding = $attrs['name'];
01418             $qn =& new ilBMFQName($attrs['type']);
01419             $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name;
01420             $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->ns;
01421         break;
01422         case 'service':
01423             // sect 2.7 wsdl:service attributes: name children: ports
01424             $this->currentService = $attrs['name'];
01425             $this->wsdl->services[$this->currentService]['ports'] = array();
01426             $this->status = 'service';
01427         break;
01428         case 'definitions':
01429             // sec 2.1 wsdl:definitions
01430             // attributes: name targetNamespace xmlns:*
01431             // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service
01432             #$this->status = 'definitions';
01433             $this->wsdl->definition = $attrs;
01434             foreach ($attrs as $key => $value) {
01435                 if (strstr($key,'xmlns:') !== FALSE) {
01436                     $qn =& new ilBMFQName($key);
01437                     // XXX need to refactor ns handling
01438                     $this->wsdl->namespaces[$qn->name] = $value;
01439                     $this->wsdl->ns[$value] = $qn->name;
01440                     if ($key == 'targetNamespace' ||
01441                         strcasecmp($value,SOAP_SCHEMA) == 0) {
01442                         $this->soapns[] = $qn->name;
01443                     } else {
01444                         if (in_array($value, $this->_XMLSchema)) {
01445                             $this->wsdl->xsd = $value;
01446                         }
01447                     }
01448                 }
01449             }
01450             if (isset($ns) && $ns) {
01451                 $namespace = 'xmlns:'.$ns;
01452                 if (!$this->wsdl->definition[$namespace]) {
01453                     return $this->_raiseSoapFault("parse error, no namespace for $namespace",$this->uri);
01454                 }
01455                 $this->tns = $ns;
01456             }
01457         break;
01458         }
01459     }
01460 
01461 
01462     // end-element handler
01463     function endElement($parser, $name)
01464     {
01465         $stacksize = count($this->element_stack);
01466         if ($stacksize > 0) {
01467             if ($this->element_stack[count($this->element_stack)-1] ==  'definitions') {
01468                 $this->status = '';
01469             }
01470             array_pop($this->element_stack);
01471         }
01472         if (stristr($name,'schema')) {
01473             array_pop($this->schema_stack);
01474             $this->schema = '';
01475         }
01476         if ($this->schema) {
01477             array_pop($this->schema_stack);
01478             if (count($this->schema_stack) <= 1) {
01479                 /* correct the type for sequences with multiple elements */
01480                 if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])
01481                     && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array'
01482                     && array_key_exists('elements',$this->wsdl->complexTypes[$this->schema][$this->currentComplexType])
01483                     && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) {
01484                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01485                 }
01486             }
01487             if (stristr($name,'complexType')) {
01488                 $this->currentComplexType = '';
01489                 if (count($this->schema_element_stack) > 0)
01490                     $this->currentElement = array_pop($this->schema_element_stack);
01491                 else
01492                     $this->currentElement = '';
01493             } else if (stristr($name,'element')) {
01494                 if (count($this->schema_element_stack) > 0)
01495                     $this->currentElement = array_pop($this->schema_element_stack);
01496                 else
01497                     $this->currentElement = '';
01498             }
01499         }
01500         // position of current element is equal to the last value left in depth_array for my depth
01501         //$pos = $this->depth_array[$this->depth];
01502         // bring depth down a notch
01503         //$this->depth--;
01504     }
01505 
01506     // element content handler
01507     function characterData($parser, $data)
01508     {
01509         # store the documentation in the WSDL file
01510         if ($this->currentTag == 'documentation') {
01511             if ($this->status ==  'service') {
01512                 $this->wsdl->services[$this->currentService][$this->currentTag] .= $data;
01513             } else if ($this->status ==  'portType') {
01514                 if ($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag])
01515                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] .= data;
01516                 else
01517                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] = data;
01518             } else if ($this->status ==  'binding') {
01519                 if ($this->wsdl->bindings[$this->currentBinding][$this->currentTag])
01520                     $this->wsdl->bindings[$this->currentBinding][$this->currentTag] .= data;
01521                 else
01522                     $this->wsdl->bindings[$this->currentBinding][$this->currentTag] = data;
01523             } else if ($this->status ==  'message') {
01524                 if ($this->wsdl->messages[$this->currentMessage][$this->currentTag])
01525                     $this->wsdl->messages[$this->currentMessage][$this->currentTag] .= data;
01526                 else
01527                     $this->wsdl->messages[$this->currentMessage][$this->currentTag] = data;
01528             } else if ($this->status ==  'operation') {
01529                 if ($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag])
01530                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] .= data;
01531                 else
01532                     $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$this->currentTag] = data;
01533             }
01534         }
01535     }
01536 
01537 
01538     // $parsed is a parse_url() resulting array
01539     function merge_url($parsed,$path) {
01540 
01541         if (! is_array($parsed)) return false;
01542 
01543         if (isset($parsed['scheme'])) {
01544             $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://');
01545             $uri = $parsed['scheme'] . $sep;
01546         } else {
01547             $uri = '';
01548         }
01549 
01550         if (isset($parsed['pass'])) {
01551             $uri .= "$parsed[user]:$parsed[pass]@";
01552         } elseif (isset($parsed['user'])) {
01553             $uri .= "$parsed[user]@";
01554         }
01555 
01556         if (isset($parsed['host']))     $uri .= $parsed['host'];
01557         if (isset($parsed['port']))     $uri .= ":$parsed[port]";
01558         if ($path[0]!='/' && isset($parsed['path'])) {
01559             if ($parsed['path'][strlen($parsed['path'])-1] != '/') {
01560                 $path = dirname($parsed['path']).'/'.$path;
01561             } else {
01562                 $path = $parsed['path'].$path;
01563             }
01564             $path = $this->_normalize($path);
01565         }
01566         $sep = $path[0]=='/'?'':'/';
01567         $uri .= $sep.$path;
01568 
01569         return $uri;
01570     }
01571 
01572     function _normalize($path_str){
01573         $pwd='';
01574         $strArr=preg_split("/(\/)/",$path_str,-1,PREG_SPLIT_NO_EMPTY);
01575         $pwdArr="";
01576         $j=0;
01577         for($i=0;$i<count($strArr);$i++){
01578             if($strArr[$i]!=".."){
01579                 if($strArr[$i]!="."){
01580                 $pwdArr[$j]=$strArr[$i];
01581                 $j++;
01582                 }
01583             }else{
01584                 array_pop($pwdArr);
01585                 $j--;
01586             }
01587         }
01588         $pStr=implode("/",$pwdArr);
01589         $pwd=(strlen($pStr)>0) ? ("/".$pStr) : "/";
01590         return $pwd;
01591     }
01592 }
01593 
01602 class ilBMFWSDL_ObjectParser extends ilBMFBase
01603 {
01604     // Target namespace for the WSDL document will have the following prefix
01605     var $tnsPrefix = 'tns';
01606 
01607     // Reference to the ilBMFWSDL object to populate
01608     var $wsdl = null;
01609 
01618     function ilBMFWSDL_ObjectParser(&$objects, &$wsdl, $targetNamespace, $service_name, $service_desc = '') {
01619         parent::ilBMFBase('WSDLOBJECTPARSER');
01620 
01621         $this->wsdl = &$wsdl;
01622 
01623         // Set up the ilBMFWSDL object
01624         $this->_initialise($service_name);
01625 
01626         // Parse each web service object
01627         $wsdl_ref = (is_array($objects)? $objects : array(&$objects));
01628 
01629         foreach ($wsdl_ref as $ref_item) {
01630             if (!is_object($ref_item))
01631                 return $this->_raiseSoapFault('Invalid web service object passed to object parser', 'urn:' . get_class($object));
01632 
01633             if ($this->_parse($ref_item, $targetNamespace, $service_name) != true)
01634                 break;
01635         }
01636 
01637         // Build bindings from abstract data
01638         if ($this->fault == NULL)
01639             $this->_generateBindingsAndServices($targetNamespace, $service_name, $service_desc);
01640     }
01641 
01650     function _initialise($service_name) {
01651         // Set up the basic namespaces that all WSDL definitions use
01652 
01653         $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL;                                      // WSDL language
01654         $this->wsdl->namespaces['soap'] = SCHEMA_SOAP;                                      // WSDL SOAP bindings
01655         $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name;                 // Target namespace
01656         $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces);           // XML Schema
01657         $this->wsdl->namespaces['SOAP-ENC'] = array_search('SOAP-ENC', $this->_namespaces); // SOAP types
01658 
01659         // XXX Refactor $namespace/$ns for Shane :-)
01660         unset($this->wsdl->ns['urn:' . $service_name]);
01661         $this->wsdl->ns += array_flip($this->wsdl->namespaces);
01662 
01663         // Imports are not implemented in WSDL generation from classes
01664         // *** <wsdl:import> ***
01665     }
01666 
01673     function _parse(&$object, $schemaNamespace, $service_name) {
01674         // Create namespace prefix for the schema
01675         // XXX not very elegant :-(
01676 
01677         list ($schPrefix, $foo) = $this->_getTypeNs('{'.$schemaNamespace.'}');
01678         unset($foo);
01679 
01680         // Parse all the types defined by the object in whatever
01681         // schema language we are using (currently __typedef arrays)
01682         // *** <wsdl:types> ***
01683 
01684         foreach ($object->__typedef as $typeName => $typeValue)
01685         {
01686             // Get/create namespace definition
01687 
01688             list($nsPrefix, $typeName) = $this->_getTypeNs($typeName);
01689 
01690             // Create type definition
01691 
01692             $this->wsdl->complexTypes[$schPrefix][$typeName] = array("name" => $typeName);
01693             $thisType =& $this->wsdl->complexTypes[$schPrefix][$typeName];
01694 
01695             // According to Dmitri's documentation, __typedef comes in two
01696             // flavors:
01697             // Array = array(array("item" => "value"))
01698             // Struct = array("item1" => "value1", "item2" => "value2", ...)
01699 
01700             if (is_array($typeValue))
01701             {
01702                 reset($typeValue);
01703                 if (is_array(current($typeValue)) && count($typeValue) == 1
01704                         && count(current($typeValue)) == 1)
01705                 {
01706                     // It's an array
01707 
01708                     $thisType['type'] = 'Array';
01709                     reset(current($typeValue));
01710                     list($nsPrefix, $typeName) = $this->_getTypeNs(current(current($typeValue)));
01711                     $thisType['namespace'] = $nsPrefix;
01712                     $thisType['arrayType'] = $typeName . '[]';
01713 
01714                 }
01715                 else if (!is_array(current($typeValue)))
01716                 {
01717                     // It's a struct
01718 
01719                     $thisType['type'] = 'Struct';
01720                     $thisType['order'] = 'all';
01721                     $thisType['namespace'] = $nsPrefix;
01722                     $thisType['elements'] = array();
01723 
01724                     foreach ($typeValue as $elementName => $elementType)
01725                     {
01726                         list($nsPrefix, $typeName) = $this->_getTypeNs($elementType);
01727                         $thisType['elements'][$elementName]['name'] = $elementName;
01728                         $thisType['elements'][$elementName]['type'] = $typeName;
01729                         $thisType['elements'][$elementName]['namespace'] = $nsPrefix;
01730                     }
01731                 }
01732                 else
01733                 {
01734                     // It's erroneous
01735 
01736                     return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
01737                 }
01738             } else {
01739                 // It's erroneous
01740 
01741                return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
01742             }
01743         }
01744 
01745         // Create an empty element array with the target namespace prefix,
01746         // to match the results of WSDL parsing
01747 
01748         $this->wsdl->elements[$schPrefix] = array();
01749 
01750         // Populate tree with message information
01751         // *** <wsdl:message> ***
01752 
01753         foreach ($object->__dispatch_map as $operationName => $messages)
01754         {
01755             foreach ($messages as $messageType => $messageParts)
01756             {
01757                 unset($thisMessage);
01758 
01759                 switch ($messageType) {
01760                 case 'in':
01761                     $this->wsdl->messages[$operationName . 'Request'] = array();
01762                     $thisMessage =& $this->wsdl->messages[$operationName . 'Request'];
01763                     break;
01764 
01765                 case 'out':
01766                     $this->wsdl->messages[$operationName . 'Response'] = array();
01767                     $thisMessage =& $this->wsdl->messages[$operationName . 'Response'];
01768                     break;
01769 
01770                 case 'alias':
01771                     // Do nothing
01772                     break;
01773 
01774                 default:
01775                     // Error condition
01776                     break;
01777                 }
01778 
01779                 if (isset($thisMessage))
01780                 {
01781                     foreach ($messageParts as $partName => $partType)
01782                     {
01783                         list ($nsPrefix, $typeName) = $this->_getTypeNs($partType);
01784 
01785                         $thisMessage[$partName] = array(
01786                             'name' => $partName,
01787                             'type' => $typeName,
01788                             'namespace' => $nsPrefix
01789                             );
01790                     }
01791                 }
01792             }
01793         }
01794 
01795         // Populate tree with portType information
01796         // XXX Current implementation only supports one portType that
01797         // encompasses all of the operations available.
01798         // *** <wsdl:portType> ***
01799 
01800         if (!isset($this->wsdl->portTypes[$service_name . 'Port']))
01801             $this->wsdl->portTypes[$service_name . 'Port'] = array();
01802         $thisPortType =& $this->wsdl->portTypes[$service_name . 'Port'];
01803 
01804         foreach ($object->__dispatch_map as $operationName => $messages)
01805         {
01806             $thisPortType[$operationName] = array('name' => $operationName);
01807 
01808             foreach ($messages as $messageType => $messageParts)
01809             {
01810                 switch ($messageType) {
01811                 case 'in':
01812                     $thisPortType[$operationName]['input'] = array(
01813                             'message' => $operationName . 'Request',
01814                             'namespace' => $this->tnsPrefix);
01815                     break;
01816 
01817                 case 'out':
01818                     $thisPortType[$operationName]['output'] = array(
01819                             'message' => $operationName . 'Response',
01820                             'namespace' => $this->tnsPrefix);
01821                     break;
01822 
01823                 default:
01824                     break;
01825                 }
01826             }
01827         }
01828 
01829         return true;
01830     }
01831 
01841     function _generateBindingsAndServices($schemaNamespace, $service_name, $service_desc = '')
01842     {
01843         // Populate tree with bindings information
01844         // XXX Current implementation only supports one binding that
01845         // matches the single portType and all of its operations.
01846         // XXX Is this the correct use of $schemaNamespace here?
01847         // *** <wsdl:binding> ***
01848 
01849         $this->wsdl->bindings[$service_name . 'Binding'] = array(
01850                 'type' => $service_name . 'Port',
01851                 'namespace' => $this->tnsPrefix,
01852                 'style' => 'rpc',
01853                 'transport' => SCHEMA_SOAP_HTTP,
01854                 'operations' => array());
01855         $thisBinding =& $this->wsdl->bindings[$service_name . 'Binding'];
01856 
01857         foreach ($this->wsdl->portTypes[$service_name . 'Port'] as $operationName => $operationData)
01858         {
01859             $thisBinding['operations'][$operationName] = array(
01860                 'soapAction' => $schemaNamespace . '#' . $operationName,
01861                 'style' => $thisBinding['style']);
01862 
01863             foreach (array('input', 'output') as $messageType)
01864                 if (isset($operationData[$messageType]))
01865                     $thisBinding['operations'][$operationName][$messageType] = array(
01866                             'use' => 'encoded',
01867                             'namespace' => $schemaNamespace,
01868                             'encodingStyle' => SOAP_SCHEMA_ENCODING);
01869         }
01870 
01871         // Populate tree with service information
01872         // XXX Current implementation supports one service which groups
01873         // all of the ports together, one port per binding
01874         // XXX What about https?
01875         // *** <wsdl:service> ***
01876 
01877         $this->wsdl->services[$service_name . 'Service'] = array('ports' => array());
01878         $thisService =& $this->wsdl->services[$service_name . 'Service']['ports'];
01879 
01880         foreach ($this->wsdl->bindings as $bindingName => $bindingData)
01881         {
01882             $thisService[$bindingData['type']] = array(
01883                     'name' => $bindingData['type'],
01884                     'binding' => $bindingName,
01885                     'namespace' => $this->tnsPrefix,
01886                     'address' => array('location' =>
01887                         'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] .
01888                         (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')),
01889                     'type' => 'soap');
01890         }
01891 
01892         // Set service
01893         $this->wsdl->set_service($service_name . 'Service');
01894         $this->wsdl->uri = $this->wsdl->namespaces[$this->tnsPrefix];
01895 
01896         // Create WSDL definition
01897         // *** <wsdl:definitions> ***
01898 
01899         $this->wsdl->definition = array(
01900                 'name' => $service_name,
01901                 'targetNamespace' => $this->wsdl->namespaces[$this->tnsPrefix],
01902                 'xmlns' => SCHEMA_WSDL);
01903 
01904         foreach ($this->wsdl->namespaces as $nsPrefix => $namespace)
01905             $this->wsdl->definition['xmlns:' . $nsPrefix] = $namespace;
01906     }
01907 
01908     // This function is adapted from Dmitri V's implementation of
01909     // DISCO/WSDL generation. It separates namespace from type name in a
01910     // __typedef key and creates a new namespace entry in the WSDL structure
01911     // if the namespace has not been used before. The namespace prefix and
01912     // type name are returned. If no namespace is specified, xsd is assumed.
01913     //
01914     // We will not need this function anymore once __typedef is eliminated.
01915     function _getTypeNs($type) {
01916         preg_match_all("'\{(.*)\}'sm",$type,$m);
01917         if (isset($m[1][0]) && $m[1][0] != '') {
01918             if (!array_key_exists($m[1][0],$this->wsdl->ns)) {
01919                 $ns_pref = 'ns' . count($this->wsdl->namespaces);
01920                 $this->wsdl->ns[$m[1][0]] = $ns_pref;
01921                 $this->wsdl->namespaces[$ns_pref] = $m[1][0];
01922             }
01923             $typens = $this->wsdl->ns[$m[1][0]];
01924             $type = ereg_replace($m[0][0],'',$type);
01925         } else {
01926             $typens = 'xsd';
01927         }
01928         return array($typens,$type);
01929     }
01930 }
01931 ?>

Generated on Fri Dec 13 2013 11:57:58 for ILIAS Release_3_6_x_branch .rev 46809 by  doxygen 1.7.1