web/lib/Zend/Soap/Wsdl.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     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 }