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 = 'Getting ' . $wsdl . ' - 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 00586 function getOperations($portName = '', $bindingType = 'soap') { 00587 $ops = array(); 00588 if ($bindingType == 'soap') { 00589 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00590 } elseif ($bindingType == 'soap12') { 00591 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00592 } else { 00593 $this->debug("getOperations bindingType $bindingType may not be supported"); 00594 } 00595 $this->debug("getOperations for port '$portName' bindingType $bindingType"); 00596 // loop thru ports 00597 foreach($this->ports as $port => $portData) { 00598 $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']); 00599 if ($portName == '' || $port == $portName) { 00600 // binding type of port matches parameter 00601 if ($portData['bindingType'] == $bindingType) { 00602 $this->debug("getOperations found port $port bindingType $bindingType"); 00603 //$this->debug("port data: " . $this->varDump($portData)); 00604 //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); 00605 // merge bindings 00606 if (isset($this->bindings[ $portData['binding'] ]['operations'])) { 00607 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); 00608 } 00609 } 00610 } 00611 } 00612 if (count($ops) == 0) { 00613 $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); 00614 } 00615 return $ops; 00616 } 00617 00626 function getOperationData($operation, $bindingType = 'soap') 00627 { 00628 if ($bindingType == 'soap') { 00629 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00630 } elseif ($bindingType == 'soap12') { 00631 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00632 } 00633 // loop thru ports 00634 foreach($this->ports as $port => $portData) { 00635 // binding type of port matches parameter 00636 if ($portData['bindingType'] == $bindingType) { 00637 // get binding 00638 //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 00639 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { 00640 // note that we could/should also check the namespace here 00641 if ($operation == $bOperation) { 00642 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; 00643 return $opData; 00644 } 00645 } 00646 } 00647 } 00648 } 00649 00658 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { 00659 if ($bindingType == 'soap') { 00660 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 00661 } elseif ($bindingType == 'soap12') { 00662 $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 00663 } 00664 // loop thru ports 00665 foreach($this->ports as $port => $portData) { 00666 // binding type of port matches parameter 00667 if ($portData['bindingType'] == $bindingType) { 00668 // loop through operations for the binding 00669 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 00670 if ($opData['soapAction'] == $soapAction) { 00671 return $opData; 00672 } 00673 } 00674 } 00675 } 00676 } 00677 00696 function getTypeDef($type, $ns) { 00697 $this->debug("in getTypeDef: type=$type, ns=$ns"); 00698 if ((! $ns) && isset($this->namespaces['tns'])) { 00699 $ns = $this->namespaces['tns']; 00700 $this->debug("in getTypeDef: type namespace forced to $ns"); 00701 } 00702 if (!isset($this->schemas[$ns])) { 00703 foreach ($this->schemas as $ns0 => $schema0) { 00704 if (strcasecmp($ns, $ns0) == 0) { 00705 $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); 00706 $ns = $ns0; 00707 break; 00708 } 00709 } 00710 } 00711 if (isset($this->schemas[$ns])) { 00712 $this->debug("in getTypeDef: have schema for namespace $ns"); 00713 for ($i = 0; $i < count($this->schemas[$ns]); $i++) { 00714 $xs = &$this->schemas[$ns][$i]; 00715 $t = $xs->getTypeDef($type); 00716 $this->appendDebug($xs->getDebug()); 00717 $xs->clearDebug(); 00718 if ($t) { 00719 $this->debug("in getTypeDef: found type $type"); 00720 if (!isset($t['phpType'])) { 00721 // get info for type to tack onto the element 00722 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); 00723 $ns = substr($t['type'], 0, strrpos($t['type'], ':')); 00724 $etype = $this->getTypeDef($uqType, $ns); 00725 if ($etype) { 00726 $this->debug("found type for [element] $type:"); 00727 $this->debug($this->varDump($etype)); 00728 if (isset($etype['phpType'])) { 00729 $t['phpType'] = $etype['phpType']; 00730 } 00731 if (isset($etype['elements'])) { 00732 $t['elements'] = $etype['elements']; 00733 } 00734 if (isset($etype['attrs'])) { 00735 $t['attrs'] = $etype['attrs']; 00736 } 00737 } else { 00738 $this->debug("did not find type for [element] $type"); 00739 } 00740 } 00741 return $t; 00742 } 00743 } 00744 $this->debug("in getTypeDef: did not find type $type"); 00745 } else { 00746 $this->debug("in getTypeDef: do not have schema for namespace $ns"); 00747 } 00748 return false; 00749 } 00750 00756 function webDescription(){ 00757 global $HTTP_SERVER_VARS; 00758 00759 if (isset($_SERVER)) { 00760 $PHP_SELF = $_SERVER['PHP_SELF']; 00761 } elseif (isset($HTTP_SERVER_VARS)) { 00762 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; 00763 } else { 00764 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); 00765 } 00766 00767 $b = ' 00768 <html><head><title>NuSOAP: '.$this->serviceName.'</title> 00769 <style type="text/css"> 00770 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; } 00771 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; } 00772 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;} 00773 ul { margin-top: 10px; margin-left: 20px; } 00774 li { list-style-type: none; margin-top: 10px; color: #000000; } 00775 .content{ 00776 margin-left: 0px; padding-bottom: 2em; } 00777 .nav { 00778 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em; 00779 margin-top: 10px; margin-left: 0px; color: #000000; 00780 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; } 00781 .title { 00782 font-family: arial; font-size: 26px; color: #ffffff; 00783 background-color: #999999; width: 100%; 00784 margin-left: 0px; margin-right: 0px; 00785 padding-top: 10px; padding-bottom: 10px;} 00786 .hidden { 00787 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px; 00788 font-family: arial; overflow: hidden; width: 600; 00789 padding: 20px; font-size: 10px; background-color: #999999; 00790 layer-background-color:#FFFFFF; } 00791 a,a:active { color: charcoal; font-weight: bold; } 00792 a:visited { color: #666666; font-weight: bold; } 00793 a:hover { color: cc3300; font-weight: bold; } 00794 </style> 00795 <script language="JavaScript" type="text/javascript"> 00796 <!-- 00797 // POP-UP CAPTIONS... 00798 function lib_bwcheck(){ //Browsercheck (needed) 00799 this.ver=navigator.appVersion 00800 this.agent=navigator.userAgent 00801 this.dom=document.getElementById?1:0 00802 this.opera5=this.agent.indexOf("Opera 5")>-1 00803 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0; 00804 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0; 00805 this.ie4=(document.all && !this.dom && !this.opera5)?1:0; 00806 this.ie=this.ie4||this.ie5||this.ie6 00807 this.mac=this.agent.indexOf("Mac")>-1 00808 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0; 00809 this.ns4=(document.layers && !this.dom)?1:0; 00810 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5) 00811 return this 00812 } 00813 var bw = new lib_bwcheck() 00814 //Makes crossbrowser object. 00815 function makeObj(obj){ 00816 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0; 00817 if(!this.evnt) return false 00818 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0; 00819 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0; 00820 this.writeIt=b_writeIt; 00821 return this 00822 } 00823 // A unit of measure that will be added when setting the position of a layer. 00824 //var px = bw.ns4||window.opera?"":"px"; 00825 function b_writeIt(text){ 00826 if (bw.ns4){this.wref.write(text);this.wref.close()} 00827 else this.wref.innerHTML = text 00828 } 00829 //Shows the messages 00830 var oDesc; 00831 function popup(divid){ 00832 if(oDesc = new makeObj(divid)){ 00833 oDesc.css.visibility = "visible" 00834 } 00835 } 00836 function popout(){ // Hides message 00837 if(oDesc) oDesc.css.visibility = "hidden" 00838 } 00839 //--> 00840 </script> 00841 </head> 00842 <body> 00843 <div class=content> 00844 <br><br> 00845 <div class=title>'.$this->serviceName.'</div> 00846 <div class=nav> 00847 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service. 00848 Click on an operation name to view it's details.</p> 00849 <ul>'; 00850 foreach($this->getOperations() as $op => $data){ 00851 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>"; 00852 // create hidden div 00853 $b .= "<div id='$op' class='hidden'> 00854 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>"; 00855 foreach($data as $donnie => $marie){ // loop through opdata 00856 if($donnie == 'input' || $donnie == 'output'){ // show input/output data 00857 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>'; 00858 foreach($marie as $captain => $tenille){ // loop through data 00859 if($captain == 'parts'){ // loop thru parts 00860 $b .= " $captain:<br>"; 00861 //if(is_array($tenille)){ 00862 foreach($tenille as $joanie => $chachi){ 00863 $b .= " $joanie: $chachi<br>"; 00864 } 00865 //} 00866 } else { 00867 $b .= " $captain: $tenille<br>"; 00868 } 00869 } 00870 } else { 00871 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>"; 00872 } 00873 } 00874 $b .= '</div>'; 00875 } 00876 $b .= ' 00877 <ul> 00878 </div> 00879 </div></body></html>'; 00880 return $b; 00881 } 00882 00890 function serialize($debug = 0) 00891 { 00892 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>'; 00893 $xml .= "\n<definitions"; 00894 foreach($this->namespaces as $k => $v) { 00895 $xml .= " xmlns:$k=\"$v\""; 00896 } 00897 // 10.9.02 - add poulter fix for wsdl and tns declarations 00898 if (isset($this->namespaces['wsdl'])) { 00899 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; 00900 } 00901 if (isset($this->namespaces['tns'])) { 00902 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; 00903 } 00904 $xml .= '>'; 00905 // imports 00906 if (sizeof($this->import) > 0) { 00907 foreach($this->import as $ns => $list) { 00908 foreach ($list as $ii) { 00909 if ($ii['location'] != '') { 00910 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />'; 00911 } else { 00912 $xml .= '<import namespace="' . $ns . '" />'; 00913 } 00914 } 00915 } 00916 } 00917 // types 00918 if (count($this->schemas)>=1) { 00919 $xml .= "\n<types>\n"; 00920 foreach ($this->schemas as $ns => $list) { 00921 foreach ($list as $xs) { 00922 $xml .= $xs->serializeSchema(); 00923 } 00924 } 00925 $xml .= '</types>'; 00926 } 00927 // messages 00928 if (count($this->messages) >= 1) { 00929 foreach($this->messages as $msgName => $msgParts) { 00930 $xml .= "\n<message name=\"" . $msgName . '">'; 00931 if(is_array($msgParts)){ 00932 foreach($msgParts as $partName => $partType) { 00933 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>'; 00934 if (strpos($partType, ':')) { 00935 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); 00936 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { 00937 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>'; 00938 $typePrefix = 'xsd'; 00939 } else { 00940 foreach($this->typemap as $ns => $types) { 00941 if (isset($types[$partType])) { 00942 $typePrefix = $this->getPrefixFromNamespace($ns); 00943 } 00944 } 00945 if (!isset($typePrefix)) { 00946 die("$partType has no namespace!"); 00947 } 00948 } 00949 $ns = $this->getNamespaceFromPrefix($typePrefix); 00950 $localPart = $this->getLocalPart($partType); 00951 $typeDef = $this->getTypeDef($localPart, $ns); 00952 if ($typeDef['typeClass'] == 'element') { 00953 $elementortype = 'element'; 00954 if (substr($localPart, -1) == '^') { 00955 $localPart = substr($localPart, 0, -1); 00956 } 00957 } else { 00958 $elementortype = 'type'; 00959 } 00960 $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />'; 00961 } 00962 } 00963 $xml .= '</message>'; 00964 } 00965 } 00966 // bindings & porttypes 00967 if (count($this->bindings) >= 1) { 00968 $binding_xml = ''; 00969 $portType_xml = ''; 00970 foreach($this->bindings as $bindingName => $attrs) { 00971 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">'; 00972 $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>'; 00973 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">'; 00974 foreach($attrs['operations'] as $opName => $opParts) { 00975 $binding_xml .= "\n" . ' <operation name="' . $opName . '">'; 00976 $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>'; 00977 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { 00978 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; 00979 } else { 00980 $enc_style = ''; 00981 } 00982 $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>'; 00983 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { 00984 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; 00985 } else { 00986 $enc_style = ''; 00987 } 00988 $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>'; 00989 $binding_xml .= "\n" . ' </operation>'; 00990 $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"'; 00991 if (isset($opParts['parameterOrder'])) { 00992 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"'; 00993 } 00994 $portType_xml .= '>'; 00995 if(isset($opParts['documentation']) && $opParts['documentation'] != '') { 00996 $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>'; 00997 } 00998 $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>'; 00999 $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>'; 01000 $portType_xml .= "\n" . ' </operation>'; 01001 } 01002 $portType_xml .= "\n" . '</portType>'; 01003 $binding_xml .= "\n" . '</binding>'; 01004 } 01005 $xml .= $portType_xml . $binding_xml; 01006 } 01007 // services 01008 $xml .= "\n<service name=\"" . $this->serviceName . '">'; 01009 if (count($this->ports) >= 1) { 01010 foreach($this->ports as $pName => $attrs) { 01011 $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">'; 01012 $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>'; 01013 $xml .= "\n" . ' </port>'; 01014 } 01015 } 01016 $xml .= "\n" . '</service>'; 01017 return $xml . "\n</definitions>"; 01018 } 01019 01029 function parametersMatchWrapped($type, &$parameters) { 01030 $this->debug("in parametersMatchWrapped type=$type, parameters="); 01031 $this->appendDebug($this->varDump($parameters)); 01032 01033 // split type into namespace:unqualified-type 01034 if (strpos($type, ':')) { 01035 $uqType = substr($type, strrpos($type, ':') + 1); 01036 $ns = substr($type, 0, strrpos($type, ':')); 01037 $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); 01038 if ($this->getNamespaceFromPrefix($ns)) { 01039 $ns = $this->getNamespaceFromPrefix($ns); 01040 $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); 01041 } 01042 } else { 01043 // TODO: should the type be compared to types in XSD, and the namespace 01044 // set to XSD if the type matches? 01045 $this->debug("in parametersMatchWrapped: No namespace for type $type"); 01046 $ns = ''; 01047 $uqType = $type; 01048 } 01049 01050 // get the type information 01051 if (!$typeDef = $this->getTypeDef($uqType, $ns)) { 01052 $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); 01053 return false; 01054 } 01055 $this->debug("in parametersMatchWrapped: found typeDef="); 01056 $this->appendDebug($this->varDump($typeDef)); 01057 if (substr($uqType, -1) == '^') { 01058 $uqType = substr($uqType, 0, -1); 01059 } 01060 $phpType = $typeDef['phpType']; 01061 $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); 01062 $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); 01063 01064 // we expect a complexType or element of complexType 01065 if ($phpType != 'struct') { 01066 $this->debug("in parametersMatchWrapped: not a struct"); 01067 return false; 01068 } 01069 01070 // see whether the parameter names match the elements 01071 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 01072 $elements = 0; 01073 $matches = 0; 01074 foreach ($typeDef['elements'] as $name => $attrs) { 01075 if (isset($parameters[$name])) { 01076 $this->debug("in parametersMatchWrapped: have parameter named $name"); 01077 $matches++; 01078 } else { 01079 $this->debug("in parametersMatchWrapped: do not have parameter named $name"); 01080 } 01081 $elements++; 01082 } 01083 01084 $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); 01085 if ($matches == 0) { 01086 return false; 01087 } 01088 return true; 01089 } 01090 01091 // since there are no elements for the type, if the user passed no 01092 // parameters, the parameters match wrapped. 01093 $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); 01094 return count($parameters) == 0; 01095 } 01096 01112 function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { 01113 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); 01114 $this->appendDebug('parameters=' . $this->varDump($parameters)); 01115 01116 if ($direction != 'input' && $direction != 'output') { 01117 $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 01118 $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 01119 return false; 01120 } 01121 if (!$opData = $this->getOperationData($operation, $bindingType)) { 01122 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 01123 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 01124 return false; 01125 } 01126 $this->debug('in serializeRPCParameters: opData:'); 01127 $this->appendDebug($this->varDump($opData)); 01128 01129 // Get encoding style for output and set to current 01130 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01131 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 01132 $encodingStyle = $opData['output']['encodingStyle']; 01133 $enc_style = $encodingStyle; 01134 } 01135 01136 // set input params 01137 $xml = ''; 01138 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 01139 $parts = &$opData[$direction]['parts']; 01140 $part_count = sizeof($parts); 01141 $style = $opData['style']; 01142 $use = $opData[$direction]['use']; 01143 $this->debug("have $part_count part(s) to serialize using $style/$use"); 01144 if (is_array($parameters)) { 01145 $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 01146 $parameter_count = count($parameters); 01147 $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); 01148 // check for Microsoft-style wrapped parameters 01149 if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { 01150 $this->debug('check whether the caller has wrapped the parameters'); 01151 if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { 01152 // TODO: consider checking here for double-wrapping, when 01153 // service function wraps, then NuSOAP wraps again 01154 $this->debug("change simple array to associative with 'parameters' element"); 01155 $parameters['parameters'] = $parameters[0]; 01156 unset($parameters[0]); 01157 } 01158 if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { 01159 $this->debug('check whether caller\'s parameters match the wrapped ones'); 01160 if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { 01161 $this->debug('wrap the parameters for the caller'); 01162 $parameters = array('parameters' => $parameters); 01163 $parameter_count = 1; 01164 } 01165 } 01166 } 01167 foreach ($parts as $name => $type) { 01168 $this->debug("serializing part $name of type $type"); 01169 // Track encoding style 01170 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 01171 $encodingStyle = $opData[$direction]['encodingStyle']; 01172 $enc_style = $encodingStyle; 01173 } else { 01174 $enc_style = false; 01175 } 01176 // NOTE: add error handling here 01177 // if serializeType returns false, then catch global error and fault 01178 if ($parametersArrayType == 'arraySimple') { 01179 $p = array_shift($parameters); 01180 $this->debug('calling serializeType w/indexed param'); 01181 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 01182 } elseif (isset($parameters[$name])) { 01183 $this->debug('calling serializeType w/named param'); 01184 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 01185 } else { 01186 // TODO: only send nillable 01187 $this->debug('calling serializeType w/null param'); 01188 $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 01189 } 01190 } 01191 } else { 01192 $this->debug('no parameters passed.'); 01193 } 01194 } 01195 $this->debug("serializeRPCParameters returning: $xml"); 01196 return $xml; 01197 } 01198 01213 function serializeParameters($operation, $direction, $parameters) 01214 { 01215 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 01216 $this->appendDebug('parameters=' . $this->varDump($parameters)); 01217 01218 if ($direction != 'input' && $direction != 'output') { 01219 $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 01220 $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 01221 return false; 01222 } 01223 if (!$opData = $this->getOperationData($operation)) { 01224 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); 01225 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); 01226 return false; 01227 } 01228 $this->debug('opData:'); 01229 $this->appendDebug($this->varDump($opData)); 01230 01231 // Get encoding style for output and set to current 01232 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01233 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 01234 $encodingStyle = $opData['output']['encodingStyle']; 01235 $enc_style = $encodingStyle; 01236 } 01237 01238 // set input params 01239 $xml = ''; 01240 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 01241 01242 $use = $opData[$direction]['use']; 01243 $this->debug("use=$use"); 01244 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); 01245 if (is_array($parameters)) { 01246 $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 01247 $this->debug('have ' . $parametersArrayType . ' parameters'); 01248 foreach($opData[$direction]['parts'] as $name => $type) { 01249 $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); 01250 // Track encoding style 01251 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 01252 $encodingStyle = $opData[$direction]['encodingStyle']; 01253 $enc_style = $encodingStyle; 01254 } else { 01255 $enc_style = false; 01256 } 01257 // NOTE: add error handling here 01258 // if serializeType returns false, then catch global error and fault 01259 if ($parametersArrayType == 'arraySimple') { 01260 $p = array_shift($parameters); 01261 $this->debug('calling serializeType w/indexed param'); 01262 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 01263 } elseif (isset($parameters[$name])) { 01264 $this->debug('calling serializeType w/named param'); 01265 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 01266 } else { 01267 // TODO: only send nillable 01268 $this->debug('calling serializeType w/null param'); 01269 $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 01270 } 01271 } 01272 } else { 01273 $this->debug('no parameters passed.'); 01274 } 01275 } 01276 $this->debug("serializeParameters returning: $xml"); 01277 return $xml; 01278 } 01279 01292 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) 01293 { 01294 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); 01295 $this->appendDebug("value=" . $this->varDump($value)); 01296 if($use == 'encoded' && $encodingStyle) { 01297 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; 01298 } 01299 01300 // if a soapval has been supplied, let its type override the WSDL 01301 if (is_object($value) && get_class($value) == 'soapval') { 01302 if ($value->type_ns) { 01303 $type = $value->type_ns . ':' . $value->type; 01304 $forceType = true; 01305 $this->debug("in serializeType: soapval overrides type to $type"); 01306 } elseif ($value->type) { 01307 $type = $value->type; 01308 $forceType = true; 01309 $this->debug("in serializeType: soapval overrides type to $type"); 01310 } else { 01311 $forceType = false; 01312 $this->debug("in serializeType: soapval does not override type"); 01313 } 01314 $attrs = $value->attributes; 01315 $value = $value->value; 01316 $this->debug("in serializeType: soapval overrides value to $value"); 01317 if ($attrs) { 01318 if (!is_array($value)) { 01319 $value['!'] = $value; 01320 } 01321 foreach ($attrs as $n => $v) { 01322 $value['!' . $n] = $v; 01323 } 01324 $this->debug("in serializeType: soapval provides attributes"); 01325 } 01326 } else { 01327 $forceType = false; 01328 } 01329 01330 $xml = ''; 01331 if (strpos($type, ':')) { 01332 $uqType = substr($type, strrpos($type, ':') + 1); 01333 $ns = substr($type, 0, strrpos($type, ':')); 01334 $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); 01335 if ($this->getNamespaceFromPrefix($ns)) { 01336 $ns = $this->getNamespaceFromPrefix($ns); 01337 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); 01338 } 01339 01340 if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ 01341 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); 01342 if ($unqualified && $use == 'literal') { 01343 $elementNS = " xmlns=\"\""; 01344 } else { 01345 $elementNS = ''; 01346 } 01347 if (is_null($value)) { 01348 if ($use == 'literal') { 01349 // TODO: depends on minOccurs 01350 $xml = "<$name$elementNS/>"; 01351 } else { 01352 // TODO: depends on nillable, which should be checked before calling this method 01353 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 01354 } 01355 $this->debug("in serializeType: returning: $xml"); 01356 return $xml; 01357 } 01358 if ($uqType == 'Array') { 01359 // JBoss/Axis does this sometimes 01360 return $this->serialize_val($value, $name, false, false, false, false, $use); 01361 } 01362 if ($uqType == 'boolean') { 01363 if ((is_string($value) && $value == 'false') || (! $value)) { 01364 $value = 'false'; 01365 } else { 01366 $value = 'true'; 01367 } 01368 } 01369 if ($uqType == 'string' && gettype($value) == 'string') { 01370 $value = $this->expandEntities($value); 01371 } 01372 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { 01373 $value = sprintf("%.0lf", $value); 01374 } 01375 // it's a scalar 01376 // TODO: what about null/nil values? 01377 // check type isn't a custom type extending xmlschema namespace 01378 if (!$this->getTypeDef($uqType, $ns)) { 01379 if ($use == 'literal') { 01380 if ($forceType) { 01381 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 01382 } else { 01383 $xml = "<$name$elementNS>$value</$name>"; 01384 } 01385 } else { 01386 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 01387 } 01388 $this->debug("in serializeType: returning: $xml"); 01389 return $xml; 01390 } 01391 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); 01392 } else if ($ns == 'http://xml.apache.org/xml-soap') { 01393 $this->debug('in serializeType: appears to be Apache SOAP type'); 01394 if ($uqType == 'Map') { 01395 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 01396 if (! $tt_prefix) { 01397 $this->debug('in serializeType: Add namespace for Apache SOAP type'); 01398 $tt_prefix = 'ns' . rand(1000, 9999); 01399 $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; 01400 // force this to be added to usedNamespaces 01401 $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 01402 } 01403 $contents = ''; 01404 foreach($value as $k => $v) { 01405 $this->debug("serializing map element: key $k, value $v"); 01406 $contents .= '<item>'; 01407 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use); 01408 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use); 01409 $contents .= '</item>'; 01410 } 01411 if ($use == 'literal') { 01412 if ($forceType) { 01413 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>"; 01414 } else { 01415 $xml = "<$name>$contents</$name>"; 01416 } 01417 } else { 01418 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>"; 01419 } 01420 $this->debug("in serializeType: returning: $xml"); 01421 return $xml; 01422 } 01423 $this->debug('in serializeType: Apache SOAP type, but only support Map'); 01424 } 01425 } else { 01426 // TODO: should the type be compared to types in XSD, and the namespace 01427 // set to XSD if the type matches? 01428 $this->debug("in serializeType: No namespace for type $type"); 01429 $ns = ''; 01430 $uqType = $type; 01431 } 01432 if(!$typeDef = $this->getTypeDef($uqType, $ns)){ 01433 $this->setError("$type ($uqType) is not a supported type."); 01434 $this->debug("in serializeType: $type ($uqType) is not a supported type."); 01435 return false; 01436 } else { 01437 $this->debug("in serializeType: found typeDef"); 01438 $this->appendDebug('typeDef=' . $this->varDump($typeDef)); 01439 if (substr($uqType, -1) == '^') { 01440 $uqType = substr($uqType, 0, -1); 01441 } 01442 } 01443 if (!isset($typeDef['phpType'])) { 01444 $this->setError("$type ($uqType) has no phpType."); 01445 $this->debug("in serializeType: $type ($uqType) has no phpType."); 01446 return false; 01447 } 01448 $phpType = $typeDef['phpType']; 01449 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 01450 // if php type == struct, map value to the <all> element names 01451 if ($phpType == 'struct') { 01452 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { 01453 $elementName = $uqType; 01454 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01455 $elementNS = " xmlns=\"$ns\""; 01456 } else { 01457 $elementNS = " xmlns=\"\""; 01458 } 01459 } else { 01460 $elementName = $name; 01461 if ($unqualified) { 01462 $elementNS = " xmlns=\"\""; 01463 } else { 01464 $elementNS = ''; 01465 } 01466 } 01467 if (is_null($value)) { 01468 if ($use == 'literal') { 01469 // TODO: depends on minOccurs 01470 $xml = "<$elementName$elementNS/>"; 01471 } else { 01472 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 01473 } 01474 $this->debug("in serializeType: returning: $xml"); 01475 return $xml; 01476 } 01477 if (is_object($value)) { 01478 $value = get_object_vars($value); 01479 } 01480 if (is_array($value)) { 01481 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); 01482 if ($use == 'literal') { 01483 if ($forceType) { 01484 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; 01485 } else { 01486 $xml = "<$elementName$elementNS$elementAttrs>"; 01487 } 01488 } else { 01489 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; 01490 } 01491 01492 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); 01493 $xml .= "</$elementName>"; 01494 } else { 01495 $this->debug("in serializeType: phpType is struct, but value is not an array"); 01496 $this->setError("phpType is struct, but value is not an array: see debug output for details"); 01497 $xml = ''; 01498 } 01499 } elseif ($phpType == 'array') { 01500 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01501 $elementNS = " xmlns=\"$ns\""; 01502 } else { 01503 if ($unqualified) { 01504 $elementNS = " xmlns=\"\""; 01505 } else { 01506 $elementNS = ''; 01507 } 01508 } 01509 if (is_null($value)) { 01510 if ($use == 'literal') { 01511 // TODO: depends on minOccurs 01512 $xml = "<$name$elementNS/>"; 01513 } else { 01514 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . 01515 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 01516 ":Array\" " . 01517 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 01518 ':arrayType="' . 01519 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . 01520 ':' . 01521 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; 01522 } 01523 $this->debug("in serializeType: returning: $xml"); 01524 return $xml; 01525 } 01526 if (isset($typeDef['multidimensional'])) { 01527 $nv = array(); 01528 foreach($value as $v) { 01529 $cols = ',' . sizeof($v); 01530 $nv = array_merge($nv, $v); 01531 } 01532 $value = $nv; 01533 } else { 01534 $cols = ''; 01535 } 01536 if (is_array($value) && sizeof($value) >= 1) { 01537 $rows = sizeof($value); 01538 $contents = ''; 01539 foreach($value as $k => $v) { 01540 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); 01541 //if (strpos($typeDef['arrayType'], ':') ) { 01542 if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) { 01543 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); 01544 } else { 01545 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); 01546 } 01547 } 01548 } else { 01549 $rows = 0; 01550 $contents = null; 01551 } 01552 // TODO: for now, an empty value will be serialized as a zero element 01553 // array. Revisit this when coding the handling of null/nil values. 01554 if ($use == 'literal') { 01555 $xml = "<$name$elementNS>" 01556 .$contents 01557 ."</$name>"; 01558 } else { 01559 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. 01560 $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') 01561 .':arrayType="' 01562 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) 01563 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" 01564 .$contents 01565 ."</$name>"; 01566 } 01567 } elseif ($phpType == 'scalar') { 01568 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 01569 $elementNS = " xmlns=\"$ns\""; 01570 } else { 01571 if ($unqualified) { 01572 $elementNS = " xmlns=\"\""; 01573 } else { 01574 $elementNS = ''; 01575 } 01576 } 01577 if ($use == 'literal') { 01578 if ($forceType) { 01579 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 01580 } else { 01581 $xml = "<$name$elementNS>$value</$name>"; 01582 } 01583 } else { 01584 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 01585 } 01586 } 01587 $this->debug("in serializeType: returning: $xml"); 01588 return $xml; 01589 } 01590 01601 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { 01602 $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); 01603 $xml = ''; 01604 if (isset($typeDef['extensionBase'])) { 01605 $nsx = $this->getPrefix($typeDef['extensionBase']); 01606 $uqTypex = $this->getLocalPart($typeDef['extensionBase']); 01607 if ($this->getNamespaceFromPrefix($nsx)) { 01608 $nsx = $this->getNamespaceFromPrefix($nsx); 01609 } 01610 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { 01611 $this->debug("serialize attributes for extension base $nsx:$uqTypex"); 01612 $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); 01613 } else { 01614 $this->debug("extension base $nsx:$uqTypex is not a supported type"); 01615 } 01616 } 01617 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { 01618 $this->debug("serialize attributes for XML Schema type $ns:$uqType"); 01619 if (is_array($value)) { 01620 $xvalue = $value; 01621 } elseif (is_object($value)) { 01622 $xvalue = get_object_vars($value); 01623 } else { 01624 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 01625 $xvalue = array(); 01626 } 01627 foreach ($typeDef['attrs'] as $aName => $attrs) { 01628 if (isset($xvalue['!' . $aName])) { 01629 $xname = '!' . $aName; 01630 $this->debug("value provided for attribute $aName with key $xname"); 01631 } elseif (isset($xvalue[$aName])) { 01632 $xname = $aName; 01633 $this->debug("value provided for attribute $aName with key $xname"); 01634 } elseif (isset($attrs['default'])) { 01635 $xname = '!' . $aName; 01636 $xvalue[$xname] = $attrs['default']; 01637 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); 01638 } else { 01639 $xname = ''; 01640 $this->debug("no value provided for attribute $aName"); 01641 } 01642 if ($xname) { 01643 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; 01644 } 01645 } 01646 } else { 01647 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); 01648 } 01649 return $xml; 01650 } 01651 01664 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { 01665 $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); 01666 $xml = ''; 01667 if (isset($typeDef['extensionBase'])) { 01668 $nsx = $this->getPrefix($typeDef['extensionBase']); 01669 $uqTypex = $this->getLocalPart($typeDef['extensionBase']); 01670 if ($this->getNamespaceFromPrefix($nsx)) { 01671 $nsx = $this->getNamespaceFromPrefix($nsx); 01672 } 01673 if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { 01674 $this->debug("serialize elements for extension base $nsx:$uqTypex"); 01675 $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); 01676 } else { 01677 $this->debug("extension base $nsx:$uqTypex is not a supported type"); 01678 } 01679 } 01680 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 01681 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); 01682 if (is_array($value)) { 01683 $xvalue = $value; 01684 } elseif (is_object($value)) { 01685 $xvalue = get_object_vars($value); 01686 } else { 01687 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 01688 $xvalue = array(); 01689 } 01690 // toggle whether all elements are present - ideally should validate against schema 01691 if (count($typeDef['elements']) != count($xvalue)){ 01692 $optionals = true; 01693 } 01694 foreach ($typeDef['elements'] as $eName => $attrs) { 01695 if (!isset($xvalue[$eName])) { 01696 if (isset($attrs['default'])) { 01697 $xvalue[$eName] = $attrs['default']; 01698 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); 01699 } 01700 } 01701 // if user took advantage of a minOccurs=0, then only serialize named parameters 01702 if (isset($optionals) 01703 && (!isset($xvalue[$eName])) 01704 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') 01705 ){ 01706 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { 01707 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); 01708 } 01709 // do nothing 01710 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); 01711 } else { 01712 // get value 01713 if (isset($xvalue[$eName])) { 01714 $v = $xvalue[$eName]; 01715 } else { 01716 $v = null; 01717 } 01718 if (isset($attrs['form'])) { 01719 $unqualified = ($attrs['form'] == 'unqualified'); 01720 } else { 01721 $unqualified = false; 01722 } 01723 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { 01724 $vv = $v; 01725 foreach ($vv as $k => $v) { 01726 if (isset($attrs['type']) || isset($attrs['ref'])) { 01727 // serialize schema-defined type 01728 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 01729 } else { 01730 // serialize generic type (can this ever really happen?) 01731 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 01732 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 01733 } 01734 } 01735 } else { 01736 if (isset($attrs['type']) || isset($attrs['ref'])) { 01737 // serialize schema-defined type 01738 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 01739 } else { 01740 // serialize generic type (can this ever really happen?) 01741 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 01742 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 01743 } 01744 } 01745 } 01746 } 01747 } else { 01748 $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); 01749 } 01750 return $xml; 01751 } 01752 01767 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { 01768 if (count($elements) > 0) { 01769 $eElements = array(); 01770 foreach($elements as $n => $e){ 01771 // expand each element 01772 $ee = array(); 01773 foreach ($e as $k => $v) { 01774 $k = strpos($k,':') ? $this->expandQname($k) : $k; 01775 $v = strpos($v,':') ? $this->expandQname($v) : $v; 01776 $ee[$k] = $v; 01777 } 01778 $eElements[$n] = $ee; 01779 } 01780 $elements = $eElements; 01781 } 01782 01783 if (count($attrs) > 0) { 01784 foreach($attrs as $n => $a){ 01785 // expand each attribute 01786 foreach ($a as $k => $v) { 01787 $k = strpos($k,':') ? $this->expandQname($k) : $k; 01788 $v = strpos($v,':') ? $this->expandQname($v) : $v; 01789 $aa[$k] = $v; 01790 } 01791 $eAttrs[$n] = $aa; 01792 } 01793 $attrs = $eAttrs; 01794 } 01795 01796 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; 01797 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType; 01798 01799 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01800 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType); 01801 } 01802 01814 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 01815 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase; 01816 01817 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01818 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); 01819 } 01820 01828 function addElement($attrs) { 01829 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 01830 $this->schemas[$typens][0]->addElement($attrs); 01831 } 01832 01847 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){ 01848 if ($use == 'encoded' && $encodingStyle == '') { 01849 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 01850 } 01851 01852 if ($style == 'document') { 01853 $elements = array(); 01854 foreach ($in as $n => $t) { 01855 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); 01856 } 01857 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); 01858 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); 01859 $in = array('parameters' => 'tns:' . $name . '^'); 01860 01861 $elements = array(); 01862 foreach ($out as $n => $t) { 01863 $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); 01864 } 01865 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); 01866 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); 01867 $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); 01868 } 01869 01870 // get binding 01871 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = 01872 array( 01873 'name' => $name, 01874 'binding' => $this->serviceName . 'Binding', 01875 'endpoint' => $this->endpoint, 01876 'soapAction' => $soapaction, 01877 'style' => $style, 01878 'input' => array( 01879 'use' => $use, 01880 'namespace' => $namespace, 01881 'encodingStyle' => $encodingStyle, 01882 'message' => $name . 'Request', 01883 'parts' => $in), 01884 'output' => array( 01885 'use' => $use, 01886 'namespace' => $namespace, 01887 'encodingStyle' => $encodingStyle, 01888 'message' => $name . 'Response', 01889 'parts' => $out), 01890 'namespace' => $namespace, 01891 'transport' => 'http://schemas.xmlsoap.org/soap/http', 01892 'documentation' => $documentation); 01893 // add portTypes 01894 // add messages 01895 if($in) 01896 { 01897 foreach($in as $pName => $pType) 01898 { 01899 if(strpos($pType,':')) { 01900 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 01901 } 01902 $this->messages[$name.'Request'][$pName] = $pType; 01903 } 01904 } else { 01905 $this->messages[$name.'Request']= '0'; 01906 } 01907 if($out) 01908 { 01909 foreach($out as $pName => $pType) 01910 { 01911 if(strpos($pType,':')) { 01912 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 01913 } 01914 $this->messages[$name.'Response'][$pName] = $pType; 01915 } 01916 } else { 01917 $this->messages[$name.'Response']= '0'; 01918 } 01919 return true; 01920 } 01921 } 01922 01923 ?>
Copyright © 2003 - 2009 MyOOS [Shopsystem]. All rights reserved. MyOOS [Shopsystem] is Free Software released under the GNU/GPL License. Webmaster: info@r23.de (Impressum) |
|