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

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

Go to the documentation of this file.
00001 <?php
00025 require_once dirname(__FILE__).'/class.ilBMFBase.php';
00026 require_once dirname(__FILE__).'/class.ilBMFFault.php';
00027 require_once 'HTTP/Request.php';
00028 
00029 define('WSDL_CACHE_MAX_AGE', 43200);
00030 define('WSDL_CACHE_USE',     0); // set to zero to turn off caching
00031 
00049 class ilBMFWSDL extends ilBMFBase
00050 {
00051     var $tns = null;
00052     var $definition = array();
00053     var $namespaces = array();
00054     var $ns = array();
00055     var $xsd = SOAP_XML_SCHEMA_VERSION;
00056     var $complexTypes = array();
00057     var $elements = array();
00058     var $messages = array();
00059     var $portTypes = array();
00060     var $bindings = array();
00061     var $imports = array();
00062     var $services = array();
00063     var $service = '';
00064     var $uri = '';
00065     var $docs = false;
00066 
00072     var $proxy = null;
00073 
00074     var $trace = 0;
00075 
00081     var $cacheUse = null;
00082 
00088     var $cacheMaxAge = null;
00089 
00096     var $wsdlParserClass = 'ilBMFWSDL_Parser';
00097 
00111     function ilBMFWSDL($wsdl_uri    = false,
00112                        $proxy       = array(),
00113                        $cacheUse    = WSDL_CACHE_USE,
00114                        $cacheMaxAge = WSDL_CACHE_MAX_AGE,
00115                        $docs        = false)
00116     {
00117         parent::ilBMFBase('WSDL');
00118         $this->uri         = $wsdl_uri;
00119         $this->proxy       = $proxy;
00120         $this->cacheUse    = $cacheUse;
00121         $this->cacheMaxAge = $cacheMaxAge;
00122         $this->docs        = $docs;
00123 
00124         if ($wsdl_uri) {
00125             if (!PEAR::isError($this->parseURL($wsdl_uri))) {
00126                 reset($this->services);
00127                 $this->service = key($this->services);
00128             }
00129         }
00130     }
00131 
00132     function set_service($service)
00133     {
00134         if (array_key_exists($service, $this->services)) {
00135             $this->service = $service;
00136         }
00137     }
00138 
00142     function parse($wsdl_uri, $proxy = array())
00143     {
00144         $this->parseURL($wsdl_uri, $proxy);
00145     }
00146 
00154     function parseURL($wsdl_uri, $proxy = array())
00155     {
00156         $parser =& new $this->wsdlParserClass($wsdl_uri, $this, $this->docs);
00157 
00158         if ($parser->fault) {
00159             $this->_raiseSoapFault($parser->fault);
00160         }
00161     }
00162 
00174     function parseObject(&$wsdl_obj, $targetNamespace, $service_name,
00175                          $service_desc = '')
00176     {
00177         $parser =& new ilBMFWSDL_ObjectParser($wsdl_obj, $this,
00178                                               $targetNamespace, $service_name,
00179                                               $service_desc);
00180 
00181          if ($parser->fault) {
00182              $this->_raiseSoapFault($parser->fault);
00183          }
00184     }
00185 
00186     function getEndpoint($portName)
00187     {
00188         if ($this->__isfault()) {
00189             return $this->__getfault();
00190         }
00191 
00192         return (isset($this->services[$this->service]['ports'][$portName]['address']['location']))
00193                 ? $this->services[$this->service]['ports'][$portName]['address']['location']
00194                 : $this->_raiseSoapFault("No endpoint for port for $portName", $this->uri);
00195     }
00196 
00197     function _getPortName($operation, $service)
00198     {
00199         if (isset($this->services[$service]['ports'])) {
00200             $ports = $this->services[$service]['ports'];
00201             foreach ($ports as $port => $portAttrs) {
00202                 $type = $ports[$port]['type'];
00203                 if ($type == 'soap' &&
00204                     isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) {
00205                     return $port;
00206                 }
00207             }
00208         }
00209         return null;
00210     }
00211 
00216     function getPortName($operation, $service = null)
00217     {
00218         if ($this->__isfault()) {
00219             return $this->__getfault();
00220         }
00221 
00222         if (!$service) {
00223             $service = $this->service;
00224         }
00225         if (isset($this->services[$service]['ports'])) {
00226             if ($portName = $this->_getPortName($operation, $service)) {
00227                 return $portName;
00228             }
00229         }
00230         // Try any service in the WSDL.
00231         foreach ($this->services as $serviceName => $service) {
00232             if (isset($this->services[$serviceName]['ports'])) {
00233                 if ($portName = $this->_getPortName($operation, $serviceName)) {
00234                     $this->service = $serviceName;
00235                     return $portName;
00236                 }
00237             }
00238         }
00239         return $this->_raiseSoapFault("No operation $operation in WSDL.", $this->uri);
00240     }
00241 
00242     function getOperationData($portName, $operation)
00243     {
00244         if ($this->__isfault()) {
00245             return $this->__getfault();
00246         }
00247 
00248         if (!isset($this->services[$this->service]['ports'][$portName]['binding']) ||
00249             !($binding = $this->services[$this->service]['ports'][$portName]['binding'])) {
00250             return $this->_raiseSoapFault("No binding for port $portName in WSDL.", $this->uri);
00251         }
00252 
00253         // Get operation data from binding.
00254         if (is_array($this->bindings[$binding]['operations'][$operation])) {
00255             $opData = $this->bindings[$binding]['operations'][$operation];
00256         }
00257         // get operation data from porttype
00258         $portType = $this->bindings[$binding]['type'];
00259         if (!$portType) {
00260             return $this->_raiseSoapFault("No port type for binding $binding in WSDL.", $this->uri);
00261         }
00262         if (is_array($type = $this->portTypes[$portType][$operation])) {
00263             if (isset($type['parameterOrder'])) {
00264                 $opData['parameterOrder'] = $type['parameterOrder'];
00265             }
00266             $opData['input'] = array_merge($opData['input'], $type['input']);
00267             $opData['output'] = array_merge($opData['output'], $type['output']);
00268         }
00269         if (!$opData)
00270             return $this->_raiseSoapFault("No operation $operation for port $portName in WSDL.", $this->uri);
00271         $opData['parameters'] = false;
00272         if (isset($this->bindings[$binding]['operations'][$operation]['input']['namespace']))
00273             $opData['namespace'] = $this->bindings[$binding]['operations'][$operation]['input']['namespace'];
00274         // Message data from messages.
00275         $inputMsg = $opData['input']['message'];
00276         if (is_array($this->messages[$inputMsg])) {
00277             foreach ($this->messages[$inputMsg] as $pname => $pattrs) {
00278                 if ($opData['style'] == 'document' &&
00279                     $opData['input']['use'] == 'literal' &&
00280                     $pname == 'parameters') {
00281                     $opData['parameters'] = true;
00282                     $opData['namespace'] = $this->namespaces[$pattrs['namespace']];
00283                     $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00284                     if (isset($el['elements'])) {
00285                         foreach ($el['elements'] as $elname => $elattrs) {
00286                             $opData['input']['parts'][$elname] = $elattrs;
00287                         }
00288                     }
00289                 } else {
00290                     $opData['input']['parts'][$pname] = $pattrs;
00291                 }
00292             }
00293         }
00294         $outputMsg = $opData['output']['message'];
00295         if (is_array($this->messages[$outputMsg])) {
00296             foreach ($this->messages[$outputMsg] as $pname => $pattrs) {
00297                 if ($opData['style'] == 'document' &&
00298                     $opData['output']['use'] == 'literal' &&
00299                     $pname == 'parameters') {
00300 
00301                     $el = $this->elements[$pattrs['namespace']][$pattrs['type']];
00302                     if (isset($el['elements'])) {
00303                         foreach ($el['elements'] as $elname => $elattrs) {
00304                             $opData['output']['parts'][$elname] = $elattrs;
00305                         }
00306                     }
00307                 } else {
00308                     $opData['output']['parts'][$pname] = $pattrs;
00309                 }
00310             }
00311         }
00312         return $opData;
00313     }
00314 
00315     function matchMethod(&$operation)
00316     {
00317         if ($this->__isfault()) {
00318             return $this->__getfault();
00319         }
00320 
00321         // Overloading lowercases function names :(
00322         foreach ($this->services[$this->service]['ports'] as $port => $portAttrs) {
00323             foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) {
00324                 if (strcasecmp($op, $operation) == 0) {
00325                     $operation = $op;
00326                 }
00327             }
00328         }
00329     }
00330 
00342     function getDataHandler($datatype, $namespace)
00343     {
00344         // See if we have an element by this name.
00345         if (isset($this->namespaces[$namespace])) {
00346             $namespace = $this->namespaces[$namespace];
00347         }
00348 
00349         if (isset($this->ns[$namespace])) {
00350             $nsp = $this->ns[$namespace];
00351             //if (!isset($this->elements[$nsp]))
00352             //    $nsp = $this->namespaces[$nsp];
00353             if (isset($this->elements[$nsp][$datatype])) {
00354                 $checkmessages = array();
00355                 // Find what messages use this datatype.
00356                 foreach ($this->messages as $messagename => $message) {
00357                     foreach ($message as $partname => $part) {
00358                         if ($part['type'] == $datatype) {
00359                             $checkmessages[] = $messagename;
00360                             break;
00361                         }
00362                     }
00363                 }
00364                 // Find the operation that uses this message.
00365                 $dataHandler = null;
00366                 foreach($this->portTypes as $portname => $porttype) {
00367                     foreach ($porttype as $opname => $opinfo) {
00368                         foreach ($checkmessages as $messagename) {
00369                             if ($opinfo['input']['message'] == $messagename) {
00370                                 return $opname;
00371                             }
00372                         }
00373                     }
00374                 }
00375             }
00376         }
00377 
00378         return null;
00379     }
00380 
00381     function getSoapAction($portName, $operation)
00382     {
00383         if ($this->__isfault()) {
00384             return $this->__getfault();
00385         }
00386 
00387         if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'])) {
00388             return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'];
00389         }
00390 
00391         return false;
00392     }
00393 
00394     function getNamespace($portName, $operation)
00395     {
00396         if ($this->__isfault()) {
00397             return $this->__getfault();
00398         }
00399 
00400         if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'])) {
00401             return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'];
00402         }
00403 
00404         return false;
00405     }
00406 
00407     function getNamespaceAttributeName($namespace)
00408     {
00409         /* If it doesn't exist at first, flip the array and check again. */
00410         if (empty($this->ns[$namespace])) {
00411             $this->ns = array_flip($this->namespaces);
00412         }
00413 
00414         /* If it doesn't exist now, add it. */
00415         if (empty($this->ns[$namespace])) {
00416             return $this->addNamespace($namespace);
00417         }
00418 
00419         return $this->ns[$namespace];
00420     }
00421 
00422     function addNamespace($namespace)
00423     {
00424         if (!empty($this->ns[$namespace])) {
00425             return $this->ns[$namespace];
00426         }
00427 
00428         $n = count($this->ns);
00429         $attr = 'ns' . $n;
00430         $this->namespaces['ns' . $n] = $namespace;
00431         $this->ns[$namespace] = $attr;
00432 
00433         return $attr;
00434     }
00435 
00436     function _validateString($string)
00437     {
00438         return preg_match('/^[\w_:#\/]+$/', $string);
00439     }
00440 
00441     function _addArg(&$args, &$argarray, $argname)
00442     {
00443         if ($args) {
00444             $args .= ', ';
00445         }
00446         $args .= '$' . $argname;
00447         if (!$this->_validateString($argname)) {
00448             return;
00449         }
00450         if ($argarray) {
00451             $argarray .= ', ';
00452         }
00453         $argarray .= "'$argname' => $" . $argname;
00454     }
00455 
00456     function _elementArg(&$args, &$argarray, &$_argtype, $_argname)
00457     {
00458         $comments = '';
00459         $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00460         $tns = isset($this->ns[$el['namespace']])
00461             ? $this->ns[$el['namespace']]
00462             : $_argtype['namespace'];
00463 
00464         if (!empty($el['complex']) ||
00465             (isset($el['type']) &&
00466              isset($this->complexTypes[$tns][$el['type']]))) {
00467             // The element is a complex type.
00468             $comments .= "        // {$_argtype['type']} is a ComplexType, refer to the WSDL for more info.\n";
00469             $attrname = "{$_argtype['type']}_attr";
00470             if (isset($el['type']) &&
00471                 isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00472                 $comments .= "        // {$_argtype['type']} may require attributes, refer to the WSDL for more info.\n";
00473             }
00474             $comments .= "        \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n";
00475             $comments .= "        \${$_argtype['type']} =& new ilBMFValue('{$_argtype['type']}', false, \${$_argtype['type']}, \$$attrname);\n";
00476             $this->_addArg($args, $argarray, $_argtype['type']);
00477             if (isset($el['type']) &&
00478                 isset($this->complexTypes[$tns][$el['type']]['attribute'])) {
00479                 if ($args) {
00480                     $args .= ', ';
00481                 }
00482                 $args .= '$' . $attrname;
00483             }
00484         } elseif (isset($el['elements'])) {
00485             foreach ($el['elements'] as $ename => $element) {
00486                 $comments .= "        \$$ename =& new ilBMFValue('{{$this->namespaces[$element['namespace']]}}$ename', '" .
00487                     (isset($element['type']) ? $element['type'] : false) .
00488                     "', \$$ename);\n";
00489                 $this->_addArg($args, $argarray, $ename);
00490             }
00491         } else {
00492             $comments .= "        \$$_argname =& new ilBMFValue('{{$this->namespaces[$tns]}}$_argname', '{$el['type']}', \$$_argname);\n";
00493             $this->_addArg($args, $argarray, $_argname);
00494         }
00495 
00496         return $comments;
00497     }
00498 
00499     function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname)
00500     {
00501         $comments = '';
00502         if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) {
00503             $comments  = "        // $_argname is a ComplexType {$_argtype['type']},\n" .
00504                 "        // refer to wsdl for more info\n";
00505             if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) {
00506                 $comments .= "        // $_argname may require attributes, refer to wsdl for more info\n";
00507             }
00508             $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $_argtype['type'];
00509             $comments .= "        \$$_argname =& new ilBMFValue('$_argname', '$wrapname', \$$_argname);\n";
00510         }
00511 
00512         $this->_addArg($args, $argarray, $_argname);
00513 
00514         return $comments;
00515     }
00516 
00521     function generateProxyCode($port = '', $classname = '')
00522     {
00523         if ($this->__isfault()) {
00524             return $this->__getfault();
00525         }
00526 
00527         $multiport = count($this->services[$this->service]['ports']) > 1;
00528         if (!$port) {
00529             reset($this->services[$this->service]['ports']);
00530             $port = current($this->services[$this->service]['ports']);
00531         }
00532         // XXX currently do not support HTTP ports
00533         if ($port['type'] != 'soap') {
00534             return null;
00535         }
00536 
00537         // XXX currentPort is BAD
00538         $clienturl = $port['address']['location'];
00539         if (!$classname) {
00540             if ($multiport || $port) {
00541                 $classname = 'WebService_' . $this->service . '_' . $port['name'];
00542             } else {
00543                 $classname = 'WebService_' . $this->service;
00544             }
00545             $classname = preg_replace('/[ .\-\(\)]+/', '_', $classname);
00546         }
00547 
00548         if (!$this->_validateString($classname)) {
00549             return null;
00550         }
00551 
00552         if (is_array($this->proxy) && count($this->proxy)) {
00553             $class = "class $classname extends ilBMFClient\n{\n" .
00554             "    function $classname(\$path = '$clienturl')\n    {\n" .
00555             "        \$this->ilBMFClient(\$path, 0, 0,\n" .
00556             '                           array(';
00557 
00558             foreach ($this->proxy as $key => $val) {
00559                 if (is_array($val)) {
00560                     $class .= "'$key' => array(";
00561                     foreach ($val as $key2 => $val2) {
00562                         $class .= "'$key2' => '$val2', ";
00563                     }
00564                     $class .= ')';
00565                 } else {
00566                     $class .= "'$key' => '$val', ";
00567                 }
00568             }
00569             $class .= "));\n    }\n";
00570             $class = str_replace(', ))', '))', $class);
00571         } else {
00572             $class = "class $classname extends ilBMFClient\n{\n" .
00573             "    function $classname(\$path = '$clienturl')\n    {\n" .
00574             "        \$this->ilBMFClient(\$path, 0);\n" .
00575             "    }\n";
00576         }
00577 
00578         // Get the binding, from that get the port type.
00579         $primaryBinding = $port['binding'];
00580         $primaryBinding = preg_replace("/^(.*:)/", '', $primaryBinding);
00581         $portType = $this->bindings[$primaryBinding]['type'];
00582         $portType = preg_replace("/^(.*:)/", '', $portType);
00583         $style = $this->bindings[$primaryBinding]['style'];
00584 
00585         // XXX currentPortType is BAD
00586         foreach ($this->portTypes[$portType] as $opname => $operation) {
00587             $binding = $this->bindings[$primaryBinding]['operations'][$opname];
00588             if (isset($binding['soapAction'])) {
00589                 $soapaction = $binding['soapAction'];
00590             } else {
00591                 $soapaction = null;
00592             }
00593             if (isset($binding['style'])) {
00594                 $opstyle = $binding['style'];
00595             } else {
00596                 $opstyle = $style;
00597             }
00598             $use = $binding['input']['use'];
00599             if ($use == 'encoded') {
00600                 $namespace = $binding['input']['namespace'];
00601             } else {
00602                 $bindingType = $this->bindings[$primaryBinding]['type'];
00603                 $ns = $this->portTypes[$bindingType][$opname]['input']['namespace'];
00604                 $namespace = $this->namespaces[$ns];
00605             }
00606 
00607             $args = '';
00608             $argarray = '';
00609             $comments = '';
00610             $wrappers = '';
00611             foreach ($operation['input'] as $argname => $argtype) {
00612                 if ($argname == 'message') {
00613                     foreach ($this->messages[$argtype] as $_argname => $_argtype) {
00614                         if ($opstyle == 'document' && $use == 'literal' &&
00615                             $_argtype['name'] == 'parameters') {
00616                             // The type or element refered to is used for
00617                             // parameters.
00618                             $elattrs = null;
00619                             $element = $_argtype['element'];
00620                             $el = $this->elements[$_argtype['namespace']][$_argtype['type']];
00621 
00622                             if ($el['complex']) {
00623                                 $namespace = $this->namespaces[$_argtype['namespace']];
00624                                 // XXX need to wrap the parameters in a
00625                                 // ilBMFValue.
00626                             }
00627                             if (isset($el['elements'])) {
00628                                 foreach ($el['elements'] as $elname => $elattrs) {
00629                                     // Is the element a complex type?
00630                                     if (isset($this->complexTypes[$elattrs['namespace']][$elname])) {
00631                                         $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00632                                     } else {
00633                                         $this->_addArg($args, $argarray, $elname);
00634                                     }
00635                                 }
00636                             }
00637                             if ($el['complex'] && $argarray) {
00638                                 $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $el['name'];
00639                                 $comments .= "        \${$el['name']} =& new ilBMFValue('$wrapname', false, \$v = array($argarray));\n";
00640                                 $argarray = "'{$el['name']}' => \${$el['name']}";
00641                             }
00642                         } else {
00643                             if (isset($_argtype['element'])) {
00644                                 // Element argument.
00645                                 $comments .= $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']);
00646                             } else {
00647                                 // Complex type argument.
00648                                 $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname);
00649                             }
00650                         }
00651                     }
00652                 }
00653             }
00654 
00655             // Validate entries.
00656 
00657             // Operation names are function names, so try to make sure it's
00658             // legal. This could potentially cause collisions, but let's try
00659             // to make everything callable and see how many problems that
00660             // causes.
00661             $opname_php = preg_replace('/[ .\-\(\)]+/', '_', $opname);
00662             if (!$this->_validateString($opname_php)) {
00663                 return null;
00664             }
00665 
00666             if ($argarray) {
00667                 $argarray = "array($argarray)";
00668             } else {
00669                 $argarray = 'null';
00670             }
00671 
00672             $class .= "    function &$opname_php($args)\n    {\n$comments$wrappers" .
00673                 "        \$result = \$this->call('$opname',\n" .
00674                 "                              \$v = $argarray,\n" .
00675                 "                              array('namespace' => '$namespace',\n" .
00676                 "                                    'soapaction' => '$soapaction',\n" .
00677                 "                                    'style' => '$opstyle',\n" .
00678                 "                                    'use' => '$use'" .
00679                 ($this->trace?",\n                                    'trace' => 1" : '') . "));\n" .
00680                 "        return \$result;\n" .
00681                 "    }\n";
00682         }
00683 
00684         $class .= "}\n";
00685 
00686         return $class;
00687     }
00688 
00689     function generateAllProxies()
00690     {
00691         $proxycode = '';
00692         foreach (array_keys($this->services[$this->service]['ports']) as $key) {
00693             $port =& $this->services[$this->service]['ports'][$key];
00694             $proxycode .= $this->generateProxyCode($port);
00695         }
00696         return $proxycode;
00697     }
00698 
00699     function &getProxy($port = '', $name = '')
00700     {
00701         if ($this->__isfault()) {
00702             $fault =& $this->__getfault();
00703             return $fault;
00704         }
00705 
00706         $multiport = count($this->services[$this->service]['ports']) > 1;
00707 
00708         if (!$port) {
00709             reset($this->services[$this->service]['ports']);
00710             $port = current($this->services[$this->service]['ports']);
00711         }
00712 
00713         if ($multiport || $port) {
00714             $classname = 'WebService_' . $this->service . '_' . $port['name'];
00715         } else {
00716             $classname = 'WebService_' . $this->service;
00717         }
00718 
00719         if ($name) {
00720             $classname = $name . '_' . $classname;
00721         }
00722 
00723         $classname = preg_replace('/[ .\-\(\)]+/', '_', $classname);
00724         if (!class_exists($classname)) {
00725             $proxy = $this->generateProxyCode($port, $classname);
00726             require_once 'SOAP/Client.php';
00727             eval($proxy);
00728         }
00729         $proxy =& new $classname;
00730 
00731         return $proxy;
00732     }
00733 
00734     function &_getComplexTypeForElement($name, $namespace)
00735     {
00736         $t = null;
00737         if (isset($this->ns[$namespace]) &&
00738             isset($this->elements[$this->ns[$namespace]][$name]['type'])) {
00739 
00740             $type = $this->elements[$this->ns[$namespace]][$name]['type'];
00741             $ns = $this->elements[$this->ns[$namespace]][$name]['namespace'];
00742 
00743             if (isset($this->complexTypes[$ns][$type])) {
00744                 $t = $this->complexTypes[$ns][$type];
00745             }
00746         }
00747         return $t;
00748     }
00749 
00750     function getComplexTypeNameForElement($name, $namespace)
00751     {
00752         $t = $this->_getComplexTypeForElement($name, $namespace);
00753         if ($t) {
00754             return $t['name'];
00755         }
00756         return null;
00757     }
00758 
00759     function getComplexTypeChildType($ns, $name, $child_ns, $child_name)
00760     {
00761         // is the type an element?
00762         $t = $this->_getComplexTypeForElement($name, $ns);
00763         if ($t) {
00764             // no, get it from complex types directly
00765             if (isset($t['elements'][$child_name]['type']))
00766                 return $t['elements'][$child_name]['type'];
00767         }
00768         return null;
00769     }
00770 
00771     function getSchemaType($type, $name, $type_namespace)
00772     {
00773         // see if it's a complex type so we can deal properly with
00774         // SOAPENC:arrayType.
00775         if ($name && $type) {
00776             // XXX TODO:
00777             // look up the name in the wsdl and validate the type.
00778             foreach ($this->complexTypes as $ns => $types) {
00779                 if (array_key_exists($type, $types)) {
00780                     if (array_key_exists('type', $types[$type])) {
00781                         list($arraytype_ns, $arraytype, $array_depth) = isset($types[$type]['arrayType'])?
00782                             $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType'])
00783                             : array($this->namespaces[$types[$type]['namespace']], null, 0);
00784                         return array($types[$type]['type'], $arraytype, $arraytype_ns, $array_depth);
00785                     }
00786                     if (array_key_exists('arrayType', $types[$type])) {
00787                         list($arraytype_ns, $arraytype, $array_depth) =
00788                             $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType']);
00789                         return array('Array', $arraytype, $arraytype_ns, $array_depth);
00790                     }
00791                     if (array_key_exists('elements', $types[$type]) &&
00792                         array_key_exists($name, $types[$type]['elements'])) {
00793                         $type = $types[$type]['elements']['type'];
00794                         return array($type, null, $this->namespaces[$types[$type]['namespace']], null);
00795                     }
00796                 }
00797             }
00798         }
00799         if ($type && $type_namespace) {
00800             $arrayType = null;
00801             // XXX TODO:
00802             // this code currently handles only one way of encoding array types in wsdl
00803             // need to do a generalized function to figure out complex types
00804             $p = $this->ns[$type_namespace];
00805             if ($p &&
00806                 array_key_exists($p, $this->complexTypes) &&
00807                 array_key_exists($type, $this->complexTypes[$p])) {
00808                 if ($arrayType = $this->complexTypes[$p][$type]['arrayType']) {
00809                     $type = 'Array';
00810                 } elseif ($this->complexTypes[$p][$type]['order']=='sequence' &&
00811                           array_key_exists('elements', $this->complexTypes[$p][$type])) {
00812                     reset($this->complexTypes[$p][$type]['elements']);
00813                     // assume an array
00814                     if (count($this->complexTypes[$p][$type]['elements']) == 1) {
00815                         $arg = current($this->complexTypes[$p][$type]['elements']);
00816                         $arrayType = $arg['type'];
00817                         $type = 'Array';
00818                     } else {
00819                         foreach ($this->complexTypes[$p][$type]['elements'] as $element) {
00820                             if ($element['name'] == $type) {
00821                                 $arrayType = $element['type'];
00822                                 $type = $element['type'];
00823                             }
00824                         }
00825                     }
00826                 } else {
00827                     $type = 'Struct';
00828                 }
00829                 return array($type, $arrayType, $type_namespace, null);
00830             }
00831         }
00832         return array(null, null, null, null);
00833     }
00834 
00846     function _getDeepestArrayType($nsPrefix, $arrayType)
00847     {
00848         static $trail = array();
00849 
00850         $arrayType = ereg_replace('\[\]$', '', $arrayType);
00851 
00852         // Protect against circular references XXX We really need to remove
00853         // trail from this altogether (it's very inefficient and in the wrong
00854         // place!) and put circular reference checking in when the WSDL info
00855         // is generated in the first place
00856         if (array_search($nsPrefix . ':' . $arrayType, $trail)) {
00857             return array(null, null, -count($trail));
00858         }
00859 
00860         if (array_key_exists($nsPrefix, $this->complexTypes) &&
00861             array_key_exists($arrayType, $this->complexTypes[$nsPrefix]) &&
00862             array_key_exists('arrayType', $this->complexTypes[$nsPrefix][$arrayType])) {
00863             $trail[] = $nsPrefix . ':' . $arrayType;
00864             $result = $this->_getDeepestArrayType($this->complexTypes[$nsPrefix][$arrayType]['namespace'],
00865                                                   $this->complexTypes[$nsPrefix][$arrayType]['arrayType']);
00866             return array($result[0], $result[1], $result[2] + 1);
00867         }
00868         return array($this->namespaces[$nsPrefix], $arrayType, 0);
00869     }
00870 
00871 }
00872 
00873 class ilBMFWSDL_Cache extends ilBMFBase
00874 {
00875     // Cache settings
00876 
00882     var $_cacheUse = null;
00883 
00889     var $_cacheMaxAge = null;
00890 
00898     function ilBMFWSDL_Cache($cacheUse = WSDL_CACHE_USE,
00899                              $cacheMaxAge = WSDL_CACHE_MAX_AGE)
00900     {
00901         parent::ilBMFBase('WSDLCACHE');
00902         $this->_cacheUse = $cacheUse;
00903         $this->_cacheMaxAge = $cacheMaxAge;
00904     }
00905 
00910     function _cacheDir()
00911     {
00912         $dir = getenv("WSDLCACHE");
00913         if (!$dir) $dir = " ./wsdlcache";
00914         @mkdir($dir, 0700);
00915         return $dir;
00916     }
00917 
00928     function get($wsdl_fname, $proxy_params = array(), $cache = 0)
00929     {
00930         $cachename = $md5_wsdl = $file_data = '';
00931         if ($this->_cacheUse) {
00932             // Try to retrieve WSDL from cache
00933             $cachename = ilBMFWSDL_Cache::_cacheDir() . '/' . md5($wsdl_fname). ' .wsdl';
00934             if (file_exists($cachename)) {
00935                 $wf = fopen($cachename, 'rb');
00936                 if ($wf) {
00937                     // Reading cached file
00938                     $file_data = fread($wf, filesize($cachename));
00939                     $md5_wsdl = md5($file_data);
00940                     fclose($wf);
00941                 }
00942                 if ($cache) {
00943                     if ($cache != $md5_wsdl) {
00944                         return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname);
00945                     }
00946                 } else {
00947                     $fi = stat($cachename);
00948                     $cache_mtime = $fi[8];
00949                     //print cache_mtime, time()
00950                     if ($cache_mtime + $this->_cacheMaxAge < time()) {
00951                         // expired
00952                         $md5_wsdl = ''; // refetch
00953                     }
00954                 }
00955             }
00956         }
00957 
00958         if (!$md5_wsdl) {
00959             // Not cached or not using cache. Retrieve WSDL from URL
00960 
00961             // is it a local file?
00962             // this section should be replace by curl at some point
00963             if (!preg_match('/^(https?|file):\/\//', $wsdl_fname)) {
00964                 if (!file_exists($wsdl_fname)) {
00965                     return $this->_raiseSoapFault("Unable to read local WSDL $wsdl_fname", $wsdl_fname);
00966                 }
00967                 if (function_exists('file_get_contents')) {
00968                     $file_data = file_get_contents($wsdl_fname);
00969                 } else {
00970                     $file_data = implode('',file($wsdl_fname));
00971                 }
00972             } else {
00973                 $uri = explode('?', $wsdl_fname);
00974                 $rq =& new HTTP_Request($uri[0], $proxy_params);
00975                 // the user agent HTTP_Request uses fouls things up
00976                 if (isset($uri[1])) {
00977                     $rq->addRawQueryString($uri[1]);
00978                 }
00979 
00980                 if (isset($proxy_params['proxy_host']) &&
00981                     isset($proxy_params['proxy_port']) &&
00982                     isset($proxy_params['proxy_user']) &&
00983                     isset($proxy_params['proxy_pass'])) {
00984                     $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port'],
00985                                   $proxy_params['proxy_user'], $proxy_params['proxy_pass']);
00986                 } elseif (isset($proxy_params['proxy_host']) &&
00987                           isset($proxy_params['proxy_port'])) {
00988                     $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port']);
00989                 }
00990 
00991                 $result = $rq->sendRequest();
00992                 if (PEAR::isError($result)) {
00993                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname," . $rq->getResponseCode(), $wsdl_fname);
00994                 }
00995                 $file_data = $rq->getResponseBody();
00996                 if (!$file_data) {
00997                     return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, no http body", $wsdl_fname);
00998                 }
00999             }
01000 
01001             $md5_wsdl = md5($file_data);
01002 
01003             if ($this->_cacheUse) {
01004                 $fp = fopen($cachename, "wb");
01005                 fwrite($fp, $file_data);
01006                 fclose($fp);
01007             }
01008         }
01009         if ($this->_cacheUse && $cache && $cache != $md5_wsdl) {
01010             return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname);
01011         }
01012         return $file_data;
01013     }
01014 
01015 }
01016 
01017 class ilBMFWSDL_Parser extends ilBMFBase
01018 {
01019 
01024     var $currentMessage;
01025     var $currentOperation;
01026     var $currentPortType;
01027     var $currentBinding;
01028     var $currentPort;
01029 
01033     var $cache;
01034 
01035     var $tns = null;
01036     var $soapns = array('soap');
01037     var $uri = '';
01038     var $wsdl = null;
01039 
01040     var $status = '';
01041     var $element_stack = array();
01042     var $parentElement = '';
01043 
01044     var $schema = '';
01045     var $schemaStatus = '';
01046     var $schema_stack = array();
01047     var $currentComplexType;
01048     var $schema_element_stack = array();
01049     var $currentElement;
01050 
01054     function ilBMFWSDL_Parser($uri, &$wsdl, $docs = false)
01055     {
01056         parent::ilBMFBase('WSDLPARSER');
01057         $this->cache =& new ilBMFWSDL_Cache($wsdl->cacheUse, $wsdl->cacheMaxAge);
01058         $this->uri = $uri;
01059         $this->wsdl = &$wsdl;
01060         $this->docs = $docs;
01061         $this->parse($uri);
01062     }
01063 
01064     function parse($uri)
01065     {
01066         // Check whether content has been read.
01067         $fd = $this->cache->get($uri, $this->wsdl->proxy);
01068         if (PEAR::isError($fd)) {
01069             return $this->_raiseSoapFault($fd);
01070         }
01071 
01072         // Create an XML parser.
01073         $parser = xml_parser_create();
01074         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
01075         xml_set_object($parser, $this);
01076         xml_set_element_handler($parser, 'startElement', 'endElement');
01077         if ($this->docs) {
01078             xml_set_character_data_handler($parser, 'characterData');
01079         }
01080 
01081         if (!xml_parse($parser, $fd, true)) {
01082             $detail = sprintf('XML error on line %d: %s',
01083                               xml_get_current_line_number($parser),
01084                               xml_error_string(xml_get_error_code($parser)));
01085             return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail");
01086         }
01087         xml_parser_free($parser);
01088         return true;
01089     }
01090 
01094     function startElement($parser, $name, $attrs)
01095     {
01096         // Get element prefix.
01097         $qname =& new QName($name);
01098         if ($qname->ns) {
01099             $ns = $qname->ns;
01100             if ($ns && ((!$this->tns && strcasecmp($qname->name, 'definitions') == 0) || $ns == $this->tns)) {
01101                 $name = $qname->name;
01102             }
01103         }
01104         $this->currentTag = $qname->name;
01105         $this->parentElement = '';
01106         $stack_size = count($this->element_stack);
01107         if ($stack_size) {
01108             $this->parentElement = $this->element_stack[$stack_size - 1];
01109         }
01110         $this->element_stack[] = $this->currentTag;
01111 
01112         // Find status, register data.
01113         switch ($this->status) {
01114         case 'types':
01115             // sect 2.2 wsdl:types
01116             // children: xsd:schema
01117             $parent_tag = '';
01118             $stack_size = count($this->schema_stack);
01119             if ($stack_size) {
01120                 $parent_tag = $this->schema_stack[$stack_size - 1];
01121             }
01122 
01123             switch ($qname->name) {
01124             case 'schema':
01125                 // No parent should be in the stack.
01126                 if (!$parent_tag || $parent_tag == 'types') {
01127                     if (array_key_exists('targetNamespace', $attrs)) {
01128                         $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
01129                     } else {
01130                         $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
01131                     }
01132                     $this->wsdl->complexTypes[$this->schema] = array();
01133                     $this->wsdl->elements[$this->schema] = array();
01134                 }
01135                 break;
01136 
01137             case 'complexType':
01138                 if ($parent_tag == 'schema') {
01139                     $this->currentComplexType = $attrs['name'];
01140                     if (!isset($attrs['namespace'])) {
01141                         $attrs['namespace'] = $this->schema;
01142                     }
01143                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs;
01144                     if (array_key_exists('base', $attrs)) {
01145                         $qn =& new QName($attrs['base']);
01146                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
01147                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns;
01148                     } else {
01149                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01150                     }
01151                     $this->schemaStatus = 'complexType';
01152                 } else {
01153                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = true;
01154                 }
01155                 break;
01156 
01157             case 'element':
01158                 if (isset($attrs['type'])) {
01159                     $qn =& new QName($attrs['type']);
01160                     $attrs['type'] = $qn->name;
01161                     if ($qn->ns && array_key_exists($qn->ns, $this->wsdl->namespaces)) {
01162                         $attrs['namespace'] = $qn->ns;
01163                     }
01164                 }
01165 
01166                 $parentElement = '';
01167                 $stack_size = count($this->schema_element_stack);
01168                 if ($stack_size > 0) {
01169                     $parentElement = $this->schema_element_stack[$stack_size - 1];
01170                 }
01171 
01172                 if (isset($attrs['ref'])) {
01173                     $qn =& new QName($attrs['ref']);
01174                     $this->currentElement = $qn->name;
01175                 } else {
01176                     $this->currentElement = $attrs['name'];
01177                 }
01178                 $this->schema_element_stack[] = $this->currentElement;
01179                 if (!isset($attrs['namespace'])) {
01180                     $attrs['namespace'] = $this->schema;
01181                 }
01182 
01183                 if ($parent_tag == 'schema') {
01184                     $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs;
01185                     $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = false;
01186                     $this->schemaStatus = 'element';
01187                 } elseif ($this->currentComplexType) {
01188                     // we're inside a complexType
01189                     if ((isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order']) &&
01190                          $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence')
01191                         && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') {
01192                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = isset($attrs['type']) ? $attrs['type'] : null;
01193                     }
01194                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs;
01195                 } else {
01196                     $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs;
01197                 }
01198                 break;
01199 
01200             case 'complexContent':
01201             case 'simpleContent':
01202                 break;
01203 
01204             case 'extension':
01205             case 'restriction':
01206                 if ($this->schemaStatus == 'complexType') {
01207                     if (!empty($attrs['base'])) {
01208                         $qn =& new QName($attrs['base']);
01209                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name;
01210 
01211                         // Types that extend from other types aren't
01212                         // *of* those types. Reflect this by denoting
01213                         // which type they extend. I'm leaving the
01214                         // 'type' setting here since I'm not sure what
01215                         // removing it might break at the moment.
01216                         if ($qname->name == 'extension') {
01217                             $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['extends'] = $qn->name;
01218                         }
01219                     } else {
01220                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01221                     }
01222                 }
01223                 break;
01224 
01225             case 'sequence':
01226                 if ($this->schemaStatus == 'complexType') {
01227                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01228                     if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
01229                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01230                     }
01231                 }
01232                 break;
01233 
01234             case 'all':
01235                 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01236                 if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
01237                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01238                 }
01239                 break;
01240 
01241             case 'choice':
01242                 $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name;
01243                 if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) {
01244                     $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01245                 }
01246 
01247             case 'attribute':
01248                 if ($this->schemaStatus == 'complexType') {
01249                     if (isset($attrs['name'])) {
01250                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs;
01251                     } else {
01252                         if (isset($attrs['ref'])) {
01253                             $q =& new QName($attrs['ref']);
01254                             foreach ($attrs as $k => $v) {
01255                                 if ($k != 'ref' && strstr($k, $q->name)) {
01256                                     $vq =& new QName($v);
01257                                     if ($q->name == 'arrayType') {
01258                                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name. $vq->arrayInfo;
01259                                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array';
01260                                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->ns;
01261                                     } else {
01262                                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name;
01263                                     }
01264                                 }
01265                             }
01266                         }
01267                     }
01268                 }
01269                 break;
01270             }
01271 
01272             $this->schema_stack[] = $qname->name;
01273             break;
01274 
01275         case 'message':
01276             // sect 2.3 wsdl:message child wsdl:part
01277             switch ($qname->name) {
01278             case 'part':
01279                 $qn = null;
01280                 if (isset($attrs['type'])) {
01281                     $qn =& new QName($attrs['type']);
01282                 } elseif (isset($attrs['element'])) {
01283                     $qn =& new QName($attrs['element']);
01284                 }
01285                 if ($qn) {
01286                     $attrs['type'] = $qn->name;
01287                     $attrs['namespace'] = $qn->ns;
01288                 }
01289                 $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs;
01290                 // error in wsdl
01291 
01292             case 'documentation':
01293                 break;
01294 
01295             default:
01296                 break;
01297             }
01298             break;
01299 
01300         case 'portType':
01301             // sect 2.4
01302             switch ($qname->name) {
01303             case 'operation':
01304                 // attributes: name
01305                 // children: wsdl:input wsdl:output wsdl:fault
01306                 $this->currentOperation = $attrs['name'];
01307                 $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs;
01308                 break;
01309 
01310             case 'input':
01311             case 'output':
01312             case 'fault':
01313                 // wsdl:input wsdl:output wsdl:fault
01314                 // attributes: name message parameterOrder(optional)
01315                 if ($this->currentOperation) {
01316                     if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) {
01317                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name], $attrs);
01318                     } else {
01319                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs;
01320                     }
01321                     if (array_key_exists('message', $attrs)) {
01322                         $qn =& new QName($attrs['message']);
01323                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name;
01324                         $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->ns;
01325                     }
01326                 }
01327                 break;
01328 
01329             case 'documentation':
01330                 break;
01331 
01332             default:
01333                 break;
01334             }
01335             break;
01336 
01337         case 'binding':
01338             $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01339             switch ($ns) {
01340             case SCHEMA_SOAP:
01341                 // this deals with wsdl section 3 soap binding
01342                 switch ($qname->name) {
01343                 case 'binding':
01344                     // sect 3.3
01345                     // soap:binding, attributes: transport(required), style(optional, default = document)
01346                     // if style is missing, it is assumed to be 'document'
01347                     if (!isset($attrs['style'])) {
01348                         $attrs['style'] = 'document';
01349                     }
01350                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs);
01351                     break;
01352 
01353                 case 'operation':
01354                     // sect 3.4
01355                     // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style)
01356                     if (!isset($attrs['style'])) {
01357                         $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style'];
01358                     }
01359                     if (isset($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation])) {
01360                         $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = array_merge($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation], $attrs);
01361                     } else {
01362                         $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs;
01363                     }
01364                     break;
01365 
01366                 case 'body':
01367                     // sect 3.5
01368                     // soap:body attributes:
01369                     // part - optional.  listed parts must appear in body, missing means all parts appear in body
01370                     // use - required. encoded|literal
01371                     // encodingStyle - optional.  space seperated list of encodings (uri's)
01372                     $this->wsdl->bindings[$this->currentBinding]
01373                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
01374                     break;
01375 
01376                 case 'fault':
01377                     // sect 3.6
01378                     // soap:fault attributes: name use  encodingStyle namespace
01379                     $this->wsdl->bindings[$this->currentBinding]
01380                                     ['operations'][$this->currentOperation][$this->opStatus] = $attrs;
01381                     break;
01382 
01383                 case 'header':
01384                     // sect 3.7
01385                     // soap:header attributes: message part use encodingStyle namespace
01386                     $this->wsdl->bindings[$this->currentBinding]
01387                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
01388                     break;
01389 
01390                 case 'headerfault':
01391                     // sect 3.7
01392                     // soap:header attributes: message part use encodingStyle namespace
01393                     $header = count($this->wsdl->bindings[$this->currentBinding]
01394                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1;
01395                     $this->wsdl->bindings[$this->currentBinding]
01396                                     ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs;
01397                     break;
01398 
01399                 case 'documentation':
01400                     break;
01401 
01402                 default:
01403                     // error!  not a valid element inside binding
01404                     break;
01405                 }
01406                 break;
01407 
01408             case SCHEMA_WSDL:
01409                 // XXX verify correct namespace
01410                 // for now, default is the 'wsdl' namespace
01411                 // other possible namespaces include smtp, http, etc. for alternate bindings
01412                 switch ($qname->name) {
01413                 case 'operation':
01414                     // sect 2.5
01415                     // wsdl:operation attributes: name
01416                     $this->currentOperation = $attrs['name'];
01417                     break;
01418 
01419                 case 'output':
01420                 case 'input':
01421                 case 'fault':
01422                     // sect 2.5
01423                     // wsdl:input attributes: name
01424                     $this->opStatus = $qname->name;
01425                     break;
01426 
01427                 case 'documentation':
01428                     break;
01429 
01430                 default:
01431                     break;
01432                 }
01433                 break;
01434 
01435             case SCHEMA_WSDL_HTTP:
01436                 switch ($qname->name) {
01437                 case 'binding':
01438                     // sect 4.4
01439                     // http:binding attributes: verb
01440                     // parent: wsdl:binding
01441                     $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs);
01442                     break;
01443 
01444                 case 'operation':
01445                     // sect 4.5
01446                     // http:operation attributes: location
01447                     // parent: wsdl:operation
01448                     $this->wsdl->bindings[$this->currentBinding]['operations']
01449                                                         [$this->currentOperation] = $attrs;
01450                     break;
01451 
01452                 case 'urlEncoded':
01453                     // sect 4.6
01454                     // http:urlEncoded attributes: location
01455                     // parent: wsdl:input wsdl:output etc.
01456                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01457                                                         [$this->currentOperation]['uri'] = 'urlEncoded';
01458                     break;
01459 
01460                 case 'urlReplacement':
01461                     // sect 4.7
01462                     // http:urlReplacement attributes: location
01463                     // parent: wsdl:input wsdl:output etc.
01464                     $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus]
01465                                                         [$this->currentOperation]['uri'] = 'urlReplacement';
01466                     break;
01467 
01468                 case 'documentation':
01469                     break;
01470 
01471                 default:
01472                     // error
01473                     break;
01474                 }
01475 
01476             case SCHEMA_MIME:
01477                 // sect 5
01478                 // all mime parts are children of wsdl:input, wsdl:output, etc.
01479                 // unsuported as of yet
01480                 switch ($qname->name) {
01481                 case 'content':
01482                     // sect 5.3 mime:content
01483                     // <mime:content part="nmtoken"? type="string"?/>
01484                     // part attribute only required if content is child of multipart related,
01485                     //        it contains the name of the part
01486                     // type attribute contains the mime type
01487                 case 'multipartRelated':
01488                     // sect 5.4 mime:multipartRelated
01489                 case 'part':
01490                 case 'mimeXml':
01491                     // sect 5.6 mime:mimeXml
01492                     // <mime:mimeXml part="nmtoken"?/>
01493                     //
01494                 case 'documentation':
01495                     break;
01496 
01497                 default:
01498                     // error
01499                     break;
01500                 }
01501 
01502             case SCHEMA_DIME:
01503                 // DIME is defined in:
01504                 // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm
01505                 // all DIME parts are children of wsdl:input, wsdl:output, etc.
01506                 // unsuported as of yet
01507                 switch ($qname->name) {
01508                 case 'message':
01509                     // sect 4.1 dime:message
01510                     // appears in binding section
01511                     $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs;
01512                     break;
01513 
01514                 default:
01515                     break;
01516                 }
01517 
01518             default:
01519                 break;
01520             }
01521             break;
01522 
01523         case 'service':
01524             $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01525 
01526             switch ($qname->name) {
01527             case 'port':
01528                 // sect 2.6 wsdl:port attributes: name binding
01529                 $this->currentPort = $attrs['name'];
01530                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs;
01531                 // XXX hack to deal with binding namespaces
01532                 $qn =& new QName($attrs['binding']);
01533                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name;
01534                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->ns;
01535                 break;
01536 
01537             case 'address':
01538                 $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs;
01539                 // what TYPE of port is it?  SOAP or HTTP?
01540                 $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL;
01541                 switch ($ns) {
01542                 case SCHEMA_WSDL_HTTP:
01543                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http';
01544                     break;
01545 
01546                 case SCHEMA_SOAP:
01547                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01548                     break;
01549 
01550                 default:
01551                     // Shouldn't happen, we'll assume SOAP.
01552                     $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap';
01553                 }
01554 
01555                 break;
01556 
01557             case 'documentation':
01558                 break;
01559 
01560             default:
01561                 break;
01562             }
01563         }
01564 
01565         // Top level elements found under wsdl:definitions.
01566         switch ($qname->name) {
01567         case 'import':
01568             // sect 2.1.1 wsdl:import attributes: namespace location
01569             if ((isset($attrs['location']) || isset($attrs['schemaLocation'])) &&
01570                 !isset($this->wsdl->imports[$attrs['namespace']])) {
01571                 $uri = isset($attrs['location']) ? $attrs['location'] : $attrs['schemaLocation'];
01572                 $location = @parse_url($uri);
01573                 if (!isset($location['scheme'])) {
01574                     $base = @parse_url($this->uri);
01575                     $uri = $this->mergeUrl($base, $uri);
01576                 }
01577 
01578                 $this->wsdl->imports[$attrs['namespace']] = $attrs;
01579                 $import_parser_class = get_class($this);
01580                 $import_parser =& new $import_parser_class($uri, $this->wsdl, $this->docs);
01581                 if ($import_parser->fault) {
01582                     unset($this->wsdl->imports[$attrs['namespace']]);
01583                     return false;
01584                 }
01585                 $this->currentImport = $attrs['namespace'];
01586             }
01587             // Continue on to the 'types' case - lack of break; is
01588             // intentional.
01589 
01590         case 'types':
01591             // sect 2.2 wsdl:types
01592             $this->status = 'types';
01593             break;
01594 
01595         case 'schema':
01596             // We can hit this at the top level if we've been asked to
01597             // import an XSD file.
01598             if (!empty($attrs['targetNamespace'])) {
01599                 $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']);
01600             } else {
01601                 $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns);
01602             }
01603             $this->wsdl->complexTypes[$this->schema] = array();
01604             $this->wsdl->elements[$this->schema] = array();
01605             $this->schema_stack[] = $qname->name;
01606             $this->status = 'types';
01607             break;
01608 
01609         case 'message':
01610             // sect 2.3 wsdl:message attributes: name children:wsdl:part
01611             $this->status = 'message';
01612             if (isset($attrs['name'])) {
01613                 $this->currentMessage = $attrs['name'];
01614                 $this->wsdl->messages[$this->currentMessage] = array();
01615             }
01616             break;
01617 
01618         case 'portType':
01619             // sect 2.4 wsdl:portType
01620             // attributes: name
01621             // children: wsdl:operation
01622             $this->status = 'portType';
01623             $this->currentPortType = $attrs['name'];
01624             $this->wsdl->portTypes[$this->currentPortType] = array();
01625             break;
01626 
01627         case 'binding':
01628             // sect 2.5 wsdl:binding attributes: name type
01629             // children: wsdl:operation soap:binding http:binding
01630             if ($qname->ns && $qname->ns != $this->tns) {
01631                 break;
01632             }
01633             $this->status = 'binding';
01634             $this->currentBinding = $attrs['name'];
01635             $qn =& new QName($attrs['type']);
01636             $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name;
01637             $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->ns;
01638             break;
01639 
01640         case 'service':
01641             // sect 2.7 wsdl:service attributes: name children: ports
01642             $this->currentService = $attrs['name'];
01643             $this->wsdl->services[$this->currentService]['ports'] = array();
01644             $this->status = 'service';
01645             break;
01646 
01647         case 'definitions':
01648             // sec 2.1 wsdl:definitions
01649             // attributes: name targetNamespace xmlns:*
01650             // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service
01651             $this->wsdl->definition = $attrs;
01652             foreach ($attrs as $key => $value) {
01653                 if (strstr($key, 'xmlns:') !== false) {
01654                     $qn =& new QName($key);
01655                     // XXX need to refactor ns handling.
01656                     $this->wsdl->namespaces[$qn->name] = $value;
01657                     $this->wsdl->ns[$value] = $qn->name;
01658                     if ($key == 'targetNamespace' ||
01659                         strcasecmp($value,SOAP_SCHEMA) == 0) {
01660                         $this->soapns[] = $qn->name;
01661                     } else {
01662                         if (in_array($value, $this->_XMLSchema)) {
01663                             $this->wsdl->xsd = $value;
01664                         }
01665                     }
01666                 }
01667             }
01668             if (isset($ns) && $ns) {
01669                 $namespace = 'xmlns:' . $ns;
01670                 if (!$this->wsdl->definition[$namespace]) {
01671                     return $this->_raiseSoapFault("parse error, no namespace for $namespace", $this->uri);
01672                 }
01673                 $this->tns = $ns;
01674             }
01675             break;
01676         }
01677     }
01678 
01682     function endElement($parser, $name)
01683     {
01684         $stacksize = count($this->element_stack);
01685         if ($stacksize) {
01686             if ($this->element_stack[$stacksize - 1] == 'definitions') {
01687                 $this->status = '';
01688             }
01689             array_pop($this->element_stack);
01690         }
01691 
01692         if (stristr($name, 'schema')) {
01693             array_pop($this->schema_stack);
01694             $this->schema = '';
01695         }
01696 
01697         if ($this->schema) {
01698             array_pop($this->schema_stack);
01699             if (count($this->schema_stack) <= 1) {
01700                 /* Correct the type for sequences with multiple
01701                  * elements. */
01702                 if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])
01703                     && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array'
01704                     && array_key_exists('elements', $this->wsdl->complexTypes[$this->schema][$this->currentComplexType])
01705                     && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) {
01706                         $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct';
01707                 }
01708             }
01709             if (stristr($name, 'complexType')) {
01710                 $this->currentComplexType = '';
01711                 if (count($this->schema_element_stack)) {
01712                     $this->currentElement = array_pop($this->schema_element_stack);
01713                 } else {
01714                     $this->currentElement = '';
01715                 }
01716             } elseif (stristr($name, 'element')) {
01717                 if (count($this->schema_element_stack)) {
01718                     $this->currentElement = array_pop($this->schema_element_stack);
01719                 } else {
01720                     $this->currentElement = '';
01721                 }
01722             }
01723         }
01724     }
01725 
01729     function characterData($parser, $data)
01730     {
01731         // Store the documentation in the WSDL file.
01732         if ($this->currentTag == 'documentation') {
01733             $data = trim(preg_replace('/\s+/', ' ', $data));
01734             if (!strlen($data)) {
01735                 return;
01736             }
01737 
01738             switch ($this->status) {
01739             case 'service':
01740                 $ptr =& $this->wsdl->services[$this->currentService];
01741                 break;
01742 
01743             case 'portType':
01744                 $ptr =& $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation];
01745                 break;
01746 
01747             case 'binding':
01748                 $ptr =& $this->wsdl->bindings[$this->currentBinding];
01749                 break;
01750 
01751             case 'message':
01752                 $ptr =& $this->wsdl->messages[$this->currentMessage];
01753                 break;
01754 
01755             case 'operation':
01756                 break;
01757 
01758             case 'types':
01759                 if (isset($this->currentComplexType) &&
01760                     isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) {
01761                     if ($this->currentElement) {
01762                         $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement];
01763                     } else {
01764                         $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType];
01765                     }
01766                 }
01767                 break;
01768             }
01769 
01770             if (isset($ptr)) {
01771                 if (!isset($ptr['documentation'])) {
01772                     $ptr['documentation'] = '';
01773                 } else {
01774                     $ptr['documentation'] .= ' ';
01775                 }
01776                 $ptr['documentation'] .= $data;
01777             }
01778         }
01779     }
01780 
01786     function mergeUrl($parsed, $path)
01787     {
01788         if (!is_array($parsed)) {
01789             return false;
01790         }
01791 
01792         $uri = '';
01793         if (!empty($parsed['scheme'])) {
01794             $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://');
01795             $uri = $parsed['scheme'] . $sep;
01796         }
01797 
01798         if (isset($parsed['pass'])) {
01799             $uri .= "$parsed[user]:$parsed[pass]@";
01800         } elseif (isset($parsed['user'])) {
01801             $uri .= "$parsed[user]@";
01802         }
01803 
01804         if (isset($parsed['host'])) {
01805             $uri .= $parsed['host'];
01806         }
01807         if (isset($parsed['port'])) {
01808             $uri .= ":$parsed[port]";
01809         }
01810         if ($path[0] != '/' && isset($parsed['path'])) {
01811             if ($parsed['path'][strlen($parsed['path']) - 1] != '/') {
01812                 $path = dirname($parsed['path']) . '/' . $path;
01813             } else {
01814                 $path = $parsed['path'] . $path;
01815             }
01816             $path = $this->_normalize($path);
01817         }
01818         $sep = $path[0] == '/' ? '' : '/';
01819         $uri .= $sep . $path;
01820 
01821         return $uri;
01822     }
01823 
01824     function _normalize($path_str)
01825     {
01826         $pwd = '';
01827         $strArr = preg_split('/(\/)/', $path_str, -1, PREG_SPLIT_NO_EMPTY);
01828         $pwdArr = '';
01829         $j = 0;
01830         for ($i = 0; $i < count($strArr); $i++) {
01831             if ($strArr[$i] != ' ..') {
01832                 if ($strArr[$i] != ' .') {
01833                     $pwdArr[$j] = $strArr[$i];
01834                     $j++;
01835                 }
01836             } else {
01837                 array_pop($pwdArr);
01838                 $j--;
01839             }
01840         }
01841         $pStr = implode('/', $pwdArr);
01842         $pwd = (strlen($pStr) > 0) ? ('/' . $pStr) : '/';
01843         return $pwd;
01844     }
01845 
01846 }
01847 
01856 class ilBMFWSDL_ObjectParser extends ilBMFBase
01857 {
01862     var $tnsPrefix = 'tns';
01863 
01867     var $wsdl = null;
01868 
01877     function ilBMFWSDL_ObjectParser(&$objects, &$wsdl, $targetNamespace, $service_name, $service_desc = '')
01878     {
01879         parent::ilBMFBase('WSDLOBJECTPARSER');
01880 
01881         $this->wsdl = &$wsdl;
01882 
01883         // Set up the ilBMFWSDL object
01884         $this->_initialise($service_name);
01885 
01886         // Parse each web service object
01887         $wsdl_ref = (is_array($objects)? $objects : array(&$objects));
01888 
01889         foreach ($wsdl_ref as $ref_item) {
01890             if (!is_object($ref_item))
01891                 return $this->_raiseSoapFault('Invalid web service object passed to object parser', 'urn:' . get_class($object));
01892 
01893             if ($this->_parse($ref_item, $targetNamespace, $service_name) != true)
01894                 break;
01895         }
01896 
01897         // Build bindings from abstract data.
01898         if ($this->fault == null) {
01899             $this->_generateBindingsAndServices($targetNamespace, $service_name, $service_desc);
01900         }
01901     }
01902 
01912     function _initialise($service_name)
01913     {
01914         // Set up the basic namespaces that all WSDL definitions use.
01915         $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL;                                      // WSDL language
01916         $this->wsdl->namespaces['soap'] = SCHEMA_SOAP;                                      // WSDL SOAP bindings
01917         $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name;                 // Target namespace
01918         $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces);           // XML Schema
01919         $this->wsdl->namespaces['SOAP-ENC'] = array_search('SOAP-ENC', $this->_namespaces); // SOAP types
01920 
01921         // XXX Refactor $namespace/$ns for Shane :-)
01922         unset($this->wsdl->ns['urn:' . $service_name]);
01923         $this->wsdl->ns += array_flip($this->wsdl->namespaces);
01924 
01925         // Imports are not implemented in WSDL generation from classes.
01926         // *** <wsdl:import> ***
01927     }
01928 
01937     function _parse(&$object, $schemaNamespace, $service_name)
01938     {
01939         // Create namespace prefix for the schema
01940         // XXX not very elegant :-(
01941 
01942         list($schPrefix, $foo) = $this->_getTypeNs('{' . $schemaNamespace.'}');
01943         unset($foo);
01944 
01945         // Parse all the types defined by the object in whatever
01946         // schema language we are using (currently __typedef arrays)
01947         // *** <wsdl:types> ***
01948 
01949         foreach ($object->__typedef as $typeName => $typeValue) {
01950             // Get/create namespace definition
01951 
01952             list($nsPrefix, $typeName) = $this->_getTypeNs($typeName);
01953 
01954             // Create type definition
01955 
01956             $this->wsdl->complexTypes[$schPrefix][$typeName] = array('name' => $typeName);
01957             $thisType =& $this->wsdl->complexTypes[$schPrefix][$typeName];
01958 
01959             // According to Dmitri's documentation, __typedef comes in two
01960             // flavors:
01961             // Array = array(array("item" => "value"))
01962             // Struct = array("item1" => "value1", "item2" => "value2", ...)
01963 
01964             if (is_array($typeValue)) {
01965                 if (is_array(current($typeValue)) && count($typeValue) == 1
01966                     && count(current($typeValue)) == 1) {
01967                     // It's an array
01968 
01969                     $thisType['type'] = 'Array';
01970                     list($nsPrefix, $typeName) = $this->_getTypeNs(current(current($typeValue)));
01971                     $thisType['namespace'] = $nsPrefix;
01972                     $thisType['arrayType'] = $typeName . '[]';
01973                 } elseif (!is_array(current($typeValue))) {
01974                     // It's a struct
01975 
01976                     $thisType['type'] = 'Struct';
01977                     $thisType['order'] = 'all';
01978                     $thisType['namespace'] = $nsPrefix;
01979                     $thisType['elements'] = array();
01980 
01981                     foreach ($typeValue as $elementName => $elementType) {
01982                         list($nsPrefix, $typeName) = $this->_getTypeNs($elementType);
01983                         $thisType['elements'][$elementName]['name'] = $elementName;
01984                         $thisType['elements'][$elementName]['type'] = $typeName;
01985                         $thisType['elements'][$elementName]['namespace'] = $nsPrefix;
01986                     }
01987                 } else {
01988                     // It's erroneous
01989                     return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
01990                 }
01991             } else {
01992                 // It's erroneous
01993                 return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object));
01994             }
01995         }
01996 
01997         // Create an empty element array with the target namespace
01998         // prefix, to match the results of WSDL parsing.
01999 
02000         $this->wsdl->elements[$schPrefix] = array();
02001 
02002         // Populate tree with message information
02003         // *** <wsdl:message> ***
02004 
02005         foreach ($object->__dispatch_map as $operationName => $messages) {
02006             foreach ($messages as $messageType => $messageParts) {
02007                 unset($thisMessage);
02008 
02009                 switch ($messageType) {
02010                 case 'in':
02011                     $this->wsdl->messages[$operationName . 'Request'] = array();
02012                     $thisMessage =& $this->wsdl->messages[$operationName . 'Request'];
02013                     break;
02014 
02015                 case 'out':
02016                     $this->wsdl->messages[$operationName . 'Response'] = array();
02017                     $thisMessage =& $this->wsdl->messages[$operationName . 'Response'];
02018                     break;
02019 
02020                 case 'alias':
02021                     // Do nothing
02022                     break;
02023 
02024                 default:
02025                     // Error condition
02026                     break;
02027                 }
02028 
02029                 if (isset($thisMessage)) {
02030                     foreach ($messageParts as $partName => $partType) {
02031                         list ($nsPrefix, $typeName) = $this->_getTypeNs($partType);
02032 
02033                         $thisMessage[$partName] = array(
02034                             'name' => $partName,
02035                             'type' => $typeName,
02036                             'namespace' => $nsPrefix
02037                             );
02038                     }
02039                 }
02040             }
02041         }
02042 
02043         // Populate tree with portType information
02044         // XXX Current implementation only supports one portType that
02045         // encompasses all of the operations available.
02046         // *** <wsdl:portType> ***
02047 
02048         if (!isset($this->wsdl->portTypes[$service_name . 'Port'])) {
02049             $this->wsdl->portTypes[$service_name . 'Port'] = array();
02050         }
02051         $thisPortType =& $this->wsdl->portTypes[$service_name . 'Port'];
02052 
02053         foreach ($object->__dispatch_map as $operationName => $messages) {
02054             $thisPortType[$operationName] = array('name' => $operationName);
02055 
02056             foreach ($messages as $messageType => $messageParts) {
02057                 switch ($messageType) {
02058                 case 'in':
02059                     $thisPortType[$operationName]['input'] = array(
02060                         'message' => $operationName . 'Request',
02061                         'namespace' => $this->tnsPrefix);
02062                     break;
02063 
02064                 case 'out':
02065                     $thisPortType[$operationName]['output'] = array(
02066                         'message' => $operationName . 'Response',
02067                         'namespace' => $this->tnsPrefix);
02068                     break;
02069                 }
02070             }
02071         }
02072 
02073         return true;
02074     }
02075 
02087     function _generateBindingsAndServices($schemaNamespace, $service_name, $service_desc = '')
02088     {
02089         // Populate tree with bindings information
02090         // XXX Current implementation only supports one binding that
02091         // matches the single portType and all of its operations.
02092         // XXX Is this the correct use of $schemaNamespace here?
02093         // *** <wsdl:binding> ***
02094 
02095         $this->wsdl->bindings[$service_name . 'Binding'] = array(
02096                 'type' => $service_name . 'Port',
02097                 'namespace' => $this->tnsPrefix,
02098                 'style' => 'rpc',
02099                 'transport' => SCHEMA_SOAP_HTTP,
02100                 'operations' => array());
02101         $thisBinding =& $this->wsdl->bindings[$service_name . 'Binding'];
02102 
02103         foreach ($this->wsdl->portTypes[$service_name . 'Port'] as $operationName => $operationData) {
02104             $thisBinding['operations'][$operationName] = array(
02105                 'soapAction' => $schemaNamespace . '#' . $operationName,
02106                 'style' => $thisBinding['style']);
02107 
02108             foreach (array('input', 'output') as $messageType)
02109                 if (isset($operationData[$messageType])) {
02110                     $thisBinding['operations'][$operationName][$messageType] = array(
02111                             'use' => 'encoded',
02112                             'namespace' => $schemaNamespace,
02113                             'encodingStyle' => SOAP_SCHEMA_ENCODING);
02114                 }
02115         }
02116 
02117         // Populate tree with service information
02118         // XXX Current implementation supports one service which groups
02119         // all of the ports together, one port per binding
02120         // XXX What about https?
02121         // *** <wsdl:service> ***
02122 
02123         $this->wsdl->services[$service_name . 'Service'] = array('ports' => array());
02124         $thisService =& $this->wsdl->services[$service_name . 'Service']['ports'];
02125 
02126         foreach ($this->wsdl->bindings as $bindingName => $bindingData) {
02127             $thisService[$bindingData['type']] = array(
02128                     'name' => $bindingData['type'],
02129                     'binding' => $bindingName,
02130                     'namespace' => $this->tnsPrefix,
02131                     'address' => array('location' =>
02132                         'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] .
02133                         (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')),
02134                     'type' => 'soap');
02135         }
02136 
02137         // Set service
02138         $this->wsdl->set_service($service_name . 'Service');
02139         $this->wsdl->uri = $this->wsdl->namespaces[$this->tnsPrefix];
02140 
02141         // Create WSDL definition
02142         // *** <wsdl:definitions> ***
02143 
02144         $this->wsdl->definition = array(
02145                 'name' => $service_name,
02146                 'targetNamespace' => $this->wsdl->namespaces[$this->tnsPrefix],
02147                 'xmlns' => SCHEMA_WSDL);
02148 
02149         foreach ($this->wsdl->namespaces as $nsPrefix => $namespace) {
02150             $this->wsdl->definition['xmlns:' . $nsPrefix] = $namespace;
02151         }
02152     }
02153 
02165     function _getTypeNs($type)
02166     {
02167         preg_match_all("'\{(.*)\}'sm", $type, $m);
02168         if (isset($m[1][0]) && $m[1][0] != '') {
02169             if (!array_key_exists($m[1][0], $this->wsdl->ns)) {
02170                 $ns_pref = 'ns' . count($this->wsdl->namespaces);
02171                 $this->wsdl->ns[$m[1][0]] = $ns_pref;
02172                 $this->wsdl->namespaces[$ns_pref] = $m[1][0];
02173             }
02174             $typens = $this->wsdl->ns[$m[1][0]];
02175             $type = ereg_replace($m[0][0], '', $type);
02176         } else {
02177             $typens = 'xsd';
02178         }
02179 
02180         return array($typens, $type);
02181     }
02182 
02183 }

Generated on Fri Dec 13 2013 17:56:54 for ILIAS Release_3_9_x_branch .rev 46835 by  doxygen 1.7.1