source: pmb4.2/trunk/fuentes/pmb/classes/nusoap/class.wsdl.php @ 815

Last change on this file since 815 was 815, checked in by jrpelegrina, 4 years ago

Initial release of pmb 4.2

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