|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Soap |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Wsdl.php 23342 2010-11-15 15:29:20Z alexander $ |
|
20 */ |
|
21 |
|
22 /** |
|
23 * @see Zend_Soap_Wsdl_Strategy_Interface |
|
24 */ |
|
25 require_once "Zend/Soap/Wsdl/Strategy/Interface.php"; |
|
26 |
|
27 /** |
|
28 * @see Zend_Soap_Wsdl_Strategy_Abstract |
|
29 */ |
|
30 require_once "Zend/Soap/Wsdl/Strategy/Abstract.php"; |
|
31 |
|
32 /** |
|
33 * Zend_Soap_Wsdl |
|
34 * |
|
35 * @category Zend |
|
36 * @package Zend_Soap |
|
37 */ |
|
38 class Zend_Soap_Wsdl |
|
39 { |
|
40 /** |
|
41 * @var object DomDocument Instance |
|
42 */ |
|
43 private $_dom; |
|
44 |
|
45 /** |
|
46 * @var object WSDL Root XML_Tree_Node |
|
47 */ |
|
48 private $_wsdl; |
|
49 |
|
50 /** |
|
51 * @var string URI where the WSDL will be available |
|
52 */ |
|
53 private $_uri; |
|
54 |
|
55 /** |
|
56 * @var DOMElement |
|
57 */ |
|
58 private $_schema = null; |
|
59 |
|
60 /** |
|
61 * Types defined on schema |
|
62 * |
|
63 * @var array |
|
64 */ |
|
65 private $_includedTypes = array(); |
|
66 |
|
67 /** |
|
68 * Strategy for detection of complex types |
|
69 */ |
|
70 protected $_strategy = null; |
|
71 |
|
72 |
|
73 /** |
|
74 * Constructor |
|
75 * |
|
76 * @param string $name Name of the Web Service being Described |
|
77 * @param string $uri URI where the WSDL will be available |
|
78 * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy |
|
79 */ |
|
80 public function __construct($name, $uri, $strategy = true) |
|
81 { |
|
82 if ($uri instanceof Zend_Uri_Http) { |
|
83 $uri = $uri->getUri(); |
|
84 } |
|
85 $this->_uri = $uri; |
|
86 |
|
87 /** |
|
88 * @todo change DomDocument object creation from cparsing to construxting using API |
|
89 * It also should authomatically escape $name and $uri values if necessary |
|
90 */ |
|
91 $wsdl = "<?xml version='1.0' ?> |
|
92 <definitions name='$name' targetNamespace='$uri' |
|
93 xmlns='http://schemas.xmlsoap.org/wsdl/' |
|
94 xmlns:tns='$uri' |
|
95 xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' |
|
96 xmlns:xsd='http://www.w3.org/2001/XMLSchema' |
|
97 xmlns:soap-enc='http://schemas.xmlsoap.org/soap/encoding/' |
|
98 xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'></definitions>"; |
|
99 $this->_dom = new DOMDocument(); |
|
100 if (!$this->_dom->loadXML($wsdl)) { |
|
101 require_once 'Zend/Server/Exception.php'; |
|
102 throw new Zend_Server_Exception('Unable to create DomDocument'); |
|
103 } else { |
|
104 $this->_wsdl = $this->_dom->documentElement; |
|
105 } |
|
106 |
|
107 $this->setComplexTypeStrategy($strategy); |
|
108 } |
|
109 |
|
110 /** |
|
111 * Set a new uri for this WSDL |
|
112 * |
|
113 * @param string|Zend_Uri_Http $uri |
|
114 * @return Zend_Server_Wsdl |
|
115 */ |
|
116 public function setUri($uri) |
|
117 { |
|
118 if ($uri instanceof Zend_Uri_Http) { |
|
119 $uri = $uri->getUri(); |
|
120 } |
|
121 $oldUri = $this->_uri; |
|
122 $this->_uri = $uri; |
|
123 |
|
124 if($this->_dom !== null) { |
|
125 // @todo: This is the worst hack ever, but its needed due to design and non BC issues of WSDL generation |
|
126 $xml = $this->_dom->saveXML(); |
|
127 $xml = str_replace($oldUri, $uri, $xml); |
|
128 $this->_dom = new DOMDocument(); |
|
129 $this->_dom->loadXML($xml); |
|
130 } |
|
131 |
|
132 return $this; |
|
133 } |
|
134 |
|
135 /** |
|
136 * Set a strategy for complex type detection and handling |
|
137 * |
|
138 * @todo Boolean is for backwards compability with extractComplexType object var. Remove it in later versions. |
|
139 * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy |
|
140 * @return Zend_Soap_Wsdl |
|
141 */ |
|
142 public function setComplexTypeStrategy($strategy) |
|
143 { |
|
144 if($strategy === true) { |
|
145 require_once "Zend/Soap/Wsdl/Strategy/DefaultComplexType.php"; |
|
146 $strategy = new Zend_Soap_Wsdl_Strategy_DefaultComplexType(); |
|
147 } else if($strategy === false) { |
|
148 require_once "Zend/Soap/Wsdl/Strategy/AnyType.php"; |
|
149 $strategy = new Zend_Soap_Wsdl_Strategy_AnyType(); |
|
150 } else if(is_string($strategy)) { |
|
151 if(class_exists($strategy)) { |
|
152 $strategy = new $strategy(); |
|
153 } else { |
|
154 require_once "Zend/Soap/Wsdl/Exception.php"; |
|
155 throw new Zend_Soap_Wsdl_Exception( |
|
156 sprintf("Strategy with name '%s does not exist.", $strategy |
|
157 )); |
|
158 } |
|
159 } |
|
160 |
|
161 if(!($strategy instanceof Zend_Soap_Wsdl_Strategy_Interface)) { |
|
162 require_once "Zend/Soap/Wsdl/Exception.php"; |
|
163 throw new Zend_Soap_Wsdl_Exception("Set a strategy that is not of type 'Zend_Soap_Wsdl_Strategy_Interface'"); |
|
164 } |
|
165 $this->_strategy = $strategy; |
|
166 return $this; |
|
167 } |
|
168 |
|
169 /** |
|
170 * Get the current complex type strategy |
|
171 * |
|
172 * @return Zend_Soap_Wsdl_Strategy_Interface |
|
173 */ |
|
174 public function getComplexTypeStrategy() |
|
175 { |
|
176 return $this->_strategy; |
|
177 } |
|
178 |
|
179 /** |
|
180 * Add a {@link http://www.w3.org/TR/wsdl#_messages message} element to the WSDL |
|
181 * |
|
182 * @param string $name Name for the {@link http://www.w3.org/TR/wsdl#_messages message} |
|
183 * @param array $parts An array of {@link http://www.w3.org/TR/wsdl#_message parts} |
|
184 * The array is constructed like: 'name of part' => 'part xml schema data type' |
|
185 * or 'name of part' => array('type' => 'part xml schema type') |
|
186 * or 'name of part' => array('element' => 'part xml element name') |
|
187 * @return object The new message's XML_Tree_Node for use in {@link function addDocumentation} |
|
188 */ |
|
189 public function addMessage($name, $parts) |
|
190 { |
|
191 $message = $this->_dom->createElement('message'); |
|
192 |
|
193 $message->setAttribute('name', $name); |
|
194 |
|
195 if (sizeof($parts) > 0) { |
|
196 foreach ($parts as $name => $type) { |
|
197 $part = $this->_dom->createElement('part'); |
|
198 $part->setAttribute('name', $name); |
|
199 if (is_array($type)) { |
|
200 foreach ($type as $key => $value) { |
|
201 $part->setAttribute($key, $value); |
|
202 } |
|
203 } else { |
|
204 $part->setAttribute('type', $type); |
|
205 } |
|
206 $message->appendChild($part); |
|
207 } |
|
208 } |
|
209 |
|
210 $this->_wsdl->appendChild($message); |
|
211 |
|
212 return $message; |
|
213 } |
|
214 |
|
215 /** |
|
216 * Add a {@link http://www.w3.org/TR/wsdl#_porttypes portType} element to the WSDL |
|
217 * |
|
218 * @param string $name portType element's name |
|
219 * @return object The new portType's XML_Tree_Node for use in {@link function addPortOperation} and {@link function addDocumentation} |
|
220 */ |
|
221 public function addPortType($name) |
|
222 { |
|
223 $portType = $this->_dom->createElement('portType'); |
|
224 $portType->setAttribute('name', $name); |
|
225 $this->_wsdl->appendChild($portType); |
|
226 |
|
227 return $portType; |
|
228 } |
|
229 |
|
230 /** |
|
231 * Add an {@link http://www.w3.org/TR/wsdl#_request-response operation} element to a portType element |
|
232 * |
|
233 * @param object $portType a portType XML_Tree_Node, from {@link function addPortType} |
|
234 * @param string $name Operation name |
|
235 * @param string $input Input Message |
|
236 * @param string $output Output Message |
|
237 * @param string $fault Fault Message |
|
238 * @return object The new operation's XML_Tree_Node for use in {@link function addDocumentation} |
|
239 */ |
|
240 public function addPortOperation($portType, $name, $input = false, $output = false, $fault = false) |
|
241 { |
|
242 $operation = $this->_dom->createElement('operation'); |
|
243 $operation->setAttribute('name', $name); |
|
244 |
|
245 if (is_string($input) && (strlen(trim($input)) >= 1)) { |
|
246 $node = $this->_dom->createElement('input'); |
|
247 $node->setAttribute('message', $input); |
|
248 $operation->appendChild($node); |
|
249 } |
|
250 if (is_string($output) && (strlen(trim($output)) >= 1)) { |
|
251 $node= $this->_dom->createElement('output'); |
|
252 $node->setAttribute('message', $output); |
|
253 $operation->appendChild($node); |
|
254 } |
|
255 if (is_string($fault) && (strlen(trim($fault)) >= 1)) { |
|
256 $node = $this->_dom->createElement('fault'); |
|
257 $node->setAttribute('message', $fault); |
|
258 $operation->appendChild($node); |
|
259 } |
|
260 |
|
261 $portType->appendChild($operation); |
|
262 |
|
263 return $operation; |
|
264 } |
|
265 |
|
266 /** |
|
267 * Add a {@link http://www.w3.org/TR/wsdl#_bindings binding} element to WSDL |
|
268 * |
|
269 * @param string $name Name of the Binding |
|
270 * @param string $type name of the portType to bind |
|
271 * @return object The new binding's XML_Tree_Node for use with {@link function addBindingOperation} and {@link function addDocumentation} |
|
272 */ |
|
273 public function addBinding($name, $portType) |
|
274 { |
|
275 $binding = $this->_dom->createElement('binding'); |
|
276 $binding->setAttribute('name', $name); |
|
277 $binding->setAttribute('type', $portType); |
|
278 |
|
279 $this->_wsdl->appendChild($binding); |
|
280 |
|
281 return $binding; |
|
282 } |
|
283 |
|
284 /** |
|
285 * Add an operation to a binding element |
|
286 * |
|
287 * @param object $binding A binding XML_Tree_Node returned by {@link function addBinding} |
|
288 * @param array $input An array of attributes for the input element, allowed keys are: 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} |
|
289 * @param array $output An array of attributes for the output element, allowed keys are: 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} |
|
290 * @param array $fault An array of attributes for the fault element, allowed keys are: 'name', 'use', 'namespace', 'encodingStyle'. {@link http://www.w3.org/TR/wsdl#_soap:body More Information} |
|
291 * @return object The new Operation's XML_Tree_Node for use with {@link function addSoapOperation} and {@link function addDocumentation} |
|
292 */ |
|
293 public function addBindingOperation($binding, $name, $input = false, $output = false, $fault = false) |
|
294 { |
|
295 $operation = $this->_dom->createElement('operation'); |
|
296 $operation->setAttribute('name', $name); |
|
297 |
|
298 if (is_array($input)) { |
|
299 $node = $this->_dom->createElement('input'); |
|
300 $soap_node = $this->_dom->createElement('soap:body'); |
|
301 foreach ($input as $name => $value) { |
|
302 $soap_node->setAttribute($name, $value); |
|
303 } |
|
304 $node->appendChild($soap_node); |
|
305 $operation->appendChild($node); |
|
306 } |
|
307 |
|
308 if (is_array($output)) { |
|
309 $node = $this->_dom->createElement('output'); |
|
310 $soap_node = $this->_dom->createElement('soap:body'); |
|
311 foreach ($output as $name => $value) { |
|
312 $soap_node->setAttribute($name, $value); |
|
313 } |
|
314 $node->appendChild($soap_node); |
|
315 $operation->appendChild($node); |
|
316 } |
|
317 |
|
318 if (is_array($fault)) { |
|
319 $node = $this->_dom->createElement('fault'); |
|
320 /** |
|
321 * Note. Do we really need name attribute to be also set at wsdl:fault node??? |
|
322 * W3C standard doesn't mention it (http://www.w3.org/TR/wsdl#_soap:fault) |
|
323 * But some real world WSDLs use it, so it may be required for compatibility reasons. |
|
324 */ |
|
325 if (isset($fault['name'])) { |
|
326 $node->setAttribute('name', $fault['name']); |
|
327 } |
|
328 |
|
329 $soap_node = $this->_dom->createElement('soap:fault'); |
|
330 foreach ($fault as $name => $value) { |
|
331 $soap_node->setAttribute($name, $value); |
|
332 } |
|
333 $node->appendChild($soap_node); |
|
334 $operation->appendChild($node); |
|
335 } |
|
336 |
|
337 $binding->appendChild($operation); |
|
338 |
|
339 return $operation; |
|
340 } |
|
341 |
|
342 /** |
|
343 * Add a {@link http://www.w3.org/TR/wsdl#_soap:binding SOAP binding} element to a Binding element |
|
344 * |
|
345 * @param object $binding A binding XML_Tree_Node returned by {@link function addBinding} |
|
346 * @param string $style binding style, possible values are "rpc" (the default) and "document" |
|
347 * @param string $transport Transport method (defaults to HTTP) |
|
348 * @return boolean |
|
349 */ |
|
350 public function addSoapBinding($binding, $style = 'document', $transport = 'http://schemas.xmlsoap.org/soap/http') |
|
351 { |
|
352 $soap_binding = $this->_dom->createElement('soap:binding'); |
|
353 $soap_binding->setAttribute('style', $style); |
|
354 $soap_binding->setAttribute('transport', $transport); |
|
355 |
|
356 $binding->appendChild($soap_binding); |
|
357 |
|
358 return $soap_binding; |
|
359 } |
|
360 |
|
361 /** |
|
362 * Add a {@link http://www.w3.org/TR/wsdl#_soap:operation SOAP operation} to an operation element |
|
363 * |
|
364 * @param object $operation An operation XML_Tree_Node returned by {@link function addBindingOperation} |
|
365 * @param string $soap_action SOAP Action |
|
366 * @return boolean |
|
367 */ |
|
368 public function addSoapOperation($binding, $soap_action) |
|
369 { |
|
370 if ($soap_action instanceof Zend_Uri_Http) { |
|
371 $soap_action = $soap_action->getUri(); |
|
372 } |
|
373 $soap_operation = $this->_dom->createElement('soap:operation'); |
|
374 $soap_operation->setAttribute('soapAction', $soap_action); |
|
375 |
|
376 $binding->insertBefore($soap_operation, $binding->firstChild); |
|
377 |
|
378 return $soap_operation; |
|
379 } |
|
380 |
|
381 /** |
|
382 * Add a {@link http://www.w3.org/TR/wsdl#_services service} element to the WSDL |
|
383 * |
|
384 * @param string $name Service Name |
|
385 * @param string $port_name Name of the port for the service |
|
386 * @param string $binding Binding for the port |
|
387 * @param string $location SOAP Address for the service |
|
388 * @return object The new service's XML_Tree_Node for use with {@link function addDocumentation} |
|
389 */ |
|
390 public function addService($name, $port_name, $binding, $location) |
|
391 { |
|
392 if ($location instanceof Zend_Uri_Http) { |
|
393 $location = $location->getUri(); |
|
394 } |
|
395 $service = $this->_dom->createElement('service'); |
|
396 $service->setAttribute('name', $name); |
|
397 |
|
398 $port = $this->_dom->createElement('port'); |
|
399 $port->setAttribute('name', $port_name); |
|
400 $port->setAttribute('binding', $binding); |
|
401 |
|
402 $soap_address = $this->_dom->createElement('soap:address'); |
|
403 $soap_address->setAttribute('location', $location); |
|
404 |
|
405 $port->appendChild($soap_address); |
|
406 $service->appendChild($port); |
|
407 |
|
408 $this->_wsdl->appendChild($service); |
|
409 |
|
410 return $service; |
|
411 } |
|
412 |
|
413 /** |
|
414 * Add a documentation element to any element in the WSDL. |
|
415 * |
|
416 * Note that the WSDL {@link http://www.w3.org/TR/wsdl#_documentation specification} uses 'document', |
|
417 * but the WSDL {@link http://schemas.xmlsoap.org/wsdl/ schema} uses 'documentation' instead. |
|
418 * The {@link http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html#WSDL_documentation_Element WS-I Basic Profile 1.1} recommends using 'documentation'. |
|
419 * |
|
420 * @param object $input_node An XML_Tree_Node returned by another method to add the documentation to |
|
421 * @param string $documentation Human readable documentation for the node |
|
422 * @return DOMElement The documentation element |
|
423 */ |
|
424 public function addDocumentation($input_node, $documentation) |
|
425 { |
|
426 if ($input_node === $this) { |
|
427 $node = $this->_dom->documentElement; |
|
428 } else { |
|
429 $node = $input_node; |
|
430 } |
|
431 |
|
432 $doc = $this->_dom->createElement('documentation'); |
|
433 $doc_cdata = $this->_dom->createTextNode(str_replace(array("\r\n", "\r"), "\n", $documentation)); |
|
434 $doc->appendChild($doc_cdata); |
|
435 |
|
436 if($node->hasChildNodes()) { |
|
437 $node->insertBefore($doc, $node->firstChild); |
|
438 } else { |
|
439 $node->appendChild($doc); |
|
440 } |
|
441 |
|
442 return $doc; |
|
443 } |
|
444 |
|
445 /** |
|
446 * Add WSDL Types element |
|
447 * |
|
448 * @param object $types A DomDocument|DomNode|DomElement|DomDocumentFragment with all the XML Schema types defined in it |
|
449 */ |
|
450 public function addTypes($types) |
|
451 { |
|
452 if ($types instanceof DomDocument) { |
|
453 $dom = $this->_dom->importNode($types->documentElement); |
|
454 $this->_wsdl->appendChild($types->documentElement); |
|
455 } elseif ($types instanceof DomNode || $types instanceof DomElement || $types instanceof DomDocumentFragment ) { |
|
456 $dom = $this->_dom->importNode($types); |
|
457 $this->_wsdl->appendChild($dom); |
|
458 } |
|
459 } |
|
460 |
|
461 /** |
|
462 * Add a complex type name that is part of this WSDL and can be used in signatures. |
|
463 * |
|
464 * @param string $type |
|
465 * @return Zend_Soap_Wsdl |
|
466 */ |
|
467 public function addType($type) |
|
468 { |
|
469 if(!in_array($type, $this->_includedTypes)) { |
|
470 $this->_includedTypes[] = $type; |
|
471 } |
|
472 return $this; |
|
473 } |
|
474 |
|
475 /** |
|
476 * Return an array of all currently included complex types |
|
477 * |
|
478 * @return array |
|
479 */ |
|
480 public function getTypes() |
|
481 { |
|
482 return $this->_includedTypes; |
|
483 } |
|
484 |
|
485 /** |
|
486 * Return the Schema node of the WSDL |
|
487 * |
|
488 * @return DOMElement |
|
489 */ |
|
490 public function getSchema() |
|
491 { |
|
492 if($this->_schema == null) { |
|
493 $this->addSchemaTypeSection(); |
|
494 } |
|
495 |
|
496 return $this->_schema; |
|
497 } |
|
498 |
|
499 /** |
|
500 * Return the WSDL as XML |
|
501 * |
|
502 * @return string WSDL as XML |
|
503 */ |
|
504 public function toXML() |
|
505 { |
|
506 return $this->_dom->saveXML(); |
|
507 } |
|
508 |
|
509 /** |
|
510 * Return DOM Document |
|
511 * |
|
512 * @return object DomDocum ent |
|
513 */ |
|
514 public function toDomDocument() |
|
515 { |
|
516 return $this->_dom; |
|
517 } |
|
518 |
|
519 /** |
|
520 * Echo the WSDL as XML |
|
521 * |
|
522 * @return boolean |
|
523 */ |
|
524 public function dump($filename = false) |
|
525 { |
|
526 if (!$filename) { |
|
527 echo $this->toXML(); |
|
528 return true; |
|
529 } else { |
|
530 return file_put_contents($filename, $this->toXML()); |
|
531 } |
|
532 } |
|
533 |
|
534 /** |
|
535 * Returns an XSD Type for the given PHP type |
|
536 * |
|
537 * @param string $type PHP Type to get the XSD type for |
|
538 * @return string |
|
539 */ |
|
540 public function getType($type) |
|
541 { |
|
542 switch (strtolower($type)) { |
|
543 case 'string': |
|
544 case 'str': |
|
545 return 'xsd:string'; |
|
546 break; |
|
547 case 'int': |
|
548 case 'integer': |
|
549 return 'xsd:int'; |
|
550 break; |
|
551 case 'float': |
|
552 case 'double': |
|
553 return 'xsd:float'; |
|
554 break; |
|
555 case 'boolean': |
|
556 case 'bool': |
|
557 return 'xsd:boolean'; |
|
558 break; |
|
559 case 'array': |
|
560 return 'soap-enc:Array'; |
|
561 break; |
|
562 case 'object': |
|
563 return 'xsd:struct'; |
|
564 break; |
|
565 case 'mixed': |
|
566 return 'xsd:anyType'; |
|
567 break; |
|
568 case 'void': |
|
569 return ''; |
|
570 default: |
|
571 // delegate retrieval of complex type to current strategy |
|
572 return $this->addComplexType($type); |
|
573 } |
|
574 } |
|
575 |
|
576 /** |
|
577 * This function makes sure a complex types section and schema additions are set. |
|
578 * |
|
579 * @return Zend_Soap_Wsdl |
|
580 */ |
|
581 public function addSchemaTypeSection() |
|
582 { |
|
583 if ($this->_schema === null) { |
|
584 $this->_schema = $this->_dom->createElement('xsd:schema'); |
|
585 $this->_schema->setAttribute('targetNamespace', $this->_uri); |
|
586 $types = $this->_dom->createElement('types'); |
|
587 $types->appendChild($this->_schema); |
|
588 $this->_wsdl->appendChild($types); |
|
589 } |
|
590 return $this; |
|
591 } |
|
592 |
|
593 /** |
|
594 * Add a {@link http://www.w3.org/TR/wsdl#_types types} data type definition |
|
595 * |
|
596 * @param string $type Name of the class to be specified |
|
597 * @return string XSD Type for the given PHP type |
|
598 */ |
|
599 public function addComplexType($type) |
|
600 { |
|
601 if (in_array($type, $this->getTypes())) { |
|
602 return "tns:$type"; |
|
603 } |
|
604 $this->addSchemaTypeSection(); |
|
605 |
|
606 $strategy = $this->getComplexTypeStrategy(); |
|
607 $strategy->setContext($this); |
|
608 // delegates the detection of a complex type to the current strategy |
|
609 return $strategy->addComplexType($type); |
|
610 } |
|
611 |
|
612 /** |
|
613 * Parse an xsd:element represented as an array into a DOMElement. |
|
614 * |
|
615 * @param array $element an xsd:element represented as an array |
|
616 * @return DOMElement parsed element |
|
617 */ |
|
618 private function _parseElement($element) |
|
619 { |
|
620 if (!is_array($element)) { |
|
621 require_once "Zend/Soap/Wsdl/Exception.php"; |
|
622 throw new Zend_Soap_Wsdl_Exception("The 'element' parameter needs to be an associative array."); |
|
623 } |
|
624 |
|
625 $elementXml = $this->_dom->createElement('xsd:element'); |
|
626 foreach ($element as $key => $value) { |
|
627 if (in_array($key, array('sequence', 'all', 'choice'))) { |
|
628 if (is_array($value)) { |
|
629 $complexType = $this->_dom->createElement('xsd:complexType'); |
|
630 if (count($value) > 0) { |
|
631 $container = $this->_dom->createElement('xsd:' . $key); |
|
632 foreach ($value as $subelement) { |
|
633 $subelementXml = $this->_parseElement($subelement); |
|
634 $container->appendChild($subelementXml); |
|
635 } |
|
636 $complexType->appendChild($container); |
|
637 } |
|
638 $elementXml->appendChild($complexType); |
|
639 } |
|
640 } else { |
|
641 $elementXml->setAttribute($key, $value); |
|
642 } |
|
643 } |
|
644 return $elementXml; |
|
645 } |
|
646 |
|
647 /** |
|
648 * Add an xsd:element represented as an array to the schema. |
|
649 * |
|
650 * Array keys represent attribute names and values their respective value. |
|
651 * The 'sequence', 'all' and 'choice' keys must have an array of elements as their value, |
|
652 * to add them to a nested complexType. |
|
653 * |
|
654 * Example: array( 'name' => 'MyElement', |
|
655 * 'sequence' => array( array('name' => 'myString', 'type' => 'string'), |
|
656 * array('name' => 'myInteger', 'type' => 'int') ) ); |
|
657 * Resulting XML: <xsd:element name="MyElement"><xsd:complexType><xsd:sequence> |
|
658 * <xsd:element name="myString" type="string"/> |
|
659 * <xsd:element name="myInteger" type="int"/> |
|
660 * </xsd:sequence></xsd:complexType></xsd:element> |
|
661 * |
|
662 * @param array $element an xsd:element represented as an array |
|
663 * @return string xsd:element for the given element array |
|
664 */ |
|
665 public function addElement($element) |
|
666 { |
|
667 $schema = $this->getSchema(); |
|
668 $elementXml = $this->_parseElement($element); |
|
669 $schema->appendChild($elementXml); |
|
670 return 'tns:' . $element['name']; |
|
671 } |
|
672 } |