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

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

View File

@ -12,15 +12,15 @@
namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
use BeSimple\SoapCommon\SoapMessage;
use BeSimple\SoapCommon\SoapRequest;
/**
* SoapRequest class for SoapClient. Provides factory function for request object.
*
* @author Andreas Schamberger <mail@andreass.net>
*/
class SoapRequest extends CommonSoapRequest
class SoapRequestFactory extends SoapRequest
{
/**
* Factory function for SoapRequest.
@ -28,14 +28,14 @@ class SoapRequest extends CommonSoapRequest
* @param string $content Content
* @param string $version SOAP version
*
* @return BeSimple\SoapClient\SoapRequest
* @return SoapRequest
*/
public static function create($content, $version)
{
$request = new SoapRequest();
// $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->setAction(isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null);
$request->setVersion($version);

View File

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

View File

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

View File

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

View File

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