diff --git a/.travis.yml b/.travis.yml index 24fccadf..395a963d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - 5.3 - 5.4 - 5.5 diff --git a/composer.json b/composer.json index 2af7c4cd..90cbf584 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=5.3.0", + "php": ">=5.4.0", "ext-soap": "*", "ext-curl": "*", "ass/xmlsecurity": "~1.0", diff --git a/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php b/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php index 29d08c36..86813597 100644 --- a/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php +++ b/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php @@ -170,10 +170,17 @@ public function exceptionAction(Request $request, FlattenException $exception, D public function __call($method, $arguments) { if ($this->serviceBinder->isServiceMethod($method)) { - // @TODO Add all SoapHeaders in SoapRequest - foreach ($this->headers as $name => $value) { - if ($this->serviceBinder->isServiceHeader($method, $name)) { - $this->soapRequest->getSoapHeaders()->add($this->serviceBinder->processServiceHeader($method, $name, $value)); + if (!empty($this->headers)) { + $firstHeaderName = array_keys($this->headers)[0]; + if ((count($this->headers) === 1) && (substr($firstHeaderName, -6) === 'Header')) { + // headers are wrapped and returned as stdClass! + $this->headers = (array) $this->headers[$firstHeaderName]; + } + // @TODO Add all SoapHeaders in SoapRequest + foreach ($this->headers as $name => $value) { + if ($this->serviceBinder->isServiceHeader($method, $name)) { + $this->soapRequest->getSoapHeaders()->add($this->serviceBinder->processServiceHeader($method, $name, $value)); + } } } $this->headers = null; diff --git a/src/BeSimple/SoapBundle/DependencyInjection/BeSimpleSoapExtension.php b/src/BeSimple/SoapBundle/DependencyInjection/BeSimpleSoapExtension.php index a0b8c514..f0f4e8d2 100644 --- a/src/BeSimple/SoapBundle/DependencyInjection/BeSimpleSoapExtension.php +++ b/src/BeSimple/SoapBundle/DependencyInjection/BeSimpleSoapExtension.php @@ -22,6 +22,9 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; +if (!defined('SOAP_LITERAL_WRAPPED')) { + define('SOAP_LITERAL_WRAPPED', 3); +} /** * BeSimpleSoapExtension. * @@ -35,6 +38,15 @@ class BeSimpleSoapExtension extends Extension 'rpc-literal' => 'rpcliteral', 'document-wrapped' => 'documentwrapped', ); + private $styleMap = [ + 'rpc' => \SOAP_RPC, + 'document' => \SOAP_DOCUMENT, + ]; + private $useMap = [ + 'encoded' => \SOAP_ENCODED, + 'literal' => \SOAP_LITERAL, + 'wrapped' => \SOAP_LITERAL_WRAPPED, + ]; public function load(array $configs, ContainerBuilder $container) { @@ -152,7 +164,10 @@ private function createClient($client, ContainerBuilder $container) private function createWebServiceContext(array $config, ContainerBuilder $container) { - $bindingSuffix = $this->bindingConfigToServiceSuffixMap[$config['binding']]; + $bindingSuffix = $this->bindingConfigToServiceSuffixMap[$config['binding']]; + list($style, $use) = explode('-', $config['binding']); + $config['style'] = $this->styleMap[$style]; + $config['use'] = $this->useMap[$use]; unset($config['binding']); $contextId = 'besimple.soap.context.'.$config['name']; diff --git a/src/BeSimple/SoapBundle/DependencyInjection/Configuration.php b/src/BeSimple/SoapBundle/DependencyInjection/Configuration.php index 9374bff2..6cfccd48 100644 --- a/src/BeSimple/SoapBundle/DependencyInjection/Configuration.php +++ b/src/BeSimple/SoapBundle/DependencyInjection/Configuration.php @@ -135,8 +135,15 @@ private function addServicesSection(ArrayNodeDefinition $rootNode) ->scalarNode('binding') ->defaultValue('document-wrapped') ->validate() - ->ifNotInArray(array('rpc-literal', 'document-wrapped')) - ->thenInvalid("Service binding style has to be either 'rpc-literal' or 'document-wrapped'") + ->ifNotInArray([ 'rpc-literal', 'document-wrapped' /*, 'rpc-encoded', , 'document-literal'*/ ]) + ->thenInvalid("Service binding style has to be either 'rpc-literal' or 'document-wrapped'!"/* or 'rpc-encoded' or 'document-literal' */) + ->end() + ->end() + ->scalarNode('version') + ->defaultValue(2) + ->validate() + ->ifNotInArray([ 1, 2 ]) + ->thenInvalid("Service protocol version has to be either 1 or 2") ->end() ->end() ->scalarNode('cache_type') diff --git a/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestHeaderMessageBinder.php b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestHeaderMessageBinder.php new file mode 100644 index 00000000..639c97dc --- /dev/null +++ b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestHeaderMessageBinder.php @@ -0,0 +1,28 @@ + + */ +class DocumentLiteralWrappedRequestHeaderMessageBinder extends DocumentLiteralWrappedRequestMessageBinder +{ + private $header; + + public function setHeader($header) + { + $this->header = $header; + } + + public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository) + { + $this->typeRepository = $typeRepository; + $headerDefinition = $messageDefinition->getHeaders()->get($this->header); + + return $this->processType($headerDefinition->getType(), $message); + } +} diff --git a/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestMessageBinder.php b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestMessageBinder.php index 5d779b01..e734183c 100644 --- a/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestMessageBinder.php +++ b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestMessageBinder.php @@ -11,14 +11,22 @@ namespace BeSimple\SoapBundle\ServiceBinding; use BeSimple\SoapBundle\ServiceDefinition\Method; +use BeSimple\SoapCommon\Definition\Type\ArrayOfType; +use BeSimple\SoapCommon\Definition\Type\ComplexType; +use BeSimple\SoapCommon\Definition\Type\TypeRepository; +use BeSimple\SoapCommon\Util\MessageBinder; /** * @author Christian Kerl */ class DocumentLiteralWrappedRequestMessageBinder implements MessageBinderInterface { - public function processMessage(Method $messageDefinition, $message) + protected $typeRepository; + + public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository) { + $this->typeRepository = $typeRepository; + if(count($message) > 1) { throw new \InvalidArgumentException(); } @@ -26,10 +34,85 @@ public function processMessage(Method $messageDefinition, $message) $result = array(); $message = $message[0]; - foreach($messageDefinition->getArguments() as $argument) { - $result[$argument->getName()] = $message->{$argument->getName()}; + foreach($messageDefinition->getInput()->all() as $argument) { + $result[$argument->getName()] = $this->processType($argument->getType(), $message->{$argument->getName()}); } return $result; } + + protected function processType($phpType, $message) + { + $isArray = false; + + $type = $this->typeRepository->getType($phpType); + if ($type instanceof ArrayOfType) { + $isArray = true; + $array = array(); + + $type = $this->typeRepository->getType($type->get('item')->getType()); + } + + // @TODO Fix array reference + if ($type instanceof ComplexType) { + $phpType = $type->getPhpType(); + + if ($isArray) { + if (isset($message->item)) { + foreach ($message->item as $complexType) { + $array[] = $this->checkComplexType($phpType, $complexType); + } + + // See https://github.com/BeSimple/BeSimpleSoapBundle/issues/29 + if (in_array('BeSimple\SoapCommon\Type\AbstractKeyValue', class_parents($phpType))) { + $assocArray = array(); + foreach ($array as $keyValue) { + $assocArray[$keyValue->getKey()] = $keyValue->getValue(); + } + + $array = $assocArray; + } + } + + $message = $array; + } else { + $message = $this->checkComplexType($phpType, $message); + } + } elseif ($isArray) { + if (isset($message->item)) { + $message = $message->item; + } else { + $message = $array; + } + } + + return $message; + } + + protected function checkComplexType($phpType, $message) + { + $hash = spl_object_hash($message); + if (isset($this->messageRefs[$hash])) { + return $this->messageRefs[$hash]; + } + + $this->messageRefs[$hash] = $message; + + $messageBinder = new MessageBinder($message); + foreach ($this->typeRepository->getType($phpType)->all() as $type) { + $property = $type->getName(); + $value = $messageBinder->readProperty($property); + + if (null !== $value) { + $value = $this->processType($type->getType(), $value); + + $messageBinder->writeProperty($property, $value); + } elseif (!$type->isNillable()) { + // @TODO use xmlType instead of phpType + throw new \SoapFault('SOAP_ERROR_COMPLEX_TYPE', sprintf('"%s:%s" cannot be null.', ucfirst($phpType), $type->getName())); + } + } + + return $message; + } } \ No newline at end of file diff --git a/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedResponseMessageBinder.php b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedResponseMessageBinder.php index 21c72e0d..d22c02c2 100644 --- a/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedResponseMessageBinder.php +++ b/src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedResponseMessageBinder.php @@ -11,17 +11,100 @@ namespace BeSimple\SoapBundle\ServiceBinding; use BeSimple\SoapBundle\ServiceDefinition\Method; +use BeSimple\SoapCommon\Definition\Type\ArrayOfType; +use BeSimple\SoapCommon\Definition\Type\ComplexType; +use BeSimple\SoapCommon\Definition\Type\TypeRepository; +use BeSimple\SoapCommon\Util\MessageBinder; /** * @author Christian Kerl */ class DocumentLiteralWrappedResponseMessageBinder implements MessageBinderInterface { - public function processMessage(Method $messageDefinition, $message) + public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository) { + $this->typeRepository = $typeRepository; + $result = new \stdClass(); - $result->{$messageDefinition->getName().'Result'} = $message; + //$result->{$messageDefinition->getName().'Result'} = $message; + foreach ($messageDefinition->getOutput()->all() as $name => $part) { + //$result->{$name} = $message; + $result->{$name} = $this->processType($part->getType(), $message); + break; // only one iteration + } return $result; } + + private function processType($phpType, $message) + { + $isArray = false; + + $type = $this->typeRepository->getType($phpType); + if ($type instanceof ArrayOfType) { + $isArray = true; + + $type = $this->typeRepository->getType($type->get('item')->getType()); + } + + if ($type instanceof ComplexType) { + $phpType = $type->getPhpType(); + + if ($isArray) { + $array = array(); + + // See https://github.com/BeSimple/BeSimpleSoapBundle/issues/29 + if (is_array($message) && in_array('BeSimple\SoapCommon\Type\AbstractKeyValue', class_parents($phpType))) { + $keyValue = array(); + foreach ($message as $key => $value) { + $keyValue[] = new $phpType($key, $value); + } + + $message = $keyValue; + } + + foreach ($message as $complexType) { + $array[] = $this->checkComplexType($phpType, $complexType); + } + + $message = $array; + } else { + $message = $this->checkComplexType($phpType, $message); + } + } + + return $message; + } + + private function checkComplexType($phpType, $message) + { + $hash = spl_object_hash($message); + if (isset($this->messageRefs[$hash])) { + return $this->messageRefs[$hash]; + } + + $this->messageRefs[$hash] = $message; + + if (!$message instanceof $phpType) { + throw new \InvalidArgumentException(sprintf('The instance class must be "%s", "%s" given.', $phpType, get_class($message))); + } + + $messageBinder = new MessageBinder($message); + foreach ($this->typeRepository->getType($phpType)->all() as $type) { + $property = $type->getName(); + $value = $messageBinder->readProperty($property); + + if (null !== $value) { + $value = $this->processType($type->getType(), $value); + + $messageBinder->writeProperty($property, $value); + } + + if (!$type->isNillable() && null === $value) { + throw new \InvalidArgumentException(sprintf('"%s::%s" cannot be null.', $phpType, $type->getName())); + } + } + + return $message; + } } \ No newline at end of file diff --git a/src/BeSimple/SoapBundle/ServiceBinding/RpcLiteralResponseMessageBinder.php b/src/BeSimple/SoapBundle/ServiceBinding/RpcLiteralResponseMessageBinder.php index b6b4361c..82d0924d 100644 --- a/src/BeSimple/SoapBundle/ServiceBinding/RpcLiteralResponseMessageBinder.php +++ b/src/BeSimple/SoapBundle/ServiceBinding/RpcLiteralResponseMessageBinder.php @@ -32,7 +32,8 @@ public function processMessage(Method $messageDefinition, $message, TypeReposito { $this->typeRepository = $typeRepository; - return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message); + //return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message); + return $this->processType(current($messageDefinition->getOutput()->all())->getType(), $message); } private function processType($phpType, $message) diff --git a/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Param.php b/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Param.php index 330569b6..257b7b3c 100644 --- a/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Param.php +++ b/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Param.php @@ -18,6 +18,7 @@ class Param extends Configuration implements TypedElementInterface private $value; private $phpType; private $xmlType; + private $isNillable = false; public function getValue() { @@ -34,6 +35,11 @@ public function getXmlType() return $this->xmlType; } + public function isNillable() + { + return $this->isNillable; + } + public function setValue($value) { $this->value = $value; @@ -49,6 +55,11 @@ public function setXmlType($xmlType) $this->xmlType = $xmlType; } + public function setNillable($isNillable) + { + $this->isNillable = (bool) $isNillable; + } + public function getAliasName() { return 'param'; diff --git a/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Result.php b/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Result.php index 0d86f8ca..52ee7e5b 100644 --- a/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Result.php +++ b/src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Result.php @@ -15,9 +15,15 @@ */ class Result extends Configuration implements TypedElementInterface { + private $value = 'return'; private $phpType; private $xmlType; + public function getValue() + { + return $this->value; + } + public function getPhpType() { return $this->phpType; @@ -28,6 +34,11 @@ public function getXmlType() return $this->xmlType; } + public function setValue($value) + { + $this->value = $value; + } + public function setPhpType($phpType) { $this->phpType = $phpType; diff --git a/src/BeSimple/SoapBundle/ServiceDefinition/Loader/AnnotationClassLoader.php b/src/BeSimple/SoapBundle/ServiceDefinition/Loader/AnnotationClassLoader.php index dcd15002..5fedee1d 100644 --- a/src/BeSimple/SoapBundle/ServiceDefinition/Loader/AnnotationClassLoader.php +++ b/src/BeSimple/SoapBundle/ServiceDefinition/Loader/AnnotationClassLoader.php @@ -73,14 +73,17 @@ public function load($class, $type = null) foreach ($class->getMethods() as $method) { $serviceHeaders = $sharedHeaders; $serviceArguments = array(); - $serviceMethod = - $serviceReturn = null; + $serviceMethod = null; + $serviceReturn = []; foreach ($this->reader->getMethodAnnotations($method) as $annotation) { if ($annotation instanceof Annotation\Header) { $serviceHeaders[$annotation->getValue()] = $this->loadType($annotation->getPhpType()); } elseif ($annotation instanceof Annotation\Param) { - $serviceArguments[$annotation->getValue()] = $this->loadType($annotation->getPhpType()); + $serviceArguments[$annotation->getValue()] = [ + 'type' => $this->loadType($annotation->getPhpType()), + 'nillable' => $annotation->isNillable() + ]; } elseif ($annotation instanceof Annotation\Method) { if ($serviceMethod) { throw new \LogicException(sprintf('@Soap\Method defined twice for "%s".', $method->getName())); @@ -95,7 +98,7 @@ public function load($class, $type = null) throw new \LogicException(sprintf('@Soap\Result defined twice for "%s".', $method->getName())); } - $serviceReturn = $annotation->getPhpType(); + $serviceReturn[$annotation->getValue()] = $annotation->getPhpType(); } } @@ -108,15 +111,17 @@ public function load($class, $type = null) $serviceMethod->addHeader($name, $type); } - foreach ($serviceArguments as $name => $type) { - $serviceMethod->addInput($name, $type); + /*foreach ($serviceArguments as $name => $type) { + $serviceMethod->addInput($name, $type);*/ + foreach ($serviceArguments as $name => $argument) { + $serviceMethod->addInput($name, $argument['type'], $argument['nillable']); } if (!$serviceReturn) { throw new \LogicException(sprintf('@Soap\Result non-existent for "%s".', $method->getName())); } - $serviceMethod->setOutput($this->loadType($serviceReturn)); + $serviceMethod->setOutput(key($serviceReturn), $this->loadType(current($serviceReturn))); $definition->addMethod($serviceMethod); } diff --git a/src/BeSimple/SoapBundle/ServiceDefinition/Method.php b/src/BeSimple/SoapBundle/ServiceDefinition/Method.php index a93953cf..245c7d7d 100644 --- a/src/BeSimple/SoapBundle/ServiceDefinition/Method.php +++ b/src/BeSimple/SoapBundle/ServiceDefinition/Method.php @@ -13,7 +13,7 @@ namespace BeSimple\SoapBundle\ServiceDefinition; use BeSimple\SoapCommon\Definition\Method as BaseMethod; -use BeSimple\SoapCommon\Definition\Type\TypeRepository; +//use BeSimple\SoapCommon\Definition\Type\TypeRepository; /** * @author Christian Kerl diff --git a/src/BeSimple/SoapBundle/WebServiceContext.php b/src/BeSimple/SoapBundle/WebServiceContext.php index dce81a76..32724b91 100644 --- a/src/BeSimple/SoapBundle/WebServiceContext.php +++ b/src/BeSimple/SoapBundle/WebServiceContext.php @@ -53,6 +53,11 @@ public function getServiceDefinition() $this->serviceDefinition = $this->loader->load($this->options['resource'], $this->options['resource_type']); $this->serviceDefinition->setName($this->options['name']); $this->serviceDefinition->setNamespace($this->options['namespace']); + $this->serviceDefinition->setOptions([ + 'style' => $this->options['style'], + 'use' => $this->options['use'], + 'version' => $this->options['version'], + ]); $cache->write('serviceDefinition), true).');'); } diff --git a/src/BeSimple/SoapCommon/Definition/Method.php b/src/BeSimple/SoapCommon/Definition/Method.php index e79e9d2b..6a19d468 100644 --- a/src/BeSimple/SoapCommon/Definition/Method.php +++ b/src/BeSimple/SoapCommon/Definition/Method.php @@ -61,14 +61,15 @@ public function addHeader($name, $type) $this->headers->add($name, $type); } - public function addInput($name, $type) + public function addInput($name, $type, $nillable = false) { - $this->input->add($name, $type); + $this->input->add($name, $type, $nillable); } - public function setOutput($type) + public function setOutput($name, $type) { - $this->output->add('return', $type); + //$this->output->add('return', $type); + $this->output->add($name, $type); } public function getHeaders() diff --git a/src/BeSimple/SoapWsdl/Dumper/AbstractVersion.php b/src/BeSimple/SoapWsdl/Dumper/AbstractVersion.php index c67c0352..da33be56 100644 --- a/src/BeSimple/SoapWsdl/Dumper/AbstractVersion.php +++ b/src/BeSimple/SoapWsdl/Dumper/AbstractVersion.php @@ -89,7 +89,7 @@ public function addOperation(Method $method) $operation->setAttribute('name', $method->getName()); $soapOperation = $this->document->createElement($this->soapNs.':operation'); - $soapOperation->setAttribute('soapAction', $this->namespace.$method->getName()); + $soapOperation->setAttribute('soapAction', $this->namespace.'/#'.$method->getName()); $operation->appendChild($soapOperation); $this->getBindingNode()->appendChild($operation); @@ -109,8 +109,8 @@ public function addOperation(Method $method) if (!$headers->isEmpty()) { foreach ($headers->all() as $part) { $soapHeader = $this->document->createElement($this->soapNs.':header'); - $soapHeader->setAttribute('part', $part->getName()); $soapHeader->setAttribute('message', $this->typeNs.':'.$headers->getName()); + $soapHeader->setAttribute('part', \SOAP_RPC === $this->style ? $part->getName() : 'parameters'); $soapHeader->setAttribute('use', $use); $soapHeader->setAttribute('namespace', $this->namespace); $soapHeader->setAttribute('encodingStyle', $this->getEncodingStyle()); diff --git a/src/BeSimple/SoapWsdl/Dumper/Dumper.php b/src/BeSimple/SoapWsdl/Dumper/Dumper.php index ef555209..786be81d 100644 --- a/src/BeSimple/SoapWsdl/Dumper/Dumper.php +++ b/src/BeSimple/SoapWsdl/Dumper/Dumper.php @@ -34,13 +34,14 @@ class Dumper const SOAP12_NS = 'soap12'; const SOAP12_NS_URI = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - const SOAP_ENC_NS = 'soap-enc'; + const SOAP_ENC_NS = 'soapenc'; const SOAP_ENC_URI = 'http://schemas.xmlsoap.org/soap/encoding/'; const XSD_NS = 'xsd'; const XSD_NS_URI = 'http://www.w3.org/2001/XMLSchema'; - const TYPES_NS = 'tns'; + const TARGET_NS = 'tns'; + const TYPES_NS = 'ns'; protected $definition; protected $options; @@ -153,28 +154,30 @@ protected function addService() protected function addDefinitions() { $this->domDefinitions = $this->document->createElement('definitions'); + + $this->domDefinitions->setAttribute('name', $this->definition->getName()); + $this->domDefinitions->setAttribute('targetNamespace', $this->definition->getNamespace()); + $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS, static::WSDL_NS_URI); - $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::TYPES_NS, $this->definition->getNamespace()); + $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::TARGET_NS, $this->definition->getNamespace()); + $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::TYPES_NS, $this->definition->getNamespace().'/types'); $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::SOAP_NS, static::SOAP_NS_URI); - $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::SOAP12_NS, static::SOAP12_NS_URI); + //$this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::SOAP12_NS, static::SOAP12_NS_URI); $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::XSD_NS, static::XSD_NS_URI); $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::SOAP_ENC_NS, static::SOAP_ENC_URI); - $this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::WSDL_NS, static::WSDL_NS_URI); + //$this->domDefinitions->setAttributeNS(static::XML_NS_URI, static::XML_NS.':'.static::WSDL_NS, static::WSDL_NS_URI); foreach ($this->definition->getTypeRepository()->getXmlNamespaces() as $prefix => $uri) { $this->domDefinitions->setAttributeNs(static::XML_NS_URI, static::XML_NS.':'.$prefix, $uri); } - $this->domDefinitions->setAttribute('name', $this->definition->getName()); - $this->domDefinitions->setAttribute('targetNamespace', $this->definition->getNamespace()); - $this->document->appendChild($this->domDefinitions); } protected function addMethods() { - $this->addPortType(); $this->addComplexTypes(); + $this->addPortType(); $this->addMessages($this->definition->getMessages()); foreach ($this->definition->getMethods() as $method) { @@ -196,19 +199,43 @@ protected function addMessages(array $messages) $messageElement = $this->document->createElement('message'); $messageElement->setAttribute('name', $message->getName()); - foreach ($message->all() as $part) { - $type = $this->definition->getTypeRepository()->getType($part->getType()); + if ($this->definition->getOption('style') === \SOAP_RPC) { - $partElement = $this->document->createElement('part'); - $partElement->setAttribute('name', $part->getName()); + foreach ($message->all() as $part) { + $type = $this->definition->getTypeRepository()->getType($part->getType()); + + $partElement = $this->document->createElement('part'); + $partElement->setAttribute('name', $part->getName()); - if ($type instanceof ComplexType) { - $partElement->setAttribute('type', static::TYPES_NS.':'.$type->getXmlType()); - } else { - $partElement->setAttribute('type', $type); + if ($type instanceof ComplexType) { + $partElement->setAttribute('type', static::TYPES_NS.':'.$type->getXmlType()); + } else { + $partElement->setAttribute('type', $type); + } + + $messageElement->appendChild($partElement); } + } else { // \SOAP_DOCUMENT (literal-wrapped) + + $partElement = $this->document->createElement('part'); + $partElement->setAttribute('name', 'parameters'); + $partElement->setAttribute('element', static::TYPES_NS.':'.$message->getName()); + $messageElement->appendChild($partElement); + + $paramsComplexType = new ComplexType('array', $message->getName()); + foreach ($message->all() as $part) { + $paramsComplexType->add($part->getName(), $part->getType(), $part->isNillable()); + } + + $this->addComplexType($paramsComplexType); + + $paramsElement = $this->document->createElement(static::XSD_NS.':element'); + $paramsElement->setAttribute('name', $paramsComplexType->getXmlType()); + $paramsElement->setAttribute('type', static::TYPES_NS.':'.$paramsComplexType->getXmlType()); + + $this->domSchema->appendChild($paramsElement); } $this->domDefinitions->appendChild($messageElement); @@ -220,8 +247,10 @@ protected function addComplexTypes() $types = $this->document->createElement('types'); $this->domDefinitions->appendChild($types); + $nsTypes = $this->definition->getNamespace() . '/types'; $this->domSchema = $this->document->createElement(static::XSD_NS.':schema'); - $this->domSchema->setAttribute('targetNamespace', $this->definition->getNamespace()); + $this->domSchema->setAttribute('targetNamespace', $nsTypes); + $this->domSchema->setAttribute(static::XML_NS, $nsTypes); $types->appendChild($this->domSchema); foreach ($this->definition->getTypeRepository()->getComplexTypes() as $type) { @@ -251,6 +280,7 @@ protected function addComplexType(ComplexType $type) $name = $childType->getName(); } + //$element->setAttribute('element', static::TYPES_NS.':'.$name); $element->setAttribute('type', static::TYPES_NS.':'.$name); } else { $element->setAttribute('type', $childType); @@ -290,7 +320,8 @@ protected function addPortOperation(Method $method) } $node = $this->document->createElement($type); - $node->setAttribute('message', static::TYPES_NS.':'.$message->getName()); + $node->setAttribute('message', static::TARGET_NS.':'.$message->getName()); + //$node->setAttribute('name', $message->getName()); $operation->appendChild($node); } @@ -311,11 +342,11 @@ protected function addStylesheet() protected function getVersion($version) { - if (\SOAP_1_2 === $version) { + /*if (\SOAP_1_2 === $version) { return $this->getVersion12(); - } + }*/ - return $this->getVersion11(); + return (\SOAP_1_2 === $version)? $this->getVersion12() : $this->getVersion11(); } protected function getVersion11() @@ -323,10 +354,10 @@ protected function getVersion11() if (!$this->version11) { $this->version11 = new $this->options['version11_class']( static::SOAP_NS, - static::TYPES_NS, + static::TARGET_NS, $this->options['version11_name'], $this->definition->getNamespace(), - static::TYPES_NS.':'.$this->definition->getName().'PortType', + static::TARGET_NS.':'.$this->definition->getName().'PortType', $this->definition->getOption('location'), $this->definition->getOption('style') ); @@ -340,10 +371,10 @@ protected function getVersion12() if (!$this->version12) { $this->version12 = new $this->options['version12_class']( static::SOAP12_NS, - static::TYPES_NS, + static::TARGET_NS, $this->options['version12_name'], $this->definition->getNamespace(), - static::TYPES_NS.':'.$this->definition->getName().'PortType', + static::TARGET_NS.':'.$this->definition->getName().'PortType', $this->definition->getOption('location'), $this->definition->getOption('style') );