use = $use; $this->binding_style=$type; $this->tns = $tns; $this->url = $url; $this->doc = new domDocument(); $this->definitions = $this->addElement("wsdl:definitions",$this->doc); $this->typesTag = $this->addElement("wsdl:types", $this->definitions); $this->xsdSchema = $this->addElement("xsd:schema", $this->typesTag); $this->xsdSchema->setAttribute("targetNamespace", $this->tns); $this->xmlSchema = new IPXMLSchema($this->xsdSchema); } /** * Adds the class to the services for this WSDL * * @param IPReflectionClass The service * @return void */ public function setService(IPReflectionClass $class){ $this->services[$class->classname] = $class; $this->services[$class->classname]->getMethods(false, false); } /** * @return string The WSDL document for this structure */ public function generateDocument(){ $this->addToDebug("Generating document"); //add all definitions $definitions=$this->definitions; $definitions->setAttribute("xmlns", self::NS_WSDL); $definitions->setAttribute("xmlns:soap", self::NS_SOAP); $definitions->setAttribute("xmlns:SOAP-ENC", self::NS_ENC); $definitions->setAttribute("xmlns:wsdl", self::NS_WSDL); $definitions->setAttribute("xmlns:xsd", self::NS_XSD); $definitions->setAttribute("xmlns:tns", $this->tns); $definitions->setAttribute("targetNamespace", $this->tns); //add all the services foreach((array)$this->services as $serviceName => $service){ //add the portType $portType = $this->addPortType($serviceName); //add binding $binding = $this->addBinding($serviceName); //loop the operations foreach((array)$service->methods as $operation){ $operationName = $operation->name; $operationTag = $this->addOperation($operationName, $serviceName); //input //only when to operation needs arguments $parameters = $operation->getParameters(); if(count($parameters)>0 || self::CREATE_EMPTY_INPUTS){ $messageName = $operationName."Request"; $input=$this->addElement("wsdl:input", $operationTag); $input->setAttribute("message", "tns:".$messageName); $para=Array(); foreach((array)$parameters as $parameterName => $parameter){ $para[$parameterName] = $parameter->type; } $this->addMessage($messageName, $para); $this->addInput($this->bindingOperationTags[$serviceName][$operationName]); } //output //only when the operation returns something if(!$operation->return || trim($operation->return) == "") throw new WSDLException('No return type for '.$operationName); if(strtolower(trim($operation->return))!='void'){ $messageName = $operationName."Response"; $output = $this->addElement("wsdl:output", $operationTag); $output->setAttribute("message", "tns:".$messageName); $this->addOutput($this->bindingOperationTags[$serviceName][$operationName]); $this->addMessage($messageName,Array($operation->name."Return" => $operation->return)); } } // SH. now add the portType and binding $this->definitions->AppendChild($portType); $this->definitions->AppendChild($binding); //add the service $this->addService($serviceName); } return $this->doc->saveXML(); } /** * Adds a new operation to the given service * @param string operation name * @param string service name * @return domElement */ private function addOperation($operationName, $serviceName){ $this->addToDebug("Adding Operation: '$operationName : $serviceName'"); $operationTag = $this->addElement("wsdl:operation",$this->portTypeTags[$serviceName]); $operationTag->setAttribute("name",$operationName); //create operation tag for binding $bindingOperationTag = $this->addElement("wsdl:operation",$this->bindingTags[$serviceName]); $bindingOperationTag->setAttribute("name",$operationName); //soap operation tag $soapOperationTag = $this->addElement("soap:operation",$bindingOperationTag); $soapOperationTag->setAttribute("soapAction",$this->url."&method=".$operationName); $soapOperationTag->setAttribute("style",($this->binding_style == SOAP_RPC)? "rpc" : "document"); //save references $this->operationTags[$serviceName][$operationName] = $operationTag; $this->bindingOperationTags[$serviceName][$operationName] = $bindingOperationTag; //and return return $operationTag; } /** * adds a new service tag to the WSDL file * @param string the service name * @return domElement */ private function addService($serviceName){ $this->addToDebug("Adding service: '$serviceName'"); //create service $serviceTag=$this->addElement("wsdl:service",$this->definitions); $serviceTag->setAttribute("name",$serviceName); //port tag $portTag=$this->addElement("wsdl:port", $serviceTag); $portTag->setAttribute("name", $serviceName."Port"); $portTag->setAttribute("binding", "tns:".$serviceName."Binding"); //address tag $addressTag = $this->addElement("soap:address", $portTag); $addressTag->setAttribute("location", $this->url); //keep a reference $this->serviceTags[$serviceName] = $serviceTag; //and return return $serviceTag; } /** * Adds a new portType to the WSDL structure * @param string the service name for which we create a portType * @return domElement */ private function addPortType($serviceName){ $this->addToDebug("Adding portType: '$serviceName'"); // SH don't add to main doc just yet // $portTypeTag=$this->addElement("wsdl:portType", $this->definitions); $portTypeTag = $this->addElement("wsdl:portType"); $portTypeTag->setAttribute("name", $serviceName."PortType"); //keep a reference $this->portTypeTags[$serviceName]=$portTypeTag; //and return return $portTypeTag; } /** * Adds a new binding to the WSDL structure * @param string serviceName to bind * @return domElement */ private function addBinding($serviceName){ $this->addToDebug("Adding binding: '$serviceName'"); // SH. don't add to main doc just yet // $bindingTag=$this->addElement("binding"); $bindingTag=$this->addElement("binding",$this->definitions); $bindingTag->setAttribute("name", $serviceName."Binding"); $bindingTag->setAttribute("type", "tns:".$serviceName."PortType"); //soap binding tag $soapBindingTag = $this->addElement("soap:binding", $bindingTag); $soapBindingTag->setAttribute("style", ($this->binding_style == SOAP_RPC)? "rpc" : "document"); $soapBindingTag->setAttribute("transport", "http://schemas.xmlsoap.org/soap/http"); //keep a reference $this->bindingTags[$serviceName] = $bindingTag; //and return return $bindingTag; } /** * Adds a message tag to the WSDL document * @param string Message name * @param Array[string=>string] Array with variables & types */ private function addMessage($name, $parts){ $this->addToDebug("Adding message: '$name'"); $msg = $this->addElement("message", $this->definitions); $msg->setAttribute("name", $name); foreach((array)$parts as $partName => $partType){ $this->addToDebug("Adding Message part: '$partName => $partType'"); $part=$this->addElement("part", $msg); $part->setAttribute("name", $partName); //check if it is a valid XML Schema datatype if($t = IPXMLSchema::checkSchemaType(strtolower($partType))) $part->setAttribute("type", "xsd:".$t); else{ //If it is an array, change the type name $partName = (substr($partType,-2) == "[]")?substr($partType,0,strpos($partType,"["))."Array":$partType; $part->setAttribute("type", "tns:".$partName); $this->xmlSchema->addComplexType($partType, $partName); } } } /** * Adds an input element to the given parent (an operation tag) * @param domNode The Parent domNode * @param boolean Kind of tag. true=input tag, false=output tag * @return domNode The input/output node */ private function addInput($parent, $input=true){ $name = $input ? "wsdl:input" : "wsdl:output"; $tag=$this->addElement($name, $parent); $soapOperation=$this->addElement("soap:body", $tag); $soapOperation->setAttribute("use", ($this->use == SOAP_ENCODED)? "encoded" : "literal"); $soapOperation->setAttribute("namespace", $this->tns); if($this->use == SOAP_ENCODED) $soapOperation->setAttribute("encodingStyle", self::NS_ENC); } /** * Adds an output element to the given parent (an operation tag) * @param domNode The Parent domNode * @return domNode The output node */ private function addOutput($parent){ return $this->addInput($parent,false); } /************************* Supporting functions ****************************/ private function addToDebug($msg){ if($this->_debug) echo '-'.$msg."
\n"; } /** * Adds an child element to the parent * @param string The name element * @param domNode * @return domNode */ private function addElement($name, $parent=false, $ns=false){ if($ns) $el=$this->doc->createElementNS($ns,$name); else $el=$this->doc->createElement($name); if($parent) $parent->appendChild($el); return $el; } } ?>