diff --git a/ServiceDefinition/Dumper/WsdlDumper.php b/ServiceDefinition/Dumper/WsdlDumper.php index 405d762..9d334a4 100644 --- a/ServiceDefinition/Dumper/WsdlDumper.php +++ b/ServiceDefinition/Dumper/WsdlDumper.php @@ -11,8 +11,10 @@ namespace Bundle\WebServiceBundle\ServiceDefinition\Dumper; use Bundle\WebServiceBundle\ServiceDefinition\Method; +use Bundle\WebServiceBundle\ServiceDefinition\Type; use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition; use Bundle\WebServiceBundle\Util\Assert; +use Bundle\WebServiceBundle\Util\QName; use Zend\Soap\Wsdl; @@ -21,38 +23,39 @@ use Zend\Soap\Wsdl; */ class WsdlDumper implements DumperInterface { + private $wsdl; private $definition; public function dumpServiceDefinition(ServiceDefinition $definition, array $options = array()) { - $options = array_merge(array('endpoint' => ''), $options); - Assert::thatArgumentNotNull('definition', $definition); + $options = array_merge(array('endpoint' => '', 'stylesheet' => null), $options); + $this->definition = $definition; - $wsdl = new Wsdl($definition->getName(), $definition->getNamespace()); - $port = $wsdl->addPortType($this->getPortTypeName()); - $binding = $wsdl->addBinding($this->getBindingName(), 'tns:' . $this->getPortTypeName()); + $this->wsdl = new Wsdl($definition->getName(), $definition->getNamespace(), new WsdlTypeStrategy()); + $port = $this->wsdl->addPortType($this->getPortTypeName()); + $binding = $this->wsdl->addBinding($this->getBindingName(), $this->qualify($this->getPortTypeName())); - $wsdl->addSoapBinding($binding, 'rpc'); - $wsdl->addService($this->getServiceName(), $this->getPortName(), 'tns:' . $this->getBindingName(), $options['endpoint']); + $this->wsdl->addSoapBinding($binding, 'rpc'); + $this->wsdl->addService($this->getServiceName(), $this->getPortName(), $this->qualify($this->getBindingName()), $options['endpoint']); - foreach($definition->getMethods() as $method) { + foreach ($definition->getMethods() as $method) { $requestParts = array(); $responseParts = array(); - foreach($method->getArguments() as $argument) { - $requestParts[$argument->getName()] = $wsdl->getType($argument->getType()->getPhpType()); + foreach ($method->getArguments() as $argument) { + $requestParts[$argument->getName()] = $this->wsdl->getType($argument->getType()->getPhpType()); } - if($method->getReturn() !== null) { - $responseParts['return'] = $wsdl->getType($method->getReturn()->getPhpType()); + if ($method->getReturn() !== null) { + $responseParts['return'] = $this->wsdl->getType($method->getReturn()->getPhpType()); } - $wsdl->addMessage($this->getRequestMessageName($method), $requestParts); - $wsdl->addMessage($this->getResponseMessageName($method), $responseParts); + $this->wsdl->addMessage($this->getRequestMessageName($method), $requestParts); + $this->wsdl->addMessage($this->getResponseMessageName($method), $responseParts); - $portOperation = $wsdl->addPortOperation($port, $method->getName(), 'tns:' . $this->getRequestMessageName($method), 'tns:' . $this->getResponseMessageName($method)); + $portOperation = $this->wsdl->addPortOperation($port, $method->getName(), $this->qualify($this->getRequestMessageName($method)), $this->qualify($this->getResponseMessageName($method))); $portOperation->setAttribute('parameterOrder', implode(' ', array_keys($requestParts))); $bindingInput = array( @@ -68,17 +71,33 @@ class WsdlDumper implements DumperInterface 'encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/', ); - $bindingOperation = $wsdl->addBindingOperation($binding, $method->getName(), $bindingInput, $bindingOutput); - $wsdl->addSoapOperation($bindingOperation, $this->getSoapOperationName($method)); + $bindingOperation = $this->wsdl->addBindingOperation($binding, $method->getName(), $bindingInput, $bindingOutput); + $this->wsdl->addSoapOperation($bindingOperation, $this->getSoapOperationName($method)); } $this->definition = null; - $wsdl->toDomDocument()->formatOutput = true; + $dom = $this->wsdl->toDomDocument(); + $dom->formatOutput = true; + + if (null !== $options['stylesheet']) { + $stylesheet = $dom->createProcessingInstruction('xml-stylesheet', sprintf('type="text/xsl" href="%s"', $options['stylesheet'])); + + $dom->insertBefore($stylesheet, $dom->documentElement); + } return $wsdl->toXml(); } + protected function qualify($name, $namespace = null) + { + if($namespace === null) { + $namespace = $this->definition->getNamespace(); + } + + return $this->wsdl->toDomDocument()->lookupPrefix($namespace).':'.$name; + } + protected function getPortName() { return $this->definition->getName().'Port'; @@ -113,4 +132,4 @@ class WsdlDumper implements DumperInterface { return $this->definition->getNamespace().$method->getName(); } -} \ No newline at end of file +} diff --git a/ServiceDefinition/Dumper/WsdlTypeStrategy.php b/ServiceDefinition/Dumper/WsdlTypeStrategy.php new file mode 100644 index 0000000..98005e6 --- /dev/null +++ b/ServiceDefinition/Dumper/WsdlTypeStrategy.php @@ -0,0 +1,69 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Bundle\WebServiceBundle\ServiceDefinition\Dumper; + +use Bundle\WebServiceBundle\Util\String; + +use Zend\Soap\Exception; +use Zend\Soap\Wsdl; +use Zend\Soap\Wsdl\Strategy; +use Zend\Soap\Wsdl\Strategy\ArrayOfTypeSequence; +use Zend\Soap\Wsdl\Strategy\DefaultComplexType; + +class WsdlTypeStrategy implements Strategy +{ + /** + * Context WSDL file + * + * @var \Zend\Soap\Wsdl|null + */ + private $context; + + private $typeStrategy; + private $arrayStrategy; + + public function __construct() + { + $this->typeStrategy = new DefaultComplexType(); + $this->arrayStrategy = new ArrayOfTypeSequence(); + } + + /** + * Method accepts the current WSDL context file. + * + * @param \Zend\Soap\Wsdl $context + */ + public function setContext(Wsdl $context) + { + $this->context = $context; + + return $this; + } + + /** + * Create a complex type based on a strategy + * + * @throws \Zend\Soap\WsdlException + * @param string $type + * @return string XSD type + */ + public function addComplexType($type) + { + if (!$this->context) { + throw new \LogicException(sprintf('Cannot add complex type "%s", no context is set for this composite strategy.', $type)); + } + + $strategy = String::endsWith($type, '[]') ? $this->arrayStrategy : $this->typeStrategy; + $strategy->setContext($this->context); + + return $strategy->addComplexType($type); + } +} \ No newline at end of file