Soap server with attachments refactoring

This commit is contained in:
Petr Bechyně
2016-11-08 15:42:52 +01:00
parent 8d033f9afc
commit 84c37b1d24
23 changed files with 511 additions and 502 deletions

View File

@ -12,9 +12,7 @@
namespace BeSimple\SoapClient;
use BeSimple\SoapCommon\Helper;
use BeSimple\SoapCommon\Converter\MtomTypeConverter;
use BeSimple\SoapCommon\Converter\SwaTypeConverter;
use BeSimple\SoapCommon\SoapKernel;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapRequestFactory;
@ -30,20 +28,10 @@ use BeSimple\SoapCommon\SoapRequestFactory;
class SoapClient extends \SoapClient
{
protected $soapVersion;
/**
* Tracing enabled?
*
* @var boolean
*/
protected $tracingEnabled = false;
/**
* cURL instance.
*
* @var \BeSimple\SoapClient\Curl
*/
protected $curl = null;
protected $tracingEnabled;
protected $soapClientOptions;
protected $soapOptions;
protected $curl;
/**
* Last request headers.
@ -73,13 +61,6 @@ class SoapClient extends \SoapClient
*/
private $lastResponse = '';
/**
* Soap kernel.
*
* @var \BeSimple\SoapClient\SoapKernel
*/
protected $soapKernel = null;
/**
* Constructor.
*
@ -88,44 +69,99 @@ class SoapClient extends \SoapClient
*/
public function __construct(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions)
{
$this->soapKernel = new SoapKernel();
$this->soapVersion = $soapOptions->getSoapVersion();
$this->tracingEnabled = $soapClientOptions->getTrace();
$this->soapClientOptions = $soapClientOptions;
$this->soapOptions = $soapOptions;
// @todo: refactor SoapClient: do not use $options as array
$options = $this->configureMime($soapOptions->toArray());
// @todo: refactor SoapClient: do not use $options as array
// @todo: refactor SoapClient: do not use $options as array: refactor Curl
$this->curl = new Curl($soapClientOptions->toArray());
// @todo: refactor SoapClient: do not use $options as array
$wsdlFile = $this->loadWsdl($soapOptions->getWsdlFile(), $soapOptions->toArray());
$wsdlFile = $this->loadWsdl(
$soapOptions->getWsdlFile(),
$soapOptions->getWsdlCacheType()
);
parent::__construct($wsdlFile, $options);
parent::__construct(
$wsdlFile,
$soapClientOptions->toArray() + $soapOptions->toArray()
);
}
/**
* Custom request method to be able to modify the SOAP messages.
* $oneWay parameter is not used at the moment.
*
* @param string $request Request string
* @param string $location Location
* @param string $action SOAP action
* @param int $version SOAP version
* @param int $oneWay 0|1
*
* @return string
*/
public function __doRequest($request, $location, $action, $version, $oneWay = 0)
{
$soapRequest = $this->createSoapRequest($location, $action, $version, $request);
$soapResponse = $this->getSoapResponseFromRequest($soapRequest);
return $soapResponse->getContent();
}
private function createSoapRequest($location, $action, $version, $request)
{
$soapRequest = SoapRequestFactory::create($location, $action, $version, $request);
if ($this->soapOptions->hasAttachments()) {
$soapKernel = new SoapKernel();
$soapRequest = $soapKernel->filterRequest(
$soapRequest,
$this->getAttachmentFilters(),
$this->soapOptions->getAttachmentType()
);
}
return $soapRequest;
}
/**
* Runs the currently registered request filters on the request, performs
* the HTTP request and runs the response filters.
*
* @param SoapRequest $soapRequest SOAP request object
*
* @return SoapResponse
*/
private function getSoapResponseFromRequest(SoapRequest $soapRequest)
{
$soapResponse = $this->performHttpSoapRequest($soapRequest);
if ($this->soapOptions->hasAttachments()) {
$soapKernel = new SoapKernel();
$soapKernel->filterResponse($soapResponse, $this->getAttachmentFilters(), $this->soapOptions->getAttachmentType());
}
return $soapResponse;
}
/**
* Perform HTTP request with cURL.
*
* @param SoapRequest $soapRequest SoapRequest object
*
* @return SoapResponse
*/
private function __doHttpRequest(SoapRequest $soapRequest)
private function performHttpSoapRequest(SoapRequest $soapRequest)
{
// HTTP headers
$soapVersion = $soapRequest->getVersion();
$soapAction = $soapRequest->getAction();
if (SOAP_1_1 == $soapVersion) {
$headers = array(
$headers = [
'Content-Type:' . $soapRequest->getContentType(),
'SOAPAction: "' . $soapAction . '"',
);
];
} else {
$headers = array(
$headers = [
'Content-Type:' . $soapRequest->getContentType() . '; action="' . $soapAction . '"',
);
];
}
$location = $soapRequest->getLocation();
@ -135,8 +171,7 @@ class SoapClient extends \SoapClient
$options = $this->filterRequestOptions($soapRequest);
// execute HTTP request with cURL
$responseSuccessfull = $this->curl->exec(
$responseSuccessful = $this->curl->exec(
$location,
$content,
$headers,
@ -149,7 +184,7 @@ class SoapClient extends \SoapClient
$this->lastRequest = $soapRequest->getContent();
}
// in case of an error while making the http request throw a soapFault
if ($responseSuccessfull === false) {
if ($responseSuccessful === false) {
// get error message from curl
$faultstring = $this->curl->getErrorMessage();
throw new \SoapFault('HTTP', $faultstring);
@ -171,53 +206,6 @@ class SoapClient extends \SoapClient
return $soapResponse;
}
/**
* 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
* @param int $version SOAP version
* @param int $oneWay 0|1
*
* @return string
*/
public function __doRequest($request, $location, $action, $version, $oneWay = 0)
{
// wrap request data in SoapRequest object
$soapRequest = SoapRequestFactory::create($location, $action, $version, $request);
// do actual SOAP request
$soapResponse = $this->__doRequest2($soapRequest);
// return SOAP response to ext/soap
return $soapResponse->getContent();
}
/**
* Runs the currently registered request filters on the request, performs
* the HTTP request and runs the response filters.
*
* @param SoapRequest $soapRequest SOAP request object
*
* @return SoapResponse
*/
protected function __doRequest2(SoapRequest $soapRequest)
{
// run SoapKernel on SoapRequest
$this->soapKernel->filterRequest($soapRequest);
// perform HTTP request with cURL
$soapResponse = $this->__doHttpRequest($soapRequest);
// run SoapKernel on SoapResponse
$this->soapKernel->filterResponse($soapResponse);
return $soapResponse;
}
/**
* Filters HTTP headers which will be sent
*
@ -240,7 +228,7 @@ class SoapClient extends \SoapClient
*/
protected function filterRequestOptions(SoapRequest $soapRequest)
{
return array();
return [];
}
/**
@ -284,81 +272,34 @@ class SoapClient extends \SoapClient
}
/**
* Get SoapKernel instance.
*
* @return \BeSimple\SoapClient\SoapKernel
*/
public function getSoapKernel()
{
return $this->soapKernel;
}
private function configureMime(array $options)
{
// @todo: PBe: refactor same as SoapServer
if (Helper::ATTACHMENTS_TYPE_BASE64 !== $options['attachment_type']) {
// register mime filter in SoapKernel
$mimeFilter = new MimeFilter($options['attachment_type']);
$this->soapKernel->registerFilter($mimeFilter);
// configure type converter
if (Helper::ATTACHMENTS_TYPE_SWA === $options['attachment_type']) {
$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);
$converter = new MtomTypeConverter();
$converter->setKernel($this->soapKernel);
}
// 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 $options;
}
/**
* Downloads WSDL files with cURL. Uses all SoapClient options for
* authentication. Uses the WSDL_CACHE_* constants and the 'soap.wsdl_*'
* ini settings. Does only file caching as SoapClient only supports a file
* name parameter.
*
* @param string $wsdl WSDL file
* @param array(string=>mixed) $options Options array
* @param string $wsdl
* @param int $wsdlCache
* @param bool $resolveRemoteIncludes
*
* @return string
*/
protected function loadWsdl($wsdl, array $options)
private function loadWsdl($wsdl, $wsdlCache, $resolveRemoteIncludes = true)
{
// option to resolve wsdl/xsd includes
$resolveRemoteIncludes = true;
if (isset($options['resolve_wsdl_remote_includes'])) {
$resolveRemoteIncludes = $options['resolve_wsdl_remote_includes'];
}
// option to enable cache
$wsdlCache = WSDL_CACHE_DISK;
if (isset($options['cache_wsdl'])) {
$wsdlCache = $options['cache_wsdl'];
}
$wsdlDownloader = new WsdlDownloader($this->curl, $resolveRemoteIncludes, $wsdlCache);
try {
$cacheFileName = $wsdlDownloader->download($wsdl);
} catch (\RuntimeException $e) {
throw new \SoapFault('WSDL', "SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl . "' : failed to load external entity \"" . $wsdl . "\"");
throw new \SoapFault('WSDL', "SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl . "'");
}
return $cacheFileName;
}
}
private function getAttachmentFilters()
{
$filters = [];
if ($this->soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) {
$filters[] = new MimeFilter();
}
if ($this->soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) {
$filters[] = new XmlMimeFilter();
}
return $filters;
}
}