parentElement = $parentElement; } /** * Ads a complexType tag with xmlschema content to the types tag * @param string The variable type (Array or class name) * @param string The variable name * @param domNode Used when adding an inline complexType * @return domNode The complexType node */ public function addComplexType($type, $name = false, $parent = false) { if(!$parent){//outline element //check if the complexType doesn't already exists if(isset($this->types[$name])) return $this->types[$name]; //create the complexType tag beneath the xsd:schema tag $complexTypeTag=$this->addElement("xsd:complexType", $this->parentElement); if($name){//might be an anonymous element $complexTypeTag->setAttribute("name",$name); $this->types[$name]=$complexTypeTag; } }else{//inline element $complexTypeTag = $this->addElement("xsd:complexType", $parent); } //check if its an array if(strtolower(substr($type,0,6)) == 'array(' || substr($type,-2) == '[]'){ $this->addArray($type,$complexTypeTag); }else{//it should be an object $tag=$this->addElement("xsd:all", $complexTypeTag); //check if it has the name 'object()' (kind of a stdClass) if(strtolower(substr($type,0,6)) == 'object'){//stdClass $content = substr($type, 7, (strlen($type)-1)); $properties = explode(",", $content);//split the content into properties foreach((array)$properties as $property){ if($pos = strpos($property, "=>")){//array with keys (order is important, so use 'sequence' tag) $keyType = substr($property,6,($pos-6)); $valueType = substr($property,($pos+2), (strlen($property)-7)); $el->$this->addTypeElement($valueType, $keyType, $tag); }else{ throw new WSDLException("Error creating WSDL: expected \"=>\". When using the object() as type, use it as object(paramname=>paramtype,paramname2=>paramtype2)"); } } }else{ //should be a known class if(!class_exists($name)) throw new WSDLException("Error creating WSDL: no class found with the name '$name' / $type : $parent, so how should we know the structure for this datatype?"); $v = new IPReflectionClass($name); //TODO: check if the class extends another class? $properties = $v->getProperties(false, false);//not protected and private properties foreach((array) $properties as $property){ if(!$property->isPrivate){ $el = $this->addTypeElement($property->type, $property->name, $tag, $property->optional); } } } } return $complexTypeTag; } /** * Adds an element tag beneath the parent and takes care * of the type (XMLSchema type or complexType) * @param string The datatype * @param string Name of the element * @param domNode The parent domNode * @param boolean If the property is optional * @return domNode */ public function addTypeElement($type, $name, $parent, $optional = false) { $el = $this->addElement("xsd:element", $parent); $el->setAttribute("name", $name); if($optional){//if it's an optional property, set minOccur to 0 $el->setAttribute("minOccurs", "0"); $el->setAttribute("maxOccurs", "1"); } //check if XML Schema datatype if($t = $this->checkSchemaType(strtolower($type))) $el->setAttribute("type", "xsd:".$t); else{//no XML Schema datatype //if valueType==Array, then create anonymouse inline complexType (within element tag without type attribute) if(substr($type,-2) == '[]'){ if($this->array_inline){ $this->addComplexType($type, false, $el); }else{ $name = substr($type, 0, -2)."Array"; $el->setAttribute("type", "tns:".$name); $this->addComplexType($type, $name, false); } }else{//else, new complextype, outline (element with 'ref' attrib) $el->setAttribute("type", "tns:".$type); $this->addComplexType($type, $type); } } return $el; } /** * Creates an xmlSchema element for the given array */ public function addArray($type, $parent) { $cc = $this->addElement("xsd:complexContent", $parent); $rs = $this->addElement("xsd:restriction", $cc); $rs->setAttribute("base", "SOAP-ENC:Array"); $type = (substr($type,-2) == '[]') ? substr($type, 0, (strlen($type)-2)) : substr($type, 6, (strlen($type)-7)); $el = $this->addElement("xsd:attribute", $rs); $el->setAttribute("ref", "SOAP-ENC:arrayType"); //check if XML Schema datatype if($t = $this->checkSchemaType(strtolower($type))) $el->setAttribute("wsdl:arrayType", "xsd:".$t."[]"); else{//no XML Schema datatype //if valueType==Array, then create anonymouse inline complexType (within element tag without type attribute) if(substr($type,-2) == '[]'){ $this->addComplexType($type, false, $el); }else{//else, new complextype, outline (element with 'ref' attrib) $el->setAttribute("wsdl:arrayType", "tns:".$type."[]"); $this->addComplexType($type, $type); } } return $el; } /** * Checks if the given type is a valid XML Schema type or can be casted to a schema type * @param string The datatype * @return string */ public static function checkSchemaType($type) { //XML Schema types $types = Array("string" => "string", "int" => "int", "integer" => "int", "boolean" => "boolean", "float" => "float"); if(isset($types[$type])) return $types[$type]; else return false; } /** * Adds an child element to the parent * @param string * @param domNode * @return domNode */ private function addElement($name, $parent = false, $ns = false) { if($ns) $el = $parent->ownerDocument->createElementNS($ns, $name); else $el = $parent->ownerDocument->createElement($name); if($parent) $parent->appendChild($el); return $el; } } ?>