Rewrited Definition of WebService and WSDL dumper
This commit is contained in:
parent
391a3f10b8
commit
c830097430
|
@ -64,6 +64,7 @@ class SoapWebServiceController extends ContainerAware
|
|||
$this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request'));
|
||||
$this->soapServer = $webServiceContext
|
||||
->getServerBuilder()
|
||||
->withSoapVersion11()
|
||||
->withHandler($this)
|
||||
->build()
|
||||
;
|
||||
|
|
|
@ -148,9 +148,9 @@ class BeSimpleSoapExtension extends Extension
|
|||
|
||||
$options = $container
|
||||
->getDefinition('besimple.soap.context.'.$bindingSuffix)
|
||||
->getArgument(5);
|
||||
->getArgument(2);
|
||||
|
||||
$definition->replaceArgument(5, array_merge($options, $config));
|
||||
$definition->replaceArgument(2, array_merge($options, $config));
|
||||
}
|
||||
|
||||
private function getCacheType($type)
|
||||
|
|
|
@ -29,10 +29,13 @@
|
|||
<service id="besimple.soap.definition.loader.annot_class" class="%besimple.soap.definition.loader.annot_class.class%" public="false">
|
||||
<tag name="besimple.soap.definition.loader" />
|
||||
<argument type="service" id="annotation_reader" />
|
||||
<argument type="service" id="besimple.soap.type.repository" />
|
||||
</service>
|
||||
|
||||
<service id="besimple.soap.definition.loader.annot_complextype" class="%besimple.soap.definition.loader.annot_complextype.class%" public="false">
|
||||
<tag name="besimple.soap.definition.loader" />
|
||||
<argument type="service" id="annotation_reader" />
|
||||
<argument type="service" id="besimple.soap.type.repository" />
|
||||
</service>
|
||||
</services>
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
<parameter key="besimple.soap.binder.request.documentwrapped.class">BeSimple\SoapBundle\ServiceBinding\DocumentLiteralWrappedRequestMessageBinder</parameter>
|
||||
<parameter key="besimple.soap.binder.request_header.documentwrapped.class">BeSimple\SoapBundle\ServiceBinding\DocumentLiteralWrappedRequestHeaderMessageBinder</parameter>
|
||||
<parameter key="besimple.soap.binder.response.documentwrapped.class">BeSimple\SoapBundle\ServiceBinding\DocumentLiteralWrappedResponseMessageBinder</parameter>
|
||||
<parameter key="besimple.soap.definition.dumper.wsdl.rpcliteral.class">BeSimple\SoapBundle\ServiceDefinition\Dumper\WsdlDumper</parameter>
|
||||
<parameter key="besimple.soap.type.repository.class">BeSimple\SoapBundle\Converter\TypeRepository</parameter>
|
||||
<parameter key="besimple.soap.type.repository.class">BeSimple\SoapCommon\Definition\Type\TypeRepository</parameter>
|
||||
<parameter key="besimple.soap.server.classmap.class">BeSimple\SoapServer\Classmap</parameter>
|
||||
</parameters>
|
||||
|
||||
|
@ -28,9 +27,6 @@
|
|||
|
||||
<service id="besimple.soap.context.rpcliteral" class="%besimple.soap.context.class%" abstract="true">
|
||||
<argument type="service" id="besimple.soap.definition.loader" />
|
||||
<argument type="service" id="besimple.soap.definition.dumper.wsdl.rpcliteral" />
|
||||
<argument type="service" id="besimple.soap.server.classmap" />
|
||||
<argument type="service" id="besimple.soap.type.repository" />
|
||||
<argument type="service" id="besimple.soap.converter.collection" />
|
||||
<argument type="collection">
|
||||
<argument key="cache_dir">%besimple.soap.cache.dir%</argument>
|
||||
|
@ -45,9 +41,6 @@
|
|||
|
||||
<service id="besimple.soap.context.documentwrapped" class="%besimple.soap.context.class%" abstract="true">
|
||||
<argument type="service" id="besimple.soap.definition.loader" />
|
||||
<argument type="service" id="besimple.soap.definition.dumper.wsdl.documentwrapped" />
|
||||
<argument type="service" id="besimple.soap.server.classmap" />
|
||||
<argument type="service" id="besimple.soap.type.repository" />
|
||||
<argument type="service" id="besimple.soap.converter.collection" />
|
||||
<argument type="collection">
|
||||
<argument key="cache_dir">%besimple.soap.cache.dir%</argument>
|
||||
|
@ -60,42 +53,35 @@
|
|||
<argument type="service" id="besimple.soap.cache" />
|
||||
</service>
|
||||
|
||||
<service id="besimple.soap.definition.dumper.wsdl.rpcliteral" class="%besimple.soap.definition.dumper.wsdl.rpcliteral.class%">
|
||||
<argument type="service" id="besimple.soap.definition.loader.annot_complextype" />
|
||||
<argument type="service" id="besimple.soap.type.repository" />
|
||||
<argument type="collection">
|
||||
<argument key="stylesheet">%besimple.soap.definition.dumper.options.stylesheet%</argument>
|
||||
</argument>
|
||||
</service>
|
||||
|
||||
<service id="besimple.soap.server.classmap" class="%besimple.soap.server.classmap.class%" public="false" />
|
||||
|
||||
<service id="besimple.soap.type.repository" class="%besimple.soap.type.repository.class%">
|
||||
<argument type="service" id="besimple.soap.server.classmap" />
|
||||
<call method="addXmlNamespace">
|
||||
<argument>xsd</argument>
|
||||
<argument>http://www.w3.org/2001/XMLSchema</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>string</argument>
|
||||
<argument>xsd:string</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>boolean</argument>
|
||||
<argument>xsd:boolean</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>int</argument>
|
||||
<argument>xsd:int</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>float</argument>
|
||||
<argument>xsd:float</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>date</argument>
|
||||
<argument>xsd:date</argument>
|
||||
</call>
|
||||
<call method="addDefaultTypeMapping">
|
||||
<call method="addType">
|
||||
<argument>dateTime</argument>
|
||||
<argument>xsd:dateTime</argument>
|
||||
</call>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
namespace BeSimple\SoapBundle\ServiceBinding;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
/**
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
|
@ -23,5 +24,5 @@ interface MessageBinderInterface
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function processMessage(Method $messageDefinition, $message, array $definitionComplexTypes = array());
|
||||
}
|
||||
function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
namespace BeSimple\SoapBundle\ServiceBinding;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
|
@ -24,10 +25,11 @@ class RpcLiteralRequestHeaderMessageBinder extends RpcLiteralRequestMessageBinde
|
|||
$this->header = $header;
|
||||
}
|
||||
|
||||
public function processMessage(Method $messageDefinition, $message, array $definitionComplexTypes = array())
|
||||
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->typeRepository = $typeRepository;
|
||||
$headerDefinition = $messageDefinition->getHeaders()->get($this->header);
|
||||
|
||||
return $this->processType($headerDefinition->getType()->getPhpType(), $message, $definitionComplexTypes);
|
||||
return $this->processType($headerDefinition->getType(), $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ namespace BeSimple\SoapBundle\ServiceBinding;
|
|||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Strategy\MethodComplexType;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Strategy\PropertyComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\ArrayOfType;
|
||||
use BeSimple\SoapCommon\Definition\Type\ComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
use BeSimple\SoapCommon\Util\MessageBinder;
|
||||
|
||||
/**
|
||||
|
@ -23,19 +26,20 @@ use BeSimple\SoapCommon\Util\MessageBinder;
|
|||
*/
|
||||
class RpcLiteralRequestMessageBinder implements MessageBinderInterface
|
||||
{
|
||||
private $messageRefs = array();
|
||||
private $definitionComplexTypes;
|
||||
protected $typeRepository;
|
||||
|
||||
public function processMessage(Method $messageDefinition, $message, array $definitionComplexTypes = array())
|
||||
private $messageRefs = array();
|
||||
|
||||
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->definitionComplexTypes = $definitionComplexTypes;
|
||||
$this->typeRepository = $typeRepository;
|
||||
|
||||
$result = array();
|
||||
$i = 0;
|
||||
|
||||
foreach ($messageDefinition->getArguments() as $argument) {
|
||||
foreach ($messageDefinition->getInput()->all() as $argument) {
|
||||
if (isset($message[$i])) {
|
||||
$result[$argument->getName()] = $this->processType($argument->getType()->getPhpType(), $message[$i]);
|
||||
$result[$argument->getName()] = $this->processType($argument->getType(), $message[$i]);
|
||||
}
|
||||
|
||||
$i++;
|
||||
|
@ -48,15 +52,21 @@ class RpcLiteralRequestMessageBinder implements MessageBinderInterface
|
|||
{
|
||||
$isArray = false;
|
||||
|
||||
if (preg_match('/^([^\[]+)\[\]$/', $phpType, $match)) {
|
||||
$type = $this->typeRepository->getType($phpType);
|
||||
if ($type instanceof ArrayOfType) {
|
||||
$isArray = true;
|
||||
$array = array();
|
||||
$phpType = $match[1];
|
||||
$arrayType = $type;
|
||||
|
||||
$type = $this->typeRepository->getType($type->get('item')->getType());
|
||||
}
|
||||
|
||||
// @TODO Fix array reference
|
||||
if (isset($this->definitionComplexTypes[$phpType])) {
|
||||
if ($type instanceof ComplexType) {
|
||||
$phpType = $type->getPhpType();
|
||||
|
||||
if ($isArray) {
|
||||
$array = array();
|
||||
|
||||
if (isset($message->item)) {
|
||||
foreach ($message->item as $complexType) {
|
||||
$array[] = $this->checkComplexType($phpType, $complexType);
|
||||
|
@ -98,12 +108,12 @@ class RpcLiteralRequestMessageBinder implements MessageBinderInterface
|
|||
$this->messageRefs[$hash] = $message;
|
||||
|
||||
$messageBinder = new MessageBinder($message);
|
||||
foreach ($this->definitionComplexTypes[$phpType]['properties'] as $type) {
|
||||
foreach ($this->typeRepository->getType($phpType)->all() as $type) {
|
||||
$property = $type->getName();
|
||||
$value = $messageBinder->readProperty($property);
|
||||
|
||||
if (null !== $value) {
|
||||
$value = $this->processType($type->getValue(), $value);
|
||||
$value = $this->processType($type->getType(), $value);
|
||||
|
||||
$messageBinder->writeProperty($property, $value);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ namespace BeSimple\SoapBundle\ServiceBinding;
|
|||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Strategy\PropertyComplexType;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Strategy\MethodComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\ArrayOfType;
|
||||
use BeSimple\SoapCommon\Definition\Type\ComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
use BeSimple\SoapCommon\Util\MessageBinder;
|
||||
|
||||
/**
|
||||
|
@ -23,26 +26,32 @@ use BeSimple\SoapCommon\Util\MessageBinder;
|
|||
*/
|
||||
class RpcLiteralResponseMessageBinder implements MessageBinderInterface
|
||||
{
|
||||
protected $typeRepository;
|
||||
|
||||
private $messageRefs = array();
|
||||
private $definitionComplexTypes;
|
||||
|
||||
public function processMessage(Method $messageDefinition, $message, array $definitionComplexTypes = array())
|
||||
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->definitionComplexTypes = $definitionComplexTypes;
|
||||
$this->typeRepository = $typeRepository;
|
||||
|
||||
return $this->processType($messageDefinition->getReturn()->getPhpType(), $message);
|
||||
return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message);
|
||||
}
|
||||
|
||||
private function processType($phpType, $message)
|
||||
{
|
||||
$isArray = false;
|
||||
|
||||
if (preg_match('/^([^\[]+)\[\]$/', $phpType, $match)) {
|
||||
$type = $this->typeRepository->getType($phpType);
|
||||
if ($type instanceof ArrayOfType) {
|
||||
$isArray = true;
|
||||
$phpType = $match[1];
|
||||
$arrayType = $type;
|
||||
|
||||
$type = $this->typeRepository->getType($type->get('item')->getType());
|
||||
}
|
||||
|
||||
if (isset($this->definitionComplexTypes[$phpType])) {
|
||||
if ($type instanceof ComplexType) {
|
||||
$phpType = $type->getPhpType();
|
||||
|
||||
if ($isArray) {
|
||||
$array = array();
|
||||
|
||||
|
@ -83,12 +92,12 @@ class RpcLiteralResponseMessageBinder implements MessageBinderInterface
|
|||
}
|
||||
|
||||
$messageBinder = new MessageBinder($message);
|
||||
foreach ($this->definitionComplexTypes[$phpType]['properties'] as $type) {
|
||||
foreach ($this->typeRepository->getType($phpType)->all() as $type) {
|
||||
$property = $type->getName();
|
||||
$value = $messageBinder->readProperty($property);
|
||||
|
||||
if (null !== $value) {
|
||||
$value = $this->processType($type->getValue(), $value);
|
||||
$value = $this->processType($type->getType(), $value);
|
||||
|
||||
$messageBinder->writeProperty($property, $value);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace BeSimple\SoapBundle\ServiceBinding;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Header;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Definition;
|
||||
use BeSimple\SoapBundle\Soap\SoapHeader;
|
||||
|
||||
/**
|
||||
|
@ -40,12 +40,12 @@ class ServiceBinder
|
|||
private $responseMessageBinder;
|
||||
|
||||
/**
|
||||
* @param ServiceDefinition $definition
|
||||
* @param Definition $definition
|
||||
* @param MessageBinderInterface $requestHeaderMessageBinder
|
||||
* @param MessageBinderInterface $requestMessageBinder
|
||||
* @param MessageBinderInterface $responseMessageBinder
|
||||
*/
|
||||
public function __construct(ServiceDefinition $definition, MessageBinderInterface $requestHeaderMessageBinder, MessageBinderInterface $requestMessageBinder, MessageBinderInterface $responseMessageBinder) {
|
||||
public function __construct(Definition $definition, MessageBinderInterface $requestHeaderMessageBinder, MessageBinderInterface $requestMessageBinder, MessageBinderInterface $responseMessageBinder) {
|
||||
$this->definition = $definition;
|
||||
|
||||
$this->requestHeaderMessageBinder = $requestHeaderMessageBinder;
|
||||
|
@ -62,7 +62,7 @@ class ServiceBinder
|
|||
*/
|
||||
public function isServiceHeader($method, $header)
|
||||
{
|
||||
return $this->definition->getMethods()->get($method)->getHeaders()->has($header);
|
||||
return $this->definition->getMethod($method)->getHeader($header);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +72,7 @@ class ServiceBinder
|
|||
*/
|
||||
public function isServiceMethod($method)
|
||||
{
|
||||
return $this->definition->getMethods()->has($method);
|
||||
return null !== $this->definition->getMethod($method);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,11 +84,11 @@ class ServiceBinder
|
|||
*/
|
||||
public function processServiceHeader($method, $header, $data)
|
||||
{
|
||||
$methodDefinition = $this->definition->getMethods()->get($method);
|
||||
$headerDefinition = $methodDefinition->getHeaders()->get($header);
|
||||
$methodDefinition = $this->definition->getMethod($method);
|
||||
$headerDefinition = $methodDefinition->getHeader($header);
|
||||
|
||||
$this->requestHeaderMessageBinder->setHeader($header);
|
||||
$data = $this->requestHeaderMessageBinder->processMessage($methodDefinition, $data, $this->definition->getDefinitionComplexTypes());
|
||||
$data = $this->requestHeaderMessageBinder->processMessage($methodDefinition, $data, $this->definition->getTypeRepository());
|
||||
|
||||
return new SoapHeader($this->definition->getNamespace(), $headerDefinition->getName(), $data);
|
||||
}
|
||||
|
@ -101,11 +101,11 @@ class ServiceBinder
|
|||
*/
|
||||
public function processServiceMethodArguments($method, $arguments)
|
||||
{
|
||||
$methodDefinition = $this->definition->getMethods()->get($method);
|
||||
$methodDefinition = $this->definition->getMethod($method);
|
||||
|
||||
return array_merge(
|
||||
array('_controller' => $methodDefinition->getController()),
|
||||
$this->requestMessageBinder->processMessage($methodDefinition, $arguments, $this->definition->getDefinitionComplexTypes())
|
||||
$this->requestMessageBinder->processMessage($methodDefinition, $arguments, $this->definition->getTypeRepository())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,8 @@ class ServiceBinder
|
|||
*/
|
||||
public function processServiceMethodReturnValue($name, $return)
|
||||
{
|
||||
$methodDefinition = $this->definition->getMethods()->get($name);
|
||||
$methodDefinition = $this->definition->getMethod($name);
|
||||
|
||||
return $this->responseMessageBinder->processMessage($methodDefinition, $return, $this->definition->getDefinitionComplexTypes());
|
||||
return $this->responseMessageBinder->processMessage($methodDefinition, $return, $this->definition->getTypeRepository());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
class Argument
|
||||
{
|
||||
private $name;
|
||||
private $type;
|
||||
|
||||
public function __construct($name = null, Type $type = null)
|
||||
{
|
||||
$this->setName($name);
|
||||
$this->setType($type);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(Type $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
|
@ -48,4 +50,4 @@ class ComplexType
|
|||
{
|
||||
$this->isNillable = (bool) $isNillable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Definition as BaseDefinition;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
/**
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Definition extends BaseDefinition
|
||||
{
|
||||
private $complexTypes;
|
||||
|
||||
public function __construct(TypeRepository $typeRepository)
|
||||
{
|
||||
$this->typeRepository = $typeRepository;
|
||||
|
||||
$this->setOptions(array());
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Dumper;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
|
||||
interface DumperInterface
|
||||
{
|
||||
function dumpServiceDefinition(ServiceDefinition $definition, $endpoint);
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Dumper;
|
||||
|
||||
use BeSimple\SoapBundle\Converter\TypeRepository;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Type;
|
||||
use Zend\Soap\Wsdl as BaseWsdl;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Wsdl extends BaseWsdl
|
||||
{
|
||||
private $typeRepository;
|
||||
|
||||
public function __construct(TypeRepository $typeRepository, $name, $uri, $strategy = true)
|
||||
{
|
||||
$this->typeRepository = $typeRepository;
|
||||
|
||||
parent::__construct($name, $uri, $strategy);
|
||||
}
|
||||
|
||||
public function getType($type)
|
||||
{
|
||||
if ($type instanceof Type) {
|
||||
return $type->getXmlType();
|
||||
}
|
||||
|
||||
if ('\\' === $type[0]) {
|
||||
$type = substr($type, 1);
|
||||
}
|
||||
|
||||
if (!$xmlType = $this->typeRepository->getXmlTypeMapping($type)) {
|
||||
$xmlType = $this->addComplexType($type);
|
||||
}
|
||||
|
||||
return $xmlType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate PHP type into WSDL QName
|
||||
*
|
||||
* @param string $type
|
||||
* @return string QName
|
||||
*/
|
||||
public function translateType($type)
|
||||
{
|
||||
if (isset($this->classMap[$type])) {
|
||||
return $this->classMap[$type];
|
||||
}
|
||||
|
||||
return str_replace('\\', '.', $type);
|
||||
}
|
||||
|
||||
public function addBindingOperationHeader(\DOMElement $bindingOperation, array $headers, array $baseBinding)
|
||||
{
|
||||
foreach ($headers as $header) {
|
||||
$inputNode = $bindingOperation->getElementsByTagName('input')->item(0);
|
||||
|
||||
$headerNode = $this->toDomDocument()->createElement('soap:header');
|
||||
$headerNode->setAttribute('part', $header);
|
||||
|
||||
foreach ($baseBinding as $name => $value) {
|
||||
$headerNode->setAttribute($name, $value);
|
||||
}
|
||||
|
||||
$inputNode->appendChild($headerNode);
|
||||
}
|
||||
|
||||
return $bindingOperation;
|
||||
}
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Dumper;
|
||||
|
||||
use BeSimple\SoapBundle\Converter\TypeRepository;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Type;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader;
|
||||
use BeSimple\SoapBundle\Util\Assert;
|
||||
use BeSimple\SoapBundle\Util\QName;
|
||||
|
||||
/**
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
*/
|
||||
class WsdlDumper implements DumperInterface
|
||||
{
|
||||
private $loader;
|
||||
private $typeRepository;
|
||||
private $options;
|
||||
|
||||
private $wsdl;
|
||||
private $definition;
|
||||
|
||||
public function __construct(AnnotationComplexTypeLoader $loader, TypeRepository $typeRepository, array $options)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
$this->typeRepository = $typeRepository;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function dumpServiceDefinition(ServiceDefinition $definition, $endpoint)
|
||||
{
|
||||
Assert::thatArgumentNotNull('definition', $definition);
|
||||
|
||||
$this->definition = $definition;
|
||||
$this->wsdl = new Wsdl($this->typeRepository, $definition->getName(), $definition->getNamespace(), new WsdlTypeStrategy($this->loader, $definition));
|
||||
$port = $this->wsdl->addPortType($this->getPortTypeName());
|
||||
$binding = $this->wsdl->addBinding($this->getBindingName(), $this->qualify($this->getPortTypeName()));
|
||||
|
||||
$this->wsdl->addSoapBinding($binding, 'rpc');
|
||||
$this->wsdl->addService($this->getServiceName(), $this->getPortName(), $this->qualify($this->getBindingName()), $endpoint);
|
||||
|
||||
foreach ($definition->getMethods() as $method) {
|
||||
$requestHeaderParts =
|
||||
$requestParts =
|
||||
$responseParts = array();
|
||||
|
||||
foreach ($method->getHeaders() as $header) {
|
||||
$requestHeaderParts[$header->getName()] = $this->wsdl->getType($header->getType()->getPhpType());
|
||||
}
|
||||
|
||||
foreach ($method->getArguments() as $argument) {
|
||||
$requestParts[$argument->getName()] = $this->wsdl->getType($argument->getType()->getPhpType());
|
||||
}
|
||||
|
||||
if ($method->getReturn() !== null) {
|
||||
$responseParts['return'] = $this->wsdl->getType($method->getReturn()->getPhpType());
|
||||
}
|
||||
|
||||
if (!empty($requestHeaderParts)) {
|
||||
$this->wsdl->addMessage($this->getRequestHeaderMessageName($method), $requestHeaderParts);
|
||||
}
|
||||
$this->wsdl->addMessage($this->getRequestMessageName($method), $requestParts);
|
||||
$this->wsdl->addMessage($this->getResponseMessageName($method), $responseParts);
|
||||
|
||||
$portOperation = $this->wsdl->addPortOperation(
|
||||
$port,
|
||||
$method->getName(),
|
||||
$this->qualify($this->getRequestMessageName($method)),
|
||||
$this->qualify($this->getResponseMessageName($method))
|
||||
);
|
||||
|
||||
$baseBinding =
|
||||
$inputBinding =
|
||||
$outputBinding = array(
|
||||
'use' => 'literal',
|
||||
'namespace' => $definition->getNamespace(),
|
||||
'encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/',
|
||||
);
|
||||
|
||||
if (!empty($requestParts)) {
|
||||
$portOperation->setAttribute('parameterOrder', implode(' ', array_keys($requestParts)));
|
||||
|
||||
$inputBinding['parts'] = implode(' ', array_keys($requestParts));
|
||||
}
|
||||
|
||||
if (!empty($responseParts)) {
|
||||
$outputBinding['parts'] = implode(' ', array_keys($responseParts));
|
||||
}
|
||||
|
||||
$bindingOperation = $this->wsdl->addBindingOperation(
|
||||
$binding,
|
||||
$method->getName(),
|
||||
$inputBinding,
|
||||
$outputBinding
|
||||
);
|
||||
$bindingOperation = $this->wsdl->addBindingOperationHeader(
|
||||
$bindingOperation,
|
||||
array_keys($requestHeaderParts),
|
||||
array_merge(array('message' => $this->qualify($this->getRequestHeaderMessageName($method))), $baseBinding)
|
||||
);
|
||||
|
||||
$this->wsdl->addSoapOperation($bindingOperation, $this->getSoapOperationName($method));
|
||||
}
|
||||
|
||||
$this->definition = null;
|
||||
|
||||
$dom = $this->wsdl->toDomDocument();
|
||||
$dom->formatOutput = true;
|
||||
|
||||
if ($this->options['stylesheet']) {
|
||||
$stylesheet = $dom->createProcessingInstruction('xml-stylesheet', sprintf('type="text/xsl" href="%s"', $this->options['stylesheet']));
|
||||
|
||||
$dom->insertBefore($stylesheet, $dom->documentElement);
|
||||
}
|
||||
|
||||
return $this->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';
|
||||
}
|
||||
|
||||
protected function getPortTypeName()
|
||||
{
|
||||
return $this->definition->getName().'PortType';
|
||||
}
|
||||
|
||||
protected function getBindingName()
|
||||
{
|
||||
return $this->definition->getName().'Binding';
|
||||
}
|
||||
|
||||
protected function getServiceName()
|
||||
{
|
||||
return $this->definition->getName().'Service';
|
||||
}
|
||||
|
||||
protected function getRequestHeaderMessageName(Method $method)
|
||||
{
|
||||
return $method->getName().'Header';
|
||||
}
|
||||
|
||||
protected function getRequestMessageName(Method $method)
|
||||
{
|
||||
return $method->getName().'Request';
|
||||
}
|
||||
|
||||
protected function getResponseMessageName(Method $method)
|
||||
{
|
||||
return $method->getName().'Response';
|
||||
}
|
||||
|
||||
protected function getSoapOperationName(Method $method)
|
||||
{
|
||||
return $this->definition->getNamespace().$method->getName();
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Dumper;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Strategy\ComplexType;
|
||||
use BeSimple\SoapBundle\Util\String;
|
||||
|
||||
use Zend\Soap\Exception;
|
||||
use Zend\Soap\Wsdl as BaseWsdl;
|
||||
use Zend\Soap\Wsdl\ComplexTypeStrategy\ComplexTypeStrategyInterface;
|
||||
use Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence;
|
||||
|
||||
class WsdlTypeStrategy implements ComplexTypeStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Context WSDL file
|
||||
*
|
||||
* @var \Zend\Soap\Wsdl|null
|
||||
*/
|
||||
private $context;
|
||||
|
||||
private $loader;
|
||||
private $definition;
|
||||
|
||||
private $typeStrategy;
|
||||
private $arrayStrategy;
|
||||
|
||||
public function __construct(AnnotationComplexTypeLoader $loader, ServiceDefinition $definition)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
$this->definition = $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method accepts the current WSDL context file.
|
||||
*
|
||||
* @param \Zend\Soap\Wsdl $context
|
||||
*/
|
||||
public function setContext(BaseWsdl $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a complex type based on a strategy
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return string XSD type
|
||||
*
|
||||
* @throws \Zend\Soap\WsdlException
|
||||
*/
|
||||
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->getArrayStrategy() : $this->getTypeStrategy();
|
||||
|
||||
return $strategy->addComplexType($type);
|
||||
}
|
||||
|
||||
private function getArrayStrategy()
|
||||
{
|
||||
if (!$this->arrayStrategy) {
|
||||
$this->arrayStrategy = new ArrayOfTypeSequence();
|
||||
$this->arrayStrategy->setContext($this->context);
|
||||
}
|
||||
|
||||
return $this->arrayStrategy;
|
||||
}
|
||||
|
||||
private function getTypeStrategy()
|
||||
{
|
||||
if (!$this->typeStrategy) {
|
||||
$this->typeStrategy = new ComplexType($this->loader, $this->definition);
|
||||
$this->typeStrategy->setContext($this->context);
|
||||
}
|
||||
|
||||
return $this->typeStrategy;
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
class Header
|
||||
{
|
||||
private $name;
|
||||
private $type;
|
||||
|
||||
public function __construct($name = null, Type $type = null)
|
||||
{
|
||||
$this->setName($name);
|
||||
$this->setType($type);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
|
@ -14,6 +14,8 @@ namespace BeSimple\SoapBundle\ServiceDefinition\Loader;
|
|||
|
||||
use BeSimple\SoapBundle\ServiceDefinition as Definition;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Annotation;
|
||||
use BeSimple\SoapCommon\Definition\Type\ComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
|
||||
|
@ -26,19 +28,23 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
|||
* Based on \Symfony\Component\Routing\Loader\AnnotationClassLoader
|
||||
*
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class AnnotationClassLoader extends Loader
|
||||
{
|
||||
protected $reader;
|
||||
|
||||
protected $typeRepository;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\Common\Annotations\Reader $reader
|
||||
*/
|
||||
public function __construct(Reader $reader)
|
||||
public function __construct(Reader $reader, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->reader = $reader;
|
||||
$this->typeRepository = $typeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,39 +64,26 @@ class AnnotationClassLoader extends Loader
|
|||
}
|
||||
|
||||
$class = new \ReflectionClass($class);
|
||||
$definition = new Definition\ServiceDefinition();
|
||||
$definition = new Definition\Definition($this->typeRepository);
|
||||
|
||||
$serviceMethodHeaders = array();
|
||||
$sharedHeaders = array();
|
||||
foreach ($this->reader->getClassAnnotations($class) as $annotation) {
|
||||
if ($annotation instanceof Annotation\Header) {
|
||||
$serviceMethodHeaders[$annotation->getValue()] = $annotation;
|
||||
$sharedHeaders[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->getMethods() as $method) {
|
||||
$serviceArguments =
|
||||
$serviceHeaders = array();
|
||||
$serviceHeaders = $sharedHeaders;
|
||||
$serviceArguments = array();
|
||||
$serviceMethod =
|
||||
$serviceReturn = null;
|
||||
|
||||
foreach ($serviceMethodHeaders as $annotation) {
|
||||
$serviceHeaders[$annotation->getValue()] = new Definition\Header(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
|
||||
if ($annotation instanceof Annotation\Header) {
|
||||
$serviceHeaders[$annotation->getValue()] = new Definition\Header(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
$serviceHeaders[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
} elseif ($annotation instanceof Annotation\Param) {
|
||||
$serviceArguments[] = new Definition\Argument(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
$serviceArguments[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
} elseif ($annotation instanceof Annotation\Method) {
|
||||
if ($serviceMethod) {
|
||||
throw new \LogicException(sprintf('@Soap\Method defined twice for "%s".', $method->getName()));
|
||||
|
@ -98,6 +91,7 @@ class AnnotationClassLoader extends Loader
|
|||
|
||||
$serviceMethod = new Definition\Method(
|
||||
$annotation->getValue(),
|
||||
$this->typeRepository,
|
||||
$this->getController($class, $method, $annotation)
|
||||
);
|
||||
} elseif ($annotation instanceof Annotation\Result) {
|
||||
|
@ -105,7 +99,7 @@ class AnnotationClassLoader extends Loader
|
|||
throw new \LogicException(sprintf('@Soap\Result defined twice for "%s".', $method->getName()));
|
||||
}
|
||||
|
||||
$serviceReturn = new Definition\Type($annotation->getPhpType(), $annotation->getXmlType());
|
||||
$serviceReturn = $annotation->getPhpType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,16 +108,21 @@ class AnnotationClassLoader extends Loader
|
|||
}
|
||||
|
||||
if ($serviceMethod) {
|
||||
$serviceMethod->setArguments($serviceArguments);
|
||||
$serviceMethod->setHeaders($serviceHeaders);
|
||||
foreach ($serviceHeaders as $name => $type) {
|
||||
$serviceMethod->addHeader($name, $type);
|
||||
}
|
||||
|
||||
foreach ($serviceArguments as $name => $type) {
|
||||
$serviceMethod->addInput($name, $type);
|
||||
}
|
||||
|
||||
if (!$serviceReturn) {
|
||||
throw new \LogicException(sprintf('@Soap\Result non-existent for "%s".', $method->getName()));
|
||||
}
|
||||
|
||||
$serviceMethod->setReturn($serviceReturn);
|
||||
$serviceMethod->setOutput($this->loadType($serviceReturn));
|
||||
|
||||
$definition->getMethods()->add($serviceMethod);
|
||||
$definition->addMethod($serviceMethod);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,6 +168,30 @@ class AnnotationClassLoader extends Loader
|
|||
return new Definition\Type($phpType, $xmlType);
|
||||
}
|
||||
|
||||
private function loadType($phpType)
|
||||
{
|
||||
if (false !== $arrayOf = $this->typeRepository->getArrayOf($phpType)) {
|
||||
$this->loadType($arrayOf);
|
||||
}
|
||||
|
||||
if (!$this->typeRepository->hasType($phpType)) {
|
||||
$complexTypeResolver = $this->resolve($phpType, 'annotation_complextype');
|
||||
if (!$complexTypeResolver) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
$loaded = $complexTypeResolver->load($phpType);
|
||||
$complexType = new ComplexType($phpType, $loaded['alias']);
|
||||
foreach ($loaded['properties'] as $name => $property) {
|
||||
$complexType->add($name, $this->loadType($property->getValue()), $property->isNillable());
|
||||
}
|
||||
|
||||
$this->typeRepository->addComplexType($complexType);
|
||||
}
|
||||
|
||||
return $phpType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class supports the given resource.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
|
@ -65,4 +65,17 @@ class AnnotationComplexTypeLoader extends AnnotationClassLoader
|
|||
|
||||
return $annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class supports the given resource.
|
||||
*
|
||||
* @param mixed $resource A resource
|
||||
* @param string $type The resource type
|
||||
*
|
||||
* @return Boolean True if this class supports the given resource, false otherwise
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return is_string($resource) && class_exists($resource) && 'annotation_complextype' === $type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Loader;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Argument;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Header;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Type;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
|
||||
use Symfony\Component\Config\Loader\FileLoader;
|
||||
|
||||
class XmlFileLoader extends FileLoader
|
||||
{
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
$path = $this->locator->locate($file);
|
||||
$xml = $this->parseFile($path);
|
||||
|
||||
$definition = new ServiceDefinition();
|
||||
$definition->setName((string) $xml['name']);
|
||||
$definition->setNamespace((string) $xml['namespace']);
|
||||
|
||||
foreach($xml->header as $header) {
|
||||
$definition->getHeaders()->add($this->parseHeader($header));
|
||||
}
|
||||
|
||||
foreach($xml->method as $method) {
|
||||
$definition->getMethods()->add($this->parseMethod($method));
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Header
|
||||
*/
|
||||
protected function parseHeader(\SimpleXMLElement $node)
|
||||
{
|
||||
return new Header((string)$node['name'], $this->parseType($node->type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Method
|
||||
*/
|
||||
protected function parseMethod(\SimpleXMLElement $node)
|
||||
{
|
||||
$method = new Method((string)$node['name'], (string)$node['controller']);
|
||||
|
||||
foreach($node->argument as $argument) {
|
||||
$method->getArguments()->add($this->parseArgument($argument));
|
||||
}
|
||||
|
||||
$method->setReturn($this->parseType($node->return->type));
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Argument
|
||||
*/
|
||||
protected function parseArgument(\SimpleXMLElement $node)
|
||||
{
|
||||
$argument = new Argument((string)$node['name'], $this->parseType($node->type));
|
||||
|
||||
return $argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Type
|
||||
*/
|
||||
protected function parseType(\SimpleXMLElement $node)
|
||||
{
|
||||
$namespaces = $node->getDocNamespaces(true);
|
||||
$qname = explode(':', $node['xml-type'], 2);
|
||||
$xmlType = sprintf('{%s}%s', $namespaces[$qname[0]], $qname[1]);
|
||||
|
||||
return new Type((string)$node['php-type'], $xmlType, (string)$node['converter']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
*
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
protected function parseFile($file)
|
||||
{
|
||||
$dom = new \DOMDocument();
|
||||
libxml_use_internal_errors(true);
|
||||
if (!$dom->load($file, LIBXML_COMPACT)) {
|
||||
throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
|
||||
}
|
||||
if (!$dom->schemaValidate(__DIR__.'/schema/servicedefinition-1.0.xsd')) {
|
||||
throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
|
||||
}
|
||||
$dom->validateOnParse = true;
|
||||
$dom->normalizeDocument();
|
||||
libxml_use_internal_errors(false);
|
||||
|
||||
return simplexml_import_dom($dom);
|
||||
}
|
||||
|
||||
protected function getXmlErrors()
|
||||
{
|
||||
$errors = array();
|
||||
foreach (libxml_get_errors() as $error) {
|
||||
$errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
|
||||
LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
|
||||
$error->code,
|
||||
trim($error->message),
|
||||
$error->file ? $error->file : 'n/a',
|
||||
$error->line,
|
||||
$error->column
|
||||
);
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors(false);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
|
@ -10,36 +12,22 @@
|
|||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
use BeSimple\SoapBundle\Util\Collection;
|
||||
use BeSimple\SoapCommon\Definition\Method as BaseMethod;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
class Method
|
||||
/**
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Method extends BaseMethod
|
||||
{
|
||||
private $name;
|
||||
private $controller;
|
||||
private $arguments;
|
||||
private $headers;
|
||||
private $return;
|
||||
|
||||
public function __construct($name = null, $controller = null, array $headers = array(), array $arguments = array(), Type $return = null)
|
||||
public function __construct($name, TypeRepository $typeRepository, $controller)
|
||||
{
|
||||
$this->setName($name);
|
||||
$this->setController($controller);
|
||||
$this->setHeaders($headers);
|
||||
$this->setArguments($arguments);
|
||||
parent::__construct($name, $typeRepository);
|
||||
|
||||
if ($return) {
|
||||
$this->setReturn($return);
|
||||
}
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->controller = $controller;
|
||||
}
|
||||
|
||||
public function getController()
|
||||
|
@ -47,40 +35,8 @@ class Method
|
|||
return $this->controller;
|
||||
}
|
||||
|
||||
public function setController($controller)
|
||||
public function getVersions()
|
||||
{
|
||||
$this->controller = $controller;
|
||||
return array(\SOAP_1_1);
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = new Collection('getName', 'BeSimple\SoapBundle\ServiceDefinition\Header');
|
||||
$this->headers->addAll($headers);
|
||||
}
|
||||
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->arguments = new Collection('getName', 'BeSimple\SoapBundle\ServiceDefinition\Argument');
|
||||
$this->arguments->addAll($arguments);
|
||||
}
|
||||
|
||||
public function getReturn()
|
||||
{
|
||||
return $this->return;
|
||||
}
|
||||
|
||||
public function setReturn(Type $return)
|
||||
{
|
||||
$this->return = $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
use BeSimple\SoapBundle\Util\Collection;
|
||||
use BeSimple\SoapCommon\Classmap;
|
||||
|
||||
class ServiceDefinition
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* @var \BeSimple\SoapBundle\Util\Collection
|
||||
*/
|
||||
private $methods;
|
||||
|
||||
/**
|
||||
* @var \BeSimple\SoapCommon\Classmap
|
||||
*/
|
||||
private $classmap;
|
||||
|
||||
private $complexTypes = array();
|
||||
|
||||
public function __construct($name = null, $namespace = null, array $methods = array(), Classmap $classmap = null)
|
||||
{
|
||||
$this->setName($name);
|
||||
$this->setNamespace($namespace);
|
||||
|
||||
$this->methods = new Collection('getName', 'BeSimple\SoapBundle\ServiceDefinition\Method');
|
||||
$this->setMethods($methods);
|
||||
|
||||
$this->classmap = $classmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \BeSimple\SoapBundle\Util\Collection
|
||||
*/
|
||||
public function getMethods()
|
||||
{
|
||||
return $this->methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $methods
|
||||
*/
|
||||
public function setMethods(array $methods)
|
||||
{
|
||||
$this->methods->addAll($methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAllTypes()
|
||||
{
|
||||
$types = array();
|
||||
|
||||
foreach ($this->methods as $method) {
|
||||
foreach ($method->getArguments() as $argument) {
|
||||
$types[] = $argument->getType();
|
||||
}
|
||||
|
||||
foreach ($method->getHeaders() as $header) {
|
||||
$types[] = $header->getType();
|
||||
}
|
||||
|
||||
$types[] = $method->getReturn();
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
public function getClassmap()
|
||||
{
|
||||
return $this->classmap ?: array();
|
||||
}
|
||||
|
||||
public function setClassmap(Classmap $classmap)
|
||||
{
|
||||
$this->classmap = $classmap;
|
||||
}
|
||||
|
||||
public function hasDefinitionComplexType($type)
|
||||
{
|
||||
return isset($this->complexTypes[$type]);
|
||||
}
|
||||
|
||||
public function addDefinitionComplexType($type, array $definition)
|
||||
{
|
||||
if ($this->hasDefinitionComplexType($type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->complexTypes[$type] = $definition;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDefinitionComplexTypes()
|
||||
{
|
||||
return $this->complexTypes;
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition\Strategy;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader;
|
||||
use Zend\Soap\Wsdl;
|
||||
use Zend\Soap\Wsdl\ComplexTypeStrategy\AbstractComplexTypeStrategy;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class ComplexType extends AbstractComplexTypeStrategy
|
||||
{
|
||||
private $loader;
|
||||
private $definition;
|
||||
|
||||
public function __construct(AnnotationComplexTypeLoader $loader, $definition)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
$this->definition = $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a complex type by recursivly using all the class properties fetched via Reflection.
|
||||
*
|
||||
* @param string $type Name of the class to be specified
|
||||
* @return string XSD Type for the given PHP type
|
||||
*/
|
||||
public function addComplexType($classname)
|
||||
{
|
||||
$classmap = $this->definition->getClassmap();
|
||||
if ($classmap->hasByClassname($classname)) {
|
||||
return 'tns:'.$classmap->getByClassname($classname);
|
||||
}
|
||||
|
||||
if (!$this->loader->supports($classname)) {
|
||||
throw new \InvalidArgumentException(sprintf('Cannot add ComplexType "%s" because it is not an object or the class could not be found.', $classname));
|
||||
}
|
||||
|
||||
$definitionComplexType = $this->loader->load($classname);
|
||||
$classnameAlias = isset($definitionComplexType['alias']) ? $definitionComplexType['alias'] : $classname;
|
||||
|
||||
$type = $this->getContext()->translateType($classnameAlias);
|
||||
$xmlType = 'tns:'.$type;
|
||||
|
||||
// Register type here to avoid recursion
|
||||
$classmap->add($type, $classname);
|
||||
$this->addXmlDefinition($definitionComplexType, $classname, $type);
|
||||
|
||||
return $xmlType;
|
||||
}
|
||||
|
||||
private function addXmlDefinition(array $definitionComplexType, $classname, $type)
|
||||
{
|
||||
$dom = $this->getContext()->toDomDocument();
|
||||
$complexType = $dom->createElement('xsd:complexType');
|
||||
$complexType->setAttribute('name', $type);
|
||||
|
||||
$all = $dom->createElement('xsd:all');
|
||||
|
||||
$elements = array();
|
||||
foreach ($definitionComplexType['properties'] as $property) {
|
||||
$element = $dom->createElement('xsd:element');
|
||||
$element->setAttribute('name', $property->getName());
|
||||
$element->setAttribute('type', $this->getContext()->getType($property->getValue()));
|
||||
|
||||
if ($property->isNillable()) {
|
||||
$element->setAttribute('nillable', 'true');
|
||||
}
|
||||
|
||||
$all->appendChild($element);
|
||||
}
|
||||
|
||||
$complexType->appendChild($all);
|
||||
$this->getContext()->getSchema()->appendChild($complexType);
|
||||
|
||||
$this->definition->addDefinitionComplexType($classname, $definitionComplexType);
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapBundle\ServiceDefinition;
|
||||
|
||||
class Type
|
||||
{
|
||||
private $phpType;
|
||||
private $xmlType;
|
||||
private $converter;
|
||||
|
||||
public function __construct($phpType = null, $xmlType = null, $converter = null)
|
||||
{
|
||||
$this->setPhpType($phpType);
|
||||
$this->setXmlType($xmlType);
|
||||
$this->setConverter($converter);
|
||||
}
|
||||
|
||||
public function getPhpType()
|
||||
{
|
||||
return $this->phpType;
|
||||
}
|
||||
|
||||
public function setPhpType($phpType)
|
||||
{
|
||||
$phpType = $phpType;
|
||||
if ($phpType[0] == '\\') {
|
||||
$phpType = substr($phpType, 1);
|
||||
}
|
||||
|
||||
$this->phpType = $phpType;
|
||||
}
|
||||
|
||||
public function getXmlType()
|
||||
{
|
||||
return $this->xmlType;
|
||||
}
|
||||
|
||||
public function setXmlType($xmlType)
|
||||
{
|
||||
$this->xmlType = $xmlType;
|
||||
}
|
||||
|
||||
public function getConverter()
|
||||
{
|
||||
return $this->converter;
|
||||
}
|
||||
|
||||
public function setConverter($converter)
|
||||
{
|
||||
$this->converter = $converter;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
* This file is part of the BeSimpleSoapBundle.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
|
@ -10,13 +11,12 @@
|
|||
|
||||
namespace BeSimple\SoapBundle;
|
||||
|
||||
use BeSimple\SoapBundle\Converter\TypeRepository;
|
||||
use BeSimple\SoapBundle\ServiceBinding\MessageBinderInterface;
|
||||
use BeSimple\SoapBundle\ServiceBinding\ServiceBinder;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Dumper\DumperInterface;
|
||||
|
||||
use BeSimple\SoapCommon\Classmap;
|
||||
use BeSimple\SoapCommon\Converter\TypeConverterCollection;
|
||||
use BeSimple\SoapWsdl\Dumper\Dumper;
|
||||
use BeSimple\SoapServer\SoapServerBuilder;
|
||||
|
||||
use Symfony\Component\Config\ConfigCache;
|
||||
|
@ -26,43 +26,31 @@ use Symfony\Component\Config\Loader\LoaderInterface;
|
|||
* WebServiceContext.
|
||||
*
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class WebServiceContext
|
||||
{
|
||||
private $classmap;
|
||||
|
||||
private $typeRepository;
|
||||
private $converterRepository;
|
||||
|
||||
private $wsdlFileDumper;
|
||||
|
||||
private $options;
|
||||
|
||||
private $serviceDefinition;
|
||||
private $serviceBinder;
|
||||
private $serverBuilder;
|
||||
|
||||
public function __construct(LoaderInterface $loader, DumperInterface $dumper, Classmap $classmap, TypeRepository $typeRepository, TypeConverterCollection $converters, array $options)
|
||||
public function __construct(LoaderInterface $loader, TypeConverterCollection $converters, array $options)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
$this->wsdlFileDumper = $dumper;
|
||||
|
||||
$this->classmap = $classmap;
|
||||
|
||||
$this->typeRepository = $typeRepository;
|
||||
$this->converters = $converters;
|
||||
|
||||
// Issue #6: keep the debug because the cache is invalid
|
||||
$options['debug'] = true;
|
||||
$this->options = $options;
|
||||
$this->loader = $loader;
|
||||
$this->converters = $converters;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function getServiceDefinition()
|
||||
{
|
||||
if (null === $this->serviceDefinition) {
|
||||
$cacheDefinition = new ConfigCache(sprintf('%s/%s.definition.php', $this->options['cache_dir'], $this->options['name']), $this->options['debug']);
|
||||
if ($cacheDefinition->isFresh()) {
|
||||
$this->serviceDefinition = include (string) $cacheDefinition;
|
||||
$cache = new ConfigCache(sprintf('%s/%s.definition.php', $this->options['cache_dir'], $this->options['name']), $this->options['debug']);
|
||||
if ($cache->isFresh()) {
|
||||
$this->serviceDefinition = include (string) $cache;
|
||||
} else {
|
||||
if (!$this->loader->supports($this->options['resource'], $this->options['resource_type'])) {
|
||||
throw new \LogicException(sprintf('Cannot load "%s" (%s)', $this->options['resource'], $this->options['resource_type']));
|
||||
|
@ -72,10 +60,7 @@ class WebServiceContext
|
|||
$this->serviceDefinition->setName($this->options['name']);
|
||||
$this->serviceDefinition->setNamespace($this->options['namespace']);
|
||||
|
||||
$this->serviceDefinition->setClassmap($this->classmap);
|
||||
$this->classmap = null;
|
||||
|
||||
$this->typeRepository->fixTypeInformation($this->serviceDefinition);
|
||||
$cache->write('<?php return unserialize('.var_export(serialize($this->serviceDefinition), true).');');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,19 +74,21 @@ class WebServiceContext
|
|||
|
||||
public function getWsdlFile($endpoint = null)
|
||||
{
|
||||
$file = sprintf('%s/%s.%s.wsdl', $this->options['cache_dir'], $this->options['name'], md5($endpoint));
|
||||
$cacheWsdl = new ConfigCache($file, $this->options['debug']);
|
||||
$file = sprintf ('%s/%s.%s.wsdl', $this->options['cache_dir'], $this->options['name'], md5($endpoint));
|
||||
$cache = new ConfigCache($file, $this->options['debug']);
|
||||
|
||||
if(!$cacheWsdl->isFresh()) {
|
||||
$serviceDefinition = $this->getServiceDefinition();
|
||||
if(!$cache->isFresh()) {
|
||||
$definition = $this->getServiceDefinition();
|
||||
|
||||
$cacheWsdl->write($this->wsdlFileDumper->dumpServiceDefinition($serviceDefinition, $endpoint));
|
||||
if ($endpoint) {
|
||||
$definition->setOption('location', $endpoint);
|
||||
}
|
||||
|
||||
$cacheDefinition = new ConfigCache(sprintf('%s/%s.definition.php', $this->options['cache_dir'], $this->options['name']), $this->options['debug']);
|
||||
$cacheDefinition->write('<?php return unserialize('.var_export(serialize($serviceDefinition), true).');');
|
||||
$dumper = new Dumper($definition);
|
||||
$cache->write($dumper->dump());
|
||||
}
|
||||
|
||||
return (string) $cacheWsdl;
|
||||
return (string) $cache;
|
||||
}
|
||||
|
||||
public function getServiceBinder()
|
||||
|
@ -123,7 +110,7 @@ class WebServiceContext
|
|||
if (null === $this->serverBuilder) {
|
||||
$this->serverBuilder = SoapServerBuilder::createWithDefaults()
|
||||
->withWsdl($this->getWsdlFile())
|
||||
->withClassmap($this->getServiceDefinition()->getClassmap())
|
||||
->withClassmap($this->getServiceDefinition()->getTypeRepository()->getClassmap())
|
||||
->withTypeConverters($this->converters)
|
||||
;
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Definition
|
||||
{
|
||||
protected $name;
|
||||
protected $namespace;
|
||||
|
||||
protected $typeRepository;
|
||||
|
||||
protected $options;
|
||||
protected $methods;
|
||||
|
||||
public function __construct($name, $namespace, TypeRepository $typeRepository, array $options = array())
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->namespace = $namespace;
|
||||
$this->methods = array();
|
||||
|
||||
$this->typeRepository = $typeRepository;
|
||||
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = array(
|
||||
'version' => \SOAP_1_1,
|
||||
'style' => \SOAP_RPC,
|
||||
'use' => \SOAP_LITERAL,
|
||||
'location' => null,
|
||||
);
|
||||
|
||||
$invalid = array();
|
||||
foreach ($options as $key => $value) {
|
||||
if (array_key_exists($key, $this->options)) {
|
||||
$this->options[$key] = $value;
|
||||
} else {
|
||||
$invalid[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($invalid) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the following options: "%s"', implode('", "', $invalid)));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
if (!array_key_exists($key, $this->options)) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key));
|
||||
}
|
||||
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOption($key)
|
||||
{
|
||||
if (!array_key_exists($key, $this->options)) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key));
|
||||
}
|
||||
|
||||
return $this->options[$key];
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
public function getType($phpType)
|
||||
{
|
||||
return $this->types[$phpType];
|
||||
}
|
||||
|
||||
public function addType($phpType, $xmlType)
|
||||
{
|
||||
if (isset($$this->types[$phpType])) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
$this->types[$phpType] = $xmlType;
|
||||
}
|
||||
|
||||
public function getMessages()
|
||||
{
|
||||
$messages = array();
|
||||
foreach ($this->methods as $method) {
|
||||
$messages[] = $method->getHeaders();
|
||||
$messages[] = $method->getInput();
|
||||
$messages[] = $method->getOutput();
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
public function getMethod($name, $default = null)
|
||||
{
|
||||
return isset($this->methods[$name]) ? $this->methods[$name] : $default;
|
||||
}
|
||||
|
||||
public function getMethods()
|
||||
{
|
||||
return $this->methods;
|
||||
}
|
||||
|
||||
public function addMethod(Method $method)
|
||||
{
|
||||
$name = $method->getName();
|
||||
if (isset($this->methods[$name])) {
|
||||
throw new \Exception(sprintf('The method "%s" already exists', $name));
|
||||
}
|
||||
|
||||
$this->methods[$name] = $method;
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
public function getTypeRepository()
|
||||
{
|
||||
return $this->typeRepository;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeInterface;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Message
|
||||
{
|
||||
protected $name;
|
||||
protected $parts;
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->parts = array();
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $this->parts;
|
||||
}
|
||||
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
return isset($this->parts[$name]) ? $this->parts[$name] : $default;
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return 0 === count($this->parts) ? true : false;
|
||||
}
|
||||
|
||||
public function add($name, $phpType, $nillable = false)
|
||||
{
|
||||
if ($phpType instanceof TypeInterface) {
|
||||
$phpType = $phpType->getPhpType();
|
||||
}
|
||||
|
||||
$this->parts[$name] = new Part($name, $phpType, $nillable);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Method
|
||||
{
|
||||
private $name;
|
||||
|
||||
private $headers;
|
||||
private $input;
|
||||
private $output;
|
||||
private $fault;
|
||||
|
||||
public function __construct($name, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
$this->headers = new Message($name.'Header', $typeRepository);
|
||||
$this->input = new Message($name.'Request', $typeRepository);
|
||||
$this->output = new Message($name.'Response', $typeRepository);
|
||||
$this->fault = new Message($name.'Fault', $typeRepository);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
public function getVersions()
|
||||
{
|
||||
return array(\SOAP_1_1, \SOAP_1_2);
|
||||
}
|
||||
|
||||
public function getUse()
|
||||
{
|
||||
return \SOAP_LITERAL;
|
||||
}
|
||||
|
||||
public function addHeader($name, $type)
|
||||
{
|
||||
$this->headers->add($name, $type);
|
||||
}
|
||||
|
||||
public function addInput($name, $type)
|
||||
{
|
||||
$this->input->add($name, $type);
|
||||
}
|
||||
|
||||
public function setOutput($type)
|
||||
{
|
||||
$this->output->add('return', $type);
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function getHeader($name, $default = null)
|
||||
{
|
||||
return $this->headers->get($name, $default);
|
||||
}
|
||||
|
||||
public function getInput()
|
||||
{
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function getOutput()
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
public function getFault()
|
||||
{
|
||||
return $this->fault;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Part
|
||||
{
|
||||
protected $name;
|
||||
protected $type;
|
||||
protected $nillable;
|
||||
|
||||
public function __construct($name, $type, $nillable = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
$this->setNillable($nillable);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function isNillable()
|
||||
{
|
||||
return $this->nillable;
|
||||
}
|
||||
|
||||
public function setNillable($nillable)
|
||||
{
|
||||
$this->nillable = (boolean) $nillable;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition\Type;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class ArrayOfType extends ComplexType
|
||||
{
|
||||
public function __construct($phpType, $arrayOf, $xmlTypeOf)
|
||||
{
|
||||
if ($arrayOf instanceof TypeInterface) {
|
||||
$arrayOf = $arrayOf->getPhpType();
|
||||
}
|
||||
|
||||
parent::__construct($phpType, 'ArrayOf'.ucfirst($xmlTypeOf ?: $arrayOf));
|
||||
|
||||
$this->add('item', $arrayOf);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition\Type;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Message;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class ComplexType extends Message implements TypeInterface
|
||||
{
|
||||
public function __construct($phpType, $xmlType)
|
||||
{
|
||||
parent::__construct($xmlType);
|
||||
|
||||
$this->phpType = $phpType;
|
||||
$this->xmlType = $xmlType;
|
||||
}
|
||||
|
||||
public function getPhpType()
|
||||
{
|
||||
return $this->phpType;
|
||||
}
|
||||
|
||||
public function getXmlType()
|
||||
{
|
||||
return $this->xmlType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition\Type;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Type implements TypeInterface
|
||||
{
|
||||
protected $phpType;
|
||||
protected $xmlType;
|
||||
|
||||
public function __construct($phpType, $xmlType)
|
||||
{
|
||||
$this->phpType = $phpType;
|
||||
$this->xmlType = $xmlType;
|
||||
}
|
||||
|
||||
public function getPhpType()
|
||||
{
|
||||
return $this->phpType;
|
||||
}
|
||||
|
||||
public function getXmlType()
|
||||
{
|
||||
return $this->xmlType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition\Type;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
interface TypeInterface
|
||||
{
|
||||
public function getPhpType();
|
||||
|
||||
public function getXmlType();
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapCommon\Definition\Type;
|
||||
|
||||
use BeSimple\SoapCommon\Classmap;
|
||||
|
||||
/**
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class TypeRepository
|
||||
{
|
||||
const ARRAY_SUFFIX = '[]';
|
||||
|
||||
protected $xmlNamespaces = array();
|
||||
protected $types = array();
|
||||
|
||||
protected $classmap;
|
||||
|
||||
public function __construct(Classmap $classmap = null)
|
||||
{
|
||||
$this->classmap = $classmap;
|
||||
}
|
||||
|
||||
public function getXmlNamespaces()
|
||||
{
|
||||
return $this->xmlNamespaces;
|
||||
}
|
||||
public function getXmlNamespace($prefix)
|
||||
{
|
||||
return $this->xmlNamespaces[$prefix];
|
||||
}
|
||||
|
||||
public function addXmlNamespace($prefix, $url)
|
||||
{
|
||||
$this->xmlNamespaces[$prefix] = $url;
|
||||
}
|
||||
|
||||
public function getComplexTypes()
|
||||
{
|
||||
$types = array();
|
||||
foreach ($this->types as $type) {
|
||||
if ($type instanceof ComplexType) {
|
||||
$types[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
public function getType($phpType)
|
||||
{
|
||||
if (!$this->hasType($phpType)) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
return $this->types[$phpType];
|
||||
}
|
||||
|
||||
public function addType($phpType, $xmlType)
|
||||
{
|
||||
return $this->types[$phpType] = $xmlType;
|
||||
}
|
||||
|
||||
public function addComplexType(ComplexType $type)
|
||||
{
|
||||
$phpType = $type->getPhpType();
|
||||
|
||||
$this->types[$phpType] = $type;
|
||||
$this->addClassmap($type->getXmlType(), $phpType);
|
||||
}
|
||||
|
||||
public function hasType($type)
|
||||
{
|
||||
if ($type instanceof TypeInterface) {
|
||||
$phpType = $type->getPhpType();
|
||||
|
||||
return !(!$this->hasType($phpType) || $type !== $this->getType($phpType));
|
||||
}
|
||||
|
||||
if (isset($this->types[$type])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (false !== $arrayOf = $this->getArrayOf($type)) {
|
||||
if ($this->hasType($arrayOf)) {
|
||||
$xmlTypeOf = null;
|
||||
$arrayOfType = $this->getType($arrayOf);
|
||||
if ($arrayOfType instanceof ComplexType) {
|
||||
$xmlTypeOf = $arrayOfType->getXmlType();
|
||||
}
|
||||
|
||||
$arrayType = new ArrayOfType($type, $arrayOf, $xmlTypeOf);
|
||||
$this->addType($type, $arrayType);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getArrayOf($arrayType)
|
||||
{
|
||||
if (!preg_match('#(.*)'.preg_quote(static::ARRAY_SUFFIX, '#').'$#', $arrayType, $match)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $match[1];
|
||||
}
|
||||
|
||||
public function getClassmap()
|
||||
{
|
||||
return $this->classmap;
|
||||
}
|
||||
|
||||
protected function addClassmap($xmlType, $phpType)
|
||||
{
|
||||
if (!$this->classmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->classmap->add($xmlType, $phpType);
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ class SoapRequest extends CommonSoapRequest
|
|||
{
|
||||
$content = is_null($content) ? file_get_contents("php://input") : $content;
|
||||
$location = self::getCurrentUrl();
|
||||
$action = $_SERVER[SoapMessage::SOAP_ACTION_HEADER];
|
||||
$action = isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null;
|
||||
$contentType = $_SERVER[SoapMessage::CONTENT_TYPE_HEADER];
|
||||
|
||||
$request = new SoapRequest();
|
||||
|
@ -68,4 +68,4 @@ class SoapRequest extends CommonSoapRequest
|
|||
$url .= isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,4 +158,4 @@ class SoapServer extends \SoapServer
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapWsdl\Dumper;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Method;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
abstract class AbstractVersion implements VersionInterface
|
||||
{
|
||||
protected $soapNs;
|
||||
|
||||
protected $typeNs;
|
||||
|
||||
protected $name;
|
||||
|
||||
protected $namespace;
|
||||
|
||||
protected $portTypeName;
|
||||
|
||||
protected $location;
|
||||
|
||||
protected $style;
|
||||
|
||||
protected $transport;
|
||||
|
||||
protected $document;
|
||||
|
||||
protected $bindingNode;
|
||||
|
||||
protected $servicePortNode;
|
||||
|
||||
public function __construct($soapNs, $typeNs, $name, $namespace, $portTypeName, $location, $style = \SOAP_RPC, $transport = 'http://schemas.xmlsoap.org/soap/http')
|
||||
{
|
||||
$this->soapNs = $soapNs;
|
||||
$this->typeNs = $typeNs;
|
||||
|
||||
$this->name = $name;
|
||||
$this->namespace = $namespace;
|
||||
$this->portTypeName = $portTypeName;
|
||||
|
||||
$this->location = $location;
|
||||
$this->style = $style;
|
||||
$this->transport = $transport;
|
||||
|
||||
$this->document = new \DOMDocument('1.0', 'utf-8');
|
||||
}
|
||||
|
||||
public function getBindingNode()
|
||||
{
|
||||
if (!$this->bindingNode) {
|
||||
$this->bindingNode = $this->document->createElement('binding');
|
||||
$this->bindingNode->setAttribute('name', $this->name.'Binding');
|
||||
$this->bindingNode->setAttribute('type', $this->portTypeName);
|
||||
|
||||
$this->addSoapBinding();
|
||||
}
|
||||
|
||||
return $this->bindingNode;
|
||||
}
|
||||
|
||||
public function getServicePortNode()
|
||||
{
|
||||
if (!$this->servicePortNode) {
|
||||
$this->servicePortNode = $this->document->createElement('port');
|
||||
$this->servicePortNode->setAttribute('name', $this->name.'Port');
|
||||
$this->servicePortNode->setAttribute('binding', $this->typeNs.':'.$this->name.'Binding');
|
||||
|
||||
$this->addSoapAddress();
|
||||
}
|
||||
|
||||
return $this->servicePortNode;
|
||||
}
|
||||
|
||||
public function addOperation(Method $method)
|
||||
{
|
||||
$operation = $this->document->createElement('operation');
|
||||
$operation->setAttribute('name', $method->getName());
|
||||
|
||||
$soapOperation = $this->document->createElement($this->soapNs.':operation');
|
||||
$soapOperation->setAttribute('soapAction', $this->namespace.$method->getName());
|
||||
$operation->appendChild($soapOperation);
|
||||
|
||||
$this->getBindingNode()->appendChild($operation);
|
||||
|
||||
$use = \SOAP_LITERAL === $method->getUse() ? 'literal' : 'encoded';
|
||||
|
||||
$input = $this->document->createElement('input');
|
||||
$operation->appendChild($input);
|
||||
|
||||
$soapBody = $this->document->createElement($this->soapNs.':body');
|
||||
$soapBody->setAttribute('use', $use);
|
||||
$soapBody->setAttribute('namespace', $this->namespace);
|
||||
$soapBody->setAttribute('encodingStyle', $this->getEncodingStyle());
|
||||
$input->appendChild($soapBody);
|
||||
|
||||
$headers = $method->getHeaders();
|
||||
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('use', $use);
|
||||
$soapHeader->setAttribute('namespace', $this->namespace);
|
||||
$soapHeader->setAttribute('encodingStyle', $this->getEncodingStyle());
|
||||
$input->appendChild($soapHeader);
|
||||
}
|
||||
}
|
||||
|
||||
$output = $this->document->createElement('output');
|
||||
$soapBody = $this->document->createElement($this->soapNs.':body');
|
||||
$soapBody->setAttribute('use', $use);
|
||||
$soapBody->setAttribute('namespace', $this->namespace);
|
||||
$soapBody->setAttribute('encodingStyle', $this->getEncodingStyle());
|
||||
$output->appendChild($soapBody);
|
||||
$operation->appendChild($output);
|
||||
}
|
||||
|
||||
protected function addSoapBinding()
|
||||
{
|
||||
$soapBinding = $this->document->createElement($this->soapNs.':binding');
|
||||
$soapBinding->setAttribute('transport', $this->transport);
|
||||
$soapBinding->setAttribute('style', \SOAP_RPC === $this->style ? 'rpc' : 'document');
|
||||
|
||||
$this->bindingNode->appendChild($soapBinding);
|
||||
|
||||
return $soapBinding;
|
||||
}
|
||||
|
||||
protected function addSoapAddress()
|
||||
{
|
||||
$soapAddress = $this->document->createElement($this->soapNs.':address');
|
||||
$soapAddress->setAttribute('location', $this->location);
|
||||
|
||||
$this->servicePortNode->appendChild($soapAddress);
|
||||
|
||||
return $soapAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,345 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapWsdl\Dumper;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Definition;
|
||||
use BeSimple\SoapCommon\Definition\Method;
|
||||
use BeSimple\SoapCommon\Definition\Part;
|
||||
use BeSimple\SoapCommon\Definition\Type\ArrayOfType;
|
||||
use BeSimple\SoapCommon\Definition\Type\ComplexType;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Dumper
|
||||
{
|
||||
const XML_NS = 'xmlns';
|
||||
const XML_NS_URI = 'http://www.w3.org/2000/xmlns/';
|
||||
|
||||
const WSDL_NS = 'wsdl';
|
||||
const WSDL_NS_URI = 'http://schemas.xmlsoap.org/wsdl/';
|
||||
|
||||
const SOAP_NS = 'soap';
|
||||
const SOAP_NS_URI = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
||||
|
||||
const SOAP12_NS = 'soap12';
|
||||
const SOAP12_NS_URI = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
||||
|
||||
const SOAP_ENC_NS = 'soap-enc';
|
||||
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';
|
||||
|
||||
protected $definition;
|
||||
protected $options;
|
||||
|
||||
protected $version11;
|
||||
protected $version12;
|
||||
|
||||
protected $document;
|
||||
protected $domDefinitions;
|
||||
protected $domSchema;
|
||||
protected $domService;
|
||||
protected $domPortType;
|
||||
|
||||
public function __construct(Definition $definition, array $options = array())
|
||||
{
|
||||
$this->definition = $definition;
|
||||
$this->document = new \DOMDocument('1.0', 'utf-8');
|
||||
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = array(
|
||||
'version11_class' => 'BeSimple\\SoapWsdl\\Dumper\\Version11',
|
||||
'version12_class' => 'BeSimple\\SoapWsdl\\Dumper\\Version12',
|
||||
'version11_name' => $this->definition->getName(),
|
||||
'version12_name' => $this->definition->getName().'12',
|
||||
);
|
||||
|
||||
$invalid = array();
|
||||
foreach ($options as $key => $value) {
|
||||
if (array_key_exists($key, $this->options)) {
|
||||
$this->options[$key] = $value;
|
||||
} else {
|
||||
$invalid[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($invalid) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the following options: "%s"', implode('", "', $invalid)));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
if (!array_key_exists($key, $this->options)) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key));
|
||||
}
|
||||
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOption($key)
|
||||
{
|
||||
if (!array_key_exists($key, $this->options)) {
|
||||
throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key));
|
||||
}
|
||||
|
||||
return $this->options[$key];
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
$this->addDefinitions();
|
||||
$this->addMethods();
|
||||
$this->addService();
|
||||
|
||||
foreach (array($this->version11, $this->version12) as $version) {
|
||||
if (!$version) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->appendVersion($version);
|
||||
}
|
||||
|
||||
$this->document->formatOutput = true;
|
||||
|
||||
return $this->document->saveXML();
|
||||
}
|
||||
|
||||
protected function appendVersion(VersionInterface $version)
|
||||
{
|
||||
$binding = $version->getBindingNode();
|
||||
$binding = $this->document->importNode($binding, true);
|
||||
$this->domDefinitions->appendChild($binding);
|
||||
|
||||
$servicePort = $version->getServicePortNode();
|
||||
$servicePort = $this->document->importNode($servicePort, true);
|
||||
$this->domService->appendChild($servicePort);
|
||||
}
|
||||
|
||||
protected function addService()
|
||||
{
|
||||
$this->domService = $this->document->createElement('service');
|
||||
$this->domService->setAttribute('name', $this->definition->getName().'Service');
|
||||
|
||||
$this->domDefinitions->appendChild($this->domService);
|
||||
|
||||
return $this->domService;
|
||||
}
|
||||
|
||||
protected function addDefinitions()
|
||||
{
|
||||
$this->domDefinitions = $this->document->createElement('definitions');
|
||||
$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::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::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);
|
||||
|
||||
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->addMessages($this->definition->getMessages());
|
||||
|
||||
foreach ($this->definition->getMethods() as $method) {
|
||||
$this->addPortOperation($method);
|
||||
|
||||
foreach ($method->getVersions() as $version) {
|
||||
$this->getVersion($version)->addOperation($method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function addMessages(array $messages)
|
||||
{
|
||||
foreach ($messages as $message) {
|
||||
if ($message->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$messageElement = $this->document->createElement('message');
|
||||
$messageElement->setAttribute('name', $message->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);
|
||||
}
|
||||
|
||||
$messageElement->appendChild($partElement);
|
||||
}
|
||||
|
||||
$this->domDefinitions->appendChild($messageElement);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addComplexTypes()
|
||||
{
|
||||
$types = $this->document->createElement('types');
|
||||
$this->domDefinitions->appendChild($types);
|
||||
|
||||
$this->domSchema = $this->document->createElement(static::XSD_NS.':schema');
|
||||
$this->domSchema->setAttribute('targetNamespace', $this->definition->getNamespace());
|
||||
$types->appendChild($this->domSchema);
|
||||
|
||||
foreach ($this->definition->getTypeRepository()->getComplexTypes() as $type) {
|
||||
$this->addComplexType($type);
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
protected function addComplexType(ComplexType $type)
|
||||
{
|
||||
$complexType = $this->document->createElement(static::XSD_NS.':complexType');
|
||||
$complexType->setAttribute('name', $type->getXmlType());
|
||||
|
||||
$all = $this->document->createElement(static::XSD_NS.':'.($type instanceof ArrayOfType ? 'sequence' : 'all'));
|
||||
$complexType->appendChild($all);
|
||||
|
||||
foreach ($type->all() as $child) {
|
||||
$childType = $this->definition->getTypeRepository()->getType($child->getType());
|
||||
|
||||
$element = $this->document->createElement(static::XSD_NS.':element');
|
||||
$element->setAttribute('name', $child->getName());
|
||||
|
||||
if ($childType instanceof ComplexType) {
|
||||
$name = $child->getName();
|
||||
if ($childType instanceof ArrayOfType) {
|
||||
$name = $childType->getName();
|
||||
} elseif ($type instanceof ArrayOfType && $childType instanceof ComplexType) {
|
||||
$name = $childType->getXmlType();
|
||||
}
|
||||
|
||||
$element->setAttribute('type', static::TYPES_NS.':'.$name);
|
||||
} else {
|
||||
$element->setAttribute('type', $childType);
|
||||
}
|
||||
|
||||
if ($child->isNillable()) {
|
||||
$element->setAttribute('nillable', 'true');
|
||||
}
|
||||
|
||||
if ($type instanceof ArrayOfType) {
|
||||
$element->setAttribute('minOccurs', 0);
|
||||
$element->setAttribute('maxOccurs', 'unbounded');
|
||||
}
|
||||
|
||||
$all->appendChild($element);
|
||||
}
|
||||
|
||||
$this->domSchema->appendChild($complexType);
|
||||
}
|
||||
|
||||
protected function addPortType()
|
||||
{
|
||||
$this->domPortType = $this->document->createElement('portType');
|
||||
$this->domPortType->setAttribute('name', $this->definition->getName().'PortType');
|
||||
|
||||
$this->domDefinitions->appendChild($this->domPortType);
|
||||
}
|
||||
|
||||
protected function addPortOperation(Method $method)
|
||||
{
|
||||
$operation = $this->document->createElement('operation');
|
||||
$operation->setAttribute('name', $method->getName());
|
||||
|
||||
foreach (array('input' => $method->getInput(), 'output' => $method->getOutput(), 'fault' => $method->getFault()) as $type => $message) {
|
||||
if ($message->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$node = $this->document->createElement($type);
|
||||
$node->setAttribute('message', static::TYPES_NS.':'.$message->getName());
|
||||
|
||||
$operation->appendChild($node);
|
||||
}
|
||||
|
||||
$this->domPortType->appendChild($operation);
|
||||
|
||||
return $operation;
|
||||
}
|
||||
|
||||
protected function getVersion($version)
|
||||
{
|
||||
if (\SOAP_1_2 === $version) {
|
||||
return $this->getVersion12();
|
||||
}
|
||||
|
||||
return $this->getVersion11();
|
||||
}
|
||||
|
||||
protected function getVersion11()
|
||||
{
|
||||
if (!$this->version11) {
|
||||
$this->version11 = new $this->options['version11_class'](
|
||||
static::SOAP_NS,
|
||||
static::TYPES_NS,
|
||||
$this->options['version11_name'],
|
||||
$this->definition->getNamespace(),
|
||||
static::TYPES_NS.':'.$this->definition->getName().'PortType',
|
||||
$this->definition->getOption('location'),
|
||||
$this->definition->getOption('style')
|
||||
);
|
||||
}
|
||||
|
||||
return $this->version11;
|
||||
}
|
||||
|
||||
protected function getVersion12()
|
||||
{
|
||||
if (!$this->version12) {
|
||||
$this->version12 = new $this->options['version12_class'](
|
||||
static::SOAP12_NS,
|
||||
static::TYPES_NS,
|
||||
$this->options['version12_name'],
|
||||
$this->definition->getNamespace(),
|
||||
static::TYPES_NS.':'.$this->definition->getName().'PortType',
|
||||
$this->definition->getOption('location'),
|
||||
$this->definition->getOption('style')
|
||||
);
|
||||
}
|
||||
|
||||
return $this->version12;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapWsdl\Dumper;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Version11 extends AbstractVersion
|
||||
{
|
||||
public function getEncodingStyle()
|
||||
{
|
||||
return 'http://schemas.xmlsoap.org/soap/encoding/';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapWsdl\Dumper;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class Version12 extends AbstractVersion
|
||||
{
|
||||
public function getEncodingStyle()
|
||||
{
|
||||
return 'http://www.w3.org/2001/12/soap-encoding';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace BeSimple\SoapWsdl\Dumper;
|
||||
|
||||
use BeSimple\SoapCommon\Definition\Method;
|
||||
|
||||
/**
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
interface VersionInterface
|
||||
{
|
||||
public function getBindingNode();
|
||||
|
||||
public function getServicePortNode();
|
||||
|
||||
public function addOperation(Method $method);
|
||||
|
||||
public function getEncodingStyle();
|
||||
}
|
Loading…
Reference in New Issue