|
Support Incident Tracker GIT4.x
|
00001 <?php 00002 00003 00004 00005 00015 class wsdl extends nusoap_base { 00016 // URL or filename of the root of this WSDL 00017 var $wsdl; 00018 // define internal arrays of bindings, ports, operations, messages, etc. 00019 var $schemas = array(); 00020 var $currentSchema; 00021 var $message = array(); 00022 var $complexTypes = array(); 00023 var $messages = array(); 00024 var $currentMessage; 00025 var $currentOperation; 00026 var $portTypes = array(); 00027 var $currentPortType; 00028 var $bindings = array(); 00029 var $currentBinding; 00030 var $ports = array(); 00031 var $currentPort; 00032 var $opData = array(); 00033 var $status = ''; 00034 var $documentation = false; 00035 var $endpoint = ''; 00036 // array of wsdl docs to import 00037 var $import = array(); 00038 // parser vars 00039 var $parser; 00040 var $position = 0; 00041 var $depth = 0; 00042 var $depth_array = array(); 00043 // for getting wsdl 00044 var $proxyhost = ''; 00045 var $proxyport = ''; 00046 var $proxyusername = ''; 00047 var $proxypassword = ''; 00048 var $timeout = 0; 00049 var $response_timeout = 30; 00050 var $curl_options = array(); // User-specified cURL options 00051 var $use_curl = false; // whether to always try to use cURL 00052 // for HTTP authentication 00053 var $username = ''; // Username for HTTP authentication 00054 var $password = ''; // Password for HTTP authentication 00055 var $authtype = ''; // Type of HTTP authentication 00056 var $certRequest = array(); // Certificate for HTTP SSL authentication 00057 00072 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){ 00073 parent::nusoap_base(); 00074 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); 00075 $this->proxyhost = $proxyhost; 00076 $this->proxyport = $proxyport; 00077 $this->proxyusername = $proxyusername; 00078 $this->proxypassword = $proxypassword; 00079 $this->timeout = $timeout; 00080 $this->response_timeout = $response_timeout; 00081 if (is_array($curl_options)) 00082 $this->curl_options = $curl_options; 00083 $this->use_curl = $use_curl; 00084 $this->fetchWSDL($wsdl); 00085 } 00086 00092 function fetchWSDL($wsdl) { 00093 $this->debug("parse and process WSDL path=$wsdl"); 00094 $this->wsdl = $wsdl; 00095 // parse wsdl file 00096 if ($this->wsdl != "") { 00097 $this->parseWSDL($this->wsdl); 00098 } 00099 // imports 00100 // TODO: handle imports more properly, grabbing them in-line and nesting them 00101 $imported_urls = array(); 00102 $imported = 1; 00103 while ($imported > 0) { 00104 $imported = 0; 00105 // Schema imports 00106 foreach ($this->schemas as $ns => $list) { 00107 foreach ($list as $xs) { 00108 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! 00109 foreach ($xs->imports as $ns2 => $list2) { 00110 for ($ii = 0; $ii < count($list2); $ii++) { 00111 if (! $list2[$ii]['loaded']) { 00112 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true; 00113 $url = $list2[$ii]['location']; 00114 if ($url != '') { 00115 $urlparts = parse_url($url); 00116 if (!isset($urlparts['host'])) { 00117 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . 00118 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; 00119 } 00120 if (! in_array($url, $imported_urls)) { 00121 $this->parseWSDL($url); 00122 $imported++; 00123 $imported_urls[] = $url; 00124 } 00125 } else { 00126 $this->debug("Unexpected scenario: empty URL for unloaded import"); 00127 } 00128 } 00129 } 00130 } 00131 } 00132 } 00133 // WSDL imports 00134 $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! 00135 foreach ($this->import as $ns => $list) { 00136 for ($ii = 0; $ii < count($list); $ii++) { 00137 if (! $list[$ii]['loaded']) { 00138 $this->import[$ns][$ii]['loaded'] = true; 00139 $url = $list[$ii]['location']; 00140 if ($url != '') { 00141 $urlparts = parse_url($url); 00142 if (!isset($urlparts['host'])) { 00143 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . 00144 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; 00145 } 00146 if (! in_array($url, $imported_urls)) { 00147 $this->parseWSDL($url); 00148 $imported++; 00149 $imported_urls[] = $url; 00150 } 00151 } else { 00152 $this->debug("Unexpected scenario: empty URL for unloaded import"); 00153 } 00154 } 00155 } 00156 } 00157 } 00158 // add new data to operation data 00159 foreach($this->bindings as $binding => $bindingData) { 00160 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { 00161 foreach($bindingData['operations'] as $operation => $data) { 00162 $this->debug('post-parse data gathering for ' . $operation); 00163 $this->bindings[$binding]['operations'][$operation]['input'] = 00164 isset($this->bindings[$binding]['operations'][$operation]['input']) ? 00165 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) : 00166 $this->portTypes[ $bindingData['portType'] ][$operation]['input']; 00167 $this->bindings[$binding]['operations'][$operation]['output'] = 00168 isset($this->bindings[$binding]['operations'][$operation]['output']) ? 00169 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) : 00170 $this->portTypes[ $bindingData['portType'] ][$operation]['output']; 00171 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){ 00172 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ]; 00173 } 00174 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){ 00175 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ]; 00176 } 00177 // Set operation style if necessary, but do not override one already provided 00178 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { 00179 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; 00180 } 00181 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; 00182 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : ''; 00183 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; 00184 } 00185 } 00186 } 00187 } 00188 00195 function parseWSDL($wsdl = '') { 00196 $this->debug("parse WSDL at path=$wsdl"); 00197 00198 if ($wsdl == '') { 00199 $this->debug('no wsdl passed to parseWSDL()!!'); 00200 $this->setError('no wsdl passed to parseWSDL()!!'); 00201 return false; 00202 } 00203 00204 // parse $wsdl for url format 00205 $wsdl_props = parse_url($wsdl); 00206 00207 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { 00208 $this->debug('getting WSDL http(s) URL ' . $wsdl); 00209 // get wsdl 00210 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); 00211 $tr->request_method = 'GET'; 00212 $tr->useSOAPAction = false; 00213 if($this->proxyhost && $this->proxyport){ 00214 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); 00215 } 00216 if ($this->authtype != '') { 00217 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); 00218 } 00219 $tr->setEncoding('gzip, deflate'); 00220 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); 00221 //$this->debug("WSDL request\n" . $tr->outgoing_payload); 00222 //$this->debug("WSDL response\n" . $tr->incoming_payload); 00223 $this->appendDebug($tr->getDebug()); 00224 // catch errors 00225 if($err = $tr->getError() ){ 00226 $errstr = 'HTTP ERROR: '.$err; 00227 $this->debug($errstr); 00228 $this->setError($errstr); 00229 unset($tr); 00230 return false; 00231 } 00232 unset($tr); 00233 $this->debug("got WSDL URL"); 00234 } else { 00235 // $wsdl is not http(s), so treat it as a file URL or plain file path 00236 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { 00237 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path']; 00238 } else { 00239 $path = $wsdl; 00240 } 00241 $this->debug('getting WSDL file ' . $path); 00242 if ($fp = @fopen($path, 'r')) { 00243 $wsdl_string = ''; 00244 while ($data = fread($fp, 32768)) { 00245 $wsdl_string .= $data; 00246 } 00247 fclose($fp); 00248 } else { 00249 $errstr = "Bad path to WSDL file $path"; 00250 $this->debug($errstr); 00251 $this->setError($errstr); 00252 return false; 00253 } 00254 } 00255 $this->debug('Parse WSDL'); 00256 // end new code added 00257 // Create an XML parser. 00258 $this->parser = xml_parser_create(); 00259 // Set the options for parsing the XML data. 00260 // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 00261 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 00262 // Set the object for the parser. 00263 xml_set_object($this->parser, $this); 00264 // Set the element handlers for the parser. 00265 xml_set_element_handler($this->parser, 'start_element', 'end_element'); 00266 xml_set_character_data_handler($this->parser, 'character_data'); 00267 // Parse the XML file. 00268 if (!xml_parse($this->parser, $wsdl_string, true)) { 00269 // Display an error message. 00270 $errstr = sprintf( 00271 'XML error parsing WSDL from %s on line %d: %s', 00272 $wsdl, 00273 xml_get_current_line_number($this->parser), 00274 xml_error_string(xml_get_error_code($this->parser)) 00275 ); 00276 $this->debug($errstr); 00277 $this->debug("XML payload:\n" . $wsdl_string); 00278 $this->setError($errstr); 00279 return false; 00280 } 00281 // free the parser 00282 xml_parser_free($this->parser); 00283 $this->debug('Parsing WSDL done'); 00284 // catch wsdl parse errors 00285 if($this->getError()){ 00286 return false; 00287 } 00288 return true; 00289 } 00290 00299 function start_element($parser, $name, $attrs) 00300 { 00301 if ($this->status == 'schema') { 00302 $this->currentSchema->schemaStartElement($parser, $name, $attrs); 00303 $this->appendDebug($this->currentSchema->getDebug()); 00304 $this->currentSchema->clearDebug(); 00305 } elseif (ereg('schema$', $name)) { 00306 $this->debug('Parsing WSDL schema'); 00307 // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); 00308 $this->status = 'schema'; 00309 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); 00310 $this->currentSchema->schemaStartElement($parser, $name, $attrs); 00311 $this->appendDebug($this->currentSchema->getDebug()); 00312 $this->currentSchema->clearDebug(); 00313 } else { 00314 // position in the total number of elements, starting from 0 00315 $pos = $this->position++; 00316 $depth = $this->depth++; 00317 // set self as current value for this depth 00318 $this->depth_array[$depth] = $pos; 00319 $this->message[$pos] = array('cdata' => ''); 00320 // process attributes 00321 if (count($attrs) > 0) { 00322 // register namespace declarations 00323 foreach($attrs as $k => $v) { 00324 if (ereg("^xmlns", $k)) { 00325 if ($ns_prefix = substr(strrchr($k, ':'), 1)) { 00326 $this->namespaces[$ns_prefix] = $v; 00327 } else { 00328 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v; 00329 } 00330 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { 00331 $this->XMLSchemaVersion = $v; 00332 $this->namespaces['xsi'] = $v . '-instance'; 00333 } 00334 } 00335 } 00336 // expand each attribute prefix to its namespace 00337 foreach($attrs as $k => $v) { 00338 $k = strpos($k, ':') ? $this->expandQname($k) : $k; 00339 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { 00340 $v = strpos($v, ':') ? $this->expandQname($v) : $v; 00341 } 00342 $eAttrs[$k] = $v; 00343 } 00344 $attrs = $eAttrs; 00345 } else { 00346 $attrs = array(); 00347 } 00348 // get element prefix, namespace and name 00349 if (ereg(':', $name)) { 00350 // get ns prefix 00351 $prefix = substr($name, 0, strpos($name, ':')); 00352 // get ns 00353 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 00354 // get unqualified name 00355 $name = substr(strstr($name, ':'), 1); 00356 } 00357 // process attributes, expanding any prefixes to namespaces 00358 // find status, register data 00359 switch ($this->status) { 00360 case 'message': 00361 if ($name == 'part') { 00362 if (isset($attrs['type'])) { 00363 $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs)); 00364 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; 00365 } 00366 if (isset($attrs['element'])) { 00367 $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs)); 00368 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^'; 00369 } 00370 } 00371 break; 00372 case 'portType': 00373 switch ($name) { 00374 case 'operation': 00375 $this->currentPortOperation = $attrs['name']; 00376 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); 00377 if (isset($attrs['parameterOrder'])) { 00378 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; 00379 } 00380 break; 00381 case 'documentation': 00382 $this->documentation = true; 00383 break; 00384 // merge input/output data 00385 default: 00386 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; 00387 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; 00388 break; 00389 } 00390 break; 00391 case 'binding': 00392 switch ($name) { 00393 case 'binding': 00394 // get ns prefix 00395 if (isset($attrs['style'])) { 00396 $this->bindings[$this->currentBinding]['prefix'] = $prefix; 00397 } 00398 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); 00399 break; 00400 case 'header': 00401 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; 00402 break; 00403 case 'operation': 00404 if (isset($attrs['soapAction'])) { 00405 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; 00406 } 00407 if (isset($attrs['style'])) { 00408 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; 00409 } 00410 if (isset($attrs['name'])) { 00411 $this->currentOperation = $attrs['name']; 00412 $this->debug("current binding operation: $this->currentOperation"); 00413 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; 00414 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; 00415 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; 00416 } 00417 break; 00418 case 'input': 00419 $this->opStatus = 'input'; 00420 break; 00421 case 'output': 00422 $this->opStatus = 'output'; 00423 break; 00424 case 'body': 00425 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { 00426 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); 00427 } else { 00428 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; 00429 } 00430 break; 00431 } 00432 break; 00433 case 'service': 00434 switch ($name) { 00435 case 'port': 00436 $this->currentPort = $attrs['name']; 00437 $this->debug('current port: ' . $this->currentPort); 00438 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); 00439 00440 break; 00441 case 'address': 00442 $this->ports[$this->currentPort]['location'] = $attrs['location']; 00443 $this->ports[$this->currentPort]['bindingType'] = $namespace; 00444 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace; 00445 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location']; 00446 break; 00447 } 00448 break; 00449 } 00450 // set status 00451 switch ($name) { 00452 case 'import': 00453 if (isset($attrs['location'])) { 00454 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false); 00455 $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')'); 00456 } else { 00457 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true); 00458 if (! $this->getPrefixFromNamespace($attrs['namespace'])) { 00459 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; 00460 } 00461 $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')'); 00462 } 00463 break; 00464 //wait for schema 00465 //case 'types': 00466 // $this->status = 'schema'; 00467 // break; 00468 case 'message': 00469 $this->status = 'message'; 00470 $this->messages[$attrs['name']] = array(); 00471 $this->currentMessage = $attrs['name']; 00472 break; 00473 case 'portType': 00474 $this->status = 'portType'; 00475 $this->portTypes[$attrs['name']] = array(); 00476 $this->currentPortType = $attrs['name']; 00477 break; 00478 case "binding": 00479 if (isset($attrs['name'])) { 00480 // get binding name 00481 if (strpos($attrs['name'], ':')) { 00482 $this->currentBinding = $this->getLocalPart($attrs['name']); 00483 } else { 00484 $this->currentBinding = $attrs['name']; 00485 } 00486 $this->status = 'binding'; 00487 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); 00488 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']); 00489 } 00490 break; 00491 case 'service': 00492 $this->serviceName = $attrs['name']; 00493 $this->status = 'service'; 00494 $this->debug('current service: ' . $this->serviceName); 00495 break; 00496 case 'definitions': 00497 foreach ($attrs as $name => $value) { 00498 $this->wsdl_info[$name] = $value; 00499 } 00500 break; 00501 } 00502 } 00503 } 00504 00512 function end_element($parser, $name){ 00513 // unset schema status 00514 if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) { 00515 $this->status = ""; 00516 $this->appendDebug($this->currentSchema->getDebug()); 00517 $this->currentSchema->clearDebug(); 00518 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; 00519 $this->debug('Parsing WSDL schema done'); 00520 } 00521 if ($this->status == 'schema') { 00522 $this->currentSchema->schemaEndElement($parser, $name); 00523 } else { 00524 // bring depth down a notch 00525 $this->depth--; 00526 } 00527 // end documentation 00528 if ($this->documentation) { 00529 //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. 00530 //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; 00531 $this->documentation = false; 00532 } 00533 } 00534 00542 function character_data($parser, $data) 00543 { 00544 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; 00545 if (isset($this->message[$pos]['cdata'])) { 00546 $this->message[$pos]['cdata'] .= $data; 00547 } 00548 if ($this->documentation) { 00549 $this->documentation .= $data; 00550 } 00551 } 00552 00562 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { 00563 $this->debug("setCredentials username=$username authtype=$authtype certRequest="); 00564 $this->appendDebug($this->varDump($certRequest)); 00565 $this->username = $username; 00566 $this->password = $password; 00567 $this->authtype = $authtype; 00568 $this->certRequest = $certRequest; 00569 } 00570 00571 function getBindingData($binding) 00572 { 00573 if (is_array($this->bindings[$binding])) { 00574 return $this->bindings[$binding]; 00575 } 00576 } 00577 00585 function getOperations($bindingType = 'soap') { 00586 $ops = array(); 00587 if ($bindingType == 'soap') { 00588 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00589 } elseif ($bindingType == 'soap12') { 00590 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00591 } 00592 // loop thru ports 00593 foreach($this->ports as $port => $portData) { 00594 // binding type of port matches parameter 00595 if ($portData['bindingType'] == $bindingType) { 00596 //$this->debug("getOperations for port $port"); 00597 //$this->debug("port data: " . $this->varDump($portData)); 00598 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); 00599 // merge bindings 00600 if (isset($this->bindings[ $portData['binding'] ]['operations'])) { 00601 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); 00602 } 00603 } 00604 } 00605 return $ops; 00606 } 00607 00616 function getOperationData($operation, $bindingType = 'soap') 00617 { 00618 if ($bindingType == 'soap') { 00619 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00620 } elseif ($bindingType == 'soap12') { 00621 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00622 } 00623 // loop thru ports 00624 foreach($this->ports as $port => $portData) { 00625 // binding type of port matches parameter 00626 if ($portData['bindingType'] == $bindingType) { 00627 // get binding 00628 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 00629 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { 00630 // note that we could/should also check the namespace here 00631 if ($operation == $bOperation) { 00632 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; 00633 return $opData; 00634 } 00635 } 00636 } 00637 } 00638 } 00639 00648 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { 00649 if ($bindingType == 'soap') { 00650 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00651 } elseif ($bindingType == 'soap12') { 00652 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00653 } 00654 // loop thru ports 00655 foreach($this->ports as $port => $portData) { 00656 // binding type of port matches parameter 00657 if ($portData['bindingType'] == $bindingType) { 00658 // loop through operations for the binding 00659 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 00660 if ($opData['soapAction'] == $soapAction) { 00661 return $opData; 00662 } 00663 } 00664 } 00665 } 00666 } 00667 00686 function getTypeDef($type, $ns) { 00687 $this->debug("in getTypeDef: type=$type, ns=$ns"); 00688 if ((! $ns) && isset($this->namespaces['tns'])) { 00689 $ns = $this->namespaces['tns']; 00690 $this->debug("in getTypeDef: type namespace forced to $ns"); 00691 } 00692 if (!isset($this->schemas[$ns])) { 00693 foreach ($this->schemas as $ns0 => $schema0) { 00694 if (strcasecmp($ns, $ns0) == 0) { 00695 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); 00696 $ns = $ns0; 00697 break; 00698 } 00699 } 00700 } 00701 if (isset($this->schemas[$ns])) { 00702 $this->debug("in getTypeDef: have schema for namespace $ns"); 00703 for ($i = 0; $i < count($this->schemas[$ns]); $i++) { 00704 $xs = &$this->schemas[$ns][$i]; 00705 $t = $xs->getTypeDef($type); 00706 //$this->appendDebug($xs->getDebug()); 00707 //$xs->clearDebug(); 00708 if ($t) { 00709 if (!isset($t['phpType'])) { 00710 // get info for type to tack onto the element 00711 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); 00712 $ns = substr($t['type'], 0, strrpos($t['type'], ':')); 00713 $etype = $this->getTypeDef($uqType, $ns); 00714 if ($etype) { 00715 $this->debug("found type for [element] $type:"); 00716 $this->debug($this->varDump($etype)); 00717 if (isset($etype['phpType'])) { 00718 $t['phpType'] = $etype['phpType']; 00719 } 00720 if (isset($etype['elements'])) { 00721 $t['elements'] = $etype['elements']; 00722 } 00723 if (isset($etype['attrs'])) { 00724 $t['attrs'] = $etype['attrs']; 00725 } 00726 } 00727 } 00728 return $t; 00729 } 00730 } 00731 } else { 00732 $this->debug("in getTypeDef: do not have schema for namespace $ns"); 00733 } 00734 return false; 00735 } 00736 00742 function webDescription(){ 00743 global $HTTP_SERVER_VARS; 00744 00745 if (isset($_SERVER)) { 00746 $PHP_SELF = $_SERVER['PHP_SELF']; 00747 } elseif (isset($HTTP_SERVER_VARS)) { 00748 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; 00749 } else { 00750 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); 00751 } 00752 00753 $b = ' 00754 <html><head><title>NuSOAP: '.$this->serviceName.'</title> 00755 <style type="text/css"> 00756 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; } 00757 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; } 00758 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;} 00759 ul { margin-top: 10px; margin-left: 20px; } 00760 li { list-style-type: none; margin-top: 10px; color: #000000; } 00761 .content{ 00762 margin-left: 0px; padding-bottom: 2em; } 00763 .nav { 00764 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em; 00765 margin-top: 10px; margin-left: 0px; color: #000000; 00766 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; } 00767 .title { 00768 font-family: arial; font-size: 26px; color: #ffffff; 00769 background-color: #999999; width: 105%; margin-left: 0px; 00770 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;} 00771 .hidden { 00772 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px; 00773 font-family: arial; overflow: hidden; width: 600; 00774 padding: 20px; font-size: 10px; background-color: #999999; 00775 layer-background-color:#FFFFFF; } 00776 a,a:active { color: charcoal; font-weight: bold; } 00777 a:visited { color: #666666; font-weight: bold; } 00778 a:hover { color: cc3300; font-weight: bold; } 00779 </style> 00780 <script language="JavaScript" type="text/javascript"> 00781 <!-- 00782 // POP-UP CAPTIONS... 00783 function lib_bwcheck(){ //Browsercheck (needed) 00784 this.ver=navigator.appVersion 00785 this.agent=navigator.userAgent 00786 this.dom=document.getElementById?1:0 00787 this.opera5=this.agent.indexOf("Opera 5")>-1 00788 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0; 00789 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0; 00790 this.ie4=(document.all && !this.dom && !this.opera5)?1:0; 00791 this.ie=this.ie4||this.ie5||this.ie6 00792 this.mac=this.agent.indexOf("Mac")>-1 00793 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0; 00794 this.ns4=(document.layers && !this.dom)?1:0; 00795 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5) 00796 return this 00797 } 00798 var bw = new lib_bwcheck() 00799 //Makes crossbrowser object. 00800 function makeObj(obj){ 00801 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0; 00802 if(!this.evnt) return false 00803 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0; 00804 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0; 00805 this.writeIt=b_writeIt; 00806 return this 00807 } 00808 // A unit of measure that will be added when setting the position of a layer. 00809 //var px = bw.ns4||window.opera?"":"px"; 00810 function b_writeIt(text){ 00811 if (bw.ns4){this.wref.write(text);this.wref.close()} 00812 else this.wref.innerHTML = text 00813 } 00814 //Shows the messages 00815 var oDesc; 00816 function popup(divid){ 00817 if(oDesc = new makeObj(divid)){ 00818 oDesc.css.visibility = "visible" 00819 } 00820 } 00821 function popout(){ // Hides message 00822 if(oDesc) oDesc.css.visibility = "hidden" 00823 } 00824 //--> 00825 </script> 00826 </head> 00827 <body> 00828 <div class=content> 00829 <br><br> 00830 <div class=title>'.$this->serviceName.'</div> 00831 <div class=nav> 00832 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service. 00833 Click on an operation name to view it's details.</p> 00834 <ul>'; 00835 foreach($this->getOperations() as $op => $data){ 00836 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>"; 00837 // create hidden div 00838 $b .= "<div id='$op' class='hidden'> 00839 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>"; 00840 foreach($data as $donnie => $marie){ // loop through opdata 00841 if($donnie == 'input' || $donnie == 'output'){ // show input/output data 00842 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>'; 00843 foreach($marie as $captain => $tenille){ // loop through data 00844 if($captain == 'parts'){ // loop thru parts 00845 $b .= " $captain:<br>"; 00846 //if(is_array($tenille)){ 00847 foreach($tenille as $joanie => $chachi){ 00848 $b .= " $joanie: $chachi<br>"; 00849 } 00850 //} 00851 } else { 00852 $b .= " $captain: $tenille<br>"; 00853 } 00854 } 00855 } else { 00856 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>"; 00857 } 00858 } 00859 $b .= '</div>'; 00860 } 00861 $b .= ' 00862 <ul> 00863 </div> 00864 </div></body></html>'; 00865 return $b; 00866 } 00867 00875 function serialize($debug = 0) 00876 { 00877 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>'; 00878 $xml .= "\n<definitions"; 00879 foreach($this->namespaces as $k => $v) { 00880 $xml .= " xmlns:$k=\"$v\""; 00881 } 00882 // 10.9.02 - add poulter fix for wsdl and tns declarations 00883 if (isset($this->namespaces['wsdl'])) { 00884 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; 00885 } 00886 if (isset($this->namespaces['tns'])) { 00887 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; 00888 } 00889 $xml .= '>'; 00890 // imports 00891 if (sizeof($this->import) > 0) { 00892 foreach($this->import as $ns => $list) { 00893 foreach ($list as $ii) { 00894 if ($ii['location'] != '') { 00895 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />'; 00896 } else { 00897 $xml .= '<import namespace="' . $ns . '" />'; 00898 } 00899 } 00900 } 00901 } 00902 // types 00903 if (count($this->schemas)>=1) { 00904 $xml .= "\n<types>\n"; 00905 foreach ($this->schemas as $ns => $list) { 00906 foreach ($list as $xs) { 00907 $xml .= $xs->serializeSchema(); 00908 } 00909 } 00910 $xml .= '</types>'; 00911 } 00912 // messages 00913 if (count($this->messages) >= 1) { 00914 foreach($this->messages as $msgName => $msgParts) { 00915 $xml .= "\n<message name=\"" . $msgName . '">'; 00916 if(is_array($msgParts)){ 00917 foreach($msgParts as $partName => $partType) { 00918 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>'; 00919 if (strpos($partType, ':')) { 00920 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); 00921 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { 00922 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>'; 00923 $typePrefix = 'xsd'; 00924 } else { 00925 foreach($this->typemap as $ns => $types) { 00926 if (isset($types[$partType])) { 00927 $typePrefix = $this->getPrefixFromNamespace($ns); 00928 } 00929 } 00930 if (!isset($typePrefix)) { 00931 die("$partType has no namespace!"); 00932 } 00933 } 00934 $ns = $this->getNamespaceFromPrefix($typePrefix); 00935 $localPart = $this->getLocalPart($partType); 00936 $typeDef = $this->getTypeDef($localPart, $ns); 00937 if ($typeDef['typeClass'] == 'element') { 00938 $elementortype = 'element'; 00939 if (substr($localPart, -1) == '^') { 00940 $localPart = substr($localPart, 0, -1); 00941 } 00942 } else { 00943 $elementortype = 'type'; 00944 } 00945 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />'; 00946 } 00947 } 00948 $xml .= '</message>'; 00949 } 00950 } 00951 // bindings & porttypes 00952 if (count($this->bindings) >= 1) { 00953 $binding_xml = ''; 00954 $portType_xml = ''; 00955 foreach($this->bindings as $bindingName => $attrs) { 00956 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">'; 00957 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>'; 00958 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">'; 00959 foreach($attrs['operations'] as $opName => $opParts) { 00960 $binding_xml .= "\n" . ' <operation name="' . $opName . '">'; 00961 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>'; 00962 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { 00963 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; 00964 } else { 00965 $enc_style = ''; 00966 } 00967 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>'; 00968 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { 00969 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; 00970 } else { 00971 $enc_style = ''; 00972 } 00973 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>'; 00974 $binding_xml .= "\n" . ' </operation>'; 00975 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"'; 00976 if (isset($opParts['parameterOrder'])) { 00977 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"'; 00978 } 00979 $portType_xml .= '>'; 00980 if(isset($opParts['documentation']) && $opParts['documentation'] != '') { 00981 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>'; 00982 } 00983 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>'; 00984 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>'; 00985 $portType_xml .= "\n" . ' </operation>'; 00986 } 00987 $portType_xml .= "\n" . '</portType>'; 00988 $binding_xml .= "\n" . '</binding>'; 00989 } 00990 $xml .= $portType_xml . $binding_xml; 00991 } 00992 // services 00993 $xml .= "\n<service name=\"" . $this->serviceName . '">'; 00994 if (count($this->ports) >= 1) { 00995 foreach($this->ports as $pName => $attrs) { 00996 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">'; 00997 $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>'; 00998 $xml .= "\n" . ' </port>'; 00999 } 01000 } 01001 $xml .= "\n" . '</service>'; 01002 return $xml . "\n</definitions>"; 01003 } 01004 01014 function parametersMatchWrapped($type, &$parameters) { 01015 $this->debug("in parametersMatchWrapped type=$type, parameters="); 01016 $this->appendDebug($this->varDump($parameters)); 01017 01018 // split type into namespace:unqualified-type 01019 if (strpos($type, ':')) { 01020 $uqType = substr($type, strrpos($type, ':') + 1); 01021 $ns = substr($type, 0, strrpos($type, ':')); 01022 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); 01023 if ($this->getNamespaceFromPrefix($ns)) { 01024 $ns = $this->getNamespaceFromPrefix($ns); 01025 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); 01026 } 01027 } else { 01028 // TODO: should the type be compared to types in XSD, and the namespace 01029 // set to XSD if the type matches? 01030 $this->debug("in parametersMatchWrapped: No namespace for type $type"); 01031 $ns = ''; 01032 $uqType = $type; 01033 } 01034 01035 // get the type information 01036 if (!$typeDef = $this->getTypeDef($uqType, $ns)) { 01037 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); 01038 return false; 01039 } 01040 $this->debug("in parametersMatchWrapped: found typeDef="); 01041 $this->appendDebug($this->varDump($typeDef)); 01042 if (substr($uqType, -1) == '^') { 01043 $uqType = substr($uqType, 0, -1); 01044 } 01045 $phpType = $typeDef['phpType']; 01046 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); 01047 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); 01048 01049 // we expect a complexType or element of complexType 01050 if ($phpType != 'struct') { 01051 $this->debug("in parametersMatchWrapped: not a struct"); 01052 return false; 01053 } 01054 01055 // see whether the parameter names match the elements 01056 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 01057 $elements = 0; 01058 $matches = 0; 01059 $change = false; 01060 if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) { 01061 $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap"); 01062 $change = true; 01063 } 01064 foreach ($typeDef['elements'] as $name => $attrs) { 01065 if ($change) { 01066 $this->debug("in parametersMatchWrapped: change parameter $element to name $name"); 01067 $parameters[$name] = $parameters[$elements]; 01068 unset($parameters[$elements]); 01069 $matches++; 01070 } elseif (isset($parameters[$name])) { 01071 $this->debug("in parametersMatchWrapped: have parameter named $name"); 01072 $matches++; 01073 } else { 01074 $this->debug("in parametersMatchWrapped: do not have parameter named $name"); 01075 } 01076 $elements++; 01077 } 01078 01079 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); 01080 if ($matches == 0) { 01081 return false; 01082 } 01083 return true; 01084 } 01085 01086 // since there are no elements for the type, if the user passed no 01087 // parameters, the parameters match wrapped. 01088 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); 01089 return count($parameters) == 0; 01090 } 01091 01107 function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { 01108 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); 01109 $this->appendDebug('parameters=' . $this->varDump($parameters)); 01110 01111 if ($direction != 'input' && $direction != 'output') { 01112 $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 01113 $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 01114 return false; 01115 } 01116 if (!$opData = $this->getOperationData($operation, $bindingType)) { 01117 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 01118 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 01119 return false; 01120 } 01121 $this->debug('in serializeRPCParameters: opData:'); 01122 $this->appendDebug($this->varDump($opData)); 01123 01124 // Get encoding style for output and set to current 01125 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01126 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 01127 $encodingStyle = $opData['output']['encodingStyle']; 01128 $enc_style = $encodingStyle; 01129 } 01130 01131 // set input params 01132 $xml = ''; 01133 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 01134 $parts = &$opData[$direction]['parts']; 01135 $part_count = sizeof($parts); 01136 $style = $opData['style']; 01137 $use = $opData[$direction]['use']; 01138 $this->debug("have $part_count part(s) to serialize using $style/$use"); 01139 if (is_array($parameters)) { 01140 $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 01141 $parameter_count = count($parameters); 01142 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); 01143 // check for Microsoft-style wrapped parameters 01144 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { 01145 $this->debug('check whether the caller has wrapped the parameters'); 01146 if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) { 01147 $this->debug('check whether caller\'s parameters match the wrapped ones'); 01148 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { 01149 $this->debug('wrap the parameters for the caller'); 01150 $parameters = array('parameters' => $parameters); 01151 $parameter_count = 1; 01152 } 01153 } 01154 } 01155 foreach ($parts as $name => $type) { 01156 $this->debug("serializing part $name of type $type"); 01157 // Track encoding style 01158 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 01159 $encodingStyle = $opData[$direction]['encodingStyle']; 01160 $enc_style = $encodingStyle; 01161 } else { 01162 $enc_style = false; 01163 } 01164 // NOTE: add error handling here 01165 // if serializeType returns false, then catch global error and fault 01166 if ($parametersArrayType == 'arraySimple') { 01167 $p = array_shift($parameters); 01168 $this->debug('calling serializeType w/indexed param'); 01169 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 01170 } elseif (isset($parameters[$name])) { 01171 $this->debug('calling serializeType w/named param'); 01172 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 01173 } else { 01174 // TODO: only send nillable 01175 $this->debug('calling serializeType w/null param'); 01176 $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 01177 } 01178 } 01179 } else { 01180 $this->debug('no parameters passed.'); 01181 } 01182 } 01183 $this->debug("serializeRPCParameters returning: $xml"); 01184 return $xml; 01185 } 01186 01201 function serializeParameters($operation, $direction, $parameters) 01202 { 01203 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 01204 $this->appendDebug('parameters=' . $this->varDump($parameters)); 01205 01206 if ($direction != 'input' && $direction != 'output') { 01207 $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 01208 $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 01209 return false; 01210 } 01211 if (!$opData = $this->getOperationData($operation)) { 01212 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); 01213 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); 01214 return false; 01215 } 01216 $this->debug('opData:'); 01217 $this->appendDebug($this->varDump($opData)); 01218 01219 // Get encoding style for output and set to current 01220 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01221 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 01222 $encodingStyle = $opData['output']['encodingStyle']; 01223 $enc_style = $encodingStyle; 01224 } 01225 01226 // set input params 01227 $xml = ''; 01228 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 01229 01230 $use = $opData[$direction]['use']; 01231 $this->debug("use=$use"); 01232 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); 01233 if (is_array($parameters)) { 01234 $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 01235 $this->debug('have ' . $parametersArrayType . ' parameters'); 01236 foreach($opData[$direction]['parts'] as $name => $type) { 01237 $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); 01238 // Track encoding style 01239 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 01240 $encodingStyle = $opData[$direction]['encodingStyle']; 01241 $enc_style = $encodingStyle; 01242 } else { 01243 $enc_style = false; 01244 } 01245 // NOTE: add error handling here 01246 // if serializeType returns false, then catch global error and fault 01247 if ($parametersArrayType == 'arraySimple') { 01248 $p = array_shift($parameters); 01249 $this->debug('calling serializeType w/indexed param'); 01250 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 01251 } elseif (isset($parameters[$name])) { 01252 $this->debug('calling serializeType w/named param'); 01253 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 01254 } else { 01255 // TODO: only send nillable 01256 $this->debug('calling serializeType w/null param'); 01257 $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 01258 } 01259 } 01260 } else { 01261 $this->debug('no parameters passed.'); 01262 } 01263 } 01264 $this->debug("serializeParameters returning: $xml"); 01265 return $xml; 01266 } 01267 01280 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) 01281 { 01282 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); 01283 $this->appendDebug("value=" . $this->varDump($value)); 01284 if($use == 'encoded' && $encodingStyle) { 01285 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; 01286 } 01287 01288 // if a soapval has been supplied, let its type override the WSDL 01289 if (is_object($value) && get_class($value) == 'soapval') { 01290 if ($value->type_ns) { 01291 $type = $value->type_ns . ':' . $value->type; 01292 $forceType = true; 01293 $this->debug("in serializeType: soapval overrides type to $type"); 01294 } elseif ($value->type) { 01295 $type = $value->type; 01296 $forceType = true; 01297 $this->debug("in serializeType: soapval overrides type to $type"); 01298 } else { 01299 $forceType = false; 01300 $this->debug("in serializeType: soapval does not override type"); 01301 } 01302 $attrs = $value->attributes; 01303 $value = $value->value; 01304 $this->debug("in serializeType: soapval overrides value to $value"); 01305 if ($attrs) { 01306 if (!is_array($value)) { 01307 $value['!'] = $value; 01308 } 01309 foreach ($attrs as $n => $v) { 01310 $value['!' . $n] = $v; 01311 } 01312 $this->debug("in serializeType: soapval provides attributes"); 01313 } 01314 } else { 01315 $forceType = false; 01316 } 01317 01318 $xml = ''; 01319 if (strpos($type, ':')) { 01320 $uqType = substr($type, strrpos($type, ':') + 1); 01321 $ns = substr($type, 0, strrpos($type, ':')); 01322 $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); 01323 if ($this->getNamespaceFromPrefix($ns)) { 01324 $ns = $this->getNamespaceFromPrefix($ns); 01325 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); 01326 } 01327 01328 if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ 01329 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); 01330 if ($unqualified && $use == 'literal') { 01331 $elementNS = " xmlns=\"\""; 01332 } else { 01333 $elementNS = ''; 01334 } 01335 if (is_null($value)) { 01336 if ($use == 'literal') { 01337 // TODO: depends on minOccurs 01338 $xml = "<$name$elementNS/>"; 01339 } else { 01340 // TODO: depends on nillable, which should be checked before calling this method 01341 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 01342 } 01343 $this->debug("in serializeType: returning: $xml"); 01344 return $xml; 01345 } 01346 if ($uqType == 'Array') { 01347 // JBoss/Axis does this sometimes 01348 return $this->serialize_val($value, $name, false, false, false, false, $use); 01349 } 01350 if ($uqType == 'boolean') { 01351 if ((is_string($value) && $value == 'false') || (! $value)) { 01352 $value = 'false'; 01353 } else { 01354 $value = 'true'; 01355 } 01356 } 01357 if ($uqType == 'string' && gettype($value) == 'string') { 01358 $value = $this->expandEntities($value); 01359 } 01360 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { 01361 $value = sprintf("%.0lf", $value); 01362 } 01363 // it's a scalar 01364 // TODO: what about null/nil values? 01365 // check type isn't a custom type extending xmlschema namespace 01366 if (!$this->getTypeDef($uqType, $ns)) { 01367 if ($use == 'literal') { 01368 if ($forceType) { 01369 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 01370 } else { 01371 $xml = "<$name$elementNS>$value</$name>"; 01372 } 01373 } else { 01374 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 01375 } 01376 $this->debug("in serializeType: returning: $xml"); 01377 return $xml; 01378 } 01379 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); 01380 } else if ($ns == 'http://xml.apache.org/xml-soap') { 01381 $this->debug('in serializeType: appears to be Apache SOAP type'); 01382 if ($uqType == 'Map') { 01383 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 01384 if (! $tt_prefix) { 01385 $this->debug('in serializeType: Add namespace for Apache SOAP type'); 01386 $tt_prefix = 'ns' . rand(1000, 9999); 01387 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; 01388 // force this to be added to usedNamespaces 01389 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 01390 } 01391 $contents = ''; 01392 foreach($value as $k => $v) { 01393 $this->debug("serializing map element: key $k, value $v"); 01394 $contents .= '<item>'; 01395 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); 01396 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); 01397 $contents .= '</item>'; 01398 } 01399 if ($use == 'literal') { 01400 if ($forceType) { 01401 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>"; 01402 } else { 01403 $xml = "<$name>$contents</$name>"; 01404 } 01405 } else { 01406 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>"; 01407 } 01408 $this->debug("in serializeType: returning: $xml"); 01409 return $xml; 01410 } 01411 $this->debug('in serializeType: Apache SOAP type, but only support Map'); 01412 } 01413 } else { 01414 // TODO: should the type be compared to types in XSD, and the namespace 01415 // set to XSD if the type matches? 01416 $this->debug("in serializeType: No namespace for type $type"); 01417 $ns = ''; 01418 $uqType = $type; 01419 } 01420 if(!$typeDef = $this->getTypeDef($uqType, $ns)){ 01421 $this->setError("$type ($uqType) is not a supported type."); 01422 $this->debug("in serializeType: $type ($uqType) is not a supported type."); 01423 return false; 01424 } else { 01425 $this->debug("in serializeType: found typeDef"); 01426 $this->appendDebug('typeDef=' . $this->varDump($typeDef)); 01427 if (substr($uqType, -1) == '^') { 01428 $uqType = substr($uqType, 0, -1); 01429 } 01430 } 01431 $phpType = $typeDef['phpType']; 01432 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 01433 // if php type == struct, map value to the <all> element names 01434 if ($phpType == 'struct') { 01435 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { 01436 $elementName = $uqType; 01437 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01438 $elementNS = " xmlns=\"$ns\""; 01439 } else { 01440 $elementNS = " xmlns=\"\""; 01441 } 01442 } else { 01443 $elementName = $name; 01444 if ($unqualified) { 01445 $elementNS = " xmlns=\"\""; 01446 } else { 01447 $elementNS = ''; 01448 } 01449 } 01450 if (is_null($value)) { 01451 if ($use == 'literal') { 01452 // TODO: depends on minOccurs 01453 $xml = "<$elementName$elementNS/>"; 01454 } else { 01455 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 01456 } 01457 $this->debug("in serializeType: returning: $xml"); 01458 return $xml; 01459 } 01460 if (is_object($value)) { 01461 $value = get_object_vars($value); 01462 } 01463 if (is_array($value)) { 01464 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); 01465 if ($use == 'literal') { 01466 if ($forceType) { 01467 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; 01468 } else { 01469 $xml = "<$elementName$elementNS$elementAttrs>"; 01470 } 01471 } else { 01472 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; 01473 } 01474 01475 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); 01476 $xml .= "</$elementName>"; 01477 } else { 01478 $this->debug("in serializeType: phpType is struct, but value is not an array"); 01479 $this->setError("phpType is struct, but value is not an array: see debug output for details"); 01480 $xml = ''; 01481 } 01482 } elseif ($phpType == 'array') { 01483 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01484 $elementNS = " xmlns=\"$ns\""; 01485 } else { 01486 if ($unqualified) { 01487 $elementNS = " xmlns=\"\""; 01488 } else { 01489 $elementNS = ''; 01490 } 01491 } 01492 if (is_null($value)) { 01493 if ($use == 'literal') { 01494 // TODO: depends on minOccurs 01495 $xml = "<$name$elementNS/>"; 01496 } else { 01497 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . 01498 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 01499 ":Array\" " . 01500 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 01501 ':arrayType="' . 01502 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . 01503 ':' . 01504 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; 01505 } 01506 $this->debug("in serializeType: returning: $xml"); 01507 return $xml; 01508 } 01509 if (isset($typeDef['multidimensional'])) { 01510 $nv = array(); 01511 foreach($value as $v) { 01512 $cols = ',' . sizeof($v); 01513 $nv = array_merge($nv, $v); 01514 } 01515 $value = $nv; 01516 } else { 01517 $cols = ''; 01518 } 01519 if (is_array($value) && sizeof($value) >= 1) { 01520 $rows = sizeof($value); 01521 $contents = ''; 01522 foreach($value as $k => $v) { 01523 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); 01524 //if (strpos($typeDef['arrayType'], ':') ) { 01525 if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) { 01526 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); 01527 } else { 01528 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); 01529 } 01530 } 01531 } else { 01532 $rows = 0; 01533 $contents = null; 01534 } 01535 // TODO: for now, an empty value will be serialized as a zero element 01536 // array. Revisit this when coding the handling of null/nil values. 01537 if ($use == 'literal') { 01538 $xml = "<$name$elementNS>" 01539 .$contents 01540 ."</$name>"; 01541 } else { 01542 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. 01543 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') 01544 .':arrayType="' 01545 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) 01546 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" 01547 .$contents 01548 ."</$name>"; 01549 } 01550 } elseif ($phpType == 'scalar') { 01551 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01552 $elementNS = " xmlns=\"$ns\""; 01553 } else { 01554 if ($unqualified) { 01555 $elementNS = " xmlns=\"\""; 01556 } else { 01557 $elementNS = ''; 01558 } 01559 } 01560 if ($use == 'literal') { 01561 if ($forceType) { 01562 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 01563 } else { 01564 $xml = "<$name$elementNS>$value</$name>"; 01565 } 01566 } else { 01567 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 01568 } 01569 } 01570 $this->debug("in serializeType: returning: $xml"); 01571 return $xml; 01572 } 01573 01584 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { 01585 $xml = ''; 01586 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { 01587 $this->debug("serialize attributes for XML Schema type $ns:$uqType"); 01588 if (is_array($value)) { 01589 $xvalue = $value; 01590 } elseif (is_object($value)) { 01591 $xvalue = get_object_vars($value); 01592 } else { 01593 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 01594 $xvalue = array(); 01595 } 01596 foreach ($typeDef['attrs'] as $aName => $attrs) { 01597 if (isset($xvalue['!' . $aName])) { 01598 $xname = '!' . $aName; 01599 $this->debug("value provided for attribute $aName with key $xname"); 01600 } elseif (isset($xvalue[$aName])) { 01601 $xname = $aName; 01602 $this->debug("value provided for attribute $aName with key $xname"); 01603 } elseif (isset($attrs['default'])) { 01604 $xname = '!' . $aName; 01605 $xvalue[$xname] = $attrs['default']; 01606 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); 01607 } else { 01608 $xname = ''; 01609 $this->debug("no value provided for attribute $aName"); 01610 } 01611 if ($xname) { 01612 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; 01613 } 01614 } 01615 } else { 01616 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); 01617 } 01618 if (isset($typeDef['extensionBase'])) { 01619 $ns = $this->getPrefix($typeDef['extensionBase']); 01620 $uqType = $this->getLocalPart($typeDef['extensionBase']); 01621 if ($this->getNamespaceFromPrefix($ns)) { 01622 $ns = $this->getNamespaceFromPrefix($ns); 01623 } 01624 if ($typeDef = $this->getTypeDef($uqType, $ns)) { 01625 $this->debug("serialize attributes for extension base $ns:$uqType"); 01626 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); 01627 } else { 01628 $this->debug("extension base $ns:$uqType is not a supported type"); 01629 } 01630 } 01631 return $xml; 01632 } 01633 01646 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { 01647 $xml = ''; 01648 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 01649 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); 01650 if (is_array($value)) { 01651 $xvalue = $value; 01652 } elseif (is_object($value)) { 01653 $xvalue = get_object_vars($value); 01654 } else { 01655 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 01656 $xvalue = array(); 01657 } 01658 // toggle whether all elements are present - ideally should validate against schema 01659 if (count($typeDef['elements']) != count($xvalue)){ 01660 $optionals = true; 01661 } 01662 foreach ($typeDef['elements'] as $eName => $attrs) { 01663 if (!isset($xvalue[$eName])) { 01664 if (isset($attrs['default'])) { 01665 $xvalue[$eName] = $attrs['default']; 01666 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); 01667 } 01668 } 01669 // if user took advantage of a minOccurs=0, then only serialize named parameters 01670 if (isset($optionals) 01671 && (!isset($xvalue[$eName])) 01672 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') 01673 ){ 01674 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { 01675 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); 01676 } 01677 // do nothing 01678 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); 01679 } else { 01680 // get value 01681 if (isset($xvalue[$eName])) { 01682 $v = $xvalue[$eName]; 01683 } else { 01684 $v = null; 01685 } 01686 if (isset($attrs['form'])) { 01687 $unqualified = ($attrs['form'] == 'unqualified'); 01688 } else { 01689 $unqualified = false; 01690 } 01691 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { 01692 $vv = $v; 01693 foreach ($vv as $k => $v) { 01694 if (isset($attrs['type']) || isset($attrs['ref'])) { 01695 // serialize schema-defined type 01696 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 01697 } else { 01698 // serialize generic type (can this ever really happen?) 01699 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 01700 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 01701 } 01702 } 01703 } else { 01704 if (isset($attrs['type']) || isset($attrs['ref'])) { 01705 // serialize schema-defined type 01706 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 01707 } else { 01708 // serialize generic type (can this ever really happen?) 01709 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 01710 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 01711 } 01712 } 01713 } 01714 } 01715 } else { 01716 $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); 01717 } 01718 if (isset($typeDef['extensionBase'])) { 01719 $ns = $this->getPrefix($typeDef['extensionBase']); 01720 $uqType = $this->getLocalPart($typeDef['extensionBase']); 01721 if ($this->getNamespaceFromPrefix($ns)) { 01722 $ns = $this->getNamespaceFromPrefix($ns); 01723 } 01724 if ($typeDef = $this->getTypeDef($uqType, $ns)) { 01725 $this->debug("serialize elements for extension base $ns:$uqType"); 01726 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); 01727 } else { 01728 $this->debug("extension base $ns:$uqType is not a supported type"); 01729 } 01730 } 01731 return $xml; 01732 } 01733 01748 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { 01749 if (count($elements) > 0) { 01750 $eElements = array(); 01751 foreach($elements as $n => $e){ 01752 // expand each element 01753 $ee = array(); 01754 foreach ($e as $k => $v) { 01755 $k = strpos($k,':') ? $this->expandQname($k) : $k; 01756 $v = strpos($v,':') ? $this->expandQname($v) : $v; 01757 $ee[$k] = $v; 01758 } 01759 $eElements[$n] = $ee; 01760 } 01761 $elements = $eElements; 01762 } 01763 01764 if (count($attrs) > 0) { 01765 foreach($attrs as $n => $a){ 01766 // expand each attribute 01767 foreach ($a as $k => $v) { 01768 $k = strpos($k,':') ? $this->expandQname($k) : $k; 01769 $v = strpos($v,':') ? $this->expandQname($v) : $v; 01770 $aa[$k] = $v; 01771 } 01772 $eAttrs[$n] = $aa; 01773 } 01774 $attrs = $eAttrs; 01775 } 01776 01777 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; 01778 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType; 01779 01780 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01781 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType); 01782 } 01783 01795 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 01796 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; 01797 01798 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01799 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); 01800 } 01801 01809 function addElement($attrs) { 01810 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01811 $this->schemas[$typens][0]->addElement($attrs); 01812 } 01813 01828 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ 01829 if ($use == 'encoded' && $encodingStyle == '') { 01830 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01831 } 01832 01833 if ($style == 'document') { 01834 $elements = array(); 01835 foreach ($in as $n => $t) { 01836 $elements[$n] = array('name' => $n, 'type' => $t); 01837 } 01838 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); 01839 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); 01840 $in = array('parameters' => 'tns:' . $name . '^'); 01841 01842 $elements = array(); 01843 foreach ($out as $n => $t) { 01844 $elements[$n] = array('name' => $n, 'type' => $t); 01845 } 01846 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); 01847 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); 01848 $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); 01849 } 01850 01851 // get binding 01852 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = 01853 array( 01854 'name' => $name, 01855 'binding' => $this->serviceName . 'Binding', 01856 'endpoint' => $this->endpoint, 01857 'soapAction' => $soapaction, 01858 'style' => $style, 01859 'input' => array( 01860 'use' => $use, 01861 'namespace' => $namespace, 01862 'encodingStyle' => $encodingStyle, 01863 'message' => $name . 'Request', 01864 'parts' => $in), 01865 'output' => array( 01866 'use' => $use, 01867 'namespace' => $namespace, 01868 'encodingStyle' => $encodingStyle, 01869 'message' => $name . 'Response', 01870 'parts' => $out), 01871 'namespace' => $namespace, 01872 'transport' => 'http://schemas.xmlsoap.org/soap/http', 01873 'documentation' => $documentation); 01874 // add portTypes 01875 // add messages 01876 if($in) 01877 { 01878 foreach($in as $pName => $pType) 01879 { 01880 if(strpos($pType,':')) { 01881 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 01882 } 01883 $this->messages[$name.'Request'][$pName] = $pType; 01884 } 01885 } else { 01886 $this->messages[$name.'Request']= '0'; 01887 } 01888 if($out) 01889 { 01890 foreach($out as $pName => $pType) 01891 { 01892 if(strpos($pType,':')) { 01893 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 01894 } 01895 $this->messages[$name.'Response'][$pName] = $pType; 01896 } 01897 } else { 01898 $this->messages[$name.'Response']= '0'; 01899 } 01900 return true; 01901 } 01902 } 01903 01904 ?>