Large refactoring of SoapKernel

This commit is contained in:
Petr Bechyně 2016-11-01 18:13:23 +01:00
parent 155aa029ce
commit 969709cae5
7 changed files with 72 additions and 169 deletions

View File

@ -295,6 +295,7 @@ class SoapClient extends \SoapClient
private function configureMime(array $options) private function configureMime(array $options)
{ {
// @todo: PBe: refactor same as SoapServer
if (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']);

View File

@ -1,34 +1,16 @@
<?php <?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\SoapCommon\Converter; namespace BeSimple\SoapCommon\Converter;
use BeSimple\SoapCommon\Mime\Part as MimePart; use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\SoapKernel;
use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface;
use BeSimple\SoapCommon\Converter\TypeConverterInterface;
/** /**
* SwA type converter. * SwA type converter.
* *
* @author Andreas Schamberger <mail@andreass.net> * @author Andreas Schamberger <mail@andreass.net>
*/ */
class SwaTypeConverter implements TypeConverterInterface, SoapKernelAwareInterface class SwaTypeConverter implements TypeConverterInterface
{ {
/**
* @var \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance
*/
protected $soapKernel = null;
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -60,6 +42,7 @@ class SwaTypeConverter implements TypeConverterInterface, SoapKernelAwareInterfa
if ('cid:' === substr($ref, 0, 4)) { if ('cid:' === substr($ref, 0, 4)) {
$contentId = urldecode(substr($ref, 4)); $contentId = urldecode(substr($ref, 4));
// @todo-critical: ci je nyni zodpovednost vygetovat attachmenty
if (null !== ($part = $this->soapKernel->getAttachment($contentId))) { if (null !== ($part = $this->soapKernel->getAttachment($contentId))) {
return $part->getContent(); return $part->getContent();
@ -80,16 +63,9 @@ class SwaTypeConverter implements TypeConverterInterface, SoapKernelAwareInterfa
$part = new MimePart($data); $part = new MimePart($data);
$contentId = trim($part->getHeader('Content-ID'), '<>'); $contentId = trim($part->getHeader('Content-ID'), '<>');
$this->soapKernel->addAttachment($part); // @todo-critical: ci je nyni zodpovednost nastrkat attachmenty
//$this->soapKernel->addAttachment($part);
return sprintf('<%s href="%s"/>', $this->getTypeName(), 'cid:' . $contentId); return sprintf('<%s href="%s"/>', $this->getTypeName(), 'cid:' . $contentId);
} }
/**
* {@inheritDoc}
*/
public function setKernel(SoapKernel $soapKernel)
{
$this->soapKernel = $soapKernel;
}
} }

View File

@ -1,23 +1,8 @@
<?php <?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
* (c) Andreas Schamberger <mail@andreass.net>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapCommon; namespace BeSimple\SoapCommon;
use BeSimple\SoapCommon\Mime\Part as MimePart; use BeSimple\SoapCommon\Mime\Part as MimePart;
use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapResponse;
use BeSimple\SoapCommon\SoapRequestFilter;
use BeSimple\SoapCommon\SoapResponseFilter;
/** /**
* SoapKernel provides methods to pre- and post-process SoapRequests and SoapResponses using * SoapKernel provides methods to pre- and post-process SoapRequests and SoapResponses using
@ -25,30 +10,10 @@ use BeSimple\SoapCommon\SoapResponseFilter;
* the chain-of-responsibility pattern). * the chain-of-responsibility pattern).
* *
* @author Christian Kerl <christian-kerl@web.de> * @author Christian Kerl <christian-kerl@web.de>
* @author Petr Bechyně <petr.bechyne@vodafone.com>
*/ */
class SoapKernel class SoapKernel
{ {
/**
* Mime attachments.
*
* @var array(\BeSimple\SoapCommon\Mime\Part)
*/
protected $attachments = array();
/**
* Request filters.
*
* @var array(SoapRequestFilter)
*/
private $requestFilters = array();
/**
* Response filters.
*
* @var array(SoapResponseFilter)
*/
private $responseFilters = array();
/** /**
* Add attachment. * Add attachment.
* *
@ -82,48 +47,40 @@ class SoapKernel
return null; return null;
} }
/**
* Registers the given object either as filter for SoapRequests or as filter for SoapResponses
* or as filter for both depending on the implemented interfaces. Inner filters have to be registered
* before outer filters. This means the order is as follows: RequestFilter2->RequestFilter1 and
* ResponseFilter1->ResponseFilter2.
*
* TODO: add priority mechanism to ensure correct order of filters
*
* @param SoapRequestFilter|SoapResponseFilter $filter Filter to register
*/
public function registerFilter($filter)
{
if ($filter instanceof SoapRequestFilter) {
array_unshift($this->requestFilters, $filter);
}
if ($filter instanceof SoapResponseFilter) {
array_push($this->responseFilters, $filter);
}
}
/** /**
* Applies all registered SoapRequestFilter to the given SoapRequest. * Applies all registered SoapRequestFilter to the given SoapRequest.
* *
* @param SoapRequest $request Soap request * @param SoapRequest $request Soap request
* @param SoapRequestFilter[]|SoapResponseFilter[] $filters
* @return SoapRequest
*/ */
public function filterRequest(SoapRequest $request) public function filterRequest(SoapRequest $request, array $filters)
{ {
foreach ($this->requestFilters as $filter) { foreach ($filters as $filter) {
$filter->filterRequest($request); if ($filter instanceof SoapRequestFilter) {
$request = $filter->filterRequest($request);
}
} }
return $request;
} }
/** /**
* Applies all registered SoapResponseFilter to the given SoapResponse. * Applies all registered SoapResponseFilter to the given SoapResponse.
* *
* @param SoapResponse $response SOAP response * @param SoapResponse $response SOAP response
* @param SoapRequestFilter[]|SoapResponseFilter[] $filters
* @return SoapResponse
*/ */
public function filterResponse(SoapResponse $response) public function filterResponse(SoapResponse $response, array $filters)
{ {
foreach ($this->responseFilters as $filter) { foreach ($filters as $filter) {
$filter->filterResponse($response); if ($filter instanceof SoapResponseFilter) {
$response = $filter->filterResponse($response);
}
} }
return $response;
} }
} }

View File

@ -53,25 +53,17 @@ class MimeFilter implements SoapRequestFilter, SoapResponseFilter
$this->attachmentType = Helper::ATTACHMENTS_TYPE_SWA; $this->attachmentType = Helper::ATTACHMENTS_TYPE_SWA;
} }
/**
* Modify the given request XML.
*
* @param \BeSimple\SoapCommon\SoapRequest $request SOAP request
*
* @return void
*/
public function filterRequest(SoapRequest $request) public function filterRequest(SoapRequest $request)
{ {
// array to store attachments $attachmentsReceived = [];
$attachmentsRecieved = array();
// check content type if it is a multipart mime message // check content type if it is a multipart mime message
$requestContentType = $request->getContentType(); $requestContentType = $request->getContentType();
if (false !== stripos($requestContentType, 'multipart/related')) { if (stripos($requestContentType, 'multipart/related') !== false) {
// parse mime message // parse mime message
$headers = array( $headers = [
'Content-Type' => trim($requestContentType), 'Content-Type' => trim($requestContentType),
); ];
$multipart = MimeParser::parseMimeMessage($request->getContent(), $headers); $multipart = MimeParser::parseMimeMessage($request->getContent(), $headers);
// get soap payload and update SoapResponse object // get soap payload and update SoapResponse object
$soapPart = $multipart->getPart(); $soapPart = $multipart->getPart();
@ -83,29 +75,20 @@ class MimeFilter implements SoapRequestFilter, SoapResponseFilter
// store attachments // store attachments
$attachments = $multipart->getParts(false); $attachments = $multipart->getParts(false);
foreach ($attachments as $cid => $attachment) { foreach ($attachments as $cid => $attachment) {
$attachmentsRecieved[$cid] = $attachment; $attachmentsReceived[$cid] = $attachment;
} }
} }
// add attachments to response object if (count($attachmentsReceived) > 0) {
if (count($attachmentsRecieved) > 0) { $request->setAttachments($attachmentsReceived);
$request->setAttachments($attachmentsRecieved);
} }
return $request;
} }
/**
* Modify the given response XML.
*
* @param \BeSimple\SoapCommon\SoapResponse $response SOAP response
*
* @return void
*/
public function filterResponse(SoapResponse $response) public function filterResponse(SoapResponse $response)
{ {
// get attachments from request object
$attachmentsToSend = $response->getAttachments(); $attachmentsToSend = $response->getAttachments();
// build mime message if we have attachments
if (count($attachmentsToSend) > 0) { if (count($attachmentsToSend) > 0) {
$multipart = new MimeMultiPart(); $multipart = new MimeMultiPart();
$soapPart = new MimePart($response->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); $soapPart = new MimePart($response->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT);
@ -134,5 +117,7 @@ class MimeFilter implements SoapRequestFilter, SoapResponseFilter
$response->setContentType($contentType); $response->setContentType($contentType);
} }
return $response;
} }
} }

View File

@ -1,43 +1,32 @@
<?php <?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
* (c) Andreas Schamberger <mail@andreass.net>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapServer; namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapKernel as CommonSoapKernel; use BeSimple\SoapCommon\SoapKernel;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest; use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
/** /**
* SoapKernel for Server. * SoapKernel for Server.
* *
* @todo-critical: kill this shit
* @author Andreas Schamberger <mail@andreass.net> * @author Andreas Schamberger <mail@andreass.net>
*/ */
class SoapKernel extends CommonSoapKernel class SoapServerKernel extends SoapKernel
{ {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function filterRequest(CommonSoapRequest $request) public function filterRequest(SoapRequest $request, array $filters)
{ {
parent::filterRequest($request); parent::filterRequest($request, $filters);
$this->attachments = $request->getAttachments(); // attachments are now gone from here
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function filterResponse(CommonSoapResponse $response) public function filterResponse(SoapResponse $response)
{ {
$response->setAttachments($this->attachments); $response->setAttachments($this->attachments);
$this->attachments = array(); $this->attachments = array();

View File

@ -12,7 +12,7 @@
namespace BeSimple\SoapServer; namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapMessage; use BeSimple\SoapCommon\SoapKernel;
use BeSimple\SoapCommon\SoapOptions\SoapOptions; use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapRequest;
use BeSimple\SoapCommon\SoapRequestFactory; use BeSimple\SoapCommon\SoapRequestFactory;
@ -34,6 +34,8 @@ class SoapServer extends \SoapServer
protected $soapVersion; protected $soapVersion;
protected $soapKernel; protected $soapKernel;
protected $soapServerOptions;
protected $soapOptions;
/** /**
* Constructor. * Constructor.
@ -44,11 +46,13 @@ class SoapServer extends \SoapServer
public function __construct(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions) public function __construct(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions)
{ {
if ($soapOptions->hasAttachments()) { if ($soapOptions->hasAttachments()) {
$soapOptions = $this->configureMime($soapOptions); $soapOptions = $this->configureTypeConverters($soapOptions);
} }
$this->soapKernel = new SoapKernel(); $this->soapKernel = new SoapKernel();
$this->soapVersion = $soapOptions->getSoapVersion(); $this->soapVersion = $soapOptions->getSoapVersion();
$this->soapServerOptions = $soapServerOptions;
$this->soapOptions = $soapOptions;
parent::__construct( parent::__construct(
$soapOptions->getWsdlFile(), $soapOptions->getWsdlFile(),
@ -95,8 +99,9 @@ class SoapServer extends \SoapServer
*/ */
private function handleSoapRequest(SoapRequest $soapRequest) private function handleSoapRequest(SoapRequest $soapRequest)
{ {
// run SoapKernel on SoapRequest if ($this->soapOptions->hasAttachments()) {
$this->soapKernel->filterRequest($soapRequest); $soapRequest = $this->soapKernel->filterRequest($soapRequest, $this->getFilters());
}
ob_start(); ob_start();
parent::handle($soapRequest->getContent()); parent::handle($soapRequest->getContent());
@ -114,36 +119,20 @@ class SoapServer extends \SoapServer
$soapRequest->getVersion() $soapRequest->getVersion()
); );
// run SoapKernel on SoapResponse if ($this->soapOptions->hasAttachments()) {
$this->soapKernel->filterResponse($soapResponse); $this->soapKernel->filterResponse($soapResponse, $this->getFilters());
}
return $soapResponse; return $soapResponse;
} }
/** private function configureTypeConverters(SoapOptions $soapOptions)
* Get SoapKernel instance.
*
* @return \BeSimple\SoapServer\SoapKernel
*/
public function getSoapKernel()
{
return $this->soapKernel;
}
private function configureMime(SoapOptions $soapOptions)
{ {
if ($soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) { if ($soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) {
$mimeFilter = new MimeFilter($soapOptions->getAttachmentType());
$this->soapKernel->registerFilter($mimeFilter);
if ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA) { if ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA) {
$converter = new SwaTypeConverter(); $soapOptions->getTypeConverterCollection()->add(new SwaTypeConverter());
$converter->setKernel($this->soapKernel);
$soapOptions->getTypeConverterCollection()->add($converter);
} elseif ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) { } elseif ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) {
$this->soapKernel->registerFilter(new XmlMimeFilter($soapOptions->getAttachmentType())); $soapOptions->getTypeConverterCollection()->add(new MtomTypeConverter());
$converter = new MtomTypeConverter();
$converter->setKernel($this->soapKernel);
$soapOptions->getTypeConverterCollection()->add($converter);
} else { } else {
throw new Exception('Unresolved SOAP_ATTACHMENTS_TYPE: ' . $soapOptions->getAttachmentType()); throw new Exception('Unresolved SOAP_ATTACHMENTS_TYPE: ' . $soapOptions->getAttachmentType());
} }
@ -151,4 +140,17 @@ class SoapServer extends \SoapServer
return $soapOptions; return $soapOptions;
} }
private function getFilters()
{
$filters = [];
if ($this->soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) {
$filters[] = new MimeFilter($this->soapOptions->getAttachmentType());
}
if ($this->soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) {
$filters[] = new XmlMimeFilter($this->soapOptions->getAttachmentType());
}
return $filters;
}
} }

View File

@ -31,16 +31,8 @@ class XmlMimeFilter implements SoapResponseFilter
{ {
} }
/**
* Modify the given response XML.
*
* @param \BeSimple\SoapCommon\SoapResponse $response SOAP request
*
* @return void
*/
public function filterResponse(SoapResponse $response) public function filterResponse(SoapResponse $response)
{ {
// get \DOMDocument from SOAP request
$dom = $response->getContentDocument(); $dom = $response->getContentDocument();
// create FilterHelper // create FilterHelper
@ -66,5 +58,6 @@ class XmlMimeFilter implements SoapResponseFilter
} }
} }
return $response;
} }
} }