wsdl

Parses a WSDL file, allows access to it's data, other utility methods.

Defined (1)

The class is defined in the following location(s).

/src/vendor/codecasts/nusoap-php7/lib/class.wsdl.php  
  1. class wsdl extends nusoap_base { 
  2. // URL or filename of the root of this WSDL 
  3. var $wsdl;  
  4. // define internal arrays of bindings, ports, operations, messages, etc. 
  5. var $schemas = array(); 
  6. var $currentSchema; 
  7. var $message = array(); 
  8. var $complexTypes = array(); 
  9. var $messages = array(); 
  10. var $currentMessage; 
  11. var $currentOperation; 
  12. var $portTypes = array(); 
  13. var $currentPortType; 
  14. var $bindings = array(); 
  15. var $currentBinding; 
  16. var $ports = array(); 
  17. var $currentPort; 
  18. var $opData = array(); 
  19. var $status = ''; 
  20. var $documentation = false; 
  21. var $endpoint = '';  
  22. // array of wsdl docs to import 
  23. var $import = array();  
  24. // parser vars 
  25. var $parser; 
  26. var $position = 0; 
  27. var $depth = 0; 
  28. var $depth_array = array(); 
  29. // for getting wsdl 
  30. var $proxyhost = ''; 
  31. var $proxyport = ''; 
  32. var $proxyusername = ''; 
  33. var $proxypassword = ''; 
  34. var $timeout = 0; 
  35. var $response_timeout = 30; 
  36. var $curl_options = array(); // User-specified cURL options 
  37. var $use_curl = false; // whether to always try to use cURL 
  38. // for HTTP authentication 
  39. var $username = ''; // Username for HTTP authentication 
  40. var $password = ''; // Password for HTTP authentication 
  41. var $authtype = ''; // Type of HTTP authentication 
  42. var $certRequest = array(); // Certificate for HTTP SSL authentication 
  43.  
  44. /** 
  45. * constructor 
  46. *  
  47. * @param string $wsdl WSDL document URL 
  48. * @param string $proxyhost 
  49. * @param string $proxyport 
  50. * @param string $proxyusername 
  51. * @param string $proxypassword 
  52. * @param integer $timeout set the connection timeout 
  53. * @param integer $response_timeout set the response timeout 
  54. * @param array $curl_options user-specified cURL options 
  55. * @param boolean $use_curl try to use cURL 
  56. * @access public  
  57. */ 
  58. function __construct($wsdl = '', $proxyhost=false, $proxyport=false, $proxyusername=false, $proxypassword=false, $timeout=0, $response_timeout=30, $curl_options=null, $use_curl=false) { 
  59. parent::__construct(); 
  60. $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout"); 
  61. $this->proxyhost = $proxyhost; 
  62. $this->proxyport = $proxyport; 
  63. $this->proxyusername = $proxyusername; 
  64. $this->proxypassword = $proxypassword; 
  65. $this->timeout = $timeout; 
  66. $this->response_timeout = $response_timeout; 
  67. if (is_array($curl_options)) 
  68. $this->curl_options = $curl_options; 
  69. $this->use_curl = $use_curl; 
  70. $this->fetchWSDL($wsdl); 
  71.  
  72. /** 
  73. * fetches the WSDL document and parses it 
  74. * @access public 
  75. */ 
  76. function fetchWSDL($wsdl) { 
  77. $this->debug("parse and process WSDL path=$wsdl"); 
  78. $this->wsdl = $wsdl; 
  79. // parse wsdl file 
  80. if ($this->wsdl != "") { 
  81. $this->parseWSDL($this->wsdl); 
  82. // imports 
  83. // TODO: handle imports more properly, grabbing them in-line and nesting them 
  84. $imported_urls = array(); 
  85. $imported = 1; 
  86. while ($imported > 0) { 
  87. $imported = 0; 
  88. // Schema imports 
  89. foreach ($this->schemas as $ns => $list) { 
  90. foreach ($list as $xs) { 
  91. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! 
  92. foreach ($xs->imports as $ns2 => $list2) { 
  93. for ($ii = 0; $ii < count($list2); $ii++) { 
  94. if (! $list2[$ii]['loaded']) { 
  95. $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true; 
  96. $url = $list2[$ii]['location']; 
  97. if ($url != '') { 
  98. $urlparts = parse_url($url); 
  99. if (!isset($urlparts['host'])) { 
  100. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . 
  101. substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) .$urlparts['path']; 
  102. if (! in_array($url, $imported_urls)) { 
  103. $this->parseWSDL($url); 
  104. $imported++; 
  105. $imported_urls[] = $url; 
  106. } else { 
  107. $this->debug("Unexpected scenario: empty URL for unloaded import"); 
  108. }  
  109. // WSDL imports 
  110. $wsdlparts = parse_url($this->wsdl); // this is bogusly simple! 
  111. foreach ($this->import as $ns => $list) { 
  112. for ($ii = 0; $ii < count($list); $ii++) { 
  113. if (! $list[$ii]['loaded']) { 
  114. $this->import[$ns][$ii]['loaded'] = true; 
  115. $url = $list[$ii]['location']; 
  116. if ($url != '') { 
  117. $urlparts = parse_url($url); 
  118. if (!isset($urlparts['host'])) { 
  119. $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . 
  120. substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) .$urlparts['path']; 
  121. if (! in_array($url, $imported_urls)) { 
  122. $this->parseWSDL($url); 
  123. $imported++; 
  124. $imported_urls[] = $url; 
  125. } else { 
  126. $this->debug("Unexpected scenario: empty URL for unloaded import"); 
  127. }  
  128. // add new data to operation data 
  129. foreach($this->bindings as $binding => $bindingData) { 
  130. if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { 
  131. foreach($bindingData['operations'] as $operation => $data) { 
  132. $this->debug('post-parse data gathering for ' . $operation); 
  133. $this->bindings[$binding]['operations'][$operation]['input'] =  
  134. isset($this->bindings[$binding]['operations'][$operation]['input']) ?  
  135. array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) : 
  136. $this->portTypes[ $bindingData['portType'] ][$operation]['input']; 
  137. $this->bindings[$binding]['operations'][$operation]['output'] =  
  138. isset($this->bindings[$binding]['operations'][$operation]['output']) ? 
  139. array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) : 
  140. $this->portTypes[ $bindingData['portType'] ][$operation]['output']; 
  141. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])) { 
  142. $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ]; 
  143. if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])) { 
  144. $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ]; 
  145. // Set operation style if necessary, but do not override one already provided 
  146. if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) { 
  147. $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style']; 
  148. $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; 
  149. $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : ''; 
  150. $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : ''; 
  151. }  
  152. }  
  153.  
  154. /** 
  155. * parses the wsdl document 
  156. *  
  157. * @param string $wsdl path or URL 
  158. * @access private  
  159. */ 
  160. function parseWSDL($wsdl = '') { 
  161. $this->debug("parse WSDL at path=$wsdl"); 
  162.  
  163. if ($wsdl == '') { 
  164. $this->debug('no wsdl passed to parseWSDL()!!'); 
  165. $this->setError('no wsdl passed to parseWSDL()!!'); 
  166. return false; 
  167.  
  168. // parse $wsdl for url format 
  169. $wsdl_props = parse_url($wsdl); 
  170.  
  171. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) { 
  172. $this->debug('getting WSDL http(s) URL ' . $wsdl); 
  173. // get wsdl 
  174. $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl); 
  175. $tr->request_method = 'GET'; 
  176. $tr->useSOAPAction = false; 
  177. if($this->proxyhost && $this->proxyport) { 
  178. $tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword); 
  179. if ($this->authtype != '') { 
  180. $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest); 
  181. $tr->setEncoding('gzip, deflate'); 
  182. $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); 
  183. //$this->debug("WSDL request\n" . $tr->outgoing_payload); 
  184. //$this->debug("WSDL response\n" . $tr->incoming_payload); 
  185. $this->appendDebug($tr->getDebug()); 
  186. // catch errors 
  187. if($err = $tr->getError() ) { 
  188. $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err; 
  189. $this->debug($errstr); 
  190. $this->setError($errstr); 
  191. unset($tr); 
  192. return false; 
  193. unset($tr); 
  194. $this->debug("got WSDL URL"); 
  195. } else { 
  196. // $wsdl is not http(s), so treat it as a file URL or plain file path 
  197. if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) { 
  198. $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path']; 
  199. } else { 
  200. $path = $wsdl; 
  201. $this->debug('getting WSDL file ' . $path); 
  202. if ($fp = @fopen($path, 'r')) { 
  203. $wsdl_string = ''; 
  204. while ($data = fread($fp, 32768)) { 
  205. $wsdl_string .= $data; 
  206. }  
  207. fclose($fp); 
  208. } else { 
  209. $errstr = "Bad path to WSDL file $path"; 
  210. $this->debug($errstr); 
  211. $this->setError($errstr); 
  212. return false; 
  213. }  
  214. $this->debug('Parse WSDL'); 
  215. // end new code added 
  216. // Create an XML parser. 
  217. $this->parser = xml_parser_create();  
  218. // Set the options for parsing the XML data. 
  219. // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
  220. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);  
  221. // Set the object for the parser. 
  222. xml_set_object($this->parser, $this);  
  223. // Set the element handlers for the parser. 
  224. xml_set_element_handler($this->parser, 'start_element', 'end_element'); 
  225. xml_set_character_data_handler($this->parser, 'character_data'); 
  226. // Parse the XML file. 
  227. if (!xml_parse($this->parser, $wsdl_string, true)) { 
  228. // Display an error message. 
  229. $errstr = sprintf( 
  230. 'XML error parsing WSDL from %s on line %d: %s',  
  231. $wsdl,  
  232. xml_get_current_line_number($this->parser),  
  233. xml_error_string(xml_get_error_code($this->parser)) 
  234. ); 
  235. $this->debug($errstr); 
  236. $this->debug("XML payload:\n" . $wsdl_string); 
  237. $this->setError($errstr); 
  238. return false; 
  239. }  
  240. // free the parser 
  241. xml_parser_free($this->parser); 
  242. unset($this->parser); 
  243. $this->debug('Parsing WSDL done'); 
  244. // catch wsdl parse errors 
  245. if($this->getError()) { 
  246. return false; 
  247. return true; 
  248. }  
  249.  
  250. /** 
  251. * start-element handler 
  252. *  
  253. * @param string $parser XML parser object 
  254. * @param string $name element name 
  255. * @param string $attrs associative array of attributes 
  256. * @access private  
  257. */ 
  258. function start_element($parser, $name, $attrs) 
  259. if ($this->status == 'schema') { 
  260. $this->currentSchema->schemaStartElement($parser, $name, $attrs); 
  261. $this->appendDebug($this->currentSchema->getDebug()); 
  262. $this->currentSchema->clearDebug(); 
  263. } elseif (preg_match('/schema$/', $name)) { 
  264. $this->debug('Parsing WSDL schema'); 
  265. // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); 
  266. $this->status = 'schema'; 
  267. $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces); 
  268. $this->currentSchema->schemaStartElement($parser, $name, $attrs); 
  269. $this->appendDebug($this->currentSchema->getDebug()); 
  270. $this->currentSchema->clearDebug(); 
  271. } else { 
  272. // position in the total number of elements, starting from 0 
  273. $pos = $this->position++; 
  274. $depth = $this->depth++;  
  275. // set self as current value for this depth 
  276. $this->depth_array[$depth] = $pos; 
  277. $this->message[$pos] = array('cdata' => '');  
  278. // process attributes 
  279. if (count($attrs) > 0) { 
  280. // register namespace declarations 
  281. foreach($attrs as $k => $v) { 
  282. if (preg_match('/^xmlns/', $k)) { 
  283. if ($ns_prefix = substr(strrchr($k, ':'), 1)) { 
  284. $this->namespaces[$ns_prefix] = $v; 
  285. } else { 
  286. $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v; 
  287. }  
  288. if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') { 
  289. $this->XMLSchemaVersion = $v; 
  290. $this->namespaces['xsi'] = $v . '-instance'; 
  291. }  
  292. // expand each attribute prefix to its namespace 
  293. foreach($attrs as $k => $v) { 
  294. $k = strpos($k, ':') ? $this->expandQname($k) : $k; 
  295. if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') { 
  296. $v = strpos($v, ':') ? $this->expandQname($v) : $v; 
  297. }  
  298. $eAttrs[$k] = $v; 
  299. }  
  300. $attrs = $eAttrs; 
  301. } else { 
  302. $attrs = array(); 
  303. }  
  304. // get element prefix, namespace and name 
  305. if (preg_match('/:/', $name)) { 
  306. // get ns prefix 
  307. $prefix = substr($name, 0, strpos($name, ':'));  
  308. // get ns 
  309. $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';  
  310. // get unqualified name 
  311. $name = substr(strstr($name, ':'), 1); 
  312. }  
  313. // process attributes, expanding any prefixes to namespaces 
  314. // find status, register data 
  315. switch ($this->status) { 
  316. case 'message': 
  317. if ($name == 'part') { 
  318. if (isset($attrs['type'])) { 
  319. $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(', ', $attrs)); 
  320. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; 
  321. }  
  322. if (isset($attrs['element'])) { 
  323. $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(', ', $attrs)); 
  324. $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^'; 
  325. }  
  326. }  
  327. break; 
  328. case 'portType': 
  329. switch ($name) { 
  330. case 'operation': 
  331. $this->currentPortOperation = $attrs['name']; 
  332. $this->debug("portType $this->currentPortType operation: $this->currentPortOperation"); 
  333. if (isset($attrs['parameterOrder'])) { 
  334. $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; 
  335. }  
  336. break; 
  337. case 'documentation': 
  338. $this->documentation = true; 
  339. break;  
  340. // merge input/output data 
  341. default: 
  342. $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : ''; 
  343. $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m; 
  344. break; 
  345. }  
  346. break; 
  347. case 'binding': 
  348. switch ($name) { 
  349. case 'binding':  
  350. // get ns prefix 
  351. if (isset($attrs['style'])) { 
  352. $this->bindings[$this->currentBinding]['prefix'] = $prefix; 
  353. }  
  354. $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs); 
  355. break; 
  356. case 'header': 
  357. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; 
  358. break; 
  359. case 'operation': 
  360. if (isset($attrs['soapAction'])) { 
  361. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; 
  362. }  
  363. if (isset($attrs['style'])) { 
  364. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style']; 
  365. }  
  366. if (isset($attrs['name'])) { 
  367. $this->currentOperation = $attrs['name']; 
  368. $this->debug("current binding operation: $this->currentOperation"); 
  369. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name']; 
  370. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding; 
  371. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : ''; 
  372. }  
  373. break; 
  374. case 'input': 
  375. $this->opStatus = 'input'; 
  376. break; 
  377. case 'output': 
  378. $this->opStatus = 'output'; 
  379. break; 
  380. case 'body': 
  381. if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) { 
  382. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs); 
  383. } else { 
  384. $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; 
  385. }  
  386. break; 
  387. }  
  388. break; 
  389. case 'service': 
  390. switch ($name) { 
  391. case 'port': 
  392. $this->currentPort = $attrs['name']; 
  393. $this->debug('current port: ' . $this->currentPort); 
  394. $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']); 
  395.  
  396. break; 
  397. case 'address': 
  398. $this->ports[$this->currentPort]['location'] = $attrs['location']; 
  399. $this->ports[$this->currentPort]['bindingType'] = $namespace; 
  400. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace; 
  401. $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location']; 
  402. break; 
  403. }  
  404. break; 
  405. }  
  406. // set status 
  407. switch ($name) { 
  408. case 'import': 
  409. if (isset($attrs['location'])) { 
  410. $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false); 
  411. $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')'); 
  412. } else { 
  413. $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true); 
  414. if (! $this->getPrefixFromNamespace($attrs['namespace'])) { 
  415. $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace']; 
  416. $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')'); 
  417. break; 
  418. //wait for schema 
  419. //case 'types': 
  420. // $this->status = 'schema'; 
  421. // break; 
  422. case 'message': 
  423. $this->status = 'message'; 
  424. $this->messages[$attrs['name']] = array(); 
  425. $this->currentMessage = $attrs['name']; 
  426. break; 
  427. case 'portType': 
  428. $this->status = 'portType'; 
  429. $this->portTypes[$attrs['name']] = array(); 
  430. $this->currentPortType = $attrs['name']; 
  431. break; 
  432. case "binding": 
  433. if (isset($attrs['name'])) { 
  434. // get binding name 
  435. if (strpos($attrs['name'], ':')) { 
  436. $this->currentBinding = $this->getLocalPart($attrs['name']); 
  437. } else { 
  438. $this->currentBinding = $attrs['name']; 
  439. }  
  440. $this->status = 'binding'; 
  441. $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']); 
  442. $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']); 
  443. }  
  444. break; 
  445. case 'service': 
  446. $this->serviceName = $attrs['name']; 
  447. $this->status = 'service'; 
  448. $this->debug('current service: ' . $this->serviceName); 
  449. break; 
  450. case 'definitions': 
  451. foreach ($attrs as $name => $value) { 
  452. $this->wsdl_info[$name] = $value; 
  453. }  
  454. break; 
  455. }  
  456. }  
  457. }  
  458.  
  459. /** 
  460. * end-element handler 
  461. *  
  462. * @param string $parser XML parser object 
  463. * @param string $name element name 
  464. * @access private  
  465. */ 
  466. function end_element($parser, $name) {  
  467. // unset schema status 
  468. if (/**preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) { 
  469. $this->status = ""; 
  470. $this->appendDebug($this->currentSchema->getDebug()); 
  471. $this->currentSchema->clearDebug(); 
  472. $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema; 
  473. $this->debug('Parsing WSDL schema done'); 
  474. }  
  475. if ($this->status == 'schema') { 
  476. $this->currentSchema->schemaEndElement($parser, $name); 
  477. } else { 
  478. // bring depth down a notch 
  479. $this->depth--; 
  480. }  
  481. // end documentation 
  482. if ($this->documentation) { 
  483. //TODO: track the node to which documentation should be assigned; it can be a part, message, etc. 
  484. //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation; 
  485. $this->documentation = false; 
  486. }  
  487. }  
  488.  
  489. /** 
  490. * element content handler 
  491. *  
  492. * @param string $parser XML parser object 
  493. * @param string $data element content 
  494. * @access private  
  495. */ 
  496. function character_data($parser, $data) 
  497. $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0; 
  498. if (isset($this->message[$pos]['cdata'])) { 
  499. $this->message[$pos]['cdata'] .= $data; 
  500. }  
  501. if ($this->documentation) { 
  502. $this->documentation .= $data; 
  503. }  
  504. }  
  505.  
  506. /** 
  507. * if authenticating, set user credentials here 
  508. * @param string $username 
  509. * @param string $password 
  510. * @param string $authtype (basic|digest|certificate|ntlm) 
  511. * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs) 
  512. * @access public 
  513. */ 
  514. function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { 
  515. $this->debug("setCredentials username=$username authtype=$authtype certRequest="); 
  516. $this->appendDebug($this->varDump($certRequest)); 
  517. $this->username = $username; 
  518. $this->password = $password; 
  519. $this->authtype = $authtype; 
  520. $this->certRequest = $certRequest; 
  521.  
  522. function getBindingData($binding) 
  523. if (is_array($this->bindings[$binding])) { 
  524. return $this->bindings[$binding]; 
  525. }  
  526.  
  527. /** 
  528. * returns an assoc array of operation names => operation data 
  529. *  
  530. * @param string $portName WSDL port name 
  531. * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported) 
  532. * @return array  
  533. * @access public  
  534. */ 
  535. function getOperations($portName = '', $bindingType = 'soap') { 
  536. $ops = array(); 
  537. if ($bindingType == 'soap') { 
  538. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 
  539. } elseif ($bindingType == 'soap12') { 
  540. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 
  541. } else { 
  542. $this->debug("getOperations bindingType $bindingType may not be supported"); 
  543. $this->debug("getOperations for port '$portName' bindingType $bindingType"); 
  544. // loop thru ports 
  545. foreach($this->ports as $port => $portData) { 
  546. $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']); 
  547. if ($portName == '' || $port == $portName) { 
  548. // binding type of port matches parameter 
  549. if ($portData['bindingType'] == $bindingType) { 
  550. $this->debug("getOperations found port $port bindingType $bindingType"); 
  551. //$this->debug("port data: " . $this->varDump($portData)); 
  552. //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ])); 
  553. // merge bindings 
  554. if (isset($this->bindings[ $portData['binding'] ]['operations'])) { 
  555. $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']); 
  556. if (count($ops) == 0) { 
  557. $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType"); 
  558. return $ops; 
  559. }  
  560.  
  561. /** 
  562. * returns an associative array of data necessary for calling an operation 
  563. *  
  564. * @param string $operation name of operation 
  565. * @param string $bindingType type of binding eg: soap, soap12 
  566. * @return array  
  567. * @access public  
  568. */ 
  569. function getOperationData($operation, $bindingType = 'soap') 
  570. if ($bindingType == 'soap') { 
  571. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 
  572. } elseif ($bindingType == 'soap12') { 
  573. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 
  574. // loop thru ports 
  575. foreach($this->ports as $port => $portData) { 
  576. // binding type of port matches parameter 
  577. if ($portData['bindingType'] == $bindingType) { 
  578. // get binding 
  579. //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 
  580. foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) { 
  581. // note that we could/should also check the namespace here 
  582. if ($operation == $bOperation) { 
  583. $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation]; 
  584. return $opData; 
  585. }  
  586. }  
  587. }  
  588.  
  589. /** 
  590. * returns an associative array of data necessary for calling an operation 
  591. *  
  592. * @param string $soapAction soapAction for operation 
  593. * @param string $bindingType type of binding eg: soap, soap12 
  594. * @return array  
  595. * @access public  
  596. */ 
  597. function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { 
  598. if ($bindingType == 'soap') { 
  599. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; 
  600. } elseif ($bindingType == 'soap12') { 
  601. $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/'; 
  602. // loop thru ports 
  603. foreach($this->ports as $port => $portData) { 
  604. // binding type of port matches parameter 
  605. if ($portData['bindingType'] == $bindingType) { 
  606. // loop through operations for the binding 
  607. foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) { 
  608. if ($opData['soapAction'] == $soapAction) { 
  609. return $opData; 
  610. }  
  611. }  
  612. }  
  613.  
  614. /** 
  615. * returns an array of information about a given type 
  616. * returns false if no type exists by the given name 
  617. * typeDef = array( 
  618. * 'elements' => array(), // refs to elements array 
  619. * 'restrictionBase' => '',  
  620. * 'phpType' => '',  
  621. * 'order' => '(sequence|all)',  
  622. * 'attrs' => array() // refs to attributes array 
  623. * ) 
  624. * @param string $type the type 
  625. * @param string $ns namespace (not prefix) of the type 
  626. * @return mixed 
  627. * @access public 
  628. * @see nusoap_xmlschema 
  629. */ 
  630. function getTypeDef($type, $ns) { 
  631. $this->debug("in getTypeDef: type=$type, ns=$ns"); 
  632. if ((! $ns) && isset($this->namespaces['tns'])) { 
  633. $ns = $this->namespaces['tns']; 
  634. $this->debug("in getTypeDef: type namespace forced to $ns"); 
  635. if (!isset($this->schemas[$ns])) { 
  636. foreach ($this->schemas as $ns0 => $schema0) { 
  637. if (strcasecmp($ns, $ns0) == 0) { 
  638. $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0"); 
  639. $ns = $ns0; 
  640. break; 
  641. if (isset($this->schemas[$ns])) { 
  642. $this->debug("in getTypeDef: have schema for namespace $ns"); 
  643. for ($i = 0; $i < count($this->schemas[$ns]); $i++) { 
  644. $xs = &$this->schemas[$ns][$i]; 
  645. $t = $xs->getTypeDef($type); 
  646. $this->appendDebug($xs->getDebug()); 
  647. $xs->clearDebug(); 
  648. if ($t) { 
  649. $this->debug("in getTypeDef: found type $type"); 
  650. if (!isset($t['phpType'])) { 
  651. // get info for type to tack onto the element 
  652. $uqType = substr($t['type'], strrpos($t['type'], ':') + 1); 
  653. $ns = substr($t['type'], 0, strrpos($t['type'], ':')); 
  654. $etype = $this->getTypeDef($uqType, $ns); 
  655. if ($etype) { 
  656. $this->debug("found type for [element] $type:"); 
  657. $this->debug($this->varDump($etype)); 
  658. if (isset($etype['phpType'])) { 
  659. $t['phpType'] = $etype['phpType']; 
  660. if (isset($etype['elements'])) { 
  661. $t['elements'] = $etype['elements']; 
  662. if (isset($etype['attrs'])) { 
  663. $t['attrs'] = $etype['attrs']; 
  664. } else { 
  665. $this->debug("did not find type for [element] $type"); 
  666. return $t; 
  667. $this->debug("in getTypeDef: did not find type $type"); 
  668. } else { 
  669. $this->debug("in getTypeDef: do not have schema for namespace $ns"); 
  670. return false; 
  671.  
  672. /** 
  673. * prints html description of services 
  674. * @access private 
  675. */ 
  676. function webDescription() { 
  677. global $HTTP_SERVER_VARS; 
  678.  
  679. if (isset($_SERVER)) { 
  680. $PHP_SELF = $_SERVER['PHP_SELF']; 
  681. } elseif (isset($HTTP_SERVER_VARS)) { 
  682. $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; 
  683. } else { 
  684. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); 
  685.  
  686. $b = ' 
  687. <html><head><title>NuSOAP: '.$this->serviceName.'</title> 
  688. <style type="text/css"> 
  689. body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; } 
  690. p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; } 
  691. pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;} 
  692. ul { margin-top: 10px; margin-left: 20px; } 
  693. li { list-style-type: none; margin-top: 10px; color: #000000; } 
  694. .content{ 
  695. margin-left: 0px; padding-bottom: 2em; } 
  696. .nav { 
  697. padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em; 
  698. margin-top: 10px; margin-left: 0px; color: #000000; 
  699. background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; } 
  700. .title { 
  701. font-family: arial; font-size: 26px; color: #ffffff; 
  702. background-color: #999999; width: 100%; 
  703. margin-left: 0px; margin-right: 0px; 
  704. padding-top: 10px; padding-bottom: 10px;} 
  705. .hidden { 
  706. position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px; 
  707. font-family: arial; overflow: hidden; width: 600; 
  708. padding: 20px; font-size: 10px; background-color: #999999; 
  709. layer-background-color:#FFFFFF; } 
  710. a, a:active { color: charcoal; font-weight: bold; } 
  711. a:visited { color: #666666; font-weight: bold; } 
  712. a:hover { color: cc3300; font-weight: bold; } 
  713. </style> 
  714. <script language="JavaScript" type="text/javascript"> 
  715. <!-- 
  716. // POP-UP CAPTIONS... 
  717. function lib_bwcheck() { //Browsercheck (needed) 
  718. this.ver=navigator.appVersion 
  719. this.agent=navigator.userAgent 
  720. this.dom=document.getElementById?1:0 
  721. this.opera5=this.agent.indexOf("Opera 5")>-1 
  722. this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0; 
  723. this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0; 
  724. this.ie4=(document.all && !this.dom && !this.opera5)?1:0; 
  725. this.ie=this.ie4||this.ie5||this.ie6 
  726. this.mac=this.agent.indexOf("Mac")>-1 
  727. this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0; 
  728. this.ns4=(document.layers && !this.dom)?1:0; 
  729. this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5) 
  730. return this 
  731. var bw = new lib_bwcheck() 
  732. //Makes crossbrowser object. 
  733. function makeObj(obj) { 
  734. this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0; 
  735. if(!this.evnt) return false 
  736. this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0; 
  737. this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0; 
  738. this.writeIt=b_writeIt; 
  739. return this 
  740. // A unit of measure that will be added when setting the position of a layer. 
  741. //var px = bw.ns4||window.opera?"":"px"; 
  742. function b_writeIt(text) { 
  743. if (bw.ns4) {this.wref.write(text);this.wref.close()} 
  744. else this.wref.innerHTML = text 
  745. //Shows the messages 
  746. var oDesc; 
  747. function popup(divid) { 
  748. if(oDesc = new makeObj(divid)) { 
  749. oDesc.css.visibility = "visible" 
  750. function popout() { // Hides message 
  751. if(oDesc) oDesc.css.visibility = "hidden" 
  752. //--> 
  753. </script> 
  754. </head> 
  755. <body> 
  756. <div class=content> 
  757. <br><br> 
  758. <div class=title>'.$this->serviceName.'</div> 
  759. <div class=nav> 
  760. <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service. 
  761. Click on an operation name to view it's details.</p> 
  762. <ul>'; 
  763. foreach($this->getOperations() as $op => $data) { 
  764. $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>"; 
  765. // create hidden div 
  766. $b .= "<div id='$op' class='hidden'> 
  767. <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>"; 
  768. foreach($data as $donnie => $marie) { // loop through opdata 
  769. if($donnie == 'input' || $donnie == 'output') { // show input/output data 
  770. $b .= "<font color='white'>".ucfirst($donnie).':</font><br>'; 
  771. foreach($marie as $captain => $tenille) { // loop through data 
  772. if($captain == 'parts') { // loop thru parts 
  773. $b .= "  $captain:<br>"; 
  774. //if(is_array($tenille)) { 
  775. foreach($tenille as $joanie => $chachi) { 
  776. $b .= "    $joanie: $chachi<br>"; 
  777. //} 
  778. } else { 
  779. $b .= "  $captain: $tenille<br>"; 
  780. } else { 
  781. $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>"; 
  782. $b .= '</div>'; 
  783. $b .= ' 
  784. <ul> 
  785. </div> 
  786. </div></body></html>'; 
  787. return $b; 
  788.  
  789. /** 
  790. * serialize the parsed wsdl 
  791. * @param mixed $debug whether to put debug=1 in endpoint URL 
  792. * @return string serialization of WSDL 
  793. * @access public  
  794. */ 
  795. function serialize($debug = 0) 
  796. $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>'; 
  797. $xml .= "\n<definitions"; 
  798. foreach($this->namespaces as $k => $v) { 
  799. $xml .= " xmlns:$k=\"$v\""; 
  800. }  
  801. // 10.9.02 - add poulter fix for wsdl and tns declarations 
  802. if (isset($this->namespaces['wsdl'])) { 
  803. $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\""; 
  804. }  
  805. if (isset($this->namespaces['tns'])) { 
  806. $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\""; 
  807. }  
  808. $xml .= '>';  
  809. // imports 
  810. if (sizeof($this->import) > 0) { 
  811. foreach($this->import as $ns => $list) { 
  812. foreach ($list as $ii) { 
  813. if ($ii['location'] != '') { 
  814. $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />'; 
  815. } else { 
  816. $xml .= '<import namespace="' . $ns . '" />'; 
  817. }  
  818. }  
  819. // types 
  820. if (count($this->schemas)>=1) { 
  821. $xml .= "\n<types>\n"; 
  822. foreach ($this->schemas as $ns => $list) { 
  823. foreach ($list as $xs) { 
  824. $xml .= $xs->serializeSchema(); 
  825. $xml .= '</types>'; 
  826. }  
  827. // messages 
  828. if (count($this->messages) >= 1) { 
  829. foreach($this->messages as $msgName => $msgParts) { 
  830. $xml .= "\n<message name=\"" . $msgName . '">'; 
  831. if(is_array($msgParts)) { 
  832. foreach($msgParts as $partName => $partType) { 
  833. // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>'; 
  834. if (strpos($partType, ':')) { 
  835. $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType)); 
  836. } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) { 
  837. // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>'; 
  838. $typePrefix = 'xsd'; 
  839. } else { 
  840. foreach($this->typemap as $ns => $types) { 
  841. if (isset($types[$partType])) { 
  842. $typePrefix = $this->getPrefixFromNamespace($ns); 
  843. }  
  844. }  
  845. if (!isset($typePrefix)) { 
  846. die("$partType has no namespace!"); 
  847. }  
  848. $ns = $this->getNamespaceFromPrefix($typePrefix); 
  849. $localPart = $this->getLocalPart($partType); 
  850. $typeDef = $this->getTypeDef($localPart, $ns); 
  851. if ($typeDef['typeClass'] == 'element') { 
  852. $elementortype = 'element'; 
  853. if (substr($localPart, -1) == '^') { 
  854. $localPart = substr($localPart, 0, -1); 
  855. } else { 
  856. $elementortype = 'type'; 
  857. $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />'; 
  858. $xml .= '</message>'; 
  859. }  
  860. }  
  861. // bindings & porttypes 
  862. if (count($this->bindings) >= 1) { 
  863. $binding_xml = ''; 
  864. $portType_xml = ''; 
  865. foreach($this->bindings as $bindingName => $attrs) { 
  866. $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">'; 
  867. $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>'; 
  868. $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">'; 
  869. foreach($attrs['operations'] as $opName => $opParts) { 
  870. $binding_xml .= "\n" . ' <operation name="' . $opName . '">'; 
  871. $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>'; 
  872. if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { 
  873. $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; 
  874. } else { 
  875. $enc_style = ''; 
  876. $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>'; 
  877. if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') { 
  878. $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; 
  879. } else { 
  880. $enc_style = ''; 
  881. $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>'; 
  882. $binding_xml .= "\n" . ' </operation>'; 
  883. $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"'; 
  884. if (isset($opParts['parameterOrder'])) { 
  885. $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"'; 
  886. }  
  887. $portType_xml .= '>'; 
  888. if(isset($opParts['documentation']) && $opParts['documentation'] != '') { 
  889. $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>'; 
  890. $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>'; 
  891. $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>'; 
  892. $portType_xml .= "\n" . ' </operation>'; 
  893. }  
  894. $portType_xml .= "\n" . '</portType>'; 
  895. $binding_xml .= "\n" . '</binding>'; 
  896. }  
  897. $xml .= $portType_xml . $binding_xml; 
  898. }  
  899. // services 
  900. $xml .= "\n<service name=\"" . $this->serviceName . '">'; 
  901. if (count($this->ports) >= 1) { 
  902. foreach($this->ports as $pName => $attrs) { 
  903. $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">'; 
  904. $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>'; 
  905. $xml .= "\n" . ' </port>'; 
  906. }  
  907. }  
  908. $xml .= "\n" . '</service>'; 
  909. return $xml . "\n</definitions>"; 
  910. }  
  911.  
  912. /** 
  913. * determine whether a set of parameters are unwrapped 
  914. * when they are expect to be wrapped, Microsoft-style. 
  915. * @param string $type the type (element name) of the wrapper 
  916. * @param array $parameters the parameter values for the SOAP call 
  917. * @return boolean whether they parameters are unwrapped (and should be wrapped) 
  918. * @access private 
  919. */ 
  920. function parametersMatchWrapped($type, &$parameters) { 
  921. $this->debug("in parametersMatchWrapped type=$type, parameters="); 
  922. $this->appendDebug($this->varDump($parameters)); 
  923.  
  924. // split type into namespace:unqualified-type 
  925. if (strpos($type, ':')) { 
  926. $uqType = substr($type, strrpos($type, ':') + 1); 
  927. $ns = substr($type, 0, strrpos($type, ':')); 
  928. $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns"); 
  929. if ($this->getNamespaceFromPrefix($ns)) { 
  930. $ns = $this->getNamespaceFromPrefix($ns); 
  931. $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns"); 
  932. } else { 
  933. // TODO: should the type be compared to types in XSD, and the namespace 
  934. // set to XSD if the type matches? 
  935. $this->debug("in parametersMatchWrapped: No namespace for type $type"); 
  936. $ns = ''; 
  937. $uqType = $type; 
  938.  
  939. // get the type information 
  940. if (!$typeDef = $this->getTypeDef($uqType, $ns)) { 
  941. $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type."); 
  942. return false; 
  943. $this->debug("in parametersMatchWrapped: found typeDef="); 
  944. $this->appendDebug($this->varDump($typeDef)); 
  945. if (substr($uqType, -1) == '^') { 
  946. $uqType = substr($uqType, 0, -1); 
  947. $phpType = $typeDef['phpType']; 
  948. $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''); 
  949. $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType"); 
  950.  
  951. // we expect a complexType or element of complexType 
  952. if ($phpType != 'struct') { 
  953. $this->debug("in parametersMatchWrapped: not a struct"); 
  954. return false; 
  955.  
  956. // see whether the parameter names match the elements 
  957. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 
  958. $elements = 0; 
  959. $matches = 0; 
  960. foreach ($typeDef['elements'] as $name => $attrs) { 
  961. if (isset($parameters[$name])) { 
  962. $this->debug("in parametersMatchWrapped: have parameter named $name"); 
  963. $matches++; 
  964. } else { 
  965. $this->debug("in parametersMatchWrapped: do not have parameter named $name"); 
  966. $elements++; 
  967.  
  968. $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names"); 
  969. if ($matches == 0) { 
  970. return false; 
  971. return true; 
  972.  
  973. // since there are no elements for the type, if the user passed no 
  974. // parameters, the parameters match wrapped. 
  975. $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType"); 
  976. return count($parameters) == 0; 
  977.  
  978. /** 
  979. * serialize PHP values according to a WSDL message definition 
  980. * contrary to the method name, this is not limited to RPC 
  981. * TODO 
  982. * - multi-ref serialization 
  983. * - validate PHP values against type definitions, return errors if invalid 
  984. *  
  985. * @param string $operation operation name 
  986. * @param string $direction (input|output) 
  987. * @param mixed $parameters parameter value(s) 
  988. * @param string $bindingType (soap|soap12) 
  989. * @return mixed parameters serialized as XML or false on error (e.g. operation not found) 
  990. * @access public 
  991. */ 
  992. function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') { 
  993. $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType"); 
  994. $this->appendDebug('parameters=' . $this->varDump($parameters)); 
  995.  
  996. if ($direction != 'input' && $direction != 'output') { 
  997. $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 
  998. $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 
  999. return false; 
  1000. }  
  1001. if (!$opData = $this->getOperationData($operation, $bindingType)) { 
  1002. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 
  1003. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType); 
  1004. return false; 
  1005. $this->debug('in serializeRPCParameters: opData:'); 
  1006. $this->appendDebug($this->varDump($opData)); 
  1007.  
  1008. // Get encoding style for output and set to current 
  1009. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 
  1010. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 
  1011. $encodingStyle = $opData['output']['encodingStyle']; 
  1012. $enc_style = $encodingStyle; 
  1013.  
  1014. // set input params 
  1015. $xml = ''; 
  1016. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 
  1017. $parts = &$opData[$direction]['parts']; 
  1018. $part_count = sizeof($parts); 
  1019. $style = $opData['style']; 
  1020. $use = $opData[$direction]['use']; 
  1021. $this->debug("have $part_count part(s) to serialize using $style/$use"); 
  1022. if (is_array($parameters)) { 
  1023. $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 
  1024. $parameter_count = count($parameters); 
  1025. $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize"); 
  1026. // check for Microsoft-style wrapped parameters 
  1027. if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) { 
  1028. $this->debug('check whether the caller has wrapped the parameters'); 
  1029. if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) { 
  1030. // TODO: consider checking here for double-wrapping, when 
  1031. // service function wraps, then NuSOAP wraps again 
  1032. $this->debug("change simple array to associative with 'parameters' element"); 
  1033. $parameters['parameters'] = $parameters[0]; 
  1034. unset($parameters[0]); 
  1035. if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) { 
  1036. $this->debug('check whether caller\'s parameters match the wrapped ones'); 
  1037. if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) { 
  1038. $this->debug('wrap the parameters for the caller'); 
  1039. $parameters = array('parameters' => $parameters); 
  1040. $parameter_count = 1; 
  1041. foreach ($parts as $name => $type) { 
  1042. $this->debug("serializing part $name of type $type"); 
  1043. // Track encoding style 
  1044. if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 
  1045. $encodingStyle = $opData[$direction]['encodingStyle'];  
  1046. $enc_style = $encodingStyle; 
  1047. } else { 
  1048. $enc_style = false; 
  1049. // NOTE: add error handling here 
  1050. // if serializeType returns false, then catch global error and fault 
  1051. if ($parametersArrayType == 'arraySimple') { 
  1052. $p = array_shift($parameters); 
  1053. $this->debug('calling serializeType w/indexed param'); 
  1054. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 
  1055. } elseif (isset($parameters[$name])) { 
  1056. $this->debug('calling serializeType w/named param'); 
  1057. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 
  1058. } else { 
  1059. // TODO: only send nillable 
  1060. $this->debug('calling serializeType w/null param'); 
  1061. $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 
  1062. } else { 
  1063. $this->debug('no parameters passed.'); 
  1064. $this->debug("serializeRPCParameters returning: $xml"); 
  1065. return $xml; 
  1066. }  
  1067.  
  1068. /** 
  1069. * serialize a PHP value according to a WSDL message definition 
  1070. *  
  1071. * TODO 
  1072. * - multi-ref serialization 
  1073. * - validate PHP values against type definitions, return errors if invalid 
  1074. *  
  1075. * @param string $operation operation name 
  1076. * @param string $direction (input|output) 
  1077. * @param mixed $parameters parameter value(s) 
  1078. * @return mixed parameters serialized as XML or false on error (e.g. operation not found) 
  1079. * @access public 
  1080. * @deprecated 
  1081. */ 
  1082. function serializeParameters($operation, $direction, $parameters) 
  1083. $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");  
  1084. $this->appendDebug('parameters=' . $this->varDump($parameters)); 
  1085.  
  1086. if ($direction != 'input' && $direction != 'output') { 
  1087. $this->debug('The value of the \$direction argument needs to be either "input" or "output"'); 
  1088. $this->setError('The value of the \$direction argument needs to be either "input" or "output"'); 
  1089. return false; 
  1090. }  
  1091. if (!$opData = $this->getOperationData($operation)) { 
  1092. $this->debug('Unable to retrieve WSDL data for operation: ' . $operation); 
  1093. $this->setError('Unable to retrieve WSDL data for operation: ' . $operation); 
  1094. return false; 
  1095. $this->debug('opData:'); 
  1096. $this->appendDebug($this->varDump($opData)); 
  1097.  
  1098. // Get encoding style for output and set to current 
  1099. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 
  1100. if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) { 
  1101. $encodingStyle = $opData['output']['encodingStyle']; 
  1102. $enc_style = $encodingStyle; 
  1103.  
  1104. // set input params 
  1105. $xml = ''; 
  1106. if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 
  1107.  
  1108. $use = $opData[$direction]['use']; 
  1109. $this->debug("use=$use"); 
  1110. $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)'); 
  1111. if (is_array($parameters)) { 
  1112. $parametersArrayType = $this->isArraySimpleOrStruct($parameters); 
  1113. $this->debug('have ' . $parametersArrayType . ' parameters'); 
  1114. foreach($opData[$direction]['parts'] as $name => $type) { 
  1115. $this->debug('serializing part "'.$name.'" of type "'.$type.'"'); 
  1116. // Track encoding style 
  1117. if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { 
  1118. $encodingStyle = $opData[$direction]['encodingStyle'];  
  1119. $enc_style = $encodingStyle; 
  1120. } else { 
  1121. $enc_style = false; 
  1122. // NOTE: add error handling here 
  1123. // if serializeType returns false, then catch global error and fault 
  1124. if ($parametersArrayType == 'arraySimple') { 
  1125. $p = array_shift($parameters); 
  1126. $this->debug('calling serializeType w/indexed param'); 
  1127. $xml .= $this->serializeType($name, $type, $p, $use, $enc_style); 
  1128. } elseif (isset($parameters[$name])) { 
  1129. $this->debug('calling serializeType w/named param'); 
  1130. $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style); 
  1131. } else { 
  1132. // TODO: only send nillable 
  1133. $this->debug('calling serializeType w/null param'); 
  1134. $xml .= $this->serializeType($name, $type, null, $use, $enc_style); 
  1135. } else { 
  1136. $this->debug('no parameters passed.'); 
  1137. $this->debug("serializeParameters returning: $xml"); 
  1138. return $xml; 
  1139. }  
  1140.  
  1141. /** 
  1142. * serializes a PHP value according a given type definition 
  1143. *  
  1144. * @param string $name name of value (part or element) 
  1145. * @param string $type XML schema type of value (type or element) 
  1146. * @param mixed $value a native PHP value (parameter value) 
  1147. * @param string $use use for part (encoded|literal) 
  1148. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) 
  1149. * @param boolean $unqualified a kludge for what should be XML namespace form handling 
  1150. * @return string value serialized as an XML string 
  1151. * @access private 
  1152. */ 
  1153. function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false) 
  1154. $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified")); 
  1155. $this->appendDebug("value=" . $this->varDump($value)); 
  1156. if($use == 'encoded' && $encodingStyle) { 
  1157. $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"'; 
  1158.  
  1159. // if a soapval has been supplied, let its type override the WSDL 
  1160. if (is_object($value) && get_class($value) == 'soapval') { 
  1161. if ($value->type_ns) { 
  1162. $type = $value->type_ns . ':' . $value->type; 
  1163. $forceType = true; 
  1164. $this->debug("in serializeType: soapval overrides type to $type"); 
  1165. } elseif ($value->type) { 
  1166. $type = $value->type; 
  1167. $forceType = true; 
  1168. $this->debug("in serializeType: soapval overrides type to $type"); 
  1169. } else { 
  1170. $forceType = false; 
  1171. $this->debug("in serializeType: soapval does not override type"); 
  1172. $attrs = $value->attributes; 
  1173. $value = $value->value; 
  1174. $this->debug("in serializeType: soapval overrides value to $value"); 
  1175. if ($attrs) { 
  1176. if (!is_array($value)) { 
  1177. $value['!'] = $value; 
  1178. foreach ($attrs as $n => $v) { 
  1179. $value['!' . $n] = $v; 
  1180. $this->debug("in serializeType: soapval provides attributes"); 
  1181. } else { 
  1182. $forceType = false; 
  1183.  
  1184. $xml = ''; 
  1185. if (strpos($type, ':')) { 
  1186. $uqType = substr($type, strrpos($type, ':') + 1); 
  1187. $ns = substr($type, 0, strrpos($type, ':')); 
  1188. $this->debug("in serializeType: got a prefixed type: $uqType, $ns"); 
  1189. if ($this->getNamespaceFromPrefix($ns)) { 
  1190. $ns = $this->getNamespaceFromPrefix($ns); 
  1191. $this->debug("in serializeType: expanded prefixed type: $uqType, $ns"); 
  1192.  
  1193. if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') { 
  1194. $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); 
  1195. if ($unqualified && $use == 'literal') { 
  1196. $elementNS = " xmlns=\"\""; 
  1197. } else { 
  1198. $elementNS = ''; 
  1199. if (is_null($value)) { 
  1200. if ($use == 'literal') { 
  1201. // TODO: depends on minOccurs 
  1202. $xml = "<$name$elementNS/>"; 
  1203. } else { 
  1204. // TODO: depends on nillable, which should be checked before calling this method 
  1205. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 
  1206. $this->debug("in serializeType: returning: $xml"); 
  1207. return $xml; 
  1208. if ($uqType == 'Array') { 
  1209. // JBoss/Axis does this sometimes 
  1210. return $this->serialize_val($value, $name, false, false, false, false, $use); 
  1211. if ($uqType == 'boolean') { 
  1212. if ((is_string($value) && $value == 'false') || (! $value)) { 
  1213. $value = 'false'; 
  1214. } else { 
  1215. $value = 'true'; 
  1216. }  
  1217. if ($uqType == 'string' && gettype($value) == 'string') { 
  1218. $value = $this->expandEntities($value); 
  1219. if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') { 
  1220. $value = sprintf("%.0lf", $value); 
  1221. // it's a scalar 
  1222. // TODO: what about null/nil values? 
  1223. // check type isn't a custom type extending xmlschema namespace 
  1224. if (!$this->getTypeDef($uqType, $ns)) { 
  1225. if ($use == 'literal') { 
  1226. if ($forceType) { 
  1227. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 
  1228. } else { 
  1229. $xml = "<$name$elementNS>$value</$name>"; 
  1230. } else { 
  1231. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 
  1232. $this->debug("in serializeType: returning: $xml"); 
  1233. return $xml; 
  1234. $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)'); 
  1235. } else if ($ns == 'http://xml.apache.org/xml-soap') { 
  1236. $this->debug('in serializeType: appears to be Apache SOAP type'); 
  1237. if ($uqType == 'Map') { 
  1238. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 
  1239. if (! $tt_prefix) { 
  1240. $this->debug('in serializeType: Add namespace for Apache SOAP type'); 
  1241. $tt_prefix = 'ns' . rand(1000, 9999); 
  1242. $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap'; 
  1243. // force this to be added to usedNamespaces 
  1244. $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap'); 
  1245. $contents = ''; 
  1246. foreach($value as $k => $v) { 
  1247. $this->debug("serializing map element: key $k, value $v"); 
  1248. $contents .= '<item>'; 
  1249. $contents .= $this->serialize_val($k, 'key', false, false, false, false, $use); 
  1250. $contents .= $this->serialize_val($v, 'value', false, false, false, false, $use); 
  1251. $contents .= '</item>'; 
  1252. if ($use == 'literal') { 
  1253. if ($forceType) { 
  1254. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>"; 
  1255. } else { 
  1256. $xml = "<$name>$contents</$name>"; 
  1257. } else { 
  1258. $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>"; 
  1259. $this->debug("in serializeType: returning: $xml"); 
  1260. return $xml; 
  1261. $this->debug('in serializeType: Apache SOAP type, but only support Map'); 
  1262. } else { 
  1263. // TODO: should the type be compared to types in XSD, and the namespace 
  1264. // set to XSD if the type matches? 
  1265. $this->debug("in serializeType: No namespace for type $type"); 
  1266. $ns = ''; 
  1267. $uqType = $type; 
  1268. if(!$typeDef = $this->getTypeDef($uqType, $ns)) { 
  1269. $this->setError("$type ($uqType) is not a supported type."); 
  1270. $this->debug("in serializeType: $type ($uqType) is not a supported type."); 
  1271. return false; 
  1272. } else { 
  1273. $this->debug("in serializeType: found typeDef"); 
  1274. $this->appendDebug('typeDef=' . $this->varDump($typeDef)); 
  1275. if (substr($uqType, -1) == '^') { 
  1276. $uqType = substr($uqType, 0, -1); 
  1277. if (!isset($typeDef['phpType'])) { 
  1278. $this->setError("$type ($uqType) has no phpType."); 
  1279. $this->debug("in serializeType: $type ($uqType) has no phpType."); 
  1280. return false; 
  1281. $phpType = $typeDef['phpType']; 
  1282. $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );  
  1283. // if php type == struct, map value to the <all> element names 
  1284. if ($phpType == 'struct') { 
  1285. if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') { 
  1286. $elementName = $uqType; 
  1287. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 
  1288. $elementNS = " xmlns=\"$ns\""; 
  1289. } else { 
  1290. $elementNS = " xmlns=\"\""; 
  1291. } else { 
  1292. $elementName = $name; 
  1293. if ($unqualified) { 
  1294. $elementNS = " xmlns=\"\""; 
  1295. } else { 
  1296. $elementNS = ''; 
  1297. if (is_null($value)) { 
  1298. if ($use == 'literal') { 
  1299. // TODO: depends on minOccurs and nillable 
  1300. $xml = "<$elementName$elementNS/>"; 
  1301. } else { 
  1302. $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>"; 
  1303. $this->debug("in serializeType: returning: $xml"); 
  1304. return $xml; 
  1305. if (is_object($value)) { 
  1306. $value = get_object_vars($value); 
  1307. if (is_array($value)) { 
  1308. $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType); 
  1309. if ($use == 'literal') { 
  1310. if ($forceType) { 
  1311. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">"; 
  1312. } else { 
  1313. $xml = "<$elementName$elementNS$elementAttrs>"; 
  1314. } else { 
  1315. $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>"; 
  1316.  
  1317. if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') { 
  1318. if (isset($value['!'])) { 
  1319. $xml .= $value['!']; 
  1320. $this->debug("in serializeType: serialized simpleContent for type $type"); 
  1321. } else { 
  1322. $this->debug("in serializeType: no simpleContent to serialize for type $type"); 
  1323. } else { 
  1324. // complexContent 
  1325. $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle); 
  1326. $xml .= "</$elementName>"; 
  1327. } else { 
  1328. $this->debug("in serializeType: phpType is struct, but value is not an array"); 
  1329. $this->setError("phpType is struct, but value is not an array: see debug output for details"); 
  1330. $xml = ''; 
  1331. } elseif ($phpType == 'array') { 
  1332. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 
  1333. $elementNS = " xmlns=\"$ns\""; 
  1334. } else { 
  1335. if ($unqualified) { 
  1336. $elementNS = " xmlns=\"\""; 
  1337. } else { 
  1338. $elementNS = ''; 
  1339. if (is_null($value)) { 
  1340. if ($use == 'literal') { 
  1341. // TODO: depends on minOccurs 
  1342. $xml = "<$name$elementNS/>"; 
  1343. } else { 
  1344. $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . 
  1345. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 
  1346. ":Array\" " . 
  1347. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . 
  1348. ':arrayType="' . 
  1349. $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) . 
  1350. ':' . 
  1351. $this->getLocalPart($typeDef['arrayType'])."[0]\"/>"; 
  1352. $this->debug("in serializeType: returning: $xml"); 
  1353. return $xml; 
  1354. if (isset($typeDef['multidimensional'])) { 
  1355. $nv = array(); 
  1356. foreach($value as $v) { 
  1357. $cols = ', ' . sizeof($v); 
  1358. $nv = array_merge($nv, $v); 
  1359. }  
  1360. $value = $nv; 
  1361. } else { 
  1362. $cols = ''; 
  1363. }  
  1364. if (is_array($value) && sizeof($value) >= 1) { 
  1365. $rows = sizeof($value); 
  1366. $contents = ''; 
  1367. foreach($value as $k => $v) { 
  1368. $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]"); 
  1369. //if (strpos($typeDef['arrayType'], ':') ) { 
  1370. if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) { 
  1371. $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use); 
  1372. } else { 
  1373. $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use); 
  1374. }  
  1375. } else { 
  1376. $rows = 0; 
  1377. $contents = null; 
  1378. // TODO: for now, an empty value will be serialized as a zero element 
  1379. // array. Revisit this when coding the handling of null/nil values. 
  1380. if ($use == 'literal') { 
  1381. $xml = "<$name$elementNS>" 
  1382. .$contents 
  1383. ."</$name>"; 
  1384. } else { 
  1385. $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '. 
  1386. $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') 
  1387. .':arrayType="' 
  1388. .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) 
  1389. .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">" 
  1390. .$contents 
  1391. ."</$name>"; 
  1392. } elseif ($phpType == 'scalar') { 
  1393. if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) { 
  1394. $elementNS = " xmlns=\"$ns\""; 
  1395. } else { 
  1396. if ($unqualified) { 
  1397. $elementNS = " xmlns=\"\""; 
  1398. } else { 
  1399. $elementNS = ''; 
  1400. if ($use == 'literal') { 
  1401. if ($forceType) { 
  1402. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>"; 
  1403. } else { 
  1404. $xml = "<$name$elementNS>$value</$name>"; 
  1405. } else { 
  1406. $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>"; 
  1407. $this->debug("in serializeType: returning: $xml"); 
  1408. return $xml; 
  1409.  
  1410. /** 
  1411. * serializes the attributes for a complexType 
  1412. * @param array $typeDef our internal representation of an XML schema type (or element) 
  1413. * @param mixed $value a native PHP value (parameter value) 
  1414. * @param string $ns the namespace of the type 
  1415. * @param string $uqType the local part of the type 
  1416. * @return string value serialized as an XML string 
  1417. * @access private 
  1418. */ 
  1419. function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) { 
  1420. $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType"); 
  1421. $xml = ''; 
  1422. if (isset($typeDef['extensionBase'])) { 
  1423. $nsx = $this->getPrefix($typeDef['extensionBase']); 
  1424. $uqTypex = $this->getLocalPart($typeDef['extensionBase']); 
  1425. if ($this->getNamespaceFromPrefix($nsx)) { 
  1426. $nsx = $this->getNamespaceFromPrefix($nsx); 
  1427. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { 
  1428. $this->debug("serialize attributes for extension base $nsx:$uqTypex"); 
  1429. $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex); 
  1430. } else { 
  1431. $this->debug("extension base $nsx:$uqTypex is not a supported type"); 
  1432. if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) { 
  1433. $this->debug("serialize attributes for XML Schema type $ns:$uqType"); 
  1434. if (is_array($value)) { 
  1435. $xvalue = $value; 
  1436. } elseif (is_object($value)) { 
  1437. $xvalue = get_object_vars($value); 
  1438. } else { 
  1439. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 
  1440. $xvalue = array(); 
  1441. foreach ($typeDef['attrs'] as $aName => $attrs) { 
  1442. if (isset($xvalue['!' . $aName])) { 
  1443. $xname = '!' . $aName; 
  1444. $this->debug("value provided for attribute $aName with key $xname"); 
  1445. } elseif (isset($xvalue[$aName])) { 
  1446. $xname = $aName; 
  1447. $this->debug("value provided for attribute $aName with key $xname"); 
  1448. } elseif (isset($attrs['default'])) { 
  1449. $xname = '!' . $aName; 
  1450. $xvalue[$xname] = $attrs['default']; 
  1451. $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName); 
  1452. } else { 
  1453. $xname = ''; 
  1454. $this->debug("no value provided for attribute $aName"); 
  1455. if ($xname) { 
  1456. $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\""; 
  1457. }  
  1458. } else { 
  1459. $this->debug("no attributes to serialize for XML Schema type $ns:$uqType"); 
  1460. return $xml; 
  1461.  
  1462. /** 
  1463. * serializes the elements for a complexType 
  1464. * @param array $typeDef our internal representation of an XML schema type (or element) 
  1465. * @param mixed $value a native PHP value (parameter value) 
  1466. * @param string $ns the namespace of the type 
  1467. * @param string $uqType the local part of the type 
  1468. * @param string $use use for part (encoded|literal) 
  1469. * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style) 
  1470. * @return string value serialized as an XML string 
  1471. * @access private 
  1472. */ 
  1473. function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) { 
  1474. $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType"); 
  1475. $xml = ''; 
  1476. if (isset($typeDef['extensionBase'])) { 
  1477. $nsx = $this->getPrefix($typeDef['extensionBase']); 
  1478. $uqTypex = $this->getLocalPart($typeDef['extensionBase']); 
  1479. if ($this->getNamespaceFromPrefix($nsx)) { 
  1480. $nsx = $this->getNamespaceFromPrefix($nsx); 
  1481. if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) { 
  1482. $this->debug("serialize elements for extension base $nsx:$uqTypex"); 
  1483. $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle); 
  1484. } else { 
  1485. $this->debug("extension base $nsx:$uqTypex is not a supported type"); 
  1486. if (isset($typeDef['elements']) && is_array($typeDef['elements'])) { 
  1487. $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType"); 
  1488. if (is_array($value)) { 
  1489. $xvalue = $value; 
  1490. } elseif (is_object($value)) { 
  1491. $xvalue = get_object_vars($value); 
  1492. } else { 
  1493. $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType"); 
  1494. $xvalue = array(); 
  1495. // toggle whether all elements are present - ideally should validate against schema 
  1496. if (count($typeDef['elements']) != count($xvalue)) { 
  1497. $optionals = true; 
  1498. foreach ($typeDef['elements'] as $eName => $attrs) { 
  1499. if (!isset($xvalue[$eName])) { 
  1500. if (isset($attrs['default'])) { 
  1501. $xvalue[$eName] = $attrs['default']; 
  1502. $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName); 
  1503. // if user took advantage of a minOccurs=0, then only serialize named parameters 
  1504. if (isset($optionals) 
  1505. && (!isset($xvalue[$eName]))  
  1506. && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true') 
  1507. ) { 
  1508. if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') { 
  1509. $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']); 
  1510. // do nothing 
  1511. $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing"); 
  1512. } else { 
  1513. // get value 
  1514. if (isset($xvalue[$eName])) { 
  1515. $v = $xvalue[$eName]; 
  1516. } else { 
  1517. $v = null; 
  1518. if (isset($attrs['form'])) { 
  1519. $unqualified = ($attrs['form'] == 'unqualified'); 
  1520. } else { 
  1521. $unqualified = false; 
  1522. if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') { 
  1523. $vv = $v; 
  1524. foreach ($vv as $k => $v) { 
  1525. if (isset($attrs['type']) || isset($attrs['ref'])) { 
  1526. // serialize schema-defined type 
  1527. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 
  1528. } else { 
  1529. // serialize generic type (can this ever really happen?) 
  1530. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 
  1531. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 
  1532. } else { 
  1533. if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') { 
  1534. // do nothing 
  1535. } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') { 
  1536. // TODO: serialize a nil correctly, but for now serialize schema-defined type 
  1537. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 
  1538. } elseif (isset($attrs['type']) || isset($attrs['ref'])) { 
  1539. // serialize schema-defined type 
  1540. $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified); 
  1541. } else { 
  1542. // serialize generic type (can this ever really happen?) 
  1543. $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use"); 
  1544. $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use); 
  1545. }  
  1546. } else { 
  1547. $this->debug("no elements to serialize for XML Schema type $ns:$uqType"); 
  1548. return $xml; 
  1549.  
  1550. /** 
  1551. * adds an XML Schema complex type to the WSDL types 
  1552. * @param string $name 
  1553. * @param string $typeClass (complexType|simpleType|attribute) 
  1554. * @param string $phpType currently supported are array and struct (php assoc array) 
  1555. * @param string $compositor (all|sequence|choice) 
  1556. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) 
  1557. * @param array $elements e.g. array ( name => array(name=>'', type=>'') ) 
  1558. * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType', 'wsdl:arrayType'=>'xsd:string[]')) 
  1559. * @param string $arrayType as namespace:name (xsd:string) 
  1560. * @see nusoap_xmlschema 
  1561. * @access public 
  1562. */ 
  1563. function addComplexType($name, $typeClass='complexType', $phpType='array', $compositor='', $restrictionBase='', $elements=array(), $attrs=array(), $arrayType='') { 
  1564. if (count($elements) > 0) { 
  1565. $eElements = array(); 
  1566. foreach($elements as $n => $e) { 
  1567. // expand each element 
  1568. $ee = array(); 
  1569. foreach ($e as $k => $v) { 
  1570. $k = strpos($k, ':') ? $this->expandQname($k) : $k; 
  1571. $v = strpos($v, ':') ? $this->expandQname($v) : $v; 
  1572. $ee[$k] = $v; 
  1573. $eElements[$n] = $ee; 
  1574. $elements = $eElements; 
  1575.  
  1576. if (count($attrs) > 0) { 
  1577. foreach($attrs as $n => $a) { 
  1578. // expand each attribute 
  1579. foreach ($a as $k => $v) { 
  1580. $k = strpos($k, ':') ? $this->expandQname($k) : $k; 
  1581. $v = strpos($v, ':') ? $this->expandQname($v) : $v; 
  1582. $aa[$k] = $v; 
  1583. $eAttrs[$n] = $aa; 
  1584. $attrs = $eAttrs; 
  1585.  
  1586. $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase; 
  1587. $arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType; 
  1588.  
  1589. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 
  1590. $this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType); 
  1591.  
  1592. /** 
  1593. * adds an XML Schema simple type to the WSDL types 
  1594. * @param string $name 
  1595. * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) 
  1596. * @param string $typeClass (should always be simpleType) 
  1597. * @param string $phpType (should always be scalar) 
  1598. * @param array $enumeration array of values 
  1599. * @see nusoap_xmlschema 
  1600. * @access public 
  1601. */ 
  1602. function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 
  1603. $restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase; 
  1604.  
  1605. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 
  1606. $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration); 
  1607.  
  1608. /** 
  1609. * adds an element to the WSDL types 
  1610. * @param array $attrs attributes that must include name and type 
  1611. * @see nusoap_xmlschema 
  1612. * @access public 
  1613. */ 
  1614. function addElement($attrs) { 
  1615. $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns']; 
  1616. $this->schemas[$typens][0]->addElement($attrs); 
  1617.  
  1618. /** 
  1619. * register an operation with the server 
  1620. *  
  1621. * @param string $name operation (method) name 
  1622. * @param array $in assoc array of input values: key = param name, value = param type 
  1623. * @param array $out assoc array of output values: key = param name, value = param type 
  1624. * @param string $namespace optional The namespace for the operation 
  1625. * @param string $soapaction optional The soapaction for the operation 
  1626. * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically 
  1627. * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now) 
  1628. * @param string $documentation optional The description to include in the WSDL 
  1629. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) 
  1630. * @access public  
  1631. */ 
  1632. function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '') { 
  1633. if ($use == 'encoded' && $encodingStyle == '') { 
  1634. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 
  1635.  
  1636. if ($style == 'document') { 
  1637. $elements = array(); 
  1638. foreach ($in as $n => $t) { 
  1639. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); 
  1640. $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); 
  1641. $this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); 
  1642. $in = array('parameters' => 'tns:' . $name . '^'); 
  1643.  
  1644. $elements = array(); 
  1645. foreach ($out as $n => $t) { 
  1646. $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified'); 
  1647. $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); 
  1648. $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified')); 
  1649. $out = array('parameters' => 'tns:' . $name . 'Response' . '^'); 
  1650.  
  1651. // get binding 
  1652. $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] = 
  1653. array( 
  1654. 'name' => $name,  
  1655. 'binding' => $this->serviceName . 'Binding',  
  1656. 'endpoint' => $this->endpoint,  
  1657. 'soapAction' => $soapaction,  
  1658. 'style' => $style,  
  1659. 'input' => array( 
  1660. 'use' => $use,  
  1661. 'namespace' => $namespace,  
  1662. 'encodingStyle' => $encodingStyle,  
  1663. 'message' => $name . 'Request',  
  1664. 'parts' => $in),  
  1665. 'output' => array( 
  1666. 'use' => $use,  
  1667. 'namespace' => $namespace,  
  1668. 'encodingStyle' => $encodingStyle,  
  1669. 'message' => $name . 'Response',  
  1670. 'parts' => $out),  
  1671. 'namespace' => $namespace,  
  1672. 'transport' => 'http://schemas.xmlsoap.org/soap/http',  
  1673. 'documentation' => $documentation);  
  1674. // add portTypes 
  1675. // add messages 
  1676. if($in) 
  1677. foreach($in as $pName => $pType) 
  1678. if(strpos($pType, ':')) { 
  1679. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 
  1680. $this->messages[$name.'Request'][$pName] = $pType; 
  1681. } else { 
  1682. $this->messages[$name.'Request']= '0'; 
  1683. if($out) 
  1684. foreach($out as $pName => $pType) 
  1685. if(strpos($pType, ':')) { 
  1686. $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType); 
  1687. $this->messages[$name.'Response'][$pName] = $pType; 
  1688. } else { 
  1689. $this->messages[$name.'Response']= '0'; 
  1690. return true; 
  1691. }