diff --git a/Cache.php b/Cache.php new file mode 100644 index 0000000..f5a4f88 --- /dev/null +++ b/Cache.php @@ -0,0 +1,41 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapBundle; + +use BeSimple\SoapCommon\Cache as BaseCache; + +/** + * @author Francis Besset + */ +class Cache +{ + public function __construct($disabled, $type, $directory, $lifetime = null, $limit = null) + { + $isEnabled = $disabled ? BaseCache::DISABLED : BaseCache::ENABLED; + + BaseCache::setEnabled($isEnabled); + + if (BaseCache::ENABLED == BaseCache::isEnabled()) { + BaseCache::setType($type); + BaseCache::setDirectory($directory); + + if (null !== $lifetime) { + BaseCache::setLifetime($lifetime); + } + + if (null !== $limit) { + BaseCache::setLimit($limit); + } + } + } +} \ No newline at end of file diff --git a/Controller/SoapWebServiceController.php b/Controller/SoapWebServiceController.php index fc93eb8..fee611d 100644 --- a/Controller/SoapWebServiceController.php +++ b/Controller/SoapWebServiceController.php @@ -58,9 +58,11 @@ class SoapWebServiceController extends ContainerAware $this->serviceBinder = $webServiceContext->getServiceBinder(); $this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request')); - $this->soapServer = $webServiceContext->getServerFactory()->create($this->soapRequest, $this->getResponse()); - - $this->soapServer->setObject($this); + $this->soapServer = $webServiceContext + ->getServerBuilder() + ->withHandler($this) + ->build() + ; ob_start(); $this->soapServer->handle($this->soapRequest->getSoapMessage()); diff --git a/Converter/ConverterRepository.php b/Converter/ConverterRepository.php deleted file mode 100644 index a3d9392..0000000 --- a/Converter/ConverterRepository.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Converter; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * @author Christian Kerl - */ -class ConverterRepository -{ - private $typeConverters = array(); - - public function addTypeConverter(TypeConverterInterface $converter) - { - $this->typeConverters[] = $converter; - } - - public function getTypeConverters() - { - return $this->typeConverters; - } -} diff --git a/Converter/DateTimeTypeConverter.php b/Converter/DateTimeTypeConverter.php deleted file mode 100644 index 9f692fc..0000000 --- a/Converter/DateTimeTypeConverter.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Converter; - -use BeSimple\SoapBundle\Soap\SoapRequest; -use BeSimple\SoapBundle\Soap\SoapResponse; -use BeSimple\SoapBundle\Util\String; - -/** - * @author Christian Kerl - */ -class DateTimeTypeConverter implements TypeConverterInterface -{ - public function getTypeNamespace() - { - return 'http://www.w3.org/2001/XMLSchema'; - } - - public function getTypeName() - { - return 'dateTime'; - } - - public function convertXmlToPhp(SoapRequest $request, $data) - { - $doc = new \DOMDocument(); - $doc->loadXML($data); - - return new \DateTime($doc->textContent); - } - - public function convertPhpToXml(SoapResponse $response, $data) - { - return sprintf('<%1$s>%2$s', $this->getTypeName(), $data->format('Y-m-d\TH:i:sP')); - } -} diff --git a/Converter/DateTypeConverter.php b/Converter/DateTypeConverter.php deleted file mode 100644 index 61f7119..0000000 --- a/Converter/DateTypeConverter.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Converter; - -use BeSimple\SoapBundle\Soap\SoapRequest; -use BeSimple\SoapBundle\Soap\SoapResponse; -use BeSimple\SoapBundle\Util\String; - -/** - * @author Francis Besset - */ -class DateTypeConverter implements TypeConverterInterface -{ - public function getTypeNamespace() - { - return 'http://www.w3.org/2001/XMLSchema'; - } - - public function getTypeName() - { - return 'date'; - } - - public function convertXmlToPhp(SoapRequest $request, $data) - { - $doc = new \DOMDocument(); - $doc->loadXML($data); - - return new \DateTime($doc->textContent); - } - - public function convertPhpToXml(SoapResponse $response, $data) - { - return sprintf('<%1$s>%2$s', $this->getTypeName(), $data->format('Y-m-d')); - } -} diff --git a/Converter/TypeConverterInterface.php b/Converter/TypeConverterInterface.php deleted file mode 100644 index ae74ed3..0000000 --- a/Converter/TypeConverterInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Converter; - -use BeSimple\SoapBundle\Soap\SoapRequest; -use BeSimple\SoapBundle\Soap\SoapResponse; - -/** - * @author Christian Kerl - */ -interface TypeConverterInterface -{ - function getTypeNamespace(); - - function getTypeName(); - - function convertXmlToPhp(SoapRequest $request, $data); - - function convertPhpToXml(SoapResponse $response, $data); -} \ No newline at end of file diff --git a/DependencyInjection/BeSimpleSoapExtension.php b/DependencyInjection/BeSimpleSoapExtension.php index 5870366..941cbf0 100644 --- a/DependencyInjection/BeSimpleSoapExtension.php +++ b/DependencyInjection/BeSimpleSoapExtension.php @@ -1,8 +1,10 @@ + * (c) Francis Besset * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. @@ -10,6 +12,8 @@ namespace BeSimple\SoapBundle\DependencyInjection; +use BeSimple\SoapCommon\Cache; + use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -22,6 +26,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; * BeSimpleSoapExtension. * * @author Christian Kerl + * @author Francis Besset */ class BeSimpleSoapExtension extends Extension { @@ -44,6 +49,12 @@ class BeSimpleSoapExtension extends Extension $config = $processor->process($configuration->getConfigTree(), $configs); + $this->registerCacheConfiguration($config['cache'], $container, $loader); + + if (!empty($config['clients'])) { + $this->registerClientConfiguration($config['clients'], $container, $loader); + } + $container->setParameter('besimple.soap.definition.dumper.options.stylesheet', $config['wsdl_dumper']['stylesheet']); foreach($config['services'] as $name => $serviceConfig) { @@ -52,6 +63,74 @@ class BeSimpleSoapExtension extends Extension } } + private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('soap.xml'); + + $config['type'] = $this->getCacheType($config['type']); + + foreach (array('type', 'lifetime', 'limit') as $key) { + $container->setParameter('besimple.soap.cache.'.$key, $config[$key]); + } + } + + private function registerClientConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('client.xml'); + + foreach ($config as $client => $options) { + $definition = new DefinitionDecorator('besimple.soap.client.builder'); + $context = $container->setDefinition(sprintf('besimple.soap.client.builder.%s', $client), $definition); + + $definition->replaceArgument(0, $options['wsdl']); + + $defOptions = $container + ->getDefinition('besimple.soap.client.builder') + ->getArgument(1); + + foreach (array('cache_type', 'user_agent') as $key) { + if (isset($options[$key])) { + $defOptions[$key] = $options[$key]; + } + } + + if (isset($defOptions['cache_type'])) { + $defOptions['cache_type'] = $this->getCacheType($defOptions['cache_type']); + } + + $definition->replaceArgument(1, $defOptions); + + if (!empty($options['classmap'])) { + $classmap = $this->createClientClassmap($client, $options['classmap'], $container); + $definition->replaceArgument(2, new Reference($classmap)); + } else { + $definition->replaceArgument(2, null); + } + + $this->createClient($client, $container); + } + } + + private function createClientClassmap($client, array $classmap, ContainerBuilder $container) + { + $definition = new DefinitionDecorator('besimple.soap.classmap'); + $context = $container->setDefinition(sprintf('besimple.soap.classmap.%s', $client), $definition); + + $definition->setMethodCalls(array( + array('set', array($classmap)), + )); + + return sprintf('besimple.soap.classmap.%s', $client); + } + + private function createClient($client, ContainerBuilder $container) + { + $definition = new DefinitionDecorator('besimple.soap.client'); + $context = $container->setDefinition(sprintf('besimple.soap.client.%s', $client), $definition); + + $definition->setFactoryService(sprintf('besimple.soap.client.builder.%s', $client)); + } + private function createWebServiceContext(array $config, ContainerBuilder $container) { $bindingSuffix = $this->bindingConfigToServiceSuffixMap[$config['binding']]; @@ -61,10 +140,31 @@ class BeSimpleSoapExtension extends Extension $definition = new DefinitionDecorator('besimple.soap.context.'.$bindingSuffix); $context = $container->setDefinition($contextId, $definition); + if (isset($config['cache_type'])) { + $config['cache_type'] = $this->getCacheType($config['cache_type']); + } + $options = $container ->getDefinition('besimple.soap.context.'.$bindingSuffix) - ->getArgument(4); + ->getArgument(5); - $definition->replaceArgument(4, array_merge($options, $config)); + $definition->replaceArgument(5, array_merge($options, $config)); + } + + private function getCacheType($type) + { + switch ($type) { + case 'none': + return Cache::TYPE_NONE; + + case 'disk': + return Cache::TYPE_DISK; + + case 'memory': + return Cache::TYPE_MEMORY; + + case 'disk_memory': + return Cache::TYPE_DISK_MEMORY; + } } } diff --git a/DependencyInjection/Compiler/TypeConverterPass.php b/DependencyInjection/Compiler/TypeConverterPass.php index be97bb6..828c9c9 100644 --- a/DependencyInjection/Compiler/TypeConverterPass.php +++ b/DependencyInjection/Compiler/TypeConverterPass.php @@ -23,14 +23,14 @@ class TypeConverterPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { - if (false === $container->hasDefinition('besimple.soap.converter.repository')) { + if (false === $container->hasDefinition('besimple.soap.converter.collection')) { return; } - $definition = $container->getDefinition('besimple.soap.converter.repository'); + $definition = $container->getDefinition('besimple.soap.converter.collection'); foreach ($container->findTaggedServiceIds('besimple.soap.converter') as $id => $attributes) { - $definition->addMethodCall('addTypeConverter', array(new Reference($id))); + $definition->addMethodCall('add', array(new Reference($id))); } } } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 0f538cc..c56f3c9 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1,8 +1,10 @@ + * (c) Francis Besset * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. @@ -17,9 +19,12 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; * WebServiceExtension configuration structure. * * @author Christian Kerl + * @author Francis Besset */ class Configuration { + private $cacheTypes = array('none', 'disk', 'memory', 'disk_memory'); + /** * Generates the configuration tree. * @@ -30,12 +35,62 @@ class Configuration $treeBuilder = new TreeBuilder(); $rootNode = $treeBuilder->root('be_simple_soap'); + $this->addCacheSection($rootNode); + $this->addClientSection($rootNode); $this->addServicesSection($rootNode); $this->addWsdlDumperSection($rootNode); return $treeBuilder->buildTree(); } + private function addCacheSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('cache') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('type') + ->defaultValue('disk') + ->validate() + ->ifNotInArray($this->cacheTypes) + ->thenInvalid(sprintf('The cache type has to be either %s', implode(', ', $this->cacheTypes))) + ->end() + ->end() + ->scalarNode('lifetime')->defaultNull()->end() + ->scalarNode('limit')->defaultNull()->end() + ->end() + ->end() + ->end() + ; + } + + private function addClientSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('clients') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('wsdl')->isRequired()->end() + ->scalarNode('user_agent')->end() + ->scalarNode('cache_type') + ->validate() + ->ifNotInArray($this->cacheTypes) + ->thenInvalid(sprintf('The cache type has to be either %s', implode(', ', $this->cacheTypes))) + ->end() + ->end() + ->arrayNode('classmap') + ->useAttributeAsKey('name') + ->prototype('scalar') + ->end() + ->end() + ->end() + ->end() + ; + } + private function addServicesSection(ArrayNodeDefinition $rootNode) { $rootNode @@ -60,6 +115,12 @@ class Configuration ->thenInvalid("Service binding style has to be either 'rpc-literal' or 'document-wrapped'") ->end() ->end() + ->scalarNode('cache_type') + ->validate() + ->ifNotInArray($this->cacheTypes) + ->thenInvalid(sprintf('The cache type has to be either %s', implode(', ', $this->cacheTypes))) + ->end() + ->end() ->end() ->end() ->end() diff --git a/Resources/config/client.xml b/Resources/config/client.xml new file mode 100644 index 0000000..939e470 --- /dev/null +++ b/Resources/config/client.xml @@ -0,0 +1,27 @@ + + + + + BeSimple\SoapBundle\Soap\SoapClientBuilder + BeSimple\SoapCommon\Classmap + + + + + + + %kernel.debug% + + + + + + + + + + + + diff --git a/Resources/config/converters.xml b/Resources/config/converters.xml index ec6e5c5..f3f9c52 100644 --- a/Resources/config/converters.xml +++ b/Resources/config/converters.xml @@ -5,13 +5,13 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - BeSimple\SoapBundle\Converter\ConverterRepository - BeSimple\SoapBundle\Converter\DateTimeTypeConverter - BeSimple\SoapBundle\Converter\DateTypeConverter + BeSimple\SoapCommon\Converter\TypeConverterCollection + BeSimple\SoapCommon\Converter\DateTimeTypeConverter + BeSimple\SoapCommon\Converter\DateTypeConverter - + diff --git a/Resources/config/soap.xml b/Resources/config/soap.xml new file mode 100644 index 0000000..3fb3d4c --- /dev/null +++ b/Resources/config/soap.xml @@ -0,0 +1,21 @@ + + + + + BeSimple\SoapBundle\Cache + %kernel.cache_dir%/besimple/soap + + + + + %kernel.debug% + %besimple.soap.cache.type% + %besimple.soap.cache.directory% + %besimple.soap.cache.lifetime% + %besimple.soap.cache.limit% + + + + diff --git a/Resources/config/webservice.xml b/Resources/config/webservice.xml index a33b0c2..95e97b6 100644 --- a/Resources/config/webservice.xml +++ b/Resources/config/webservice.xml @@ -15,6 +15,7 @@ BeSimple\SoapBundle\ServiceBinding\DocumentLiteralWrappedResponseMessageBinder BeSimple\SoapBundle\ServiceDefinition\Dumper\WsdlDumper BeSimple\SoapBundle\Converter\TypeRepository + BeSimple\SoapCommon\Classmap @@ -23,39 +24,48 @@ + - + %besimple.soap.cache_dir% %kernel.debug% + null %besimple.soap.binder.request_header.rpcliteral.class% %besimple.soap.binder.request.rpcliteral.class% %besimple.soap.binder.response.rpcliteral.class% + + - + %besimple.soap.cache_dir% %kernel.debug% + null %besimple.soap.binder.request_header.documentwrapped.class% %besimple.soap.binder.request.documentwrapped.class% %besimple.soap.binder.response.documentwrapped.class% + + %besimple.soap.definition.dumper.options.stylesheet% + + xsd diff --git a/Resources/doc/cache.rst b/Resources/doc/cache.rst new file mode 100644 index 0000000..0090361 --- /dev/null +++ b/Resources/doc/cache.rst @@ -0,0 +1,26 @@ +Cache +===== + +Configuration +------------- + +Configure the cache of PHP Soap WSDL in your config file: + +.. code-block:: yaml + + # app/config/config.yml + be_simple_soap: + cache: + type: disk + lifetime: 86400 + limit: 5 + +The cache type can be: **none**, **disk** (default value), **memory**, **disk_memory**. + +The lifetime in seconds of a WSDL file in the cache (**86400 is the default value by PHP**). + +The limit is the maximum number of in-memory cached WSDL files (**5 is the default value by PHP**). + +If you want more information you can visit the following page `PHP Soap runtime configuration`_. + +.. _`PHP Soap runtime configuration`: http://www.php.net/manual/en/soap.configuration.php \ No newline at end of file diff --git a/Resources/doc/index.rst b/Resources/doc/index.rst index 19be4f2..9182aa0 100644 --- a/Resources/doc/index.rst +++ b/Resources/doc/index.rst @@ -1,9 +1,11 @@ +================== BeSimpleSoapBundle ================== The BeSimpleSoapBundle is a Symfony2 bundle to build WSDL and SOAP based web services. It is based on the `ckWebServicePlugin`_ for symfony. +--------------- Reference Guide --------------- @@ -11,19 +13,25 @@ Reference Guide :maxdepth: 1 :numbered: - reference/installation - reference/configuration - reference/types + installation + cache -Tutorial --------- +---------- +SoapServer +---------- .. toctree:: :maxdepth: 1 :numbered: - tutorial/array - tutorial/complex_type - tutorial/header + soapserver/configuration + soapserver/types + soapserver/tutorials + +---------- +SoapClient +---------- + +Coming soon. .. _`ckWebServicePlugin`: http://www.symfony-project.org/plugins/ckWebServicePlugin \ No newline at end of file diff --git a/Resources/doc/reference/installation.rst b/Resources/doc/installation.rst similarity index 52% rename from Resources/doc/reference/installation.rst rename to Resources/doc/installation.rst index 495bec3..7a6c2e1 100644 --- a/Resources/doc/reference/installation.rst +++ b/Resources/doc/installation.rst @@ -4,8 +4,39 @@ Installation Requirements ------------ -Install and enable PHP's SOAP extension -Download `Zend\\Soap`_ and `Zend\\Mime`_ or add in `deps` file +Install and enable PHP's SOAP extension. + +Download `BeSimple\\SoapCommon`_ and `BeSimple\\SoapServer`_ (only for the server part) and/or `BeSimple\\SoapClient`_ (only for ther client part). + +.. code-block:: ini + + ; deps file + [BeSimple\SoapCommon] + git=http://github.com/BeSimple/SoapCommon + target=/besimple-soapcommon + + [BeSimple\SoapClient] + git=http://github.com/BeSimple/SoapClient + target=/besimple-soapclient + + [BeSimple\SoapServer] + git=http://github.com/BeSimple/SoapServer + target=/besimple-soapserver + + +Add `BeSimple` libraries in autoload.php + +.. code-block:: php + + // app/autoload.php + $loader->registerNamespaces(array( + 'BeSimple\\SoapCommon' => __DIR__.'/../vendor/besimple-soapcommon', + 'BeSimple\\SoapServer' => __DIR__.'/../vendor/besimple-soapserver', + 'BeSimple\\SoapClient' => __DIR__.'/../vendor/besimple-soapclient', + // your other namespaces + )); + +Download `Zend\\Soap`_ and `Zend\\Mime`_ or add in `deps` file. `Zend` library is required only for the server part. .. code-block:: ini @@ -67,4 +98,7 @@ Add `BeSimpleSoapBundle` in your Kernel class .. _`Zend\\Soap`: http://github.com/BeSimple/zend-soap .. _`Zend\\Mime`: http://github.com/BeSimple/zend-mime +.. _`BeSimple\\SoapCommon`: http://github.com/BeSimple/BeSimpleSoapCommon +.. _`BeSimple\\SoapServer`: http://github.com/BeSimple/BeSimpleSoapServer +.. _`BeSimple\\SoapClient`: http://github.com/BeSimple/BeSimpleSoapClient .. _`Download`: http://github.com/BeSimple/BeSimpleSoapBundle diff --git a/Resources/doc/reference/configuration.rst b/Resources/doc/soapserver/configuration.rst similarity index 91% rename from Resources/doc/reference/configuration.rst rename to Resources/doc/soapserver/configuration.rst index 1ccd620..1662e86 100644 --- a/Resources/doc/reference/configuration.rst +++ b/Resources/doc/soapserver/configuration.rst @@ -50,4 +50,9 @@ Annotations for Controllers { return $this->container->get('besimple.soap.response')->setReturnValue(sprintf('Hello %s!', $name)); } - } \ No newline at end of file + } + +Get your WSDL +------------- + +To access your WSDL go to the following address: http://localhost/app_dev.php/ws/DemoApi?wsdl diff --git a/Resources/doc/tutorial/array.rst b/Resources/doc/soapserver/tutorial/array.rst similarity index 100% rename from Resources/doc/tutorial/array.rst rename to Resources/doc/soapserver/tutorial/array.rst diff --git a/Resources/doc/tutorial/complex_type.rst b/Resources/doc/soapserver/tutorial/complex_type.rst similarity index 100% rename from Resources/doc/tutorial/complex_type.rst rename to Resources/doc/soapserver/tutorial/complex_type.rst diff --git a/Resources/doc/tutorial/header.rst b/Resources/doc/soapserver/tutorial/header.rst similarity index 100% rename from Resources/doc/tutorial/header.rst rename to Resources/doc/soapserver/tutorial/header.rst diff --git a/Resources/doc/soapserver/tutorials.rst b/Resources/doc/soapserver/tutorials.rst new file mode 100644 index 0000000..d1d36a4 --- /dev/null +++ b/Resources/doc/soapserver/tutorials.rst @@ -0,0 +1,9 @@ +Tutorials +========= + +.. toctree:: + :maxdepth: 1 + + tutorial/array + tutorial/complex_type + tutorial/header diff --git a/Resources/doc/reference/types.rst b/Resources/doc/soapserver/types.rst similarity index 100% rename from Resources/doc/reference/types.rst rename to Resources/doc/soapserver/types.rst diff --git a/ServiceDefinition/Dumper/WsdlDumper.php b/ServiceDefinition/Dumper/WsdlDumper.php index 97517f7..bf348e2 100644 --- a/ServiceDefinition/Dumper/WsdlDumper.php +++ b/ServiceDefinition/Dumper/WsdlDumper.php @@ -18,21 +18,25 @@ use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader; use BeSimple\SoapBundle\Util\Assert; use BeSimple\SoapBundle\Util\QName; +use BeSimple\SoapCommon\Classmap; + /** * @author Christian Kerl */ class WsdlDumper implements DumperInterface { private $loader; + private $classmap; private $typeRepository; private $options; private $wsdl; private $definition; - public function __construct(AnnotationComplexTypeLoader $loader, TypeRepository $typeRepository, array $options) + public function __construct(AnnotationComplexTypeLoader $loader, Classmap $classmap, TypeRepository $typeRepository, array $options) { $this->loader = $loader; + $this->classmap = $classmap; $this->typeRepository = $typeRepository; $this->options = $options; } @@ -42,7 +46,7 @@ class WsdlDumper implements DumperInterface Assert::thatArgumentNotNull('definition', $definition); $this->definition = $definition; - $this->wsdl = new Wsdl($this->typeRepository, $definition->getName(), $definition->getNamespace(), new WsdlTypeStrategy($this->loader, $definition)); + $this->wsdl = new Wsdl($this->typeRepository, $definition->getName(), $definition->getNamespace(), new WsdlTypeStrategy($this->loader, $this->classmap, $definition)); $port = $this->wsdl->addPortType($this->getPortTypeName()); $binding = $this->wsdl->addBinding($this->getBindingName(), $this->qualify($this->getPortTypeName())); diff --git a/ServiceDefinition/Dumper/WsdlTypeStrategy.php b/ServiceDefinition/Dumper/WsdlTypeStrategy.php index 62610e8..1d35d9c 100644 --- a/ServiceDefinition/Dumper/WsdlTypeStrategy.php +++ b/ServiceDefinition/Dumper/WsdlTypeStrategy.php @@ -15,6 +15,8 @@ use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader; use BeSimple\SoapBundle\ServiceDefinition\Strategy\ComplexType; use BeSimple\SoapBundle\Util\String; +use BeSimple\SoapCommon\Classmap; + use Zend\Soap\Exception; use Zend\Soap\Wsdl as BaseWsdl; use Zend\Soap\Wsdl\Strategy; @@ -30,14 +32,16 @@ class WsdlTypeStrategy implements Strategy private $context; private $loader; + private $classmap; private $definition; private $typeStrategy; private $arrayStrategy; - public function __construct(AnnotationComplexTypeLoader $loader, ServiceDefinition $definition) + public function __construct(AnnotationComplexTypeLoader $loader, Classmap $classmap, ServiceDefinition $definition) { $this->loader = $loader; + $this->classmap = $classmap; $this->definition = $definition; } @@ -86,7 +90,7 @@ class WsdlTypeStrategy implements Strategy private function getTypeStrategy() { if (!$this->typeStrategy) { - $this->typeStrategy = new ComplexType($this->loader, $this->definition); + $this->typeStrategy = new ComplexType($this->loader, $this->classmap, $this->definition); $this->typeStrategy->setContext($this->context); } diff --git a/ServiceDefinition/Strategy/ComplexType.php b/ServiceDefinition/Strategy/ComplexType.php index 8af3fb1..b608902 100644 --- a/ServiceDefinition/Strategy/ComplexType.php +++ b/ServiceDefinition/Strategy/ComplexType.php @@ -12,6 +12,7 @@ namespace BeSimple\SoapBundle\ServiceDefinition\Strategy; use BeSimple\SoapBundle\ServiceDefinition\Loader\AnnotationComplexTypeLoader; +use BeSimple\SoapCommon\Classmap; use Zend\Soap\Wsdl; use Zend\Soap\Wsdl\Strategy\AbstractStrategy; @@ -21,11 +22,13 @@ use Zend\Soap\Wsdl\Strategy\AbstractStrategy; class ComplexType extends AbstractStrategy { private $loader; + private $classmap; private $definition; - public function __construct(AnnotationComplexTypeLoader $loader, $definition) + public function __construct(AnnotationComplexTypeLoader $loader, Classmap $classmap, $definition) { $this->loader = $loader; + $this->classmap = $classmap; $this->definition = $definition; } @@ -50,6 +53,8 @@ class ComplexType extends AbstractStrategy $soapTypeName = Wsdl::translateType($type); $soapType = 'tns:'.$soapTypeName; + $this->classmap->add($soapTypeName, $type); + // Register type here to avoid recursion $this->getContext()->addType($type, $soapType); diff --git a/Soap/SoapClientBuilder.php b/Soap/SoapClientBuilder.php new file mode 100644 index 0000000..c21993f --- /dev/null +++ b/Soap/SoapClientBuilder.php @@ -0,0 +1,77 @@ +checkOptions($options); + + $this + ->withWsdl($wsdl) + ->withTrace($options['debug']) + ; + + if (isset($options['user_agent'])) { + $this->withUserAgent($options['user_agent']); + } + + if (isset($options['cache_type'])) { + $this->withWsdlCache($options['cache_type']); + } + + if ($classmap) { + $this->withClassmap($classmap); + } + + if ($converters) { + $this->withTypeConverters($converters); + } + } + + public function build() + { + if (!$this->soapClient) { + $this->soapClient = parent::build(); + } + + return $this->soapClient; + } + + protected function checkOptions(array $options) + { + $checkOptions = array( + 'debug' => false, + 'cache_type' => null, + 'exceptions' => true, + 'user_agent' => 'BeSimpleSoap', + ); + + // check option names and live merge, if errors are encountered Exception will be thrown + $invalid = array(); + $isInvalid = false; + foreach ($options as $key => $value) { + if (!array_key_exists($key, $checkOptions)) { + $isInvalid = true; + $invalid[] = $key; + } + } + + if ($isInvalid) { + throw new \InvalidArgumentException(sprintf( + 'The "%s" class does not support the following options: "%s".', + get_class($this), + implode('\', \'', $invalid) + )); + } + } +} \ No newline at end of file diff --git a/Soap/SoapServerFactory.php b/Soap/SoapServerFactory.php deleted file mode 100644 index 1e18767..0000000 --- a/Soap/SoapServerFactory.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Soap; - -use BeSimple\SoapBundle\Converter\ConverterRepository; -use Zend\Soap\Wsdl; - -/** - * @author Christian Kerl - */ -class SoapServerFactory -{ - private $wsdlFile; - private $classmap; - private $converters; - private $debug; - - public function __construct($wsdlFile, array $classmap, ConverterRepository $converters, $debug = false) - { - $this->wsdlFile = $wsdlFile; - $this->classmap = $this->fixSoapServerClassmap($classmap); - $this->converters = $converters; - $this->debug = $debug; - } - - public function create($request, $response) - { - return new \SoapServer( - $this->wsdlFile, - array( - 'classmap' => $this->classmap, - 'typemap' => $this->createSoapServerTypemap($request, $response), - 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, - 'cache_wsdl' => $this->debug ? WSDL_CACHE_NONE : WSDL_CACHE_DISK, - ) - ); - } - - private function createSoapServerTypemap($request, $response) - { - $typemap = array(); - - foreach($this->converters->getTypeConverters() as $typeConverter) { - $typemap[] = array( - 'type_name' => $typeConverter->getTypeName(), - 'type_ns' => $typeConverter->getTypeNamespace(), - 'from_xml' => function($input) use ($request, $typeConverter) { - return $typeConverter->convertXmlToPhp($request, $input); - }, - 'to_xml' => function($input) use ($response, $typeConverter) { - return $typeConverter->convertPhpToXml($response, $input); - }, - ); - } - - return $typemap; - } - - private function fixSoapServerClassmap($classmap) - { - $classmapFixed = array(); - - foreach ($classmap as $class => $definition) { - $classmapFixed[Wsdl::translateType($class)] = $class; - } - - return $classmapFixed; - } -} \ No newline at end of file diff --git a/Tests/Converter/DateTimeTypeConverterTest.php b/Tests/Converter/DateTimeTypeConverterTest.php deleted file mode 100644 index b04acd3..0000000 --- a/Tests/Converter/DateTimeTypeConverterTest.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Tests\Converter; - -use BeSimple\SoapBundle\Soap\SoapRequest; -use BeSimple\SoapBundle\Soap\SoapResponse; -use BeSimple\SoapBundle\Converter\DateTimeTypeConverter; - -/** - * UnitTest for \BeSimple\SoapBundle\Converter\DateTimeTypeConverter. - * - * @author Christian Kerl - */ -class DateTimeTypeConverterTest extends \PHPUnit_Framework_TestCase -{ - public function testConvertXmlToPhp() - { - $converter = new DateTimeTypeConverter(); - - $dateXml = '2002-10-10T12:00:00-05:00'; - $date = $converter->convertXmlToPhp(new SoapRequest(), $dateXml); - - $this->assertEquals(new \DateTime('2002-10-10T12:00:00-05:00'), $date); - } - - public function testConvertPhpToXml() - { - $converter = new DateTimeTypeConverter(); - - $date = new \DateTime('2002-10-10T12:00:00-05:00'); - $dateXml = $converter->convertPhpToXml(new SoapResponse(), $date); - - $this->assertEquals('2002-10-10T12:00:00-05:00', $dateXml); - } -} diff --git a/Tests/Converter/DateTypeConverterTest.php b/Tests/Converter/DateTypeConverterTest.php deleted file mode 100644 index db53dd1..0000000 --- a/Tests/Converter/DateTypeConverterTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapBundle\Tests\Converter; - -use BeSimple\SoapBundle\Soap\SoapRequest; -use BeSimple\SoapBundle\Soap\SoapResponse; -use BeSimple\SoapBundle\Converter\DateTypeConverter; - -/** - * UnitTest for \BeSimple\SoapBundle\Converter\DateTimeTypeConverter. - */ -class DateTypeConverterTest extends \PHPUnit_Framework_TestCase -{ - public function testConvertXmlToPhp() - { - $converter = new DateTypeConverter(); - - $dateXml = '2002-10-10'; - $date = $converter->convertXmlToPhp(new SoapRequest(), $dateXml); - - $this->assertEquals(new \DateTime('2002-10-10'), $date); - } - - public function testConvertPhpToXml() - { - $converter = new DateTypeConverter(); - - $date = new \DateTime('2002-10-10'); - $dateXml = $converter->convertPhpToXml(new SoapResponse(), $date); - - $this->assertEquals('2002-10-10', $dateXml); - } -} diff --git a/WebServiceContext.php b/WebServiceContext.php index ccf1ad9..eaeb588 100644 --- a/WebServiceContext.php +++ b/WebServiceContext.php @@ -10,12 +10,14 @@ namespace BeSimple\SoapBundle; -use BeSimple\SoapBundle\Converter\ConverterRepository; use BeSimple\SoapBundle\Converter\TypeRepository; use BeSimple\SoapBundle\ServiceBinding\MessageBinderInterface; use BeSimple\SoapBundle\ServiceBinding\ServiceBinder; use BeSimple\SoapBundle\ServiceDefinition\Dumper\DumperInterface; -use BeSimple\SoapBundle\Soap\SoapServerFactory; + +use BeSimple\SoapCommon\Classmap; +use BeSimple\SoapCommon\Converter\TypeConverterCollection; +use BeSimple\SoapServer\SoapServerBuilder; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Loader\LoaderInterface; @@ -36,14 +38,16 @@ class WebServiceContext private $serviceDefinition; private $serviceBinder; - private $serverFactory; + private $serverBuilder; - public function __construct(LoaderInterface $loader, DumperInterface $dumper, TypeRepository $typeRepository, ConverterRepository $converterRepository, array $options) { + public function __construct(LoaderInterface $loader, DumperInterface $dumper, Classmap $classmap, TypeRepository $typeRepository, TypeConverterCollection $converters, array $options) { $this->loader = $loader; $this->wsdlFileDumper = $dumper; - $this->typeRepository = $typeRepository; - $this->converterRepository = $converterRepository; + $this->classmap = $classmap; + + $this->typeRepository = $typeRepository; + $this->converters = $converters; $this->options = $options; } @@ -96,17 +100,22 @@ class WebServiceContext return $this->serviceBinder; } - public function getServerFactory() + public function getServerBuilder() { - if (null === $this->serverFactory) { - $this->serverFactory = new SoapServerFactory( - $this->getWsdlFile(), - $this->serviceDefinition->getDefinitionComplexTypes(), - $this->converterRepository, - $this->options['debug'] - ); + if (null === $this->serverBuilder) { + $this->serverBuilder = SoapServerBuilder::createWithDefaults() + ->withWsdl($this->getWsdlFile()) + ->withClassmap($this->classmap) + ->withTypeConverters($this->converters) + ; + + if (!$this->options['debug']) { + $this->serverBuilder->withWsdlCacheNone(); + } elseif (null !== $this->options['cache_type']) { + $this->serverBuilder->withWsdlCache($this->options['cache_type']); + } } - return $this->serverFactory; + return $this->serverBuilder; } } \ No newline at end of file