* @author Wei Zhuo * @version $Id: Wsdl.php 3314 2013-08-20 10:00:47Z ctrlaltca $ * @package System.Web.Services.SOAP */ /** * Contains the dom object used to build up the wsdl. The * operations generated by the generator are stored in here until the getWsdl() * method is called which builds and returns the generated XML string. * @author Marcus Nyeholt * @author Wei Zhuo * @version $Revision$ */ class Wsdl { /** * The name of the service (usually the classname) * @var string */ private $serviceName; /** * The URI to find the service at. If empty, the current * uri will be used (minus any query string) */ private $serviceUri; /** * The complex types declarations * @var ArrayObject */ private $types; /** * A collection of SOAP operations * @var array */ private $operations=array(); /** * Wsdl DOMDocument that's generated. */ private $wsdl = null; /** * The definitions created for the WSDL */ private $definitions = null; /** * The target namespace variable? */ private $targetNamespace =''; /** * The binding style (default at the moment) */ private $bindingStyle = 'rpc'; /** * The binding uri */ private $bindingTransport = 'http://schemas.xmlsoap.org/soap/http'; private $_encoding=''; private static $_primitiveTypes = array('string', 'int', 'float', 'boolean', 'date', 'time', 'dateTime'); /** * Creates a new Wsdl thing * @param string $name the name of the service. * @param string $serviceUri The URI of the service that handles this WSDL * @param string character encoding */ public function __construct($name, $serviceUri='', $encoding='') { $this->_encoding = $encoding; $this->serviceName = $name; $protocol=(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!=='off'))?'https://':'http://'; if ($serviceUri === '') $serviceUri = $protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; $this->serviceUri = str_replace('&', '&', $serviceUri); $this->types = new ArrayObject(); $this->targetNamespace = 'urn:'.$name.'wsdl'; } public function getWsdl() { $this->buildWsdl(); return $this->wsdl; } /** * Generates the WSDL file into the $this->wsdl variable */ protected function buildWsdl() { $encoding = $this->_encoding==='' ? '' : 'encoding="'.$this->_encoding.'"'; $xml = ' '; $dom = new DOMDocument(); $dom->loadXml($xml); $this->definitions = $dom->documentElement; $this->addTypes($dom); $this->addMessages($dom); $this->addPortTypes($dom); $this->addBindings($dom); $this->addService($dom); $this->wsdl = $dom->saveXML(); } /** * Adds complexType definitions to the document * @param DomDocument $dom The document to add to */ public function addTypes(DomDocument $dom) { if (!count($this->types)) return; $types = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:types'); $schema = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:schema'); $schema->setAttribute('targetNamespace', $this->targetNamespace); foreach($this->types as $type => $elements) { $complexType = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType'); $complexType->setAttribute('name', $type); if(substr($type, strlen($type) - 5, 5) == 'Array') // if it's an array { $sequence = $dom->createElement("xsd:sequence"); $singularType = substr($type, 0, strlen($type) - 5); $e = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $e->setAttribute('name', $singularType); $e->setAttribute('type', sprintf('tns:%s',$singularType)); $e->setAttribute('minOccurs','0'); $e->setAttribute('maxOccurs','unbounded'); $sequence->appendChild($e); $complexType->appendChild($sequence); } else { $all = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:all'); foreach($elements as $elem) { $e = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $e->setAttribute('name', $elem['name']); $e->setAttribute('type', $elem['type']); if($elem['minOc']!==false) $e->setAttribute('minOccurs',$elem['minOc']); if($elem['maxOc']!==false) $e->setAttribute('maxOccurs',$elem['maxOc']); if($elem['nil']!==false) $e->setAttribute('nillable',$elem['nil']); $all->appendChild($e); } $complexType->appendChild($all); } $schema->appendChild($complexType); $types->appendChild($schema); } $this->definitions->appendChild($types); } /** * @return string prefix 'xsd:' for primitive array types, otherwise, 'tns:' */ protected function getArrayTypePrefix($type) { $elementType = substr($type, 0, strlen($type) - 5); return in_array($elementType, self::$_primitiveTypes) ? 'xsd:' : 'tns:'; } /** * Add messages for the service * @param DomDocument $dom The document to add to */ protected function addMessages(DomDocument $dom) { foreach ($this->operations as $operation) { $operation->setMessageElements($this->definitions, $dom); } } /** * Add the port types for the service * @param DomDocument $dom The document to add to */ protected function addPortTypes(DOMDocument $dom) { $portType = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:portType'); $portType->setAttribute('name', $this->serviceName.'PortType'); $this->definitions->appendChild($portType); foreach ($this->operations as $operation) { $portOperation = $operation->getPortOperation($dom); $portType->appendChild($portOperation); } } /** * Add the bindings for the service * @param DomDocument $dom The document to add to */ protected function addBindings(DOMDocument $dom) { $binding = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:binding'); $binding->setAttribute('name', $this->serviceName.'Binding'); $binding->setAttribute('type', 'tns:'.$this->serviceName.'PortType'); $soapBinding = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/soap/', 'soap:binding'); $soapBinding->setAttribute('style', $this->bindingStyle); $soapBinding->setAttribute('transport', $this->bindingTransport); $binding->appendChild($soapBinding); $this->definitions->appendChild($binding); foreach ($this->operations as $operation) { $bindingOperation = $operation->getBindingOperation($dom, $this->targetNamespace, $this->bindingStyle); $binding->appendChild($bindingOperation); } } /** * Add the service definition * @param DomDocument $dom The document to add to */ protected function addService(DomDocument $dom) { $service = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:service'); $service->setAttribute('name', $this->serviceName.'Service'); $port = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:port'); $port->setAttribute('name', $this->serviceName.'Port'); $port->setAttribute('binding', 'tns:'.$this->serviceName.'Binding'); $soapAddress = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/soap/', 'soap:address'); $soapAddress->setAttribute('location', $this->serviceUri); $port->appendChild($soapAddress); $service->appendChild($port); $this->definitions->appendChild($service); } /** * Adds an operation to have port types and bindings output * @param WsdlOperation $operation The operation to add */ public function addOperation(WsdlOperation $operation) { $this->operations[] = $operation; } /** * Adds complexTypes to the wsdl * @param string $type Name of the type * @param Array $elements Elements of the type (each one is an associative array('name','type')) */ public function addComplexType($type, $elements) { $this->types[$type] = $elements; } }