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

@ -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
*/

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?
@ -86,37 +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'];
}
$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();
// 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);
}
@ -191,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
@ -308,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);
@ -346,6 +323,8 @@ class SoapClient extends \SoapClient
},
);
}
return $options;
}
/**

View File

@ -12,237 +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 $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 $contentType Content type header
*
* @return BeSimple\SoapClient\SoapResponse
* @return SoapResponse
*/
public static function create($content, $location, $action, $version, $contentType)
{

View File

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