Large refactoring removing states, abstract magic, vague fluent interfaces

This commit is contained in:
Petr Bechyně 2016-10-27 16:24:44 +02:00
parent c4a9b58b08
commit 0a157748a8
32 changed files with 953 additions and 933 deletions

View File

@ -1,5 +1,5 @@
{ {
"name": "catch-of-the-day/soap", "name": "tuscanicz/soap",
"type": "library", "type": "library",
"description": "A fork of the abandoned besimple/soap package with added support for Symfony 3.0", "description": "A fork of the abandoned besimple/soap package with added support for Symfony 3.0",
"keywords": ["soap"], "keywords": ["soap"],

View File

@ -141,8 +141,8 @@ class SoapWebServiceController implements ContainerAwareInterface
$request->query->remove('_besimple_soap_fault'); $request->query->remove('_besimple_soap_fault');
} }
$server = SoapServerBuilder::createWithDefaults() $server = SoapServerBuilder::createWithDefaults(__DIR__.'/../Handler/wsdl/exception.wsdl')
->withWsdl(__DIR__.'/../Handler/wsdl/exception.wsdl') ->withWsdl()
->withWsdlCacheNone() ->withWsdlCacheNone()
->withHandler($handler) ->withHandler($handler)
->build() ->build()

View File

@ -50,6 +50,7 @@ class Curl
/** /**
* Constructor. * Constructor.
* *
* @todo: do not use options as Array
* @param array $options Options array from SoapClient constructor * @param array $options Options array from SoapClient constructor
* @param int $followLocationMaxRedirects Redirection limit for Location header * @param int $followLocationMaxRedirects Redirection limit for Location header
*/ */

View File

@ -15,7 +15,8 @@ namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\Helper; use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Converter\MtomTypeConverter; use BeSimple\SoapCommon\Converter\MtomTypeConverter;
use BeSimple\SoapCommon\Converter\SwaTypeConverter; 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 * Extended SoapClient that uses a a cURL wrapper for all underlying HTTP
@ -27,12 +28,7 @@ use BeSimple\SoapCommon\SoapMessage;
*/ */
class SoapClient extends \SoapClient class SoapClient extends \SoapClient
{ {
/** protected $soapVersion;
* Soap version.
*
* @var int
*/
protected $soapVersion = SOAP_1_1;
/** /**
* Tracing enabled? * Tracing enabled?
@ -86,37 +82,24 @@ class SoapClient extends \SoapClient
/** /**
* Constructor. * Constructor.
* *
* @param string $wsdl WSDL file * @param SoapClientOptions $soapClientOptions
* @param array(string=>mixed) $options Options array * @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'];
}
$this->curl = new Curl($options);
if (isset($options['extra_options'])) {
unset($options['extra_options']);
}
$wsdlFile = $this->loadWsdl($wsdl, $options);
// TODO $wsdlHandler = new WsdlHandler($wsdlFile, $this->soapVersion);
$this->soapKernel = new SoapKernel(); $this->soapKernel = new SoapKernel();
// set up type converter and mime filter $this->soapVersion = $soapOptions->getSoapVersion();
$this->configureMime($options); $this->tracingEnabled = $soapClientOptions->getTrace();
// we want the exceptions option to be set
$options['exceptions'] = true; // @todo: refactor SoapClient: do not use $options as array
// disable obsolete trace option for native SoapClient as we need to do our own tracing anyways $options = $this->configureMime($soapOptions->toArray());
$options['trace'] = false;
// disable WSDL caching as we handle WSDL caching for remote URLs ourself // @todo: refactor SoapClient: do not use $options as array
$options['cache_wsdl'] = WSDL_CACHE_NONE; $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); parent::__construct($wsdlFile, $options);
} }
@ -191,6 +174,7 @@ class SoapClient extends \SoapClient
* Custom request method to be able to modify the SOAP messages. * Custom request method to be able to modify the SOAP messages.
* $oneWay parameter is not used at the moment. * $oneWay parameter is not used at the moment.
* *
* @todo: refactor SoapClient: refactoring starts from here
* @param string $request Request string * @param string $request Request string
* @param string $location Location * @param string $location Location
* @param string $action SOAP action * @param string $action SOAP action
@ -308,16 +292,9 @@ class SoapClient extends \SoapClient
return $this->soapKernel; return $this->soapKernel;
} }
/** private function configureMime(array $options)
* Configure filter and type converter for SwA/MTOM.
*
* @param array &$options SOAP constructor options array.
*
* @return void
*/
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 // register mime filter in SoapKernel
$mimeFilter = new MimeFilter($options['attachment_type']); $mimeFilter = new MimeFilter($options['attachment_type']);
$this->soapKernel->registerFilter($mimeFilter); $this->soapKernel->registerFilter($mimeFilter);
@ -346,6 +323,8 @@ class SoapClient extends \SoapClient
}, },
); );
} }
return $options;
} }
/** /**

View File

@ -12,237 +12,22 @@
namespace BeSimple\SoapClient; namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\AbstractSoapBuilder; use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\Helper;
/** /**
* Fluent interface builder for SoapClient instance. * Provides a SoapClient instance.
* *
* @author Francis Besset <francis.besset@gmail.com> * @author Francis Besset <francis.besset@gmail.com>
* @author Christian Kerl <christian-kerl@web.de> * @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/ */
class SoapClientBuilder extends AbstractSoapBuilder class SoapClientBuilder
{ {
/** public function build(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions)
* Authentication options.
*
* @var array(string=>mixed)
*/
protected $soapOptionAuthentication = array();
/**
* Create new instance with default options.
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public static function createWithDefaults()
{ {
return parent::createWithDefaults() return new SoapClient(
->withUserAgent('BeSimpleSoap'); $soapClientOptions,
} $soapOptions
/**
* 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 $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 $login Login
* @param string $password Password
* @param int $auth Authentication method
*
* @return \BeSimple\SoapClient\SoapClientBuilder
*/
public function withProxy($host, $port, $login = null, $password = null, $auth = null)
{
$this->soapOptions['proxy_host'] = $host;
$this->soapOptions['proxy_port'] = $port;
if ($login) {
$this->soapOptions['proxy_login'] = $login;
$this->soapOptions['proxy_password'] = $password;
if ($auth) {
if (!in_array($auth, array(\CURLAUTH_BASIC, \CURLAUTH_NTLM), true)) {
throw new \InvalidArgumentException('Invalid authentication method: CURLAUTH_BASIC or CURLAUTH_NTLM constants are availables.');
}
$this->soapOptions['proxy_auth'] = $auth;
}
}
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

@ -30,7 +30,7 @@ class SoapResponse extends CommonSoapResponse
* @param string $version SOAP version * @param string $version SOAP version
* @param string $contentType Content type header * @param string $contentType Content type header
* *
* @return BeSimple\SoapClient\SoapResponse * @return SoapResponse
*/ */
public static function create($content, $location, $action, $version, $contentType) public static function create($content, $location, $action, $version, $contentType)
{ {

View File

@ -114,7 +114,7 @@ class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase
public function testCreateWithDefaults() public function testCreateWithDefaults()
{ {
$builder = SoapClientBuilder::createWithDefaults(); $builder = SoapClientBuilder::createClientWithDefaults();
$this->assertInstanceOf('BeSimple\SoapClient\SoapClientBuilder', $builder); $this->assertInstanceOf('BeSimple\SoapClient\SoapClientBuilder', $builder);

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_MEMORY = WSDL_CACHE_MEMORY;
const TYPE_DISK_MEMORY = WSDL_CACHE_BOTH; const TYPE_DISK_MEMORY = WSDL_CACHE_BOTH;
static protected $types = array( static protected $types = [
self::TYPE_NONE, self::TYPE_NONE,
self::TYPE_DISK, self::TYPE_DISK,
self::TYPE_MEMORY, self::TYPE_MEMORY,
self::TYPE_DISK_MEMORY, self::TYPE_DISK_MEMORY,
); ];
static public function getTypes() static public function getTypes()
{ {
return self::$types; return self::$types;
} }
static public function hasType($cacheType)
{
return in_array($cacheType, self::$types);
}
static public function isEnabled() static public function isEnabled()
{ {
return self::iniGet('soap.wsdl_cache_enabled'); return self::iniGet('soap.wsdl_cache_enabled');

View File

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

View File

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

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; namespace BeSimple\SoapCommon;
use BeSimple\SoapCommon\SoapMessage;
/** /**
* SOAP request message. * SOAP request message.
@ -22,5 +21,27 @@ use BeSimple\SoapCommon\SoapMessage;
*/ */
class SoapRequest extends 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'])); $this->assertEquals(1, count($options['classmap']));
$classmap = new Classmap(); $classmap = new ClassMap();
$classmap->add('bar', __CLASS__); $classmap->add('bar', __CLASS__);
$builder->withClassmap($classmap); $builder->withClassmap($classmap);
$options = $builder->getSoapOptions(); $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(); $dateTimeTypeConverter = new DateTimeTypeConverter();
$converters->add($dateTimeTypeConverter); $converters->add($dateTimeTypeConverter);
$this->assertSame(array($dateTimeTypeConverter), $converters->all()); $this->assertSame(array($dateTimeTypeConverter), $converters->getAll());
$dateTypeConverter = new DateTypeConverter(); $dateTypeConverter = new DateTypeConverter();
$converters->add($dateTypeConverter); $converters->add($dateTypeConverter);
$this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->all()); $this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->getAll());
} }
public function testGetTypemap() public function testGetTypemap()
@ -73,7 +73,7 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$converter = array(new DateTypeConverter); $converter = array(new DateTypeConverter);
$converters->set($converter); $converters->set($converter);
$this->assertSame($converter, $converters->all()); $this->assertSame($converter, $converters->getAll());
} }
public function testAddCollection() public function testAddCollection()
@ -85,7 +85,7 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$converters2->add($dateTimeTypeConverter); $converters2->add($dateTimeTypeConverter);
$converters1->addCollection($converters2); $converters1->addCollection($converters2);
$this->assertSame(array($dateTimeTypeConverter), $converters1->all()); $this->assertSame(array($dateTimeTypeConverter), $converters1->getAll());
$this->setExpectedException('InvalidArgumentException'); $this->setExpectedException('InvalidArgumentException');
$converters1->addCollection($converters2); $converters1->addCollection($converters2);

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; namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapMessage; use BeSimple\SoapCommon\SoapMessage;
use BeSimple\SoapCommon\SoapRequest;
/** /**
* SoapRequest class for SoapClient. Provides factory function for request object. * SoapRequest class for SoapClient. Provides factory function for request object.
* *
* @author Andreas Schamberger <mail@andreass.net> * @author Andreas Schamberger <mail@andreass.net>
*/ */
class SoapRequest extends CommonSoapRequest class SoapRequestFactory extends SoapRequest
{ {
/** /**
* Factory function for SoapRequest. * Factory function for SoapRequest.
@ -28,14 +28,14 @@ class SoapRequest extends CommonSoapRequest
* @param string $content Content * @param string $content Content
* @param string $version SOAP version * @param string $version SOAP version
* *
* @return BeSimple\SoapClient\SoapRequest * @return SoapRequest
*/ */
public static function create($content, $version) public static function create($content, $version)
{ {
$request = new SoapRequest(); $request = new SoapRequest();
// $content is if unmodified from SoapClient not a php string type! // $content is if unmodified from SoapClient not a php string type!
$request->setContent((string) (null === $content ? file_get_contents("php://input") : $content)); $request->setContent($content);
$request->setLocation(self::getCurrentUrl()); $request->setLocation(self::getCurrentUrl());
$request->setAction(isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null); $request->setAction(isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null);
$request->setVersion($version); $request->setVersion($version);

View File

@ -29,10 +29,11 @@ class SoapResponse extends CommonSoapResponse
* @param string $location Location * @param string $location Location
* @param string $action SOAP action * @param string $action SOAP action
* @param string $version SOAP version * @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 = new SoapResponse();
$response->setContent($content); $response->setContent($content);
@ -48,12 +49,11 @@ class SoapResponse extends CommonSoapResponse
/** /**
* Send SOAP response to client. * Send SOAP response to client.
*/ */
public function send() public function getResponseContent()
{ {
// set Content-Type header // set Content-Type header
header('Content-Type: '.$this->getContentType()); header('Content-Type: ' . $this->getContentType());
// send content to client return $this->getContent();
echo $this->getContent();
} }
} }

View File

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