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