71 Commits
v0.2.0 ... v0.4

Author SHA1 Message Date
4d7894b66e Composer info updated 2016-10-27 16:38:53 +02:00
0a157748a8 Large refactoring removing states, abstract magic, vague fluent interfaces 2016-10-27 16:24:44 +02:00
c4a9b58b08 Use request_stack service instead of deprecated request service 2016-01-11 16:28:20 +11:00
fc15bf36ab Call getPath() instead of string casting 2016-01-11 16:28:05 +11:00
8462233a08 Update FlattenException use statements 2016-01-11 16:20:13 +11:00
03227295f6 Use ContainerAwareTrait and ContainerAwareInterface 2016-01-11 16:09:42 +11:00
f285adfa14 Use path attribute rather than pattern 2016-01-11 16:06:22 +11:00
2ecdbe9714 Change package name and description 2016-01-08 11:47:15 +11:00
e5c54164c1 Support Symfony 3.* 2016-01-08 11:42:56 +11:00
27ebf0fbce Merge remote-tracking branch 'origin/0.2' 2015-06-01 16:04:32 +02:00
855e382590 [SoapBundle] Fixed service definition with factory 2015-06-01 16:04:29 +02:00
2974a4f838 Stop support of Symfony <2.6 2015-06-01 16:04:24 +02:00
fb56d51bd8 fixup! [SoapBundle] Set _format route to xml 2015-03-27 16:07:42 +01:00
f2a8a7ebb3 Merge branch '0.2' 2014-08-18 14:20:19 +02:00
7a9119cef1 [SoapBundle] Added configuration to configure client proxy 2014-08-18 13:54:19 +02:00
1a7f60b679 [SoapClient] Added proxy authentication option in SoapClientBuilder
Fixed #47
2014-08-18 11:45:53 +02:00
70db0c42fd [SoapClient] Renamed proxy_user to proxy_login option to keep compatibility with SoapClient of PHP 2014-08-18 10:58:40 +02:00
960c9f557a [SoapClient] Fixed typo for proxy options
Fixed #46
2014-08-18 10:31:20 +02:00
33d641de4e [SoapClient] Fixed tests if proxy exists in environment variables 2014-08-18 10:29:49 +02:00
bbd4c26134 Merge branch '0.2' 2014-08-16 15:48:45 +02:00
29170576c2 [Doc] Added documentation for SoapClient 2014-08-15 21:18:24 +02:00
50ab5a93ad [SoapBundle] Update the cache dir 2014-08-15 19:46:23 +02:00
1290573285 [SoapBundle] Add a hack to load BeSimpleSoap cache with a client 2014-08-15 19:45:21 +02:00
f5675f6ece [SoapBundle] Set cache informations even though it is disabled 2014-08-15 19:43:31 +02:00
15b208d861 Replaced cli_webserver_workaround client option by a check of CONTENT_TYPE AND HTTP_CONTENT_TYPE entry in SERVER superglobal 2014-08-14 21:40:13 +02:00
294a9fe90e Stop support of Symfony <2.3 2014-08-14 15:02:52 +02:00
313840d5a4 Revert "[SoapClient] [Tests] Down required version of symfony/filesystem vendor"
This reverts commit 726ee89936.

Conflicts:
	composer.json
	src/BeSimple/SoapClient/composer.json
2014-08-14 14:57:00 +02:00
8e4d8b0300 Updated BeSimpleSoap vendor requierement to 0.3 2014-08-14 14:56:39 +02:00
621b2080e0 Updated version to 0.3 2014-08-14 14:21:49 +02:00
fe67cff5ff Merge branch 'fixed_tests' 2014-08-14 13:39:12 +02:00
e676eb0432 [composer] Used a stable version of vfsStream 2014-08-14 13:33:32 +02:00
fd402731af Fixed travis configuration 2014-08-14 13:20:09 +02:00
f5d6f5e759 Updated travis 2014-08-14 13:06:18 +02:00
726ee89936 [SoapClient] [Tests] Down required version of symfony/filesystem vendor 2014-08-14 13:06:18 +02:00
36a368e695 [composer] Removed dev minimum-stability 2014-08-14 13:06:18 +02:00
e2de214ea5 [SoapClient] [Tests] Removed uploaded file 2014-08-14 13:06:18 +02:00
3cfeea8371 [SoapClient] [Tests] Fixed typo 2014-08-14 13:06:18 +02:00
c24e8775bf [SoapClient] Add possiblity to disable proxy if present in environment variable 2014-08-14 13:05:50 +02:00
b3c6353af8 [composer] Removed dev minimum-stability 2014-08-14 13:05:50 +02:00
10bba6a3bd [Test] Force replace unziped file for axis server 2014-08-13 22:08:17 +02:00
a122f2a0f6 [SoapBundle] Skipped test for SoapRequest 2014-08-13 22:02:46 +02:00
8d13d2dd5c [Doc] Add missing methods 2014-08-13 06:57:03 +02:00
1c1cd377f1 Merge branch 'ch3ric-fix-doc' 2014-08-13 06:55:07 +02:00
1efa348ae5 Merge branch 'fix-doc' of https://github.com/ch3ric/BeSimpleSoap into ch3ric-fix-doc 2014-08-13 06:55:01 +02:00
ccc4d57501 Merge pull request #42 from mremi/handle-request-options
Handled additional request options
2014-07-10 16:16:27 +02:00
740f146bad Handled additional request options 2014-07-01 15:47:46 +02:00
5e8e669299 Fix Doc 2014-05-25 16:48:26 +02:00
e4cb612aed Created a client classmap even when it is empty 2014-04-30 10:54:07 +02:00
59ea6b1ce0 Merge pull request #33 from borissamardzija/master
Update Curl class to support CURLOPT_CAINFO and CURLOPT_CAPATH options
2014-04-25 13:36:04 +02:00
7bb849e394 Update Curl class to support CURLOPT_CAINFO and CURLOPT_CAPATH options 2014-04-25 11:16:34 +02:00
02722eae8f Merge pull request #32 from mremi/filter-request-headers
Added method to tweak HTTP headers of request
2014-04-24 17:22:00 +02:00
b7581f29b0 Removed reference to return an array of HTTP headers 2014-04-24 09:29:58 +02:00
dc6e1e0889 Merge pull request #31 from mremi/http-auth
Added extra option to configure HTTP authentication
2014-04-24 08:38:03 +02:00
f986400dc2 Merge pull request #30 from mremi/method-visibility
Updated visibility from private to protected
2014-04-24 08:36:23 +02:00
67410805ba Added method to tweak HTTP headers of request 2014-04-22 22:29:11 +02:00
2ae7515294 Added extra option to configure HTTP authentication 2014-04-22 22:05:04 +02:00
cdfc3cd5bd Updated visibility from private to protected 2014-04-22 21:53:14 +02:00
9ac755d86e [SoapBundle] Set _format route to xml 2013-12-13 15:25:20 +01:00
321dcf3058 [SoapBundle] Set wsdl request type only if the "wsdl" parameter in present in URL 2013-12-13 11:24:25 +01:00
3a2b8e32ee [SoapBundle] Enhanced SoapFault management 2013-12-13 08:26:18 +01:00
fd5154a469 Fixed typo 2013-12-10 15:25:09 +01:00
188f282a87 [SoapWsdl] Specify an empty message if the input is empty 2013-12-10 15:25:09 +01:00
f9e230400d [SoapBundle] Fixed RpcLiteralRequestMessageBinderTest 2013-12-08 00:27:33 +01:00
1b4e262c60 [SoapBundle] Simplified conditional statement 2013-12-08 00:25:20 +01:00
60e3714602 [SoapBundle][SoapCommon] Removed unused TypeRepository in Definition\Method classes 2013-12-08 00:23:30 +01:00
1e82d7fdd7 Fix WSDL schema stylesheet including 2013-12-07 19:55:33 +01:00
8788d7595d Cleaned unused method, property, variable or parameter 2013-12-02 16:02:29 +01:00
b45224587a Added use TypeConverterInterface 2013-12-02 15:39:59 +01:00
c8baf14c75 Fixed typo 2013-12-02 15:39:39 +01:00
53849c68e0 Removed unused use statement 2013-12-02 15:35:36 +01:00
ecdf7e1872 Fixed an undefined variable
Fixed commit c830097430
Fixed issue #22
2013-11-20 08:45:12 +01:00
96 changed files with 1644 additions and 1300 deletions

View File

@ -4,16 +4,16 @@ php:
- 5.3
- 5.4
- 5.5
- 5.6
env:
- SYMFONY_VERSION=2.0.*
- SYMFONY_VERSION=2.1.*
- SYMFONY_VERSION=2.2.*
- SYMFONY_VERSION=2.3.*
- SYMFONY_VERSION=dev-master
- SYMFONY_VERSION=2.6.*
- SYMFONY_VERSION="dev-master symfony/debug:~2.7@dev symfony/http-kernel:~2.7@dev"
before_script:
- composer require symfony/http-foundation:${SYMFONY_VERSION} --no-interaction --prefer-source
- composer self-update
- composer require symfony/framework-bundle:${SYMFONY_VERSION} --no-update
- composer update --no-interaction --prefer-source
- ./src/BeSimple/SoapClient/Tests/bin/phpwebserver.sh
- ./src/BeSimple/SoapClient/Tests/bin/axis.sh
@ -22,4 +22,4 @@ script:
matrix:
allow_failures:
- env: SYMFONY_VERSION=dev-master
- env: SYMFONY_VERSION="dev-master symfony/debug:~2.7@dev symfony/http-kernel:~2.7@dev"

View File

@ -1,9 +1,8 @@
{
"name": "besimple/soap",
"name": "tuscanicz/soap",
"type": "library",
"description": "Build and consume SOAP and WSDL based web services",
"keywords": ["soap"],
"homepage": "http://besim.pl",
"description": "A fork of the abandoned besimple/soap package with added support for Symfony 3.0",
"keywords": ["soap", "soap server", "soap client"],
"license": "MIT",
"authors": [
{
@ -17,6 +16,10 @@
{
"name": "Andreas Schamberger",
"email": "mail@andreass.net"
},
{
"name": "Petr Bechyně",
"email": "petr.bechyne@vodafone.com"
}
],
"require": {
@ -24,8 +27,8 @@
"ext-soap": "*",
"ext-curl": "*",
"ass/xmlsecurity": "~1.0",
"symfony/framework-bundle": "~2.0",
"symfony/twig-bundle": "~2.0",
"symfony/framework-bundle": "~2.6|~3.0",
"symfony/twig-bundle": "~2.6|~3.0",
"zendframework/zend-mime": "2.1.*"
},
"replace": {
@ -37,17 +40,16 @@
},
"require-dev": {
"ext-mcrypt": "*",
"mikey179/vfsStream": "dev-master",
"mikey179/vfsStream": "~1.0",
"symfony/filesystem": "~2.3",
"symfony/process": "~2.3"
},
"autoload": {
"psr-0": { "BeSimple\\": "src/" }
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.4-dev"
}
}
}

View File

@ -25,7 +25,6 @@ class Cache
BaseCache::setEnabled($isEnabled);
if (BaseCache::ENABLED == BaseCache::isEnabled()) {
BaseCache::setType($type);
BaseCache::setDirectory($directory);
@ -37,5 +36,4 @@ class Cache
BaseCache::setLimit($limit);
}
}
}
}

View File

@ -15,12 +15,12 @@ namespace BeSimple\SoapBundle\Controller;
use BeSimple\SoapBundle\Handler\ExceptionHandler;
use BeSimple\SoapBundle\Soap\SoapRequest;
use BeSimple\SoapBundle\Soap\SoapResponse;
use BeSimple\SoapServer\Exception as SoapException;
use Symfony\Component\DependencyInjection\ContainerAware;
use BeSimple\SoapServer\SoapServerBuilder;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
@ -29,8 +29,10 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
* @author Christian Kerl <christian-kerl@web.de>
* @author Francis Besset <francis.besset@gmail.com>
*/
class SoapWebServiceController extends ContainerAware
class SoapWebServiceController implements ContainerAwareInterface
{
use ContainerAwareTrait;
/**
* @var \SoapServer
*/
@ -65,7 +67,7 @@ class SoapWebServiceController extends ContainerAware
$this->serviceBinder = $webServiceContext->getServiceBinder();
$this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request'));
$this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request_stack')->getCurrentRequest());
$this->soapServer = $webServiceContext
->getServerBuilder()
->withSoapVersion11()
@ -96,9 +98,10 @@ class SoapWebServiceController extends ContainerAware
)
));
$query = $this->container->get('request')->query;
if (!$query->has('wsdl') && !$query->has('WSDL')) {
$this->container->get('request')->setRequestFormat('xml');
$request = $this->container->get('request');
$query = $request->query;
if ($query->has('wsdl') || $query->has('WSDL')) {
$request->setRequestFormat('wsdl');
}
return $response;
@ -130,16 +133,30 @@ class SoapWebServiceController extends ContainerAware
'logger' => $logger,
));
$server = $this
->container
->get(sprintf('besimple.soap.context.%s', $webservice))
->getServerBuilder()
->withHandler(new ExceptionHandler($exception, $details))
$handler = new ExceptionHandler($exception, $details);
if ($soapFault = $request->query->get('_besimple_soap_fault')) {
$handler->setSoapFault($soapFault);
// Remove parameter from query because cannot be Serialized in Logger
$request->query->remove('_besimple_soap_fault');
}
$server = SoapServerBuilder::createWithDefaults(__DIR__.'/../Handler/wsdl/exception.wsdl')
->withWsdl()
->withWsdlCacheNone()
->withHandler($handler)
->build()
;
ob_start();
$server->handle($request->getContent());
$server->handle(
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://besim.pl/soap/exception/1.0/">'.
'<soapenv:Header/>'.
'<soapenv:Body>'.
'<ns:exception />'.
'</soapenv:Body>'.
'</soapenv:Envelope>'
);
return new Response(ob_get_clean());
}

View File

@ -12,8 +12,6 @@ namespace BeSimple\SoapBundle\Converter;
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
use BeSimple\SoapBundle\Util\Assert;
use BeSimple\SoapBundle\Util\QName;
use BeSimple\SoapBundle\Util\String;
/**
* @author Christian Kerl <christian-kerl@web.de>
@ -50,8 +48,6 @@ class TypeRepository
public function fixTypeInformation(ServiceDefinition $definition)
{
$typeMap = $this->defaultTypeMap;
foreach($definition->getAllTypes() as $type) {
$phpType = $type->getPhpType();
$xmlType = $type->getXmlType();

View File

@ -13,6 +13,7 @@ namespace BeSimple\SoapBundle\Converter;
use BeSimple\SoapBundle\Soap\SoapRequest;
use BeSimple\SoapBundle\Soap\SoapResponse;
use BeSimple\SoapBundle\Util\String;
use BeSimple\SoapCommon\Converter\TypeConverterInterface;
/**
* @author Christian Kerl <christian-kerl@web.de>

View File

@ -84,7 +84,7 @@ class BeSimpleSoapExtension extends Extension
foreach ($config as $client => $options) {
$definition = new DefinitionDecorator('besimple.soap.client.builder');
$context = $container->setDefinition(sprintf('besimple.soap.client.builder.%s', $client), $definition);
$container->setDefinition(sprintf('besimple.soap.client.builder.%s', $client), $definition);
$definition->replaceArgument(0, $options['wsdl']);
@ -98,18 +98,31 @@ class BeSimpleSoapExtension extends Extension
}
}
$proxy = $options['proxy'];
if (false !== $proxy['host']) {
if (null !== $proxy['auth']) {
if ('basic' === $proxy['auth']) {
$proxy['auth'] = \CURLAUTH_BASIC;
} elseif ('ntlm' === $proxy['auth']) {
$proxy['auth'] = \CURLAUTH_NTLM;
}
}
$definition->addMethodCall('withProxy', array(
$proxy['host'], $proxy['port'],
$proxy['login'], $proxy['password'],
$proxy['auth']
));
}
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);
}
@ -118,11 +131,13 @@ class BeSimpleSoapExtension extends Extension
private function createClientClassmap($client, array $classmap, ContainerBuilder $container)
{
$definition = new DefinitionDecorator('besimple.soap.classmap');
$context = $container->setDefinition(sprintf('besimple.soap.classmap.%s', $client), $definition);
$container->setDefinition(sprintf('besimple.soap.classmap.%s', $client), $definition);
if (!empty($classmap)) {
$definition->setMethodCalls(array(
array('set', array($classmap)),
));
}
return sprintf('besimple.soap.classmap.%s', $client);
}
@ -130,9 +145,12 @@ class BeSimpleSoapExtension extends Extension
private function createClient($client, ContainerBuilder $container)
{
$definition = new DefinitionDecorator('besimple.soap.client');
$context = $container->setDefinition(sprintf('besimple.soap.client.%s', $client), $definition);
$container->setDefinition(sprintf('besimple.soap.client.%s', $client), $definition);
$definition->setFactoryService(sprintf('besimple.soap.client.builder.%s', $client));
$definition->setFactory(array(
new Reference(sprintf('besimple.soap.client.builder.%s', $client)),
'build'
));
}
private function createWebServiceContext(array $config, ContainerBuilder $container)
@ -142,7 +160,7 @@ class BeSimpleSoapExtension extends Extension
$contextId = 'besimple.soap.context.'.$config['name'];
$definition = new DefinitionDecorator('besimple.soap.context.'.$bindingSuffix);
$context = $container->setDefinition($contextId, $definition);
$container->setDefinition($contextId, $definition);
if (isset($config['cache_type'])) {
$config['cache_type'] = $this->getCacheType($config['cache_type']);

View File

@ -24,6 +24,7 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder;
class Configuration
{
private $cacheTypes = array('none', 'disk', 'memory', 'disk_memory');
private $proxyAuth = array('basic', 'ntlm');
/**
* Generates the configuration tree.
@ -85,12 +86,33 @@ class Configuration
->scalarNode('cache_type')
->validate()
->ifNotInArray($this->cacheTypes)
->thenInvalid(sprintf('The cache type has to be either %s', implode(', ', $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()
->arrayNode('proxy')
->info('proxy configuration')
->addDefaultsIfNotSet()
->beforeNormalization()
->ifTrue(function ($v) { return !is_array($v); })
->then(function ($v) { return array('host' => null === $v ? false : $v); })
->end()
->children()
->scalarNode('host')->defaultFalse()->end()
->scalarNode('port')->defaultValue(3128)->end()
->scalarNode('login')->defaultNull()->end()
->scalarNode('password')->defaultNull()->end()
->scalarNode('auth')
->defaultNull()
->validate()
->ifNotInArray($this->proxyAuth)
->thenInvalid(sprintf('The proxy auth has to be either: %s', implode(', ', $this->proxyAuth)))
->end()
->end()
->end()
->end()
->end()
->end()
->end()

View File

@ -2,7 +2,6 @@
namespace BeSimple\SoapBundle\EventListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class RequestFormatListener

View File

@ -51,7 +51,9 @@ class SoapExceptionListener extends ExceptionListener
}
$request = $event->getRequest();
if ('soap' !== $request->getRequestFormat()) {
if (!in_array($request->getRequestFormat(), array('soap', 'xml'))) {
return;
} elseif ('xml' === $request->getRequestFormat() && '_webservice_call' !== $request->attributes->get('_route')) {
return;
}
@ -67,12 +69,18 @@ class SoapExceptionListener extends ExceptionListener
// hack to retrieve the current WebService name in the controller
$request->query->set('_besimple_soap_webservice', $webservice);
$exception = $event->getException();
if ($exception instanceof \SoapFault) {
$request->query->set('_besimple_soap_fault', $exception);
}
parent::onKernelException($event);
}
public static function getSubscribedEvents()
{
return array(
// Must be called before ExceptionListener of HttpKernel component
KernelEvents::EXCEPTION => array('onKernelException', -64),
);
}

View File

@ -13,8 +13,8 @@
namespace BeSimple\SoapBundle\Handler;
use BeSimple\SoapServer\Exception\ReceiverSoapFault;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;
/**
* @author Francis Besset <francis.besset@gmail.com>
@ -23,6 +23,7 @@ class ExceptionHandler
{
protected $exception;
protected $details;
protected $soapFault;
public function __construct(FlattenException $exception, $details = null)
{
@ -30,8 +31,17 @@ class ExceptionHandler
$this->details = $details;
}
public function setSoapFault(\SoapFault $soapFault)
{
$this->soapFault = $soapFault;
}
public function __call($method, $arguments)
{
if (isset($this->soapFault)) {
throw $this->soapFault;
}
$code = $this->exception->getStatusCode();
throw new ReceiverSoapFault(

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://besim.pl/soap/exception/1.0/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="Exception" targetNamespace="http://besim.pl/soap/exception/1.0/">
<portType name="ExceptionPortType">
<operation name="exception">
<input message="tns:empty"/>
<output message="tns:empty"/>
</operation>
</portType>
<message name="empty" />
<binding name="ExceptionBinding" type="tns:ExceptionPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="exception">
<soap:operation soapAction="http://besim.pl/soap/exception/1.0/exception"/>
<input>
<soap:body use="literal" namespace="http://besim.pl/soap/exception/1.0/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="literal" namespace="http://besim.pl/soap/exception/1.0/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="ExceptionService">
<port name="ExceptionPort" binding="tns:ExceptionBinding">
<soap:address location="http://localhost/soap/Exception"/>
</port>
</service>
</definitions>

View File

@ -16,9 +16,12 @@
</argument>
<argument type="service" id="besimple.soap.classmap" />
<argument type="service" id="besimple.soap.converter.collection" />
<argument type="service" id="besimple.soap.cache" /> <!-- hack to load besimple cache configuration -->
</service>
<service id="besimple.soap.client" factory-service="besimple.soap.client.builder" factory-method="build" class="%besimple.soap.client.builder.class%" abstract="true" />
<service id="besimple.soap.client" class="%besimple.soap.client.builder.class%" abstract="true">
<factory class="besimple.soap.client.builder" method="build" />
</service>
<service id="besimple.soap.classmap" class="%besimple.soap.classmap.class%" abstract="true" />
</services>

View File

@ -4,15 +4,15 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="_webservice_call" pattern="/{webservice}">
<route id="_webservice_call" path="/{webservice}">
<default key="_controller">BeSimpleSoapBundle:SoapWebService:Call</default>
<default key="_format">soap</default>
<default key="_format">xml</default>
<requirement key="_method">POST</requirement>
</route>
<route id="_webservice_definition" pattern="/{webservice}">
<route id="_webservice_definition" path="/{webservice}">
<default key="_controller">BeSimpleSoapBundle:SoapWebService:Definition</default>
<default key="_format">wsdl</default>
<default key="_format">xml</default>
<requirement key="_method">GET</requirement>
</route>
</routes>

View File

@ -12,7 +12,7 @@
<service id="besimple.soap.cache" class="%besimple.soap.cache.class%">
<argument>%kernel.debug%</argument>
<argument>%besimple.soap.cache.type%</argument>
<argument>%besimple.soap.cache.dir%/php</argument>
<argument>%besimple.soap.cache.dir%/cache</argument>
<argument>%besimple.soap.cache.lifetime%</argument>
<argument>%besimple.soap.cache.limit%</argument>
</service>

View File

@ -44,6 +44,7 @@
<argument key="binder_request_header_class">%besimple.soap.binder.request_header.rpcliteral.class%</argument>
<argument key="binder_request_class">%besimple.soap.binder.request.rpcliteral.class%</argument>
<argument key="binder_response_class">%besimple.soap.binder.response.rpcliteral.class%</argument>
<argument key="wsdl_stylesheet">%besimple.soap.definition.dumper.options.stylesheet%</argument>
</argument>
<argument type="service" id="besimple.soap.cache" />
</service>
@ -58,6 +59,7 @@
<argument key="binder_request_header_class">%besimple.soap.binder.request_header.documentwrapped.class%</argument>
<argument key="binder_request_class">%besimple.soap.binder.request.documentwrapped.class%</argument>
<argument key="binder_response_class">%besimple.soap.binder.response.documentwrapped.class%</argument>
<argument key="wsdl_stylesheet">%besimple.soap.definition.dumper.options.stylesheet%</argument>
</argument>
<argument type="service" id="besimple.soap.cache" />
</service>

View File

@ -33,4 +33,8 @@ SoapServer
SoapClient
----------
Coming soon.
.. toctree::
:maxdepth: 1
:numbered:
soapclient/configuration

View File

@ -0,0 +1,158 @@
Configuration
=============
Client configuration
--------------------
Configure your first client in your config file:
.. code-block:: yaml
# app/config/config.yml
be_simple_soap:
clients:
DemoApi:
# required
wsdl: http://localhost/app_dev.php/ws/DemoApi?wsdl
# classmap (optional)
classmap:
type_name: "Full\Class\Name"
# proxy (optional)
proxy:
host: proxy.domain.name # required to enable proxy configuration
port: 3128
login: ~
password: ~
auth: ~ # can be 'basic' or 'ntlm'
Using client
------------
.. code-block:: php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DemoController extends Controller
{
public function helloAction($name)
{
// The client service name is `besimple.soap.client.demoapi`:
// `besimple.soap.client.`: is the base name of your client
// `demoapi`: is the name specified in your config file converted to lowercase
$client = $this->container->get('besimple.soap.client.demoapi');
// call `hello` method on WebService with the string parameter `$name`
$helloResult = $client->hello($name);
return $this->render('AcmeDemoBundle:Demo:hello.html.twig', array(
'hello' => $helloResult,
));
}
}
Classmap
--------
Configuration
~~~~~~~~~~~~~
.. code-block:: yaml
# app/config/config.yml
be_simple_soap:
clients:
DemoApi:
# ...
classmap:
User: Acme\DemoBundle\Api\UserApi
# add other type_name: classname
UserApi class
~~~~~~~~~~~~~
.. code-block:: php
namespace Acme\DemoBundle\Api;
class UserApi
{
private $username;
private $firstname;
private $lastname;
public function __construct($username)
{
$this->username = $username;
}
public function getFirstname()
{
return $this->firstname;
}
public function getLastname()
{
return $this->lastname;
}
}
Usage
~~~~~
.. code-block:: php
namespace Acme\DemoBundle\Controller;
use Acme\DemoBundle\Api\UserApi;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DemoController extends Controller
{
public function userAction($username)
{
// The client service name is `besimple.soap.client.demoapi`:
// `besimple.soap.client.`: is the base name of your client
// `demoapi`: is the name specified in your config file converted to lowercase
$client = $this->container->get('besimple.soap.client.demoapi');
// call `getUser` method on WebService with an instance of UserApi
// if the `getUserByUsername` method return a `User` type then `$userResult` is an instance of UserApi
$userResult = $client->getUserByUsername($username);
return $this->render('AcmeDemoBundle:Demo:user.html.twig', array(
'user' => $userResult,
));
}
}
Without classmap configuration the `$userResult` is an instance of `stdClass`:
.. code-block:: text
object(stdClass)#5561 (3) {
["username"]=>
string(6) "FooBar"
["firstname"]=>
string(3) "Foo"
["lastname"]=>
string(3) "Bar"
}
With classmap configuration the `$userResult` is an instance of `Acme\DemoBundle\Api\UserApi`:
.. code-block:: text
object(Acme\DemoBundle\Api\UserApi)#208 (3) {
["username":"Acme\DemoBundle\Api\UserApi":private]=>
string(6) "FooBar"
["firstname":"Acme\DemoBundle\Api\UserApi":private]=>
string(3) "Foo"
["lastname":"Acme\DemoBundle\Api\UserApi":private]=>
string(3) "Bar"
}

View File

@ -47,9 +47,9 @@ Controller
/**
* @Soap\Method("sendAssocArray")
* @Soap\Param("assocArray", phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
* @Soap\Return(phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
* @Soap\Result(phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
*/
public function assocArrayOfStringAction(array $assocArray)
public function sendAssocArrayOfStringAction(array $assocArray)
{
// The $assocArray it's a real associative array
// var_dump($assocArray);die;
@ -97,3 +97,4 @@ How to create my Associative Array?
'user2' => new User('user2', 'user2@user.com'),
);
}
}

View File

@ -86,6 +86,16 @@ You can expose only the properties (public, protected or private) of a complex t
*/
private $newsletter;
/**
* @Soap\ComplexType("date")
*/
private $createdAt:
/**
* @Soap\ComplexType("datetime")
*/
private $updatedAt;
public function getId()
{
return $this->id;
@ -128,7 +138,27 @@ You can expose only the properties (public, protected or private) of a complex t
public function setNewsletter($newsletter)
{
$this->newletter = (Boolean) $newsletter
$this->newletter = (Boolean) $newsletter;
}
public function getCreatedAt()
{
return $this->createdAt;
}
public function setCreatedAt(\DateTime $createdAt)
{
$this->createdAt = $createdAt;
}
public function getUpdatedAt()
{
return this->updatedAt;
}
public function setUpdatedAt(\DateTime $updatedAt)
{
$this->updatedAt = $updatedAt;
}
}

View File

@ -13,8 +13,6 @@
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;
@ -55,7 +53,7 @@ class RpcLiteralRequestMessageBinder implements MessageBinderInterface
$type = $this->typeRepository->getType($phpType);
if ($type instanceof ArrayOfType) {
$isArray = true;
$arrayType = $type;
$array = array();
$type = $this->typeRepository->getType($type->get('item')->getType());
}
@ -65,8 +63,6 @@ class RpcLiteralRequestMessageBinder implements MessageBinderInterface
$phpType = $type->getPhpType();
if ($isArray) {
$array = array();
if (isset($message->item)) {
foreach ($message->item as $complexType) {
$array[] = $this->checkComplexType($phpType, $complexType);
@ -116,9 +112,8 @@ class RpcLiteralRequestMessageBinder implements MessageBinderInterface
$value = $this->processType($type->getType(), $value);
$messageBinder->writeProperty($property, $value);
}
if (!$type->isNillable() && null === $value) {
} elseif (!$type->isNillable()) {
// @TODO use xmlType instead of phpType
throw new \SoapFault('SOAP_ERROR_COMPLEX_TYPE', sprintf('"%s:%s" cannot be null.', ucfirst($phpType), $type->getName()));
}
}

View File

@ -13,8 +13,6 @@
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;
@ -44,7 +42,6 @@ class RpcLiteralResponseMessageBinder implements MessageBinderInterface
$type = $this->typeRepository->getType($phpType);
if ($type instanceof ArrayOfType) {
$isArray = true;
$arrayType = $type;
$type = $this->typeRepository->getType($type->get('item')->getType());
}
@ -88,7 +85,7 @@ class RpcLiteralResponseMessageBinder implements MessageBinderInterface
$this->messageRefs[$hash] = $message;
if (!$message instanceof $phpType) {
throw new \InvalidArgumentException(sprintf('The instance class must be "%s", "%s" given.', get_class($message), $phpType));
throw new \InvalidArgumentException(sprintf('The instance class must be "%s", "%s" given.', $phpType, get_class($message)));
}
$messageBinder = new MessageBinder($message);

View File

@ -10,7 +10,6 @@
namespace BeSimple\SoapBundle\ServiceBinding;
use BeSimple\SoapBundle\ServiceDefinition\Header;
use BeSimple\SoapBundle\ServiceDefinition\Definition;
use BeSimple\SoapBundle\Soap\SoapHeader;

View File

@ -21,8 +21,6 @@ use BeSimple\SoapCommon\Definition\Type\TypeRepository;
*/
class Definition extends BaseDefinition
{
private $complexTypes;
public function __construct(TypeRepository $typeRepository)
{
$this->typeRepository = $typeRepository;

View File

@ -16,11 +16,8 @@ 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;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
/**
* AnnotationClassLoader loads ServiceDefinition from a PHP class and its methods.
@ -91,7 +88,6 @@ class AnnotationClassLoader extends Loader
$serviceMethod = new Definition\Method(
$annotation->getValue(),
$this->typeRepository,
$this->getController($class, $method, $annotation)
);
} elseif ($annotation instanceof Annotation\Result) {
@ -144,30 +140,6 @@ class AnnotationClassLoader extends Loader
}
}
/**
* @param \ReflectionMethod $method
* @param \BeSimple\SoapBundle\ServiceDefinition\Annotation\Param $annotation
*
* @return \BeSimple\SoapBundle\ServiceDefinition\Type
*/
private function getArgumentType(\ReflectionMethod $method, Annotation\Param $annotation)
{
$phpType = $annotation->getPhpType();
$xmlType = $annotation->getXmlType();
if (null === $phpType) {
foreach ($method->getParameters() as $param) {
if ($param->name === $annotation->getName()) {
$phpType = $param->getClass()->name;
break;
}
}
}
return new Definition\Type($phpType, $xmlType);
}
private function loadType($phpType)
{
if (false !== $arrayOf = $this->typeRepository->getArrayOf($phpType)) {
@ -177,7 +149,7 @@ class AnnotationClassLoader extends Loader
if (!$this->typeRepository->hasType($phpType)) {
$complexTypeResolver = $this->resolve($phpType, 'annotation_complextype');
if (!$complexTypeResolver) {
throw new Exception();
throw new \Exception();
}
$loaded = $complexTypeResolver->load($phpType);

View File

@ -16,7 +16,6 @@ use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Resource\FileResource;
/**
* AnnotationFileLoader loads ServiceDefinition from annotations set
@ -62,7 +61,7 @@ class AnnotationFileLoader extends FileLoader
$path = $this->locator->locate($file);
if ($class = $this->findClass($path)) {
return $definition = $this->loader->load($class, $type);
return $this->loader->load($class, $type);
}
return null;

View File

@ -23,9 +23,9 @@ class Method extends BaseMethod
{
private $controller;
public function __construct($name, TypeRepository $typeRepository, $controller)
public function __construct($name, $controller)
{
parent::__construct($name, $typeRepository);
parent::__construct($name);
$this->controller = $controller;
}

View File

@ -11,10 +11,7 @@
namespace BeSimple\SoapBundle\Soap;
use BeSimple\SoapBundle\Util\Collection;
use Symfony\Component\HttpFoundation\Request;
use Zend\Mime\Mime;
use Zend\Mime\Message;
/**

View File

@ -16,66 +16,70 @@ use BeSimple\SoapBundle\ServiceBinding\RpcLiteralRequestMessageBinder;
use BeSimple\SoapBundle\ServiceDefinition as Definition;
use BeSimple\SoapBundle\Tests\fixtures\ServiceBinding as Fixtures;
use BeSimple\SoapBundle\Util\Collection;
use BeSimple\SoapCommon\Definition\Type\ComplexType;
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider messageProvider
*/
public function testProcessMessage(Definition\Method $method, $message, $assert)
public function testProcessMessage(Definition\Method $method, array $message, array $assert)
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$result = $messageBinder->processMessage($method, $message);
$result = $messageBinder->processMessage($method, $message, $this->getTypeRepository());
$this->assertSame($assert, $result);
}
public function testProcessMessageWithComplexType()
{
$typeRepository = $this->addComplexTypes($this->getTypeRepository());
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('complextype_argument', null);
$method->addInput('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo');
$foo = new Fixtures\Foo('foobar', 19395);
$result = $messageBinder->processMessage(
new Definition\Method('complextype_argument', null, array(), array(
new Definition\Argument('foo', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo')),
)),
$method,
array($foo),
$this->getDefinitionComplexTypes()
$typeRepository
);
$this->assertEquals(array('foo' => $foo), $result);
$foo1 = new Fixtures\Foo('foobar', 29291);
$foo2 = new Fixtures\Foo('barfoo', 39392);
$foos = new \stdClass();
$foos->item = array($foo1, $foo2);
$method = new Definition\Method('complextype_argument', null);
$method->addInput('foos', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]');
$result = $messageBinder->processMessage(
new Definition\Method('complextype_argument', null, array(), array(
new Definition\Argument('foos', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]')),
)),
$method,
array($foos),
$this->getDefinitionComplexTypes()
$typeRepository
);
$this->assertEquals(array('foos' => array($foo1, $foo2)), $result);
}
/**
* @expectedException SoapFault
*/
public function testProcessMessageSoapFault()
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('complextype_argument', null);
$method->addInput('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo');
$foo = new Fixtures\Foo('foo', null);
$result = $messageBinder->processMessage(
new Definition\Method('complextype_argument', null, array(), array(
new Definition\Argument('foo', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo')),
)),
$this->setExpectedException('SoapFault');
$messageBinder->processMessage(
$method,
array($foo),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
}
@ -83,16 +87,17 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('complextype_argument', null);
$method->addInput('foos', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]');
$foo = new Fixtures\Foo('foo', 2499104);
$foos = new \stdClass();
$foos->item = array($foo, $foo);
$result = $messageBinder->processMessage(
new Definition\Method('complextype_argument', null, array(), array(
new Definition\Argument('foos', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]')),
)),
$method,
array($foos),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
$this->assertEquals(array('foos' => array($foo, $foo)), $result);
@ -102,16 +107,17 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('complextype_argument', null);
$method->addInput('fooBar', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooBar');
$foo = new Fixtures\Foo('foo', 38845);
$bar = new Fixtures\Bar('bar', null);
$fooBar = new Fixtures\FooBar($foo, $bar);
$result = $messageBinder->processMessage(
new Definition\Method('complextype_argument', null, array(), array(
new Definition\Argument('fooBar', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooBar')),
)),
$method,
array($fooBar),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
$this->assertEquals(array('fooBar' => $fooBar), $result);
@ -121,17 +127,18 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('complextype_with_array', null);
$method->addInput('simple_arrays', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\SimpleArrays');
$array = array(1, 2, 3, 4);
$stdClass = new \stdClass();
$stdClass->item = $array;
$simpleArrays = new Fixtures\SimpleArrays(null, new \stdClass(), $stdClass);
$result = $messageBinder->processMessage(
new Definition\Method('complextype_with_array', null, array(), array(
new Definition\Argument('simple_arrays', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\SimpleArrays')),
)),
$method,
array($simpleArrays),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
$result = $result['simple_arrays'];
@ -144,12 +151,13 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('empty_array_complex_type', null);
$method->addInput('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]');
$result = $messageBinder->processMessage(
new Definition\Method('empty_array_complex_type', null, array(), array(
new Definition\Argument('foo', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo[]')),
)),
$method,
array(new \stdClass()),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
$this->assertEquals(array('foo' => array()), $result);
@ -159,16 +167,17 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
{
$messageBinder = new RpcLiteralRequestMessageBinder();
$method = new Definition\Method('prevent_infinite_recursion', null);
$method->addInput('foo_recursive', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive');
$foo = new Fixtures\FooRecursive('foo', '');
$bar = new Fixtures\BarRecursive($foo, 10394);
$foo->bar = $bar;
$result = $messageBinder->processMessage(
new Definition\Method('prevent_infinite_recursion', null, array(), array(
new Definition\Argument('foo_recursive', new Definition\Type('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive')),
)),
$method,
array($foo),
$this->getDefinitionComplexTypes()
$this->addComplexTypes($this->getTypeRepository())
);
$this->assertEquals(array('foo_recursive' => $foo), $result);
@ -179,43 +188,43 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
$messages = array();
$messages[] = array(
new Definition\Method('no_argument'),
new Definition\Method('no_argument', null),
array(),
array(),
);
$method = new Definition\Method('string_argument', null);
$method->addInput('foo', 'string');
$messages[] = array(
new Definition\Method('string_argument', null, array(), array(
new Definition\Argument('foo', new Definition\Type('string')),
)),
$method,
array('bar'),
array('foo' => 'bar'),
);
$method = new Definition\Method('string_int_arguments', null);
$method->addInput('foo', 'string');
$method->addInput('bar', 'int');
$messages[] = array(
new Definition\Method('string_int_arguments', null, array(), array(
new Definition\Argument('foo', new Definition\Type('string')),
new Definition\Argument('bar', new Definition\Type('int')),
)),
$method,
array('test', 20),
array('foo' => 'test', 'bar' => 20),
);
$method = new Definition\Method('array_string_arguments', null);
$method->addInput('foo', 'string[]');
$method->addInput('bar', 'int');
$strings = new \stdClass();
$strings->item = array('foo', 'bar', 'barfoo');
$messages[] = array(
new Definition\Method('array_string_arguments', null, array(), array(
new Definition\Argument('foo', new Definition\Type('string[]')),
new Definition\Argument('bar', new Definition\Type('int')),
)),
$method,
array($strings, 4),
array('foo' => array('foo', 'bar', 'barfoo'), 'bar' => 4),
);
$method = new Definition\Method('empty_array', null);
$method->addInput('foo', 'string[]');
$messages[] = array(
new Definition\Method('empty_array', null, array(), array(
new Definition\Argument('foo', new Definition\Type('string[]')),
)),
$method,
array(new \stdClass()),
array('foo' => array()),
);
@ -223,40 +232,38 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
return $messages;
}
private function getDefinitionComplexTypes()
private function addComplexTypes(TypeRepository $typeRepository)
{
$definitionComplexTypes = array();
$foo = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo', 'Foo');
$foo->add('foo', 'string');
$foo->add('bar', 'int');
$typeRepository->addComplexType($foo);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo'] = $this->createComplexTypeCollection(array(
array('foo', 'string'),
array('bar', 'int'),
));
$bar = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Bar', 'Bar');
$bar->add('foo', 'string');
$bar->add('bar', 'int', true);
$typeRepository->addComplexType($bar);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Bar'] = $this->createComplexTypeCollection(array(
array('foo', 'string'),
array('bar', 'int', true),
));
$fooBar = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooBar', 'FooBar');
$fooBar->add('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo');
$fooBar->add('bar', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Bar');
$typeRepository->addComplexType($fooBar);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooBar'] = $this->createComplexTypeCollection(array(
array('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Foo'),
array('bar', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\Bar'),
));
$simpleArrays = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\SimpleArrays', 'SimpleArrays');
$simpleArrays->add('array1', 'string[]', true);
$simpleArrays->add('array2', 'string[]');
$simpleArrays->add('array3', 'string[]');
$typeRepository->addComplexType($simpleArrays);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\SimpleArrays'] = $this->createComplexTypeCollection(array(
array('array1', 'string[]', true),
array('array2', 'string[]'),
array('array3', 'string[]'),
));
$fooRecursive = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive', 'FooRecursive');
$fooRecursive->add('bar', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\BarRecursive');
$typeRepository->addComplexType($fooRecursive);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive'] = $this->createComplexTypeCollection(array(
array('bar', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\BarRecursive'),
));
$barRecursive = new ComplexType('BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\BarRecursive', 'BarRecursive');
$barRecursive->add('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive');
$typeRepository->addComplexType($barRecursive);
$definitionComplexTypes['BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\BarRecursive'] = $this->createComplexTypeCollection(array(
array('foo', 'BeSimple\SoapBundle\Tests\fixtures\ServiceBinding\FooRecursive'),
));
return $definitionComplexTypes;
return $typeRepository;
}
private function createComplexTypeCollection(array $properties)
@ -277,4 +284,18 @@ class RpcLiteralRequestMessageBinderTest extends \PHPUnit_Framework_TestCase
return array('properties' => $collection);
}
private function getTypeRepository()
{
$typeRepository = new TypeRepository();
$typeRepository->addXmlNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');
$typeRepository->addType('string', 'xsd:string');
$typeRepository->addType('boolean', 'xsd:boolean');
$typeRepository->addType('int', 'xsd:int');
$typeRepository->addType('float', 'xsd:float');
$typeRepository->addType('date', 'xsd:date');
$typeRepository->addType('dateTime', 'xsd:dateTime');
return $typeRepository;
}
}

View File

@ -23,6 +23,8 @@ class SoapRequestTest extends \PHPUnit_Framework_TestCase
{
public function testMtomMessage()
{
$this->markTestSkipped('Skip because I\'m not sure that SoapRequest is used in a HTTP Request process.');
$content = $this->loadRequestContentFixture('mtom/simple.txt');
$request = new SoapRequest(array(), array(), array(), array(), array(), array(), $content);

View File

@ -11,14 +11,10 @@
namespace BeSimple\SoapBundle;
use BeSimple\SoapBundle\ServiceBinding\MessageBinderInterface;
use BeSimple\SoapBundle\ServiceBinding\ServiceBinder;
use BeSimple\SoapBundle\ServiceDefinition\Dumper\DumperInterface;
use BeSimple\SoapCommon\Converter\TypeConverterCollection;
use BeSimple\SoapWsdl\Dumper\Dumper;
use BeSimple\SoapServer\SoapServerBuilder;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Loader\LoaderInterface;
@ -30,8 +26,6 @@ use Symfony\Component\Config\Loader\LoaderInterface;
*/
class WebServiceContext
{
private $converterRepository;
private $options;
private $serviceDefinition;
@ -50,7 +44,7 @@ class WebServiceContext
if (null === $this->serviceDefinition) {
$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;
$this->serviceDefinition = include $cache->getPath();
} 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']));
@ -84,11 +78,11 @@ class WebServiceContext
$definition->setOption('location', $endpoint);
}
$dumper = new Dumper($definition);
$dumper = new Dumper($definition, array('stylesheet' => $this->options['wsdl_stylesheet']));
$cache->write($dumper->dump());
}
return (string) $cache;
return $cache->getPath();
}
public function getServiceBinder()

View File

@ -22,25 +22,24 @@
"require": {
"php": ">=5.3.0",
"ext-soap": "*",
"besimple/soap-common": "0.2.*",
"besimple/soap-wsdl": "0.2.*",
"besimple/soap-common": "0.3.*",
"besimple/soap-wsdl": "0.3.*",
"ass/xmlsecurity": "~1.0",
"symfony/framework-bundle": "~2.0",
"symfony/twig-bundle": "~2.0",
"symfony/framework-bundle": "~2.6",
"symfony/twig-bundle": "~2.6",
"zendframework/zend-mime": "2.1.*"
},
"suggest": {
"besimple/soap-client": "0.2.*",
"besimple/soap-server": "0.2.*"
"besimple/soap-client": "0.3.*",
"besimple/soap-server": "0.3.*"
},
"autoload": {
"psr-0": { "BeSimple\\SoapBundle": "" }
},
"target-dir": "BeSimple/SoapBundle",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.3-dev"
}
}
}

View File

@ -50,6 +50,7 @@ class Curl
/**
* Constructor.
*
* @todo: do not use options as Array
* @param array $options Options array from SoapClient constructor
* @param int $followLocationMaxRedirects Redirection limit for Location header
*/
@ -80,21 +81,39 @@ class Curl
if (isset($options['connection_timeout'])) {
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $options['connection_timeout']);
}
if (isset($options['proxy_host'])) {
$port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080;
curl_setopt($this->ch, CURLOPT_PROXY, $options['proxy_host'] . ':' . $port);
if (false !== $options['proxy_host']) {
$proxyHost = $options['proxy_host'].(isset($options['proxy_port']) ? $options['proxy_port'] : 8080);
} else {
$proxyHost = false;
}
if (isset($options['proxy_user'])) {
curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $options['proxy_user'] . ':' . $options['proxy_password']);
curl_setopt($this->ch, CURLOPT_PROXY, $proxyHost);
if (false !== $proxyHost && isset($options['proxy_login'])) {
curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $options['proxy_login'].':'.$options['proxy_password']);
if (isset($options['proxy_auth'])) {
curl_setopt($this->ch, CURLOPT_PROXYAUTH, $options['proxy_auth']);
}
}
}
if (isset($options['login'])) {
curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($this->ch, CURLOPT_HTTPAUTH, isset($options['extra_options']['http_auth']) ? $options['extra_options']['http_auth'] : CURLAUTH_ANY);
curl_setopt($this->ch, CURLOPT_USERPWD, $options['login'].':'.$options['password']);
}
if (isset($options['local_cert'])) {
curl_setopt($this->ch, CURLOPT_SSLCERT, $options['local_cert']);
curl_setopt($this->ch, CURLOPT_SSLCERTPASSWD, $options['passphrase']);
}
if (isset($options['ca_info'])) {
curl_setopt($this->ch, CURLOPT_CAINFO, $options['ca_info']);
}
if (isset($options['ca_path'])) {
curl_setopt($this->ch, CURLOPT_CAPATH, $options['ca_path']);
}
}
/**
@ -112,10 +131,11 @@ class Curl
* @param string $location HTTP location
* @param string $request Request body
* @param array $requestHeaders Request header strings
* @param array $requestOptions An array of request options
*
* @return bool
*/
public function exec($location, $request = null, $requestHeaders = array())
public function exec($location, $request = null, $requestHeaders = array(), $requestOptions = array())
{
curl_setopt($this->ch, CURLOPT_URL, $location);
@ -128,6 +148,10 @@ class Curl
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $requestHeaders);
}
if (count($requestOptions) > 0) {
curl_setopt_array($this->ch, $requestOptions);
}
$this->response = $this->execManualRedirect();
return ($this->response === false) ? false : true;

View File

@ -90,7 +90,7 @@ class MimeFilter implements SoapRequestFilter, SoapResponseFilter
// TODO
$headers = $multipart->getHeadersForHttp();
list($name, $contentType) = explode(': ', $headers[0]);
list(, $contentType) = explode(': ', $headers[0]);
$request->setContentType($contentType);
}

View File

@ -15,7 +15,8 @@ namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Converter\MtomTypeConverter;
use BeSimple\SoapCommon\Converter\SwaTypeConverter;
use BeSimple\SoapCommon\SoapMessage;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\SoapRequest;
/**
* Extended SoapClient that uses a a cURL wrapper for all underlying HTTP
@ -27,12 +28,7 @@ use BeSimple\SoapCommon\SoapMessage;
*/
class SoapClient extends \SoapClient
{
/**
* Soap version.
*
* @var int
*/
protected $soapVersion = SOAP_1_1;
protected $soapVersion;
/**
* Tracing enabled?
@ -41,15 +37,6 @@ class SoapClient extends \SoapClient
*/
protected $tracingEnabled = false;
/**
* Work around missing header/php://input access in PHP cli webserver by
* setting headers additionally as GET parameters and SOAP request body
* explicitly as POST variable.
*
* @var boolean
*/
private $cliWebserverWorkaround = false;
/**
* cURL instance.
*
@ -95,35 +82,24 @@ class SoapClient extends \SoapClient
/**
* Constructor.
*
* @param string $wsdl WSDL file
* @param array(string=>mixed) $options Options array
* @param SoapClientOptions $soapClientOptions
* @param SoapOptions $soapOptions
*/
public function __construct($wsdl, array $options = array())
public function __construct(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions)
{
// tracing enabled: store last request/response header and body
if (isset($options['trace']) && $options['trace'] === true) {
$this->tracingEnabled = true;
}
// store SOAP version
if (isset($options['soap_version'])) {
$this->soapVersion = $options['soap_version'];
}
// activate cli webserver workaround
if (isset($options['cli_webserver_workaround'])) {
$this->cliWebserverWorkaround = $options['cli_webserver_workaround'];
}
$this->curl = new Curl($options);
$wsdlFile = $this->loadWsdl($wsdl, $options);
// TODO $wsdlHandler = new WsdlHandler($wsdlFile, $this->soapVersion);
$this->soapKernel = new SoapKernel();
// set up type converter and mime filter
$this->configureMime($options);
// we want the exceptions option to be set
$options['exceptions'] = true;
// disable obsolete trace option for native SoapClient as we need to do our own tracing anyways
$options['trace'] = false;
// disable WSDL caching as we handle WSDL caching for remote URLs ourself
$options['cache_wsdl'] = WSDL_CACHE_NONE;
$this->soapVersion = $soapOptions->getSoapVersion();
$this->tracingEnabled = $soapClientOptions->getTrace();
// @todo: refactor SoapClient: do not use $options as array
$options = $this->configureMime($soapOptions->toArray());
// @todo: refactor SoapClient: do not use $options as array
$this->curl = new Curl($soapClientOptions->toArray());
// @todo: refactor SoapClient: do not use $options as array
$wsdlFile = $this->loadWsdl($soapOptions->getWsdlFile(), $soapOptions->toArray());
parent::__construct($wsdlFile, $options);
}
@ -153,32 +129,19 @@ class SoapClient extends \SoapClient
$location = $soapRequest->getLocation();
$content = $soapRequest->getContent();
/*
* Work around missing header/php://input access in PHP cli webserver by
* setting headers additionally as GET parameters and SOAP request body
* explicitly as POST variable
*/
if ($this->cliWebserverWorkaround === true) {
if (strpos($location, '?') === false) {
$location .= '?';
} else {
$location .= '&';
}
$location .= SoapMessage::CONTENT_TYPE_HEADER.'='.urlencode($soapRequest->getContentType());
$location .= '&';
$location .= SoapMessage::SOAP_ACTION_HEADER.'='.urlencode($soapRequest->getAction());
$content = http_build_query(array('request' => $content));
$headers = $this->filterRequestHeaders($soapRequest, $headers);
$headers = array();
}
$options = $this->filterRequestOptions($soapRequest);
// execute HTTP request with cURL
$responseSuccessfull = $this->curl->exec(
$location,
$content,
$headers
$headers,
$options
);
// tracing enabled: store last request header and body
if ($this->tracingEnabled === true) {
$this->lastRequestHeaders = $this->curl->getRequestHeaders();
@ -211,6 +174,7 @@ class SoapClient extends \SoapClient
* Custom request method to be able to modify the SOAP messages.
* $oneWay parameter is not used at the moment.
*
* @todo: refactor SoapClient: refactoring starts from here
* @param string $request Request string
* @param string $location Location
* @param string $action SOAP action
@ -253,6 +217,31 @@ class SoapClient extends \SoapClient
return $soapResponse;
}
/**
* Filters HTTP headers which will be sent
*
* @param SoapRequest $soapRequest SOAP request object
* @param array $headers An array of HTTP headers
*
* @return array
*/
protected function filterRequestHeaders(SoapRequest $soapRequest, array $headers)
{
return $headers;
}
/**
* Adds additional cURL options for the request
*
* @param SoapRequest $soapRequest SOAP request object
*
* @return array
*/
protected function filterRequestOptions(SoapRequest $soapRequest)
{
return array();
}
/**
* Get last request HTTP headers.
*
@ -303,16 +292,9 @@ class SoapClient extends \SoapClient
return $this->soapKernel;
}
/**
* Configure filter and type converter for SwA/MTOM.
*
* @param array &$options SOAP constructor options array.
*
* @return void
*/
private function configureMime(array &$options)
private function configureMime(array $options)
{
if (isset($options['attachment_type']) && Helper::ATTACHMENTS_TYPE_BASE64 !== $options['attachment_type']) {
if (Helper::ATTACHMENTS_TYPE_BASE64 !== $options['attachment_type']) {
// register mime filter in SoapKernel
$mimeFilter = new MimeFilter($options['attachment_type']);
$this->soapKernel->registerFilter($mimeFilter);
@ -341,6 +323,8 @@ class SoapClient extends \SoapClient
},
);
}
return $options;
}
/**
@ -354,7 +338,7 @@ class SoapClient extends \SoapClient
*
* @return string
*/
private function loadWsdl($wsdl, array $options)
protected function loadWsdl($wsdl, array $options)
{
// option to resolve wsdl/xsd includes
$resolveRemoteIncludes = true;

View File

@ -12,228 +12,22 @@
namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\AbstractSoapBuilder;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
/**
* Fluent interface builder for SoapClient instance.
* Provides a SoapClient instance.
*
* @author Francis Besset <francis.besset@gmail.com>
* @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/
class SoapClientBuilder extends AbstractSoapBuilder
class SoapClientBuilder
{
/**
* Authentication options.
*
* @var array(string=>mixed)
*/
protected $soapOptionAuthentication = array();
/**
* Create new instance with default options.
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public static function createWithDefaults()
public function build(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions)
{
return parent::createWithDefaults()
->withUserAgent('BeSimpleSoap');
}
/**
* Finally returns a SoapClient instance.
*
* @return \BeSimple\SoapClient\SoapClient
*/
public function build()
{
$this->validateOptions();
return new SoapClient($this->wsdl, $this->getSoapOptions());
}
/**
* Get final array of SOAP options.
*
* @return array(string=>mixed)
*/
public function getSoapOptions()
{
return parent::getSoapOptions() + $this->soapOptionAuthentication;
}
/**
* Configure option 'trace'.
*
* @param boolean $trace Enable/Disable
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withTrace($trace = true)
{
$this->soapOptions['trace'] = $trace;
return $this;
}
/**
* Configure option 'exceptions'.
*
* @param boolean $exceptions Enable/Disable
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withExceptions($exceptions = true)
{
$this->soapOptions['exceptions'] = $exceptions;
return $this;
}
/**
* Configure option 'user_agent'.
*
* @param string $userAgent User agent string
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withUserAgent($userAgent)
{
$this->soapOptions['user_agent'] = $userAgent;
return $this;
}
/**
* Enable gzip compression.
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withCompressionGzip()
{
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP;
return $this;
}
/**
* Enable deflate compression.
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withCompressionDeflate()
{
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE;
return $this;
}
/**
* Configure basic authentication
*
* @param string $username Username
* @param string $password Password
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withBasicAuthentication($username, $password)
{
$this->soapOptionAuthentication = array(
'authentication' => SOAP_AUTHENTICATION_BASIC,
'login' => $username,
'password' => $password,
return new SoapClient(
$soapClientOptions,
$soapOptions
);
return $this;
}
/**
* Configure digest authentication.
*
* @param string $certificate Certificate
* @param string $passphrase Passphrase
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withDigestAuthentication($certificate, $passphrase = null)
{
$this->soapOptionAuthentication = array(
'authentication' => SOAP_AUTHENTICATION_DIGEST,
'local_cert' => $certificate,
);
if ($passphrase) {
$this->soapOptionAuthentication['passphrase'] = $passphrase;
}
return $this;
}
/**
* Configure proxy.
*
* @param string $host Host
* @param int $port Port
* @param string $username Username
* @param string $password Password
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withProxy($host, $port, $username = null, $password = null)
{
$this->soapOptions['proxy_host'] = $host;
$this->soapOptions['proxy_port'] = $port;
if ($username) {
$this->soapOptions['proxy_login'] = $username;
$this->soapOptions['proxy_password'] = $password;
}
return $this;
}
/**
* SOAP attachment type Base64.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withBase64Attachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_BASE64;
return $this;
}
/**
* SOAP attachment type SwA.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withSwaAttachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_SWA;
return $this;
}
/**
* SOAP attachment type MTOM.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withMtomAttachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_MTOM;
return $this;
}
/**
* Validate options.
*/
protected function validateOptions()
{
$this->validateWsdl();
}
}

View File

@ -0,0 +1,35 @@
<?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\SoapClient;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
/**
* Provides a SoapClient instance.
*
* @author Francis Besset <francis.besset@gmail.com>
* @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/
class SoapClientOptionsBuilder
{
public static function createWithDefaults()
{
return new SoapClientOptions(
SoapClientOptions::SOAP_CLIENT_TRACE_OFF,
SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON,
'BeSimpleSoap',
SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE
);
}
}

View File

@ -0,0 +1,107 @@
<?php
namespace BeSimple\SoapClient;
use BeSimple\SoapClient\SoapServerAuthentication\SoapServerAuthenticationInterface;
use BeSimple\SoapClient\SoapServerProxy\SoapServerProxy;
class SoapClientOptions
{
const SOAP_CLIENT_TRACE_ON = true;
const SOAP_CLIENT_TRACE_OFF = false;
const SOAP_CLIENT_EXCEPTIONS_ON = true;
const SOAP_CLIENT_EXCEPTIONS_OFF = false;
const SOAP_CLIENT_COMPRESSION_NONE = null;
const SOAP_CLIENT_COMPRESSION_GZIP = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP;
const SOAP_CLIENT_COMPRESSION_DEFLATE = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE;
private $trace;
private $exceptions;
private $userAgent;
private $compression;
private $authentication;
private $proxy;
/**
* @param bool $trace = SoapClientOptions::SOAP_CLIENT_TRACE_ON|SoapClientOptions::SOAP_CLIENT_TRACE_OFF
* @param bool $exceptions = SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON|SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_OFF
* @param string $userAgent
* @param int $compression = SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE|SoapClientOptions::SOAP_CLIENT_COMPRESSION_GZIP|SoapClientOptions::SOAP_CLIENT_COMPRESSION_DEFLATE
* @param SoapServerAuthenticationInterface $authentication = null
* @param SoapServerProxy $proxy = null
*/
public function __construct($trace, $exceptions, $userAgent, $compression = null, SoapServerAuthenticationInterface $authentication = null, SoapServerProxy $proxy = null)
{
$this->trace = $trace;
$this->exceptions = $exceptions;
$this->userAgent = $userAgent;
$this->compression = $compression;
$this->authentication = $authentication;
$this->proxy = $proxy;
}
public function getTrace()
{
return $this->trace;
}
public function getExceptions()
{
return $this->exceptions;
}
public function getUserAgent()
{
return $this->userAgent;
}
public function hasCompression()
{
return $this->compression !== self::SOAP_CLIENT_COMPRESSION_NONE;
}
public function getCompression()
{
return $this->compression;
}
public function hasAuthentication()
{
return $this->authentication !== null;
}
public function hasProxy()
{
return $this->proxy !== null;
}
public function getAuthentication()
{
return $this->authentication;
}
public function getProxy()
{
return $this->proxy;
}
public function toArray()
{
$optionsAsArray = [
'trace' => $this->getTrace(),
'exceptions' => $this->getExceptions(),
'user_agent' => $this->getUserAgent(),
];
if ($this->hasCompression()) {
$optionsAsArray['compression'] = $this->getCompression();
}
if ($this->hasAuthentication()) {
$optionsAsArray += $this->getAuthentication()->toArray();
}
if ($this->hasProxy()) {
$optionsAsArray += $this->getProxy()->toArray();
}
return $optionsAsArray;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace BeSimple\SoapClient\SoapServerAuthentication;
class SoapServerAuthenticationBasic implements SoapServerAuthenticationInterface
{
private $login;
private $password;
public function __construct($login, $password)
{
$this->login = $login;
$this->password = $password;
}
public function getAuthentication()
{
return \SOAP_AUTHENTICATION_BASIC;
}
public function getLogin()
{
return $this->login;
}
public function getPassword()
{
return $this->password;
}
public function toArray()
{
return [
'authentication' => $this->getAuthentication(),
'login' => $this->getLogin(),
'password' => $this->getPassword(),
];
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace BeSimple\SoapClient\SoapServerAuthentication;
class SoapServerAuthenticationDigest implements SoapServerAuthenticationInterface
{
private $localCert;
private $passPhrase;
/**
* @param string $localCert
* @param string $passPhrase = null
*/
public function __construct($localCert, $passPhrase = null)
{
$this->localCert = $localCert;
$this->passPhrase = $passPhrase;
}
public function getLocalCert()
{
return $this->localCert;
}
public function hasPassPhrase()
{
return $this->passPhrase !== null;
}
public function getPassPhrase()
{
return $this->passPhrase;
}
public function getAuthentication()
{
return \SOAP_AUTHENTICATION_DIGEST;
}
public function toArray()
{
$authenticationAsArray = [
'authentication' => $this->getAuthentication(),
'local_cert' => $this->getLocalCert()
];
if ($this->hasPassPhrase()) {
$authenticationAsArray['passphrase'] = $this->getPassPhrase();
}
return $authenticationAsArray;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace BeSimple\SoapClient\SoapServerAuthentication;
interface SoapServerAuthenticationInterface
{
/**
* @return int
*/
public function getAuthentication();
/**
* @return array
*/
public function toArray();
}

View File

@ -0,0 +1,84 @@
<?php
namespace BeSimple\SoapClient\SoapServerProxy;
class SoapServerProxy
{
const PROXY_AUTHENTICATION_TYPE_NONE = null;
const PROXY_AUTHENTICATION_TYPE_BASIC = \CURLAUTH_BASIC;
const PROXY_AUTHENTICATION_TYPE_NTLM = \CURLAUTH_NTLM;
private $host;
private $port;
private $login;
private $password;
private $authenticationType;
/**
* @param string $host
* @param int $port
* @param string $login = null
* @param string $password = null
* @param int $authenticationType = null|SoapServerProxy::PROXY_AUTHENTICATION_TYPE_BASIC|SoapServerProxy::PROXY_AUTHENTICATION_TYPE_NTLM
*/
public function __construct($host, $port, $login = null, $password = null, $authenticationType = null)
{
$this->host = $host;
$this->port = $port;
$this->login = $login;
$this->password = $password;
$this->authenticationType = $authenticationType;
}
public function getHost()
{
return $this->host;
}
public function getPort()
{
return $this->port;
}
public function hasCredentials()
{
return $this->login !== null;
}
public function getLogin()
{
return $this->login;
}
public function getPassword()
{
return $this->password;
}
public function hasAuthenticationType()
{
return $this->authenticationType !== self::PROXY_AUTHENTICATION_TYPE_NONE;
}
public function getAuthenticationType()
{
return $this->authenticationType;
}
public function toArray()
{
$proxyAsArray = [
'proxy_host' => $this->getHost(),
'proxy_port' => $this->getPort(),
];
if ($this->hasCredentials()) {
$proxyAsArray['proxy_login'] = $this->getLogin();
$proxyAsArray['proxy_password'] = $this->getPassword();
}
if ($this->hasAuthenticationType()) {
$proxyAsArray['proxy_auth'] = $this->getAuthenticationType();
}
return $proxyAsArray;
}
}

View File

@ -1,48 +0,0 @@
<?php
/*
* This file is part of the BeSimpleSoapClient.
*
* (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\SoapClient;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapMessage;
/**
* SoapRequest class for SoapClient. Provides factory function for request object.
*
* @author Andreas Schamberger <mail@andreass.net>
*/
class SoapRequest extends CommonSoapRequest
{
/**
* Factory function for SoapRequest.
*
* @param string $content Content
* @param string $location Location
* @param string $action SOAP action
* @param string $version SOAP version
*
* @return BeSimple\SoapClient\SoapRequest
*/
public static function create($content, $location, $action, $version)
{
$request = new SoapRequest();
// $content is if unmodified from SoapClient not a php string type!
$request->setContent((string) $content);
$request->setLocation($location);
$request->setAction($action);
$request->setVersion($version);
$contentType = SoapMessage::getContentTypeForVersion($version);
$request->setContentType($contentType);
return $request;
}
}

View File

@ -13,7 +13,6 @@
namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
use BeSimple\SoapCommon\SoapMessage;
/**
* SoapResponse class for SoapClient. Provides factory function for response object.
@ -31,7 +30,7 @@ class SoapResponse extends CommonSoapResponse
* @param string $version SOAP version
* @param string $contentType Content type header
*
* @return BeSimple\SoapClient\SoapResponse
* @return SoapResponse
*/
public static function create($content, $location, $action, $version, $contentType)
{

View File

@ -28,6 +28,7 @@ class MtomAxisInteropTest extends TestCase
'base64Binary' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\base64Binary',
'AttachmentRequest' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\AttachmentRequest',
),
'proxy_host' => false,
);
public function testAttachment()

View File

@ -37,6 +37,7 @@ class SwaAxisInteropTest extends TestCase
'uploadFile' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\uploadFile',
'uploadFileResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\uploadFileResponse',
),
'proxy_host' => false,
);
public function testUploadDownloadText()

View File

@ -32,6 +32,7 @@ class WsAddressingAxisInteropTest extends TestCase
private $options = array(
'soap_version' => SOAP_1_2,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
'proxy_host' => false,
);
public function testSession()

View File

@ -64,6 +64,7 @@ class WsSecuritySigEncAxisInteropTest extends TestCase
'addBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation',
),
'proxy_host' => false,
);
public function testSigEnc()

View File

@ -40,6 +40,7 @@ class WsSecurityUserPassAxisInteropTest extends TestCase
'addBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation',
),
'proxy_host' => false,
);
public function testUserPassText()

View File

@ -21,7 +21,9 @@ class CurlTest extends AbstractWebserverTest
{
public function testExec()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$this->assertTrue($curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)));
$this->assertTrue($curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT)));
@ -29,7 +31,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetErrorMessage()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec('http://unknown/curl.txt');
$this->assertEquals('Could not connect to host', $curl->getErrorMessage());
@ -43,7 +47,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetRequestHeaders()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals(132 + self::$websererPortLength, strlen($curl->getRequestHeaders()));
@ -54,7 +60,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetResponse()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertSame('OK', $curl->getResponseStatusMessage());
@ -66,7 +74,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetResponseBody()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals('This is a testfile for cURL.', $curl->getResponseBody());
@ -74,7 +84,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetResponseContentType()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals('text/plain; charset=UTF-8', $curl->getResponseContentType());
@ -85,7 +97,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetResponseHeaders()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals(117 + self::$websererPortLength, strlen($curl->getResponseHeaders()));
@ -96,7 +110,9 @@ class CurlTest extends AbstractWebserverTest
public function testGetResponseStatusCode()
{
$curl = new Curl();
$curl = new Curl(array(
'proxy_host' => false,
));
$curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT));
$this->assertEquals(200, $curl->getResponseStatusCode());

View File

@ -18,7 +18,6 @@ $options = array(
'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary',
'AttachmentRequest' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
'connection_timeout' => 1,
);

View File

@ -14,13 +14,13 @@ $options = array(
'cache_wsdl' => WSDL_CACHE_NONE,
'classmap' => array(
'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary',
'AttachmentRequest' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest',
'AttachmentType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest',
),
);
class Mtom
{
public function attachment(AttachmentRequest $attachment)
public function attachment(Fixtures\AttachmentRequest $attachment)
{
$b64 = $attachment->binaryData;

View File

@ -20,7 +20,7 @@ class MtomServerInteropTest extends TestCase
'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary',
'AttachmentRequest' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
'proxy_host' => false,
);
public function testAttachment()

View File

@ -24,7 +24,6 @@ $options = array(
'uploadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFile',
'uploadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFileResponse',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
);
$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $options);

View File

@ -23,7 +23,7 @@ class SwaServerInteropTest extends TestCase
'uploadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFile',
'uploadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFileResponse',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
'proxy_host' => false,
);
public function testUploadDownloadText()
@ -42,6 +42,8 @@ class SwaServerInteropTest extends TestCase
$result = $sc->downloadFile($download);
$this->assertEquals($upload->data, $result->data);
unlink(__DIR__.'/../ServerInterop/'.$download->name);
}
public function testUploadDownloadImage()
@ -60,5 +62,7 @@ class SwaServerInteropTest extends TestCase
$result = $sc->downloadFile($download);
$this->assertEquals($upload->data, $result->data);
unlink(__DIR__.'/../ServerInterop/'.$download->name);
}
}

View File

@ -31,7 +31,6 @@ $options = array(
'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
);
$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecuritySigEnc.wsdl', $options);

View File

@ -30,7 +30,7 @@ class WsSecuritySigEncServerInteropTest extends TestCase
'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
'proxy_host' => false,
);
public function testSigEnc()

View File

@ -28,7 +28,6 @@ $options = array(
'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
);
$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $options);

View File

@ -29,7 +29,7 @@ class WsSecurityUserPassServerInteropTest extends TestCase
'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse',
'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation',
),
'cli_webserver_workaround' => true, // Work around missing header access in PHP cli webserver by setting headers additionally as GET parameters.
'proxy_host' => false,
);
public function testUserPassText()

View File

@ -96,11 +96,25 @@ class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase
$builder->withProxy('127.0.0.1', 8585, 'foo', 'bar');
$this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar')), $builder->getSoapOptions());
$builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', \CURLAUTH_BASIC);
$this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar', 'proxy_auth' => \CURLAUTH_BASIC)), $builder->getSoapOptions());
$builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', \CURLAUTH_NTLM);
$this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar', 'proxy_auth' => \CURLAUTH_NTLM)), $builder->getSoapOptions());
try {
$builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', -100);
$this->fail('An expected exception has not been raised.');
} catch (\Exception $e) {
$this->assertInstanceOf('InvalidArgumentException', $e);
}
}
public function testCreateWithDefaults()
{
$builder = SoapClientBuilder::createWithDefaults();
$builder = SoapClientBuilder::createClientWithDefaults();
$this->assertInstanceOf('BeSimple\SoapClient\SoapClientBuilder', $builder);

View File

@ -41,7 +41,9 @@ class WsdlDownloaderTest extends AbstractWebserverTest
Cache::setDirectory($wsdlCacheUrl);
$cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#');
$wsdlDownloader = new WsdlDownloader(new Curl());
$wsdlDownloader = new WsdlDownloader(new Curl(array(
'proxy_host' => false,
)));
$this->assertCount(0, $wsdlCacheDir->getChildren());
$cacheFileName = $wsdlDownloader->download($source);
@ -113,7 +115,9 @@ class WsdlDownloaderTest extends AbstractWebserverTest
Cache::setDirectory($wsdlCacheUrl);
$cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#');
$wsdlDownloader = new WsdlDownloader(new Curl());
$wsdlDownloader = new WsdlDownloader(new Curl(array(
'proxy_host' => false,
)));
$r = new \ReflectionClass($wsdlDownloader);
$m = $r->getMethod('resolveRemoteIncludes');
$m->setAccessible(true);
@ -176,7 +180,9 @@ class WsdlDownloaderTest extends AbstractWebserverTest
Cache::setDirectory($wsdlCacheUrl);
$cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#');
$wsdlDownloader = new WsdlDownloader(new Curl());
$wsdlDownloader = new WsdlDownloader(new Curl(array(
'proxy_host' => false,
)));
$r = new \ReflectionClass($wsdlDownloader);
$m = $r->getMethod('resolveRemoteIncludes');
$m->setAccessible(true);

View File

@ -23,12 +23,12 @@ if [ ! -f "$DIR/$ZIP_RAMPART" ]; then
curl -O -s $PATH_RAMPART
fi
unzip -qq "$DIR/$ZIP_AXIS"
unzip -o -qq "$DIR/$ZIP_AXIS"
AXIS_DIR=$DIR/axis2-$VERSION_AXIS
unzip -qq -j "$DIR/$ZIP_RAMPART" '*/lib/*.jar' -d $AXIS_DIR/lib
unzip -qq -j "$DIR/$ZIP_RAMPART" '*/modules/*.mar' -d $AXIS_DIR/repository/modules
unzip -o -qq -j "$DIR/$ZIP_RAMPART" '*/lib/*.jar' -d $AXIS_DIR/lib
unzip -o -qq -j "$DIR/$ZIP_RAMPART" '*/modules/*.mar' -d $AXIS_DIR/repository/modules
cp -r $DIR/../AxisInterop/axis_services/* $AXIS_DIR/repository/services

View File

@ -14,16 +14,12 @@ namespace BeSimple\SoapClient;
use ass\XmlSecurity\DSig as XmlSecurityDSig;
use ass\XmlSecurity\Enc as XmlSecurityEnc;
use ass\XmlSecurity\Key as XmlSecurityKey;
use ass\XmlSecurity\Pem as XmlSecurityPem;
use BeSimple\SoapCommon\FilterHelper;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
use BeSimple\SoapCommon\SoapResponseFilter;
use BeSimple\SoapCommon\WsSecurityKey;
use BeSimple\SoapCommon\WsSecurityFilterClientServer;
/**
@ -214,7 +210,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque
$referenceList = XmlSecurityEnc::createReferenceList($encryptedKey);
// token reference to encrypted key
$keyInfo = $this->createKeyInfo($filterHelper, self::TOKEN_REFERENCE_SECURITY_TOKEN, $guid);
$nodes = $this->createNodeListForEncryption($dom, $security);
$nodes = $this->createNodeListForEncryption($dom);
foreach ($nodes as $node) {
$type = XmlSecurityEnc::ELEMENT;
if ($node->localName == 'Body') {

View File

@ -14,13 +14,8 @@ namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\FilterHelper;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Mime\MultiPart as MimeMultiPart;
use BeSimple\SoapCommon\Mime\Parser as MimeParser;
use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponse;
use BeSimple\SoapCommon\SoapResponseFilter;
/**
* XML MIME filter that fixes the namespace of xmime:contentType attribute.

View File

@ -23,11 +23,11 @@
"php": ">=5.3.0",
"ext-soap": "*",
"ext-curl": "*",
"besimple/soap-common": "0.2.*",
"besimple/soap-common": "0.3.*",
"ass/xmlsecurity": "~1.0"
},
"require-dev": {
"mikey179/vfsStream": "dev-master",
"mikey179/vfsStream": "~1.0",
"symfony/filesystem": "~2.3",
"symfony/process": "~2.3"
},
@ -35,10 +35,9 @@
"psr-0": { "BeSimple\\SoapClient": "" }
},
"target-dir": "BeSimple/SoapClient",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.3-dev"
}
}
}

View File

@ -1,246 +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\SoapCommon;
use BeSimple\SoapCommon\Converter\TypeConverterCollection;
use BeSimple\SoapCommon\Converter\TypeConverterInterface;
/**
* @author Christian Kerl <christian-kerl@web.de>
* @author Francis Besset <francis.besset@gmail.com>
*/
abstract class AbstractSoapBuilder
{
protected $wsdl;
protected $soapOptions = array();
/**
* @return AbstractSoapBuilder
*/
static public function createWithDefaults()
{
$builder = new static();
return $builder
->withSoapVersion12()
->withEncoding('UTF-8')
->withSingleElementArrays()
;
}
public function __construct()
{
$this->soapOptions['features'] = 0;
$this->soapOptions['classmap'] = new Classmap();
$this->soapOptions['typemap'] = new TypeConverterCollection();
}
public function getWsdl()
{
return $this->wsdl;
}
public function getSoapOptions()
{
$options = $this->soapOptions;
$options['classmap'] = $this->soapOptions['classmap']->all();
$options['typemap'] = $this->soapOptions['typemap']->getTypemap();
return $options;
}
/**
* @return AbstractSoapBuilder
*/
public function withWsdl($wsdl)
{
$this->wsdl = $wsdl;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withSoapVersion11()
{
$this->soapOptions['soap_version'] = \SOAP_1_1;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withSoapVersion12()
{
$this->soapOptions['soap_version'] = \SOAP_1_2;
return $this;
}
public function withEncoding($encoding)
{
$this->soapOptions['encoding'] = $encoding;
return $this;
}
public function withWsdlCache($cache)
{
if (!in_array($cache, Cache::getTypes(), true)) {
throw new \InvalidArgumentException();
}
$this->soapOptions['cache_wsdl'] = $cache;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withWsdlCacheNone()
{
$this->soapOptions['cache_wsdl'] = Cache::TYPE_NONE;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withWsdlCacheDisk()
{
$this->soapOptions['cache_wsdl'] = Cache::TYPE_DISK;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withWsdlCacheMemory()
{
$this->soapOptions['cache_wsdl'] = Cache::TYPE_MEMORY;
return $this;
}
/**
* @return AbstractSoapBuilder
*/
public function withWsdlCacheDiskAndMemory()
{
$this->soapOptions['cache_wsdl'] = Cache::TYPE_DISK_MEMORY;
return $this;
}
/**
* Enables the SOAP_SINGLE_ELEMENT_ARRAYS feature.
* If enabled arrays containing only one element will be passed as arrays otherwise the single element is extracted and directly passed.
*
* @return AbstractSoapBuilder
*/
public function withSingleElementArrays()
{
$this->soapOptions['features'] |= \SOAP_SINGLE_ELEMENT_ARRAYS;
return $this;
}
/**
* Enables the SOAP_WAIT_ONE_WAY_CALLS feature.
*
* @return AbstractSoapBuilder
*/
public function withWaitOneWayCalls()
{
$this->soapOptions['features'] |= \SOAP_WAIT_ONE_WAY_CALLS;
return $this;
}
/**
* Enables the SOAP_USE_XSI_ARRAY_TYPE feature.
*
* @return AbstractSoapBuilder
*/
public function withUseXsiArrayType()
{
$this->soapOptions['features'] |= \SOAP_USE_XSI_ARRAY_TYPE;
return $this;
}
public function withTypeConverter(TypeConverterInterface $converter)
{
$this->soapOptions['typemap']->add($converter);
return $this;
}
public function withTypeConverters(TypeConverterCollection $converters, $merge = true)
{
if ($merge) {
$this->soapOptions['typemap']->addCollection($converters);
} else {
$this->soapOptions['typemap']->set($converters->all());
}
return $this;
}
/**
* Adds a class mapping to the classmap.
*
* @param string $xmlType
* @param string $phpType
*
* @return AbstractSoapBuilder
*/
public function withClassMapping($xmlType, $phpType)
{
$this->soapOptions['classmap']->add($xmlType, $phpType);
return $this;
}
/**
* Sets the classmap.
*
* @param array $classmap The classmap.
* @param boolean $merge If true the given classmap is merged into the existing one, otherwise the existing one is overwritten.
*
* @return AbstractSoapBuilder
*/
public function withClassmap(Classmap $classmap, $merge = true)
{
if ($merge) {
$this->soapOptions['classmap']->addClassmap($classmap);
} else {
$this->soapOptions['classmap']->set($classmap->all());
}
return $this;
}
protected function validateWsdl()
{
if (null === $this->wsdl) {
throw new \InvalidArgumentException('The WSDL has to be configured!');
}
}
}

View File

@ -25,18 +25,23 @@ class Cache
const TYPE_MEMORY = WSDL_CACHE_MEMORY;
const TYPE_DISK_MEMORY = WSDL_CACHE_BOTH;
static protected $types = array(
static protected $types = [
self::TYPE_NONE,
self::TYPE_DISK,
self::TYPE_MEMORY,
self::TYPE_DISK_MEMORY,
);
];
static public function getTypes()
{
return self::$types;
}
static public function hasType($cacheType)
{
return in_array($cacheType, self::$types);
}
static public function isEnabled()
{
return self::iniGet('soap.wsdl_cache_enabled');

View File

@ -15,27 +15,29 @@ namespace BeSimple\SoapCommon;
/**
* @author Francis Besset <francis.besset@gmail.com>
*/
class Classmap
class ClassMap
{
/**
* @var array
*/
protected $classmap = array();
protected $classMap;
public function __construct(array $classMap = [])
{
$this->classmap = [];
foreach ($classMap as $type => $className) {
$this->add($type, $className);
}
}
/**
* @return array
*/
public function all()
public function getAll()
{
return $this->classmap;
return $this->classMap;
}
/**
* @param string $type
*
* @return string
*
* @throws \InvalidArgumentException
*/
public function get($type)
@ -44,39 +46,25 @@ class Classmap
throw new \InvalidArgumentException(sprintf('The type "%s" does not exists', $type));
}
return $this->classmap[$type];
return $this->classMap[$type];
}
/**
* @param string $type
* @param string $classname
*
* @param string $className
* @throws \InvalidArgumentException
*/
public function add($type, $classname)
public function add($type, $className)
{
if ($this->has($type)) {
throw new \InvalidArgumentException(sprintf('The type "%s" already exists', $type));
}
$this->classmap[$type] = $classname;
}
/**
* @param array $classmap
*/
public function set(array $classmap)
{
$this->classmap = array();
foreach ($classmap as $type => $classname) {
$this->add($type, $classname);
}
$this->classMap[$type] = $className;
}
/**
* @param string $type
*
* @return boolean
*/
public function has($type)
@ -84,10 +72,10 @@ class Classmap
return isset($this->classmap[$type]);
}
public function addClassmap(Classmap $classmap)
public function addClassMap(ClassMap $classMap)
{
foreach ($classmap->all() as $type => $classname) {
$this->add($type, $classname);
foreach ($classMap->getAll() as $type => $className) {
$this->add($type, $className);
}
}
}

View File

@ -12,7 +12,6 @@
namespace BeSimple\SoapCommon\Converter;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\SoapKernel;
use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface;

View File

@ -19,7 +19,7 @@ class TypeConverterCollection
{
private $converters = array();
public function all()
public function getAll()
{
return array_values($this->converters);
}
@ -58,7 +58,7 @@ class TypeConverterCollection
public function addCollection(TypeConverterCollection $converterCollection)
{
foreach ($converterCollection->all() as $converter) {
foreach ($converterCollection->getAll() as $converter) {
$this->add($converter);
}
}

View File

@ -26,14 +26,14 @@ class Method
private $output;
private $fault;
public function __construct($name, TypeRepository $typeRepository)
public function __construct($name)
{
$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);
$this->headers = new Message($name.'Header');
$this->input = new Message($name.'Request');
$this->output = new Message($name.'Response');
$this->fault = new Message($name.'Fault');
}
public function getName()

View File

@ -14,9 +14,6 @@
namespace BeSimple\SoapCommon;
use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\Converter\MtomTypeConverter;
use BeSimple\SoapCommon\Converter\SwaTypeConverter;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapResponse;
use BeSimple\SoapCommon\SoapRequestFilter;

View File

@ -13,8 +13,6 @@
namespace BeSimple\SoapCommon;
use BeSimple\SoapCommon\Mime\Part as MimePart;
/**
* Base class for SoapRequest and SoapResponse.
*
@ -30,6 +28,13 @@ abstract class SoapMessage
*/
const CONTENT_TYPE_HEADER = 'CONTENT_TYPE';
/**
* $_SERVER key for 'Content-Type' header (with PHP cli-webserver)
*
* @var string
*/
const HTTP_CONTENT_TYPE_HEADER = 'HTTP_CONTENT_TYPE';
/**
* $_SERVER key for 'SOAPAction' header.
*

View File

@ -0,0 +1,70 @@
<?php
namespace BeSimple\SoapCommon\SoapOptions\SoapFeatures;
use Exception;
class SoapFeatures
{
const SINGLE_ELEMENT_ARRAYS = \SOAP_SINGLE_ELEMENT_ARRAYS;
const WAIT_ONE_WAY_CALLS = \SOAP_WAIT_ONE_WAY_CALLS;
const USE_XSI_ARRAY_TYPE = \SOAP_USE_XSI_ARRAY_TYPE;
private $featuresSum;
private $singleElementArrays = false;
private $oneWayCallsOn = false;
private $useXsiArrayType = false;
/**
* @param array $features array of SoapFeatures::FEATURE_NAME
* @throws Exception
*/
public function __construct(array $features)
{
$this->resolveFeatures($features);
}
public function isSingleElementArrays()
{
return $this->singleElementArrays;
}
public function isOneWayCallsOn()
{
return $this->oneWayCallsOn;
}
public function isUseXsiArrayType()
{
return $this->useXsiArrayType;
}
public function getFeaturesSum()
{
return $this->featuresSum;
}
private function resolveFeatures(array $features)
{
$featuresSum = 0;
foreach ($features as $feature) {
switch ($feature) {
case self::SINGLE_ELEMENT_ARRAYS:
$this->singleElementArrays = true;
$featuresSum += $feature;
break;
case self::WAIT_ONE_WAY_CALLS:
$this->oneWayCallsOn = true;
$featuresSum += $feature;
break;
case self::USE_XSI_ARRAY_TYPE:
$this->useXsiArrayType = true;
$featuresSum += $feature;
break;
default:
throw new Exception('Unknown SOAP feature: ' . $feature);
}
}
$this->featuresSum = $featuresSum;
}
}

View File

@ -0,0 +1,124 @@
<?php
namespace BeSimple\SoapCommon\SoapOptions;
use BeSimple\SoapCommon\Cache;
use BeSimple\SoapCommon\ClassMap;
use BeSimple\SoapCommon\Converter\TypeConverterCollection;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapOptions\SoapFeatures\SoapFeatures;
class SoapOptions
{
const SOAP_VERSION_1_1 = \SOAP_1_1;
const SOAP_VERSION_1_2 = \SOAP_1_2;
const SOAP_ENCODING_UTF8 = 'UTF-8';
const SOAP_SINGLE_ELEMENT_ARRAYS_OFF = 0;
const SOAP_CACHE_TYPE_NONE = Cache::TYPE_NONE;
const SOAP_CACHE_TYPE_DISK = Cache::TYPE_DISK;
const SOAP_CACHE_TYPE_MEMORY = Cache::TYPE_MEMORY;
const SOAP_CACHE_TYPE_DISK_MEMORY = Cache::TYPE_DISK_MEMORY;
const SOAP_ATTACHMENTS_OFF = null;
const SOAP_ATTACHMENTS_TYPE_BASE64 = Helper::ATTACHMENTS_TYPE_BASE64;
const SOAP_ATTACHMENTS_TYPE_MTOM = Helper::ATTACHMENTS_TYPE_MTOM;
const SOAP_ATTACHMENTS_TYPE_SWA = Helper::ATTACHMENTS_TYPE_SWA;
protected $soapVersion;
protected $encoding;
protected $soapFeatures;
protected $wsdlFile;
protected $wsdlCacheType;
protected $classMap;
protected $typeConverterCollection;
protected $attachmentType;
/**
* @param int $soapVersion = SoapOptions::SOAP_VERSION_1_1|SoapOptions::SOAP_VERSION_1_2
* @param string $encoding = SoapOptions::SOAP_ENCODING_UTF8
* @param SoapFeatures $features
* @param string $wsdlFile
* @param string $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE|SoapOptions::SOAP_CACHE_TYPE_MEMORY|SoapOptions::SOAP_CACHE_TYPE_DISK|SoapOptions::SOAP_CACHE_TYPE_DISK_MEMORY
* @param ClassMap $classMap
* @param TypeConverterCollection $typeConverterCollection
* @param string $attachmentType = SoapOptions::SOAP_ATTACHMENTS_OFF|SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64
*/
public function __construct(
$soapVersion,
$encoding,
SoapFeatures $features,
$wsdlFile,
$wsdlCacheType,
ClassMap $classMap,
TypeConverterCollection $typeConverterCollection,
$attachmentType = null
) {
$this->soapVersion = $soapVersion;
$this->encoding = $encoding;
$this->soapFeatures = $features;
$this->wsdlFile = $wsdlFile;
$this->wsdlCacheType = $wsdlCacheType;
$this->classMap = $classMap;
$this->typeConverterCollection = $typeConverterCollection;
$this->attachmentType = $attachmentType;
}
public function getSoapVersion()
{
return $this->soapVersion;
}
public function getEncoding()
{
return $this->encoding;
}
public function getWsdlFile()
{
return $this->wsdlFile;
}
public function getWsdlCacheType()
{
return $this->wsdlCacheType;
}
public function hasAttachments()
{
return $this->attachmentType !== self::SOAP_ATTACHMENTS_OFF;
}
public function getAttachmentType()
{
return $this->attachmentType;
}
public function getSoapFeatures()
{
return $this->soapFeatures;
}
public function getClassMap()
{
return $this->classMap;
}
public function getTypeConverterCollection()
{
return $this->typeConverterCollection;
}
public function toArray()
{
$optionsAsArray = [
'soap_version' => $this->getSoapVersion(),
'encoding' => $this->getEncoding(),
'features' => $this->getSoapFeatures(),
'wsdl' => $this->getWsdlFile(),
'cache_wsdl' => $this->getWsdlCacheType(),
'classmap' => $this->getClassMap()->getAll(),
'typemap' => $this->getTypeConverterCollection()->getTypemap(),
];
return $optionsAsArray;
}
}

View File

@ -0,0 +1,44 @@
<?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\SoapCommon;
use BeSimple\SoapCommon\Converter\TypeConverterCollection;
use BeSimple\SoapCommon\SoapOptions\SoapFeatures\SoapFeatures;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use InvalidArgumentException;
/**
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/
class SoapOptionsBuilder
{
static public function createWithDefaults($wsdlFile, $wsdlCacheType = Cache::TYPE_NONE)
{
if (!Cache::hasType($wsdlCacheType)) {
throw new InvalidArgumentException;
}
$soapOptions = new SoapOptions(
SoapOptions::SOAP_VERSION_1_2,
SoapOptions::SOAP_ENCODING_UTF8,
new SoapFeatures([
SoapFeatures::SINGLE_ELEMENT_ARRAYS
]),
$wsdlFile,
$wsdlCacheType,
new ClassMap(),
new TypeConverterCollection()
);
return $soapOptions;
}
}

View File

@ -13,7 +13,6 @@
namespace BeSimple\SoapCommon;
use BeSimple\SoapCommon\SoapMessage;
/**
* SOAP request message.
@ -22,5 +21,27 @@ use BeSimple\SoapCommon\SoapMessage;
*/
class SoapRequest extends SoapMessage
{
/**
* Factory function for SoapRequest.
*
* @param string $content Content
* @param string $location Location
* @param string $action SOAP action
* @param string $version SOAP version
*
* @return SoapRequest
*/
public static function create($content, $location, $action, $version)
{
$request = new SoapRequest();
// $content is if unmodified from SoapClient not a php string type!
$request->setContent((string) $content);
$request->setLocation($location);
$request->setAction($action);
$request->setVersion($version);
$contentType = SoapMessage::getContentTypeForVersion($version);
$request->setContentType($contentType);
return $request;
}
}

View File

@ -177,7 +177,7 @@ class AbstractSoapBuilderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(1, count($options['classmap']));
$classmap = new Classmap();
$classmap = new ClassMap();
$classmap->add('bar', __CLASS__);
$builder->withClassmap($classmap);
$options = $builder->getSoapOptions();

View File

@ -0,0 +1,65 @@
<?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (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\Tests;
use BeSimple\SoapCommon\ClassMap;
/**
* UnitTest for \BeSimple\SoapCommon\ClassMap.
*
* @author Francis Besset <francis.besset@gmail.com>
*/
class ClassMapTest extends \PHPUnit_Framework_TestCase
{
public function testAll()
{
$classmap = new ClassMap();
$this->assertSame(array(), $classmap->getAll());
}
public function testAdd()
{
$classmap = new ClassMap();
$classmap->add('foobar', 'BeSimple\SoapCommon\ClassMap');
$this->setExpectedException('InvalidArgumentException');
$classmap->add('foobar', 'BeSimple\SoapCommon\ClassMap');
}
public function testGet()
{
$classmap = new ClassMap();
$classmap->add('foobar', 'BeSimple\SoapCommon\ClassMap');
$this->assertSame('BeSimple\SoapCommon\ClassMap', $classmap->get('foobar'));
$this->setExpectedException('InvalidArgumentException');
$classmap->get('bar');
}
public function testAddClassMap()
{
$classmap1 = new ClassMap();
$classmap2 = new ClassMap();
$classmap2->add('foobar', 'BeSimple\SoapCommon\ClassMap');
$classmap1->addClassMap($classmap2);
$this->assertEquals(array('foobar' => 'BeSimple\SoapCommon\ClassMap'), $classmap1->getAll());
$this->setExpectedException('InvalidArgumentException');
$classmap1->addClassMap($classmap2);
}
}

View File

@ -1,81 +0,0 @@
<?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (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\Tests;
use BeSimple\SoapCommon\Classmap;
/**
* UnitTest for \BeSimple\SoapCommon\Classmap.
*
* @author Francis Besset <francis.besset@gmail.com>
*/
class ClassmapTest extends \PHPUnit_Framework_TestCase
{
public function testAll()
{
$classmap = new Classmap();
$this->assertSame(array(), $classmap->all());
}
public function testAdd()
{
$classmap = new Classmap();
$classmap->add('foobar', 'BeSimple\SoapCommon\Classmap');
$this->setExpectedException('InvalidArgumentException');
$classmap->add('foobar', 'BeSimple\SoapCommon\Classmap');
}
public function testGet()
{
$classmap = new Classmap();
$classmap->add('foobar', 'BeSimple\SoapCommon\Classmap');
$this->assertSame('BeSimple\SoapCommon\Classmap', $classmap->get('foobar'));
$this->setExpectedException('InvalidArgumentException');
$classmap->get('bar');
}
public function testSet()
{
$classmap = new Classmap();
$classmap->add('foobar', 'BeSimple\SoapCommon\Tests\ClassmapTest');
$classmap->add('foo', 'BeSimple\SoapCommon\Tests\Classmap');
$map = array(
'foobar' => 'BeSimple\SoapCommon\Classmap',
'barfoo' => 'BeSimple\SoapCommon\Tests\ClassmapTest',
);
$classmap->set($map);
$this->assertSame($map, $classmap->all());
}
public function testAddClassmap()
{
$classmap1 = new Classmap();
$classmap2 = new Classmap();
$classmap2->add('foobar', 'BeSimple\SoapCommon\Classmap');
$classmap1->addClassmap($classmap2);
$this->assertEquals(array('foobar' => 'BeSimple\SoapCommon\Classmap'), $classmap1->all());
$this->setExpectedException('InvalidArgumentException');
$classmap1->addClassmap($classmap2);
}
}

View File

@ -30,12 +30,12 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$dateTimeTypeConverter = new DateTimeTypeConverter();
$converters->add($dateTimeTypeConverter);
$this->assertSame(array($dateTimeTypeConverter), $converters->all());
$this->assertSame(array($dateTimeTypeConverter), $converters->getAll());
$dateTypeConverter = new DateTypeConverter();
$converters->add($dateTypeConverter);
$this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->all());
$this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->getAll());
}
public function testGetTypemap()
@ -73,7 +73,7 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$converter = array(new DateTypeConverter);
$converters->set($converter);
$this->assertSame($converter, $converters->all());
$this->assertSame($converter, $converters->getAll());
}
public function testAddCollection()
@ -85,7 +85,7 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$converters2->add($dateTimeTypeConverter);
$converters1->addCollection($converters2);
$this->assertSame(array($dateTimeTypeConverter), $converters1->all());
$this->assertSame(array($dateTimeTypeConverter), $converters1->getAll());
$this->setExpectedException('InvalidArgumentException');
$converters1->addCollection($converters2);

View File

@ -16,13 +16,8 @@ use ass\XmlSecurity\DSig as XmlSecurityDSig;
use ass\XmlSecurity\Enc as XmlSecurityEnc;
use ass\XmlSecurity\Key as XmlSecurityKey;
use ass\XmlSecurity\Pem as XmlSecurityPem;
use BeSimple\SoapCommon\FilterHelper;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
use BeSimple\SoapCommon\SoapResponseFilter;
use BeSimple\SoapCommon\WsSecurityKey;
/**
@ -247,11 +242,10 @@ abstract class WsSecurityFilterClientServer
* Create a list of \DOMNodes that should be encrypted.
*
* @param \DOMDocument $dom DOMDocument to query
* @param \DOMElement $security Security element
*
* @return \DOMNodeList
*/
protected function createNodeListForEncryption(\DOMDocument $dom, \DOMElement $security)
protected function createNodeListForEncryption(\DOMDocument $dom)
{
$xpath = new \DOMXPath($dom);
$xpath->registerNamespace('SOAP-ENV', $dom->documentElement->namespaceURI);

View File

@ -174,7 +174,7 @@ class WsdlHandler
return true;
// type/* match
} else {
list($ctype, $csubtype) = explode('/', $currentMimeType);
list($ctype) = explode('/', $currentMimeType);
foreach ($mimeTypes as $mimeType) {
list($type, $subtype) = explode('/', $mimeType);
if ($subtype == '*' && $type == $ctype) {

View File

@ -26,16 +26,15 @@
},
"require-dev": {
"ext-mcrypt": "*",
"mikey179/vfsStream": "dev-master"
"mikey179/vfsStream": "~1.0"
},
"autoload": {
"psr-0": { "BeSimple\\SoapCommon": "" }
},
"target-dir": "BeSimple/SoapCommon",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.3-dev"
}
}
}

View File

@ -130,7 +130,7 @@ class MimeFilter implements SoapRequestFilter, SoapResponseFilter
// TODO
$headers = $multipart->getHeadersForHttp();
list($name, $contentType) = explode(': ', $headers[0]);
list(, $contentType) = explode(': ', $headers[0]);
$response->setContentType($contentType);
}

View File

@ -0,0 +1,137 @@
<?php
namespace BeSimple\SoapServer\SoapOptions;
class SoapServerOptions
{
const SOAP_SERVER_PERSISTENCE_NONE = 0;
const SOAP_SERVER_PERSISTENCE_REQUEST = \SOAP_PERSISTENCE_REQUEST;
const SOAP_SERVER_PERSISTENCE_SESSION = \SOAP_PERSISTENCE_SESSION;
const SOAP_SERVER_KEEP_ALIVE_ON = true;
const SOAP_SERVER_KEEP_ALIVE_OFF = false;
const SOAP_SERVER_ERROR_REPORTING_ON = true;
const SOAP_SERVER_ERROR_REPORTING_OFF = false;
const SOAP_SERVER_EXCEPTIONS_ON = true;
const SOAP_SERVER_EXCEPTIONS_OFF = false;
private $handlerClass;
private $handlerObject;
private $keepAlive;
private $errorReporting;
private $persistence;
/**
* @param mixed $handlerClassOrObject
* @param bool $keepAlive = SoapServerOptions::SOAP_SERVER_KEEP_ALIVE_ON|SoapServerOptions::SOAP_SERVER_KEEP_ALIVE_OFF
* @param bool $errorReporting = SoapServerOptions::SOAP_SERVER_ERROR_REPORTING_ON|SoapServerOptions::SOAP_SERVER_ERROR_REPORTING_OFF
* @param bool $exceptions = SoapServerOptions::SOAP_SERVER_EXCEPTIONS_ON|SoapServerOptions::SOAP_SERVER_EXCEPTIONS_OFF
* @param int $persistence = SoapServerOptions::SOAP_SERVER_PERSISTENCE_NONE|SoapServerOptions::SOAP_SERVER_PERSISTENCE_REQUEST|SoapServerOptions::SOAP_SERVER_PERSISTENCE_SESSION
*/
public function __construct(
$handlerClassOrObject,
$keepAlive,
$errorReporting,
$exceptions,
$persistence
) {
$this->handlerClass = $this->resolveHandlerClass($handlerClassOrObject);
$this->handlerObject = $this->resolveHandlerObject($handlerClassOrObject);
$this->keepAlive = $keepAlive;
$this->errorReporting = $errorReporting;
$this->exceptions = $exceptions;
$this->persistence = $persistence;
}
public function hasHandlerClass()
{
return $this->handlerClass !== null;
}
public function getHandlerClass()
{
return $this->handlerClass;
}
public function hasHandlerObject()
{
return $this->handlerObject !== null;
}
public function getHandlerObject()
{
return $this->handlerObject;
}
public function hasPersistence()
{
return $this->persistence !== SoapServerOptions::SOAP_SERVER_PERSISTENCE_NONE;
}
public function getPersistence()
{
return $this->persistence;
}
public function isErrorReporting()
{
return $this->errorReporting;
}
public function isExceptions()
{
return $this->exceptions;
}
public function isKeepAlive()
{
return $this->keepAlive;
}
public function toArray()
{
$optionsAsArray = [
'keep_alive' => $this->isKeepAlive(),
];
return $optionsAsArray;
}
/**
* @param mixed $handler
* @return mixed|null
*/
private function resolveHandlerObject($handler)
{
if (is_string($handler) && class_exists($handler)) {
return null;
} elseif (is_object($handler)) {
return $handler;
} else {
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
}
/**
* @param mixed $handler
* @return mixed|null
*/
private function resolveHandlerClass($handler)
{
if (is_string($handler) && class_exists($handler)) {
return $handler;
} elseif (is_object($handler)) {
return null;
} else {
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
}
}

View File

@ -12,15 +12,15 @@
namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapMessage;
use BeSimple\SoapCommon\SoapRequest;
/**
* SoapRequest class for SoapClient. Provides factory function for request object.
*
* @author Andreas Schamberger <mail@andreass.net>
*/
class SoapRequest extends CommonSoapRequest
class SoapRequestFactory extends SoapRequest
{
/**
* Factory function for SoapRequest.
@ -28,33 +28,23 @@ class SoapRequest extends CommonSoapRequest
* @param string $content Content
* @param string $version SOAP version
*
* @return BeSimple\SoapClient\SoapRequest
* @return SoapRequest
*/
public static function create($content, $version)
{
$location = self::getCurrentUrl();
/*
* Work around missing header/php://input access in PHP cli webserver by
* setting headers additionally as GET parameters and SOAP request body
* explicitly as POST variable
*/
if (php_sapi_name() == "cli-server") {
$content = is_null($content) ? $_POST['request'] : $content;
$action = $_GET[SoapMessage::SOAP_ACTION_HEADER];
$contentType = $_GET[SoapMessage::CONTENT_TYPE_HEADER];
} else {
$content = is_null($content) ? file_get_contents("php://input") : $content;
$action = isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null;
$contentType = $_SERVER[SoapMessage::CONTENT_TYPE_HEADER];
}
$request = new SoapRequest();
// $content is if unmodified from SoapClient not a php string type!
$request->setContent((string) $content);
$request->setLocation($location);
$request->setAction($action);
$request->setContent($content);
$request->setLocation(self::getCurrentUrl());
$request->setAction(isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null);
$request->setVersion($version);
$request->setContentType($contentType);
if (isset($_SERVER[SoapMessage::CONTENT_TYPE_HEADER])) {
$request->setContentType($_SERVER[SoapMessage::CONTENT_TYPE_HEADER]);
} elseif (isset($_SERVER[SoapMessage::HTTP_CONTENT_TYPE_HEADER])) {
$request->setContentType($_SERVER[SoapMessage::HTTP_CONTENT_TYPE_HEADER]);
}
return $request;
}

View File

@ -29,10 +29,11 @@ class SoapResponse extends CommonSoapResponse
* @param string $location Location
* @param string $action SOAP action
* @param string $version SOAP version
* @param array $attachments SOAP attachments
*
* @return BeSimple\SoapClient\SoapResponse
* @return SoapResponse
*/
public static function create($content, $location, $action, $version)
public static function create($content, $location, $action, $version, $attachments = [])
{
$response = new SoapResponse();
$response->setContent($content);
@ -48,12 +49,11 @@ class SoapResponse extends CommonSoapResponse
/**
* Send SOAP response to client.
*/
public function send()
public function getResponseContent()
{
// set Content-Type header
header('Content-Type: '.$this->getContentType());
header('Content-Type: ' . $this->getContentType());
// send content to client
echo $this->getContent();
return $this->getContent();
}
}

View File

@ -12,73 +12,67 @@
namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapServer\SoapOptions\SoapServerOptions;
use BeSimple\SoapCommon\Converter\MtomTypeConverter;
use BeSimple\SoapCommon\Converter\SwaTypeConverter;
use Exception;
/**
* Extended SoapServer that allows adding filters for SwA, MTOM, ... .
*
* @author Andreas Schamberger <mail@andreass.net>
* @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/
class SoapServer extends \SoapServer
{
/**
* Soap version.
*
* @var int
*/
protected $soapVersion = SOAP_1_1;
const SOAP_SERVER_REQUEST_FAILED = false;
/**
* Soap kernel.
*
* @var \BeSimple\SoapServer\SoapKernel
*/
protected $soapKernel = null;
protected $soapVersion;
protected $soapKernel;
/**
* Constructor.
*
* @param string $wsdl WSDL file
* @param array(string=>mixed) $options Options array
* @param SoapServerOptions $soapServerOptions
* @param SoapOptions $soapOptions
*/
public function __construct($wsdl, array $options = array())
public function __construct(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions)
{
// store SOAP version
if (isset($options['soap_version'])) {
$this->soapVersion = $options['soap_version'];
if ($soapOptions->hasAttachments()) {
$soapOptions = $this->configureMime($soapOptions);
}
// create soap kernel instance
$this->soapKernel = new SoapKernel();
// set up type converter and mime filter
$this->configureMime($options);
// we want the exceptions option to be set
$options['exceptions'] = true;
parent::__construct($wsdl, $options);
$this->soapVersion = $soapOptions->getSoapVersion();
parent::__construct(
$soapOptions->getWsdlFile(),
$soapServerOptions->toArray() + $soapOptions->toArray()
);
}
/**
* Custom handle method to be able to modify the SOAP messages.
*
* @param string $request Request string
* @return string
*/
public function handle($request = null)
{
// wrap request data in SoapRequest object
$soapRequest = SoapRequest::create($request, $this->soapVersion);
$soapRequest = SoapRequestFactory::create($request, $this->soapVersion);
// handle actual SOAP request
try {
$soapResponse = $this->handle2($soapRequest);
$soapResponse = $this->handleSoapRequest($soapRequest);
} catch (\SoapFault $fault) {
// issue an error to the client
$this->fault($fault->faultcode, $fault->faultstring);
return self::SOAP_SERVER_REQUEST_FAILED;
}
// send SOAP response to client
$soapResponse->send();
return $soapResponse->getResponseContent();
}
/**
@ -90,12 +84,11 @@ class SoapServer extends \SoapServer
*
* @return SoapResponse
*/
public function handle2(SoapRequest $soapRequest)
private function handleSoapRequest(SoapRequest $soapRequest)
{
// run SoapKernel on SoapRequest
$this->soapKernel->filterRequest($soapRequest);
// call parent \SoapServer->handle() and buffer output
ob_start();
parent::handle($soapRequest->getContent());
$response = ob_get_clean();
@ -128,43 +121,25 @@ class SoapServer extends \SoapServer
return $this->soapKernel;
}
/**
* Configure filter and type converter for SwA/MTOM.
*
* @param array &$options SOAP constructor options array.
*
* @return void
*/
private function configureMime(array &$options)
private function configureMime(SoapOptions $soapOptions)
{
if (isset($options['attachment_type']) && Helper::ATTACHMENTS_TYPE_BASE64 !== $options['attachment_type']) {
// register mime filter in SoapKernel
$mimeFilter = new MimeFilter($options['attachment_type']);
if ($soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) {
$mimeFilter = new MimeFilter($soapOptions->getAttachmentType());
$this->soapKernel->registerFilter($mimeFilter);
// configure type converter
if (Helper::ATTACHMENTS_TYPE_SWA === $options['attachment_type']) {
if ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA) {
$converter = new SwaTypeConverter();
$converter->setKernel($this->soapKernel);
} elseif (Helper::ATTACHMENTS_TYPE_MTOM === $options['attachment_type']) {
$xmlMimeFilter = new XmlMimeFilter($options['attachment_type']);
$this->soapKernel->registerFilter($xmlMimeFilter);
$soapOptions->getTypeConverterCollection()->add($converter);
} elseif ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) {
$this->soapKernel->registerFilter(new XmlMimeFilter($soapOptions->getAttachmentType()));
$converter = new MtomTypeConverter();
$converter->setKernel($this->soapKernel);
$soapOptions->getTypeConverterCollection()->add($converter);
} else {
throw new Exception('Unresolved SOAP_ATTACHMENTS_TYPE: ' . $soapOptions->getAttachmentType());
}
// configure typemap
if (!isset($options['typemap'])) {
$options['typemap'] = array();
}
$options['typemap'][] = array(
'type_name' => $converter->getTypeName(),
'type_ns' => $converter->getTypeNamespace(),
'from_xml' => function($input) use ($converter) {
return $converter->convertXmlToPhp($input);
},
'to_xml' => function($input) use ($converter) {
return $converter->convertPhpToXml($input);
},
);
}
return $soapOptions;
}
}

View File

@ -12,189 +12,38 @@
namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\AbstractSoapBuilder;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapServer\SoapOptions\SoapServerOptions;
/**
* SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance.
* SoapServerBuilder provides a SoapServer instance from SoapServerOptions and SoapOptions.
*
* @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/
class SoapServerBuilder extends AbstractSoapBuilder
class SoapServerBuilder
{
protected $persistence;
protected $errorReporting;
protected $handlerClass;
protected $handlerObject;
/**
* Create new instance with default options.
* Builds a SoapServer instance.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
static public function createWithDefaults()
{
return parent::createWithDefaults()
->withErrorReporting(false);
}
/**
* Initializes all options with the defaults used in the native SoapServer.
*/
public function __construct()
{
parent::__construct();
// TODO: this is not the default, but safer
$this->withErrorReporting(false);
}
/**
* Finally returns a SoapClient instance.
* @param SoapServerOptions $soapServerOptions
* @param SoapOptions $soapOptions
*
* @return \BeSimple\SoapServer\SoapServer
* @return SoapServer
*/
public function build()
public function build(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions)
{
$this->validateOptions();
use_soap_error_handler($soapServerOptions->isErrorReporting());
use_soap_error_handler($this->errorReporting);
$server = new SoapServer($this->wsdl, $this->getSoapOptions());
if (null !== $this->persistence) {
$server->setPersistence($this->persistence);
$server = new SoapServer($soapServerOptions, $soapOptions);
if ($soapServerOptions->hasPersistence()) {
$server->setPersistence($soapServerOptions->getPersistence());
}
if (null !== $this->handlerClass) {
$server->setClass($this->handlerClass);
} elseif (null !== $this->handlerObject) {
$server->setObject($this->handlerObject);
if ($soapServerOptions->hasHandlerClass()) {
$server->setClass($soapServerOptions->getHandlerClass());
} else if ($soapServerOptions->hasHandlerObject()) {
$server->setObject($soapServerOptions->getHandlerObject());
}
return $server;
}
/**
* Cofigures the SOAP actor.
*
* @param string $actor Actor name
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withActor($actor)
{
$this->options['actor'] = $actor;
return $this;
}
/**
* Enables persistence.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withPersistanceRequest()
{
$this->persistence = SOAP_PERSISTENCE_REQUEST;
return $this;
}
/**
* Enables the HTTP session. The handler object is persisted between multiple requests in a session.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withPersistenceSession()
{
$this->persistence = SOAP_PERSISTENCE_SESSION;
return $this;
}
/**
* Enables reporting of internal errors to clients. This should only be enabled in development environments.
*
* @param boolean $enable Enable error reporting
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withErrorReporting($enable = true)
{
$this->errorReporting = $enable;
return $this;
}
/**
* SOAP attachment type Base64.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withBase64Attachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_BASE64;
return $this;
}
/**
* SOAP attachment type SwA.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withSwaAttachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_SWA;
return $this;
}
/**
* SOAP attachment type MTOM.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withMtomAttachments()
{
$this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_MTOM;
return $this;
}
/**
* Configures the handler class or object.
*
* @param mixed $handler Can be either a class name or an object.
*
* @return \BeSimple\SoapServer\SoapServerBuilder
*/
public function withHandler($handler)
{
if (is_string($handler) && class_exists($handler)) {
$this->handlerClass = $handler;
$this->handlerObject = null;
} elseif (is_object($handler)) {
$this->handlerClass = null;
$this->handlerObject = $handler;
} else {
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
return $this;
}
/**
* Validate options.
*/
protected function validateOptions()
{
$this->validateWsdl();
if (null === $this->handlerClass && null === $this->handlerObject) {
throw new \InvalidArgumentException('The handler has to be configured!');
}
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace BeSimple\SoapServer;
use BeSimple\SoapServer\SoapOptions\SoapServerOptions;
class SoapServerOptionsBuilder
{
static public function createWithDefaults($handlerClassOrObject)
{
return new SoapServerOptions(
$handlerClassOrObject,
SoapServerOptions::SOAP_SERVER_KEEP_ALIVE_OFF,
SoapServerOptions::SOAP_SERVER_ERROR_REPORTING_OFF,
SoapServerOptions::SOAP_SERVER_EXCEPTIONS_ON,
SoapServerOptions::SOAP_SERVER_PERSISTENCE_NONE
);
}
}

View File

@ -14,16 +14,12 @@ namespace BeSimple\SoapServer;
use ass\XmlSecurity\DSig as XmlSecurityDSig;
use ass\XmlSecurity\Enc as XmlSecurityEnc;
use ass\XmlSecurity\Key as XmlSecurityKey;
use ass\XmlSecurity\Pem as XmlSecurityPem;
use BeSimple\SoapCommon\FilterHelper;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
use BeSimple\SoapCommon\SoapResponseFilter;
use BeSimple\SoapCommon\WsSecurityKey;
use BeSimple\SoapCommon\WsSecurityFilterClientServer;
/**
@ -230,7 +226,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque
$referenceList = XmlSecurityEnc::createReferenceList($encryptedKey);
// token reference to encrypted key
$keyInfo = $this->createKeyInfo($filterHelper, self::TOKEN_REFERENCE_SECURITY_TOKEN, $guid);
$nodes = $this->createNodeListForEncryption($dom, $security);
$nodes = $this->createNodeListForEncryption($dom);
foreach ($nodes as $node) {
$type = XmlSecurityEnc::ELEMENT;
if ($node->localName == 'Body') {

View File

@ -14,11 +14,6 @@ namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\FilterHelper;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Mime\MultiPart as MimeMultiPart;
use BeSimple\SoapCommon\Mime\Parser as MimeParser;
use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponse;
use BeSimple\SoapCommon\SoapResponseFilter;

View File

@ -22,17 +22,16 @@
"require": {
"php": ">=5.3.0",
"ext-soap": "*",
"besimple/soap-common": "0.2.*",
"besimple/soap-common": "0.3.*",
"ass/xmlsecurity": "~1.0"
},
"autoload": {
"psr-0": { "BeSimple\\SoapServer": "" }
},
"target-dir": "BeSimple/SoapServer",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.3-dev"
}
}
}

View File

@ -14,7 +14,6 @@ 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;
@ -70,6 +69,7 @@ class Dumper
'version12_class' => 'BeSimple\\SoapWsdl\\Dumper\\Version12',
'version11_name' => $this->definition->getName(),
'version12_name' => $this->definition->getName().'12',
'stylesheet' => null,
);
$invalid = array();
@ -124,6 +124,8 @@ class Dumper
$this->document->formatOutput = true;
$this->addStylesheet();
return $this->document->saveXML();
}
@ -187,7 +189,7 @@ class Dumper
protected function addMessages(array $messages)
{
foreach ($messages as $message) {
if ($message->isEmpty()) {
if (preg_match('#Header$#', $message->getName()) && $message->isEmpty()) {
continue;
}
@ -283,7 +285,7 @@ class Dumper
$operation->setAttribute('name', $method->getName());
foreach (array('input' => $method->getInput(), 'output' => $method->getOutput(), 'fault' => $method->getFault()) as $type => $message) {
if ($message->isEmpty()) {
if ('fault' === $type && $message->isEmpty()) {
continue;
}
@ -298,6 +300,15 @@ class Dumper
return $operation;
}
protected function addStylesheet()
{
if ($this->options['stylesheet']) {
$stylesheet = $this->document->createProcessingInstruction('xml-stylesheet', sprintf('type="text/xsl" href="%s"', $this->options['stylesheet']));
$this->document->insertBefore($stylesheet, $this->document->documentElement);
}
}
protected function getVersion($version)
{
if (\SOAP_1_2 === $version) {

View File

@ -22,10 +22,9 @@
"psr-0": { "BeSimple\\SoapWsdl": "" }
},
"target-dir": "BeSimple/SoapWsdl",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "0.2-dev"
"dev-master": "0.3-dev"
}
}
}