From 61946b30f8dd8a59147f9516b10015a3c89bd407 Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Wed, 28 Sep 2011 13:56:29 +0200 Subject: [PATCH 01/14] initial checkin --- phpunit.xml.dist | 31 +++++++++++++++++++ src/BeSimple/SoapServer/SoapServer.php | 21 +++++++++++++ tests/bootstrap.php | 29 ++++++++++++++++++ vendors.php | 41 ++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 phpunit.xml.dist create mode 100644 src/BeSimple/SoapServer/SoapServer.php create mode 100644 tests/bootstrap.php create mode 100644 vendors.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..6b95145 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + ./tests/BeSimple/ + + + + + + benchmark + + + + + + ./src/BeSimple/ + + + diff --git a/src/BeSimple/SoapServer/SoapServer.php b/src/BeSimple/SoapServer/SoapServer.php new file mode 100644 index 0000000..3b17e97 --- /dev/null +++ b/src/BeSimple/SoapServer/SoapServer.php @@ -0,0 +1,21 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +/** + * @author Christian Kerl + */ +class SoapServer extends \SoapServer +{ + +} \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..3fbc18f --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,29 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/* + +CAUTION: This file installs the dependencies needed to run the BeSimpleSoapClient test suite. + +https://github.com/BeSimple/BeSimpleSoapClient + +*/ + +if (!is_dir($vendorDir = dirname(__FILE__).'/vendor')) { + mkdir($vendorDir, 0777, true); +} + +$deps = array( + array('besimple-soapcommon', 'http://github.com/BeSimple/BeSimpleSoapCommon.git', 'origin/HEAD'), +); + +foreach ($deps as $dep) { + list($name, $url, $rev) = $dep; + + echo "> Installing/Updating $name\n"; + + $installDir = $vendorDir.'/'.$name; + if (!is_dir($installDir)) { + system(sprintf('git clone %s %s', escapeshellarg($url), escapeshellarg($installDir))); + } + + system(sprintf('cd %s && git fetch origin && git reset --hard %s', escapeshellarg($installDir), escapeshellarg($rev))); +} From 07ff1988222638112de0f904473563d5743c58d3 Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Wed, 28 Sep 2011 16:40:10 +0200 Subject: [PATCH 02/14] added SoapServerBuilder offering simple interface to configure the various options of a SoapServer --- src/BeSimple/SoapServer/SoapServerBuilder.php | 324 ++++++++++++++++++ .../SoapServer/SoapServerBuilderTest.php | 54 +++ 2 files changed, 378 insertions(+) create mode 100644 src/BeSimple/SoapServer/SoapServerBuilder.php create mode 100644 tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php new file mode 100644 index 0000000..b67812b --- /dev/null +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -0,0 +1,324 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\Cache; + +/** + * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. + * + * @author Christian Kerl + */ +class SoapServerBuilder +{ + public static function createEmpty() + { + return new self(); + } + + public static function createWithDefaults() + { + $builder = new self(); + $builder + ->withSoapVersion12() + ->withEncoding('UTF-8') + ->withErrorReporting(false) + ->withSingleElementArrays() + ; + + return $builder; + } + + private $options; + + private $optionWsdl = null; + private $optionPersistence; + private $optionErrorReporting; + + private $optionHandlerClass = null; + private $optionHandlerObject = null; + + /** + * Initializes all options with the defaults in the native SoapServer. + */ + private function __construct() + { + $this->optionPersistence = SOAP_PERSISTENCE_REQUEST; + + // TODO: this is not the default, but safer + $this->optionErrorReporting = false; + + $this->options = array( + 'soap_version' => SOAP_1_1, + 'cache_wsdl' => Cache::getType(), + 'classmap' => array(), + 'typemap' => array(), + 'features' => 0 + ); + } + + public function build() + { + $this->validateOptions(); + + use_soap_error_handler($this->optionErrorReporting); + + $server = new SoapServer($this->optionWsdl, $this->options); + $server->setPersistence($this->optionPersistence); + + if(null !== $this->optionHandlerClass) + { + $server->setClass($this->optionHandlerClass); + } + + if(null !== $this->optionHandlerObject) + { + $server->setObject($this->optionHandlerObject); + } + + return $server; + } + + private function validateOptions() + { + if(null === $this->optionWsdl) + { + throw new \InvalidArgumentException('The WSDL has to be configured!'); + } + + if(null === $this->optionHandlerClass && null === $this->optionHandlerObject) + { + throw new \InvalidArgumentException('The handler has to be configured!'); + } + } + + public function withWsdl($wsdl) + { + $this->optionWsdl = $wsdl; + + return $this; + } + + public function withSoapVersion11() + { + $this->options['soap_version'] = SOAP_1_1; + + return $this; + } + + public function withSoapVersion12() + { + $this->options['soap_version'] = SOAP_1_2; + + return $this; + } + + public function withEncoding($encoding) + { + $this->options['encoding'] = $encoding; + + return $this; + } + + public function withActor($actor) + { + $this->options['actor'] = $actor; + + return $this; + } + + /** + * Enables the HTTP session. The handler object is persisted between multiple requests in a session. + */ + public function withHttpSession() + { + $this->optionPersistence = SOAP_PERSISTENCE_SESSION; + + return $this; + } + + /** + * Enables reporting of internal errors to clients. This should only be enabled in development environments. + * + * @param boolean $enable + */ + public function withErrorReporting($enable = true) + { + $this->optionErrorReporting = $enable; + + return $this; + } + + public function withWsdlDiskCache() + { + $this->options['cache_wsdl'] = WSDL_CACHE_DISK; + + return $this; + } + + public function withWsdlMemoryCache() + { + $this->options['cache_wsdl'] = WSDL_CACHE_MEMORY; + + return $this; + } + + public function withWsdlDiskAndMemoryCache() + { + $this->options['cache_wsdl'] = WSDL_CACHE_BOTH; + + return $this; + } + + public function withBase64Attachments() + { + return $this; + } + + public function withSwaAttachments() + { + return $this; + } + + public function withMtomAttachments() + { + 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. + */ + public function withSingleElementArrays() + { + $this->options['features'] |= SOAP_SINGLE_ELEMENT_ARRAYS; + + return $this; + } + + /** + * Enables the SOAP_WAIT_ONE_WAY_CALLS feature. + */ + public function withWaitOneWayCalls() + { + $this->options['features'] |= SOAP_WAIT_ONE_WAY_CALLS; + + return $this; + } + + /** + * Enables the SOAP_USE_XSI_ARRAY_TYPE feature. + */ + public function withUseXsiArrayType() + { + $this->options['features'] |= SOAP_USE_XSI_ARRAY_TYPE; + + return $this; + } + + /** + * + * + * @param mixed $handler Can be either a class name or an object. + */ + public function withHandler($handler) + { + if(is_string($handler) && class_exists($handler)) + { + $this->optionHandlerClass = $handler; + $this->optionHandlerObject = null; + } + + if(is_object($handler)) + { + $this->optionHandlerClass = null; + $this->optionHandlerObject = $handler; + } + + throw new \InvalidArgumentException('The handler has to be a class name or an object!'); + } + + /** + * Adds a type mapping to the typemap. + * + * @param string $xmlNamespace + * @param string $xmlType + * @param callable $fromXmlCallback + * @param callable $toXmlCallback + */ + public function withTypeMapping($xmlNamespace, $xmlType, $fromXmlCallback, $toXmlCallback) + { + $this->options['typemap'][] = array( + 'type_ns' => $xmlNamespace, + 'type_name' => $xmlType, + 'from_xml' => $fromXmlCallback, + 'to_xml' => $toXmlCallback + ); + + return $this; + } + + /** + * Sets the typemap. + * + * @param array $typemap The typemap. + * @param boolean $merge If true the given typemap is merged into the existing one, otherwise the existing one is overwritten. + */ + public function withTypemap($typemap, $merge = true) + { + if($merge) + { + $this->options['typemap'] = array_merge($this->options['typemap'], $typemap); + } + else + { + $this->options['typemap'] = $typemap; + } + + return $this; + } + + /** + * Adds a class mapping to the classmap. + * + * @param string $xmlType + * @param string $phpType + */ + public function withClassMapping($xmlType, $phpType) + { + $this->options['classmap'][$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. + */ + public function withClassmap($classmap, $merge = true) + { + if($merge) + { + $this->options['classmap'] = array_merge($this->options['classmap'], $classmap); + } + else + { + $this->options['classmap'] = $classmap; + } + + return $this; + } +} diff --git a/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php new file mode 100644 index 0000000..c698b97 --- /dev/null +++ b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php @@ -0,0 +1,54 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\Tests\SoapServer; + +use BeSimple\SoapServer\SoapServerBuilder; + +/** + * UnitTest for \BeSimple\SoapServer\SoapServerBuilder + * + * @author Christian Kerl + */ +class SoapServerBuilderTest extends \PHPUnit_Framework_TestCase +{ + public function testUnconfiguredWsdl() + { + $builder = SoapServerBuilder::createEmpty(); + + try + { + $builder->build(); + + $this->fail('The SoapServer requires a WSDL file.'); + } + catch(\InvalidArgumentException $e) + { + } + } + + public function testUnconfiguredHandler() + { + $builder = SoapServerBuilder::createEmpty(); + $builder->withWsdl('my.wsdl'); + + try + { + $builder->build(); + + $this->fail('The SoapServer requires a handler.'); + } + catch(\InvalidArgumentException $e) + { + } + } +} \ No newline at end of file From 3b9690101b8211ddcc25d5ff205eab4b616a068e Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Wed, 28 Sep 2011 16:45:02 +0200 Subject: [PATCH 03/14] SoapServerBuilder now uses constants from SoapCommon\Cache --- src/BeSimple/SoapServer/SoapServerBuilder.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index b67812b..61b51cf 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -161,21 +161,21 @@ class SoapServerBuilder public function withWsdlDiskCache() { - $this->options['cache_wsdl'] = WSDL_CACHE_DISK; + $this->options['cache_wsdl'] = Cache::TYPE_DISK; return $this; } public function withWsdlMemoryCache() { - $this->options['cache_wsdl'] = WSDL_CACHE_MEMORY; + $this->options['cache_wsdl'] = Cache::TYPE_MEMORY; return $this; } public function withWsdlDiskAndMemoryCache() { - $this->options['cache_wsdl'] = WSDL_CACHE_BOTH; + $this->options['cache_wsdl'] = Cache::TYPE_DISK_MEMORY; return $this; } From b8beb549f586643324b09d7e7b71c81de92baf9b Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Thu, 29 Sep 2011 12:35:38 +0200 Subject: [PATCH 04/14] added .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61ead86 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor From 642c50c051597239b8d82c1e7827b4ff4bba504b Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Thu, 29 Sep 2011 13:32:01 +0200 Subject: [PATCH 05/14] added method to SoapServerBuilder to disable wsdl caching --- src/BeSimple/SoapServer/SoapServerBuilder.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index 61b51cf..7536157 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -32,6 +32,7 @@ class SoapServerBuilder $builder ->withSoapVersion12() ->withEncoding('UTF-8') + ->withNoWsdlCache() ->withErrorReporting(false) ->withSingleElementArrays() ; @@ -49,7 +50,7 @@ class SoapServerBuilder private $optionHandlerObject = null; /** - * Initializes all options with the defaults in the native SoapServer. + * Initializes all options with the defaults used in the native SoapServer. */ private function __construct() { @@ -159,6 +160,13 @@ class SoapServerBuilder return $this; } + public function withNoWsdlCache() + { + $this->options['cache_wsdl'] = Cache::TYPE_NONE; + + return $this; + } + public function withWsdlDiskCache() { $this->options['cache_wsdl'] = Cache::TYPE_DISK; @@ -237,7 +245,7 @@ class SoapServerBuilder if(is_string($handler) && class_exists($handler)) { $this->optionHandlerClass = $handler; - $this->optionHandlerObject = null; + $this->optionHandlerObject = null; } if(is_object($handler)) From 824919b537170875130ceac5e9a05cf9e87b41eb Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Thu, 29 Sep 2011 13:47:42 +0200 Subject: [PATCH 06/14] added methods to SoapServerBuilder to add TypeConverterInterface and TypeConverterCollection objects directly --- src/BeSimple/SoapServer/SoapServerBuilder.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index 7536157..f2a51de 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -13,6 +13,8 @@ namespace BeSimple\SoapServer; use BeSimple\SoapCommon\Cache; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; +use BeSimple\SoapCommon\Converter\TypeConverterCollection; /** * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. @@ -257,6 +259,20 @@ class SoapServerBuilder throw new \InvalidArgumentException('The handler has to be a class name or an object!'); } + public function withTypeConverter(TypeConverterInterface $converter) + { + $this->withTypeMapping($converter->getTypeNamespace(), $converter->getTypeName(), array($converter, 'convertXmlToPhp'), array($converter, 'convertPhpToXml')); + + return $this; + } + + public function withTypeConverters(TypeConverterCollection $converters, $merge = true) + { + $this->withTypemap($converters->getTypemap(), $merge); + + return $this; + } + /** * Adds a type mapping to the typemap. * From 3bb6d3abd4cb39a0419eb9fdb1c7a08d06f57951 Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Mon, 3 Oct 2011 13:35:37 +0200 Subject: [PATCH 07/14] added method stubs to SoapServer --- src/BeSimple/SoapServer/SoapServer.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServer.php b/src/BeSimple/SoapServer/SoapServer.php index 3b17e97..346a998 100644 --- a/src/BeSimple/SoapServer/SoapServer.php +++ b/src/BeSimple/SoapServer/SoapServer.php @@ -17,5 +17,13 @@ namespace BeSimple\SoapServer; */ class SoapServer extends \SoapServer { - -} \ No newline at end of file + public function __construct($wsdl, array $options = array()) + { + parent::__construct($wsdl, $options); + } + + public function handle($soap_request = null) + { + parent::handle($soap_request); + } +} From cd2d8d90e82d4624bc5c14901d09e209a6308a28 Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Sun, 9 Oct 2011 19:35:08 +0200 Subject: [PATCH 08/14] Extended SoapServerBuilder with AbstractSoapBuilder of SoapCommon library --- src/BeSimple/SoapServer/SoapServerBuilder.php | 313 ++++++------------ .../SoapServer/SoapServerBuilderTest.php | 39 +-- vendors.php | 0 3 files changed, 112 insertions(+), 240 deletions(-) mode change 100644 => 100755 vendors.php diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index f2a51de..ef80505 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -12,270 +12,148 @@ namespace BeSimple\SoapServer; -use BeSimple\SoapCommon\Cache; +use BeSimple\SoapCommon\AbstractSoapBuilder; use BeSimple\SoapCommon\Converter\TypeConverterInterface; use BeSimple\SoapCommon\Converter\TypeConverterCollection; /** * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. - * - * @author Christian Kerl + * + * @author Christian Kerl */ -class SoapServerBuilder +class SoapServerBuilder extends AbstractSoapBuilder { - public static function createEmpty() + protected $persistence; + protected $errorReporting; + + protected $handlerClass; + protected $handlerObject; + + /** + * @return SoapServerBuilder + */ + static public function createWithDefaults() { - return new self(); - } - - public static function createWithDefaults() - { - $builder = new self(); - $builder - ->withSoapVersion12() - ->withEncoding('UTF-8') - ->withNoWsdlCache() + return parent::createWithDefaults() ->withErrorReporting(false) - ->withSingleElementArrays() ; - - return $builder; } - - private $options; - - private $optionWsdl = null; - private $optionPersistence; - private $optionErrorReporting; - - private $optionHandlerClass = null; - private $optionHandlerObject = null; - + /** * Initializes all options with the defaults used in the native SoapServer. */ - private function __construct() + public function __construct() { - $this->optionPersistence = SOAP_PERSISTENCE_REQUEST; - + parent::__construct(); + + $this->persistence = SOAP_PERSISTENCE_REQUEST; + // TODO: this is not the default, but safer - $this->optionErrorReporting = false; - - $this->options = array( - 'soap_version' => SOAP_1_1, - 'cache_wsdl' => Cache::getType(), - 'classmap' => array(), - 'typemap' => array(), - 'features' => 0 - ); + $this->withErrorReporting(false); + + $this->options['classmap'] = array(); + $this->options['typemap'] = array(); } - + public function build() { $this->validateOptions(); - - use_soap_error_handler($this->optionErrorReporting); - - $server = new SoapServer($this->optionWsdl, $this->options); - $server->setPersistence($this->optionPersistence); - - if(null !== $this->optionHandlerClass) - { - $server->setClass($this->optionHandlerClass); + + use_soap_error_handler($this->errorReporting); + + $server = new SoapServer($this->wsdl, $this->options); + $server->setPersistence($this->persistence); + + if (null !== $this->handlerClass) { + $server->setClass($this->handlerClass); + } elseif (null !== $this->handlerObject) { + $server->setObject($this->handlerObject); } - - if(null !== $this->optionHandlerObject) - { - $server->setObject($this->optionHandlerObject); - } - + return $server; } - - private function validateOptions() - { - if(null === $this->optionWsdl) - { - throw new \InvalidArgumentException('The WSDL has to be configured!'); - } - - if(null === $this->optionHandlerClass && null === $this->optionHandlerObject) - { - throw new \InvalidArgumentException('The handler has to be configured!'); - } - } - - public function withWsdl($wsdl) - { - $this->optionWsdl = $wsdl; - - return $this; - } - - public function withSoapVersion11() - { - $this->options['soap_version'] = SOAP_1_1; - - return $this; - } - - public function withSoapVersion12() - { - $this->options['soap_version'] = SOAP_1_2; - - return $this; - } - - public function withEncoding($encoding) - { - $this->options['encoding'] = $encoding; - - return $this; - } - + public function withActor($actor) { - $this->options['actor'] = $actor; - + $this->options['actor'] = $actor; + return $this; } - + /** * Enables the HTTP session. The handler object is persisted between multiple requests in a session. */ public function withHttpSession() { - $this->optionPersistence = SOAP_PERSISTENCE_SESSION; - + $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 */ public function withErrorReporting($enable = true) { - $this->optionErrorReporting = $enable; - + $this->errorReporting = $enable; + return $this; } - - public function withNoWsdlCache() - { - $this->options['cache_wsdl'] = Cache::TYPE_NONE; - - return $this; - } - - public function withWsdlDiskCache() - { - $this->options['cache_wsdl'] = Cache::TYPE_DISK; - - return $this; - } - - public function withWsdlMemoryCache() - { - $this->options['cache_wsdl'] = Cache::TYPE_MEMORY; - - return $this; - } - - public function withWsdlDiskAndMemoryCache() - { - $this->options['cache_wsdl'] = Cache::TYPE_DISK_MEMORY; - - return $this; - } - + public function withBase64Attachments() { - return $this; + return $this; } - + public function withSwaAttachments() { - return $this; + return $this; } - + public function withMtomAttachments() { - return $this; + 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. - */ - public function withSingleElementArrays() - { - $this->options['features'] |= SOAP_SINGLE_ELEMENT_ARRAYS; - - return $this; - } - - /** - * Enables the SOAP_WAIT_ONE_WAY_CALLS feature. - */ - public function withWaitOneWayCalls() - { - $this->options['features'] |= SOAP_WAIT_ONE_WAY_CALLS; - - return $this; - } - - /** - * Enables the SOAP_USE_XSI_ARRAY_TYPE feature. - */ - public function withUseXsiArrayType() - { - $this->options['features'] |= SOAP_USE_XSI_ARRAY_TYPE; - - return $this; - } - - /** - * - * * @param mixed $handler Can be either a class name or an object. + * + * @return SoapServerBuilder */ public function withHandler($handler) { - if(is_string($handler) && class_exists($handler)) - { - $this->optionHandlerClass = $handler; - $this->optionHandlerObject = null; + 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'); } - - if(is_object($handler)) - { - $this->optionHandlerClass = null; - $this->optionHandlerObject = $handler; - } - - throw new \InvalidArgumentException('The handler has to be a class name or an object!'); + + return $this; } - + public function withTypeConverter(TypeConverterInterface $converter) { $this->withTypeMapping($converter->getTypeNamespace(), $converter->getTypeName(), array($converter, 'convertXmlToPhp'), array($converter, 'convertPhpToXml')); - + return $this; } - + public function withTypeConverters(TypeConverterCollection $converters, $merge = true) { $this->withTypemap($converters->getTypemap(), $merge); - + return $this; } - + /** * Adds a type mapping to the typemap. - * + * * @param string $xmlNamespace * @param string $xmlType * @param callable $fromXmlCallback @@ -284,65 +162,68 @@ class SoapServerBuilder public function withTypeMapping($xmlNamespace, $xmlType, $fromXmlCallback, $toXmlCallback) { $this->options['typemap'][] = array( - 'type_ns' => $xmlNamespace, + 'type_ns' => $xmlNamespace, 'type_name' => $xmlType, 'from_xml' => $fromXmlCallback, - 'to_xml' => $toXmlCallback + 'to_xml' => $toXmlCallback ); - + return $this; } - + /** * Sets the typemap. - * + * * @param array $typemap The typemap. * @param boolean $merge If true the given typemap is merged into the existing one, otherwise the existing one is overwritten. */ public function withTypemap($typemap, $merge = true) { - if($merge) - { + if ($merge) { $this->options['typemap'] = array_merge($this->options['typemap'], $typemap); - } - else - { + } else { $this->options['typemap'] = $typemap; } - + return $this; } - + /** * Adds a class mapping to the classmap. - * + * * @param string $xmlType * @param string $phpType */ public function withClassMapping($xmlType, $phpType) { $this->options['classmap'][$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. */ public function withClassmap($classmap, $merge = true) { - if($merge) - { + if ($merge) { $this->options['classmap'] = array_merge($this->options['classmap'], $classmap); - } - else - { + } else { $this->options['classmap'] = $classmap; } - + return $this; } + + protected function validateOptions() + { + $this->validateWsdl(); + + if (null === $this->handlerClass && null === $this->handlerObject) { + throw new \InvalidArgumentException('The handler has to be configured!'); + } + } } diff --git a/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php index c698b97..71a3fde 100644 --- a/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php +++ b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php @@ -16,39 +16,30 @@ use BeSimple\SoapServer\SoapServerBuilder; /** * UnitTest for \BeSimple\SoapServer\SoapServerBuilder - * + * * @author Christian Kerl */ class SoapServerBuilderTest extends \PHPUnit_Framework_TestCase { public function testUnconfiguredWsdl() { - $builder = SoapServerBuilder::createEmpty(); - - try - { - $builder->build(); - - $this->fail('The SoapServer requires a WSDL file.'); - } - catch(\InvalidArgumentException $e) - { - } + $builder = $this->getSoapServerBuilder(); + + $this->setExpectedException('InvalidArgumentException'); + $builder->build(); } - + public function testUnconfiguredHandler() { - $builder = SoapServerBuilder::createEmpty(); + $builder = $this->getSoapServerBuilder(); $builder->withWsdl('my.wsdl'); - - try - { - $builder->build(); - - $this->fail('The SoapServer requires a handler.'); - } - catch(\InvalidArgumentException $e) - { - } + + $this->setExpectedException('InvalidArgumentException'); + $builder->build(); + } + + public function getSoapServerBuilder() + { + return new SoapServerBuilder(); } } \ No newline at end of file diff --git a/vendors.php b/vendors.php old mode 100644 new mode 100755 From b270a51ba5f6a14367dfaa079d5273ea2228eea1 Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Sun, 9 Oct 2011 19:41:56 +0200 Subject: [PATCH 09/14] Replaced CLRF by LF and cleaned files --- src/BeSimple/SoapServer/SoapServer.php | 58 +-- src/BeSimple/SoapServer/SoapServerBuilder.php | 458 +++++++++--------- .../SoapServer/SoapServerBuilderTest.php | 88 ++-- 3 files changed, 302 insertions(+), 302 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServer.php b/src/BeSimple/SoapServer/SoapServer.php index 346a998..afc044c 100644 --- a/src/BeSimple/SoapServer/SoapServer.php +++ b/src/BeSimple/SoapServer/SoapServer.php @@ -1,29 +1,29 @@ - - * (c) Francis Besset - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapServer; - -/** - * @author Christian Kerl - */ -class SoapServer extends \SoapServer -{ - public function __construct($wsdl, array $options = array()) - { - parent::__construct($wsdl, $options); - } - - public function handle($soap_request = null) - { - parent::handle($soap_request); - } -} + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +/** + * @author Christian Kerl + */ +class SoapServer extends \SoapServer +{ + public function __construct($wsdl, array $options = array()) + { + parent::__construct($wsdl, $options); + } + + public function handle($soap_request = null) + { + parent::handle($soap_request); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index ef80505..0b192f9 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -1,229 +1,229 @@ - - * (c) Francis Besset - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\SoapServer; - -use BeSimple\SoapCommon\AbstractSoapBuilder; -use BeSimple\SoapCommon\Converter\TypeConverterInterface; -use BeSimple\SoapCommon\Converter\TypeConverterCollection; - -/** - * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. - * - * @author Christian Kerl - */ -class SoapServerBuilder extends AbstractSoapBuilder -{ - protected $persistence; - protected $errorReporting; - - protected $handlerClass; - protected $handlerObject; - - /** - * @return 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(); - - $this->persistence = SOAP_PERSISTENCE_REQUEST; - - // TODO: this is not the default, but safer - $this->withErrorReporting(false); - - $this->options['classmap'] = array(); - $this->options['typemap'] = array(); - } - - public function build() - { - $this->validateOptions(); - - use_soap_error_handler($this->errorReporting); - - $server = new SoapServer($this->wsdl, $this->options); - $server->setPersistence($this->persistence); - - if (null !== $this->handlerClass) { - $server->setClass($this->handlerClass); - } elseif (null !== $this->handlerObject) { - $server->setObject($this->handlerObject); - } - - return $server; - } - - public function withActor($actor) - { - $this->options['actor'] = $actor; - - return $this; - } - - /** - * Enables the HTTP session. The handler object is persisted between multiple requests in a session. - */ - public function withHttpSession() - { - $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 - */ - public function withErrorReporting($enable = true) - { - $this->errorReporting = $enable; - - return $this; - } - - public function withBase64Attachments() - { - return $this; - } - - public function withSwaAttachments() - { - return $this; - } - - public function withMtomAttachments() - { - return $this; - } - - /** - * @param mixed $handler Can be either a class name or an object. - * - * @return 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; - } - - public function withTypeConverter(TypeConverterInterface $converter) - { - $this->withTypeMapping($converter->getTypeNamespace(), $converter->getTypeName(), array($converter, 'convertXmlToPhp'), array($converter, 'convertPhpToXml')); - - return $this; - } - - public function withTypeConverters(TypeConverterCollection $converters, $merge = true) - { - $this->withTypemap($converters->getTypemap(), $merge); - - return $this; - } - - /** - * Adds a type mapping to the typemap. - * - * @param string $xmlNamespace - * @param string $xmlType - * @param callable $fromXmlCallback - * @param callable $toXmlCallback - */ - public function withTypeMapping($xmlNamespace, $xmlType, $fromXmlCallback, $toXmlCallback) - { - $this->options['typemap'][] = array( - 'type_ns' => $xmlNamespace, - 'type_name' => $xmlType, - 'from_xml' => $fromXmlCallback, - 'to_xml' => $toXmlCallback - ); - - return $this; - } - - /** - * Sets the typemap. - * - * @param array $typemap The typemap. - * @param boolean $merge If true the given typemap is merged into the existing one, otherwise the existing one is overwritten. - */ - public function withTypemap($typemap, $merge = true) - { - if ($merge) { - $this->options['typemap'] = array_merge($this->options['typemap'], $typemap); - } else { - $this->options['typemap'] = $typemap; - } - - return $this; - } - - /** - * Adds a class mapping to the classmap. - * - * @param string $xmlType - * @param string $phpType - */ - public function withClassMapping($xmlType, $phpType) - { - $this->options['classmap'][$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. - */ - public function withClassmap($classmap, $merge = true) - { - if ($merge) { - $this->options['classmap'] = array_merge($this->options['classmap'], $classmap); - } else { - $this->options['classmap'] = $classmap; - } - - return $this; - } - - protected function validateOptions() - { - $this->validateWsdl(); - - if (null === $this->handlerClass && null === $this->handlerObject) { - throw new \InvalidArgumentException('The handler has to be configured!'); - } - } -} + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\AbstractSoapBuilder; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; +use BeSimple\SoapCommon\Converter\TypeConverterCollection; + +/** + * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. + * + * @author Christian Kerl + */ +class SoapServerBuilder extends AbstractSoapBuilder +{ + protected $persistence; + protected $errorReporting; + + protected $handlerClass; + protected $handlerObject; + + /** + * @return 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(); + + $this->persistence = SOAP_PERSISTENCE_REQUEST; + + // TODO: this is not the default, but safer + $this->withErrorReporting(false); + + $this->options['classmap'] = array(); + $this->options['typemap'] = array(); + } + + public function build() + { + $this->validateOptions(); + + use_soap_error_handler($this->errorReporting); + + $server = new SoapServer($this->wsdl, $this->options); + $server->setPersistence($this->persistence); + + if (null !== $this->handlerClass) { + $server->setClass($this->handlerClass); + } elseif (null !== $this->handlerObject) { + $server->setObject($this->handlerObject); + } + + return $server; + } + + public function withActor($actor) + { + $this->options['actor'] = $actor; + + return $this; + } + + /** + * Enables the HTTP session. The handler object is persisted between multiple requests in a session. + */ + public function withHttpSession() + { + $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 + */ + public function withErrorReporting($enable = true) + { + $this->errorReporting = $enable; + + return $this; + } + + public function withBase64Attachments() + { + return $this; + } + + public function withSwaAttachments() + { + return $this; + } + + public function withMtomAttachments() + { + return $this; + } + + /** + * @param mixed $handler Can be either a class name or an object. + * + * @return 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; + } + + public function withTypeConverter(TypeConverterInterface $converter) + { + $this->withTypeMapping($converter->getTypeNamespace(), $converter->getTypeName(), array($converter, 'convertXmlToPhp'), array($converter, 'convertPhpToXml')); + + return $this; + } + + public function withTypeConverters(TypeConverterCollection $converters, $merge = true) + { + $this->withTypemap($converters->getTypemap(), $merge); + + return $this; + } + + /** + * Adds a type mapping to the typemap. + * + * @param string $xmlNamespace + * @param string $xmlType + * @param callable $fromXmlCallback + * @param callable $toXmlCallback + */ + public function withTypeMapping($xmlNamespace, $xmlType, $fromXmlCallback, $toXmlCallback) + { + $this->options['typemap'][] = array( + 'type_ns' => $xmlNamespace, + 'type_name' => $xmlType, + 'from_xml' => $fromXmlCallback, + 'to_xml' => $toXmlCallback + ); + + return $this; + } + + /** + * Sets the typemap. + * + * @param array $typemap The typemap. + * @param boolean $merge If true the given typemap is merged into the existing one, otherwise the existing one is overwritten. + */ + public function withTypemap($typemap, $merge = true) + { + if ($merge) { + $this->options['typemap'] = array_merge($this->options['typemap'], $typemap); + } else { + $this->options['typemap'] = $typemap; + } + + return $this; + } + + /** + * Adds a class mapping to the classmap. + * + * @param string $xmlType + * @param string $phpType + */ + public function withClassMapping($xmlType, $phpType) + { + $this->options['classmap'][$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. + */ + public function withClassmap($classmap, $merge = true) + { + if ($merge) { + $this->options['classmap'] = array_merge($this->options['classmap'], $classmap); + } else { + $this->options['classmap'] = $classmap; + } + + return $this; + } + + protected function validateOptions() + { + $this->validateWsdl(); + + if (null === $this->handlerClass && null === $this->handlerObject) { + throw new \InvalidArgumentException('The handler has to be configured!'); + } + } +} \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php index 71a3fde..df46d46 100644 --- a/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php +++ b/tests/BeSimple/Tests/SoapServer/SoapServerBuilderTest.php @@ -1,45 +1,45 @@ - - * (c) Francis Besset - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace BeSimple\Tests\SoapServer; - -use BeSimple\SoapServer\SoapServerBuilder; - -/** - * UnitTest for \BeSimple\SoapServer\SoapServerBuilder - * - * @author Christian Kerl - */ -class SoapServerBuilderTest extends \PHPUnit_Framework_TestCase -{ - public function testUnconfiguredWsdl() - { - $builder = $this->getSoapServerBuilder(); - - $this->setExpectedException('InvalidArgumentException'); - $builder->build(); - } - - public function testUnconfiguredHandler() - { - $builder = $this->getSoapServerBuilder(); - $builder->withWsdl('my.wsdl'); - - $this->setExpectedException('InvalidArgumentException'); - $builder->build(); - } - - public function getSoapServerBuilder() - { - return new SoapServerBuilder(); - } + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\Tests\SoapServer; + +use BeSimple\SoapServer\SoapServerBuilder; + +/** + * UnitTest for \BeSimple\SoapServer\SoapServerBuilder + * + * @author Christian Kerl + */ +class SoapServerBuilderTest extends \PHPUnit_Framework_TestCase +{ + public function testUnconfiguredWsdl() + { + $builder = $this->getSoapServerBuilder(); + + $this->setExpectedException('InvalidArgumentException'); + $builder->build(); + } + + public function testUnconfiguredHandler() + { + $builder = $this->getSoapServerBuilder(); + $builder->withWsdl('my.wsdl'); + + $this->setExpectedException('InvalidArgumentException'); + $builder->build(); + } + + public function getSoapServerBuilder() + { + return new SoapServerBuilder(); + } } \ No newline at end of file From c1a3059a9565b423aa69e04151da292844043072 Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Mon, 10 Oct 2011 00:08:06 +0200 Subject: [PATCH 10/14] Updated SoapServerBuilder --- src/BeSimple/SoapServer/SoapServerBuilder.php | 88 +------------------ 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index 0b192f9..bf8b05e 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -13,8 +13,6 @@ namespace BeSimple\SoapServer; use BeSimple\SoapCommon\AbstractSoapBuilder; -use BeSimple\SoapCommon\Converter\TypeConverterInterface; -use BeSimple\SoapCommon\Converter\TypeConverterCollection; /** * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. @@ -50,9 +48,6 @@ class SoapServerBuilder extends AbstractSoapBuilder // TODO: this is not the default, but safer $this->withErrorReporting(false); - - $this->options['classmap'] = array(); - $this->options['typemap'] = array(); } public function build() @@ -61,7 +56,7 @@ class SoapServerBuilder extends AbstractSoapBuilder use_soap_error_handler($this->errorReporting); - $server = new SoapServer($this->wsdl, $this->options); + $server = new SoapServer($this->wsdl, $this->getSoapOptions()); $server->setPersistence($this->persistence); if (null !== $this->handlerClass) { @@ -137,87 +132,6 @@ class SoapServerBuilder extends AbstractSoapBuilder return $this; } - public function withTypeConverter(TypeConverterInterface $converter) - { - $this->withTypeMapping($converter->getTypeNamespace(), $converter->getTypeName(), array($converter, 'convertXmlToPhp'), array($converter, 'convertPhpToXml')); - - return $this; - } - - public function withTypeConverters(TypeConverterCollection $converters, $merge = true) - { - $this->withTypemap($converters->getTypemap(), $merge); - - return $this; - } - - /** - * Adds a type mapping to the typemap. - * - * @param string $xmlNamespace - * @param string $xmlType - * @param callable $fromXmlCallback - * @param callable $toXmlCallback - */ - public function withTypeMapping($xmlNamespace, $xmlType, $fromXmlCallback, $toXmlCallback) - { - $this->options['typemap'][] = array( - 'type_ns' => $xmlNamespace, - 'type_name' => $xmlType, - 'from_xml' => $fromXmlCallback, - 'to_xml' => $toXmlCallback - ); - - return $this; - } - - /** - * Sets the typemap. - * - * @param array $typemap The typemap. - * @param boolean $merge If true the given typemap is merged into the existing one, otherwise the existing one is overwritten. - */ - public function withTypemap($typemap, $merge = true) - { - if ($merge) { - $this->options['typemap'] = array_merge($this->options['typemap'], $typemap); - } else { - $this->options['typemap'] = $typemap; - } - - return $this; - } - - /** - * Adds a class mapping to the classmap. - * - * @param string $xmlType - * @param string $phpType - */ - public function withClassMapping($xmlType, $phpType) - { - $this->options['classmap'][$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. - */ - public function withClassmap($classmap, $merge = true) - { - if ($merge) { - $this->options['classmap'] = array_merge($this->options['classmap'], $classmap); - } else { - $this->options['classmap'] = $classmap; - } - - return $this; - } - protected function validateOptions() { $this->validateWsdl(); From 0554e14a3e9bcd0fc94ce7d11bcd519a347b4f94 Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Wed, 12 Oct 2011 21:57:00 +0200 Subject: [PATCH 11/14] Renamed SoapServerBuilder::withHttpSession() to withPersistenceSession and added withPersistanceRequest() method --- src/BeSimple/SoapServer/SoapServerBuilder.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index bf8b05e..e05d658 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -44,8 +44,6 @@ class SoapServerBuilder extends AbstractSoapBuilder { parent::__construct(); - $this->persistence = SOAP_PERSISTENCE_REQUEST; - // TODO: this is not the default, but safer $this->withErrorReporting(false); } @@ -57,7 +55,10 @@ class SoapServerBuilder extends AbstractSoapBuilder use_soap_error_handler($this->errorReporting); $server = new SoapServer($this->wsdl, $this->getSoapOptions()); - $server->setPersistence($this->persistence); + + if (null !== $this->persistence) { + $server->setPersistence($this->persistence); + } if (null !== $this->handlerClass) { $server->setClass($this->handlerClass); @@ -75,10 +76,17 @@ class SoapServerBuilder extends AbstractSoapBuilder return $this; } + 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. */ - public function withHttpSession() + public function withPersistenceSession() { $this->persistence = SOAP_PERSISTENCE_SESSION; From 40a3bd55919a1738f03e15e8c7c16493baeebab6 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 21 Apr 2012 20:16:33 +0200 Subject: [PATCH 12/14] * sync server with client procession model * add SwA/MTOM --- .gitignore | 6 +- src/BeSimple/SoapServer/MimeFilter.php | 138 ++++++++++++++++++++++ src/BeSimple/SoapServer/SoapKernel.php | 47 ++++++++ src/BeSimple/SoapServer/SoapRequest.php | 71 +++++++++++ src/BeSimple/SoapServer/SoapResponse.php | 62 ++++++++++ src/BeSimple/SoapServer/SoapServer.php | 136 ++++++++++++++++++++- src/BeSimple/SoapServer/XmlMimeFilter.php | 75 ++++++++++++ 7 files changed, 532 insertions(+), 3 deletions(-) create mode 100644 src/BeSimple/SoapServer/MimeFilter.php create mode 100644 src/BeSimple/SoapServer/SoapKernel.php create mode 100644 src/BeSimple/SoapServer/SoapRequest.php create mode 100644 src/BeSimple/SoapServer/SoapResponse.php create mode 100644 src/BeSimple/SoapServer/XmlMimeFilter.php diff --git a/.gitignore b/.gitignore index 61ead86..f8d178e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -/vendor +vendor +/phpunit.xml +.buildpath +.project +.settings \ No newline at end of file diff --git a/src/BeSimple/SoapServer/MimeFilter.php b/src/BeSimple/SoapServer/MimeFilter.php new file mode 100644 index 0000000..84f16ba --- /dev/null +++ b/src/BeSimple/SoapServer/MimeFilter.php @@ -0,0 +1,138 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Mime\MultiPart as MimeMultiPart; +use BeSimple\SoapCommon\Mime\Parser as MimeParser; +use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapRequest; +use BeSimple\SoapCommon\SoapRequestFilter; +use BeSimple\SoapCommon\SoapResponse; +use BeSimple\SoapCommon\SoapResponseFilter; + +/** + * MIME filter. + * + * @author Andreas Schamberger + */ +class MimeFilter implements SoapRequestFilter, SoapResponseFilter +{ + /** + * Attachment type. + * + * @var int Helper::ATTACHMENTS_TYPE_SWA | Helper::ATTACHMENTS_TYPE_MTOM + */ + protected $attachmentType = Helper::ATTACHMENTS_TYPE_SWA; + + /** + * Constructor. + * + * @param int $attachmentType Helper::ATTACHMENTS_TYPE_SWA | Helper::ATTACHMENTS_TYPE_MTOM + */ + public function __construct($attachmentType) + { + $this->attachmentType = $attachmentType; + } + + /** + * Reset all properties to default values. + */ + public function resetFilter() + { + $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) + { + // array to store attachments + $attachmentsRecieved = array(); + + // check content type if it is a multipart mime message + $requestContentType = $request->getContentType(); + if (false !== stripos($requestContentType, 'multipart/related')) { + // parse mime message + $headers = array( + 'Content-Type' => trim($requestContentType), + ); + $multipart = MimeParser::parseMimeMessage($request->getContent(), $headers); + // get soap payload and update SoapResponse object + $soapPart = $multipart->getPart(); + // convert href -> myhref for external references as PHP throws exception in this case + // http://svn.php.net/viewvc/php/php-src/branches/PHP_5_4/ext/soap/php_encoding.c?view=markup#l3436 + $content = preg_replace('/href=(?!#)/', 'myhref=', $soapPart->getContent()); + $request->setContent($content); + $request->setContentType($soapPart->getHeader('Content-Type')); + // store attachments + $attachments = $multipart->getParts(false); + foreach ($attachments as $cid => $attachment) { + $attachmentsRecieved[$cid] = $attachment; + } + } + + // add attachments to response object + if (count($attachmentsRecieved) > 0) { + $request->setAttachments($attachmentsRecieved); + } + } + + /** + * Modify the given response XML. + * + * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response + * + * @return void + */ + public function filterResponse(SoapResponse $response) + { + // get attachments from request object + $attachmentsToSend = $response->getAttachments(); + + // build mime message if we have attachments + if (count($attachmentsToSend) > 0) { + $multipart = new MimeMultiPart(); + $soapPart = new MimePart($response->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); + $soapVersion = $response->getVersion(); + // change content type headers for MTOM with SOAP 1.1 + if ($soapVersion == SOAP_1_1 && $this->attachmentType & Helper::ATTACHMENTS_TYPE_MTOM) { + $multipart->setHeader('Content-Type', 'type', 'application/xop+xml'); + $multipart->setHeader('Content-Type', 'start-info', 'text/xml'); + $soapPart->setHeader('Content-Type', 'application/xop+xml'); + $soapPart->setHeader('Content-Type', 'type', 'text/xml'); + } + // change content type headers for SOAP 1.2 + elseif ($soapVersion == SOAP_1_2) { + $multipart->setHeader('Content-Type', 'type', 'application/soap+xml'); + $soapPart->setHeader('Content-Type', 'application/soap+xml'); + } + $multipart->addPart($soapPart, true); + foreach ($attachmentsToSend as $cid => $attachment) { + $multipart->addPart($attachment, false); + } + $response->setContent($multipart->getMimeMessage()); + + // TODO + $headers = $multipart->getHeadersForHttp(); + list($name, $contentType) = explode(': ', $headers[0]); + + $response->setContentType($contentType); + } + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapKernel.php b/src/BeSimple/SoapServer/SoapKernel.php new file mode 100644 index 0000000..a928738 --- /dev/null +++ b/src/BeSimple/SoapServer/SoapKernel.php @@ -0,0 +1,47 @@ + + * (c) Francis Besset + * (c) Andreas Schamberger + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\SoapKernel as CommonSoapKernel; +use BeSimple\SoapCommon\SoapRequest; +use BeSimple\SoapCommon\SoapResponse; + +/** + * SoapKernel for Server. + * + * @author Andreas Schamberger + */ +class SoapKernel extends CommonSoapKernel +{ + /** + * {@inheritDoc} + */ + public function filterRequest(SoapRequest $request) + { + parent::filterRequest($request); + + $this->attachments = $request->getAttachments(); + } + + /** + * {@inheritDoc} + */ + public function filterResponse(SoapResponse $response) + { + $response->setAttachments($this->attachments); + $this->attachments = array(); + + parent::filterResponse($response); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapRequest.php b/src/BeSimple/SoapServer/SoapRequest.php new file mode 100644 index 0000000..8a03d7a --- /dev/null +++ b/src/BeSimple/SoapServer/SoapRequest.php @@ -0,0 +1,71 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest; +use BeSimple\SoapCommon\SoapMessage; + +/** + * SoapRequest class for SoapClient. Provides factory function for request object. + * + * @author Andreas Schamberger + */ +class SoapRequest extends CommonSoapRequest +{ + /** + * Factory function for SoapRequest. + * + * @param string $content Content + * @param string $version SOAP version + * + * @return BeSimple\SoapClient\SoapRequest + */ + public static function create($content, $version) + { + $content = is_null($content) ? file_get_contents("php://input") : $content; + $location = self::getCurrentUrl(); + $action = $_SERVER[SoapMessage::SOAP_ACTION_HEADER]; + $contentType = $_SERVER[SoapMessage::CONTENT_TYPE_HEADER]; + + $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); + $request->setContentType($contentType); + + return $request; + } + + /** + * Builds the current URL from the $_SERVER array. + * + * @return string + */ + public static function getCurrentUrl() + { + $url = ''; + if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) === 'on' || $_SERVER['HTTPS'] === '1')) { + $url .= 'https://'; + } else { + $url .= 'http://'; + } + $url .= isset( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : ''; + if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80) { + $url .= ":{$_SERVER['SERVER_PORT']}"; + } + $url .= isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + return $url; + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapResponse.php b/src/BeSimple/SoapServer/SoapResponse.php new file mode 100644 index 0000000..e624fcb --- /dev/null +++ b/src/BeSimple/SoapServer/SoapResponse.php @@ -0,0 +1,62 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; +use BeSimple\SoapCommon\SoapMessage; + +/** + * SoapResponse class for SoapClient. Provides factory function for response object. + * + * @author Andreas Schamberger + */ +class SoapResponse extends CommonSoapResponse +{ + /** + * Factory function for SoapResponse. + * + * @param string $content Content + * @param string $location Location + * @param string $action SOAP action + * @param string $version SOAP version + * + * @return BeSimple\SoapClient\SoapResponse + */ + public static function create($content, $location, $action, $version) + { + $response = new SoapResponse(); + $response->setContent($content); + $response->setLocation($location); + $response->setAction($action); + $response->setVersion($version); + $contentType = SoapMessage::getContentTypeForVersion($version); + $response->setContentType($contentType); + + return $response; + } + + /** + * Send SOAP response to client. + */ + public function send() + { + // set Content-Type header + header('Content-Type: ' . $this->getContentType()); + // get content to send + $response = $this->getContent(); + // set Content-Length header + header('Content-Length: '. strlen($response)); + // send response to client + echo $response; + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapServer.php b/src/BeSimple/SoapServer/SoapServer.php index afc044c..ced2ad0 100644 --- a/src/BeSimple/SoapServer/SoapServer.php +++ b/src/BeSimple/SoapServer/SoapServer.php @@ -12,18 +12,150 @@ namespace BeSimple\SoapServer; +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Converter\MtomTypeConverter; +use BeSimple\SoapCommon\Converter\SwaTypeConverter; + /** + * Extended SoapServer that allows adding filters for SwA, MTOM, ... . + * + * @author Andreas Schamberger * @author Christian Kerl */ class SoapServer extends \SoapServer { + /** + * Soap version. + * + * @var int + */ + protected $soapVersion = SOAP_1_1; + + /** + * Soap kernel. + * + * @var \BeSimple\SoapServer\SoapKernel + */ + protected $soapKernel = null; + + /** + * Constructor. + * + * @param string $wsdl WSDL file + * @param array(string=>mixed) $options Options array + */ public function __construct($wsdl, array $options = array()) { + // store SOAP version + if (isset($options['soap_version'])) { + $this->soapVersion = $options['soap_version']; + } + // 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); } - public function handle($soap_request = null) + /** + * Custom handle method to be able to modify the SOAP messages. + * + * @param string $request Request string + */ + public function handle($request = null) { - parent::handle($soap_request); + // wrap request data in SoapRequest object + $soapRequest = SoapRequest::create($request, $this->soapVersion); + + // handle actual SOAP request + $soapResponse = $this->handle2($soapRequest); + + // send SOAP response to client + $soapResponse->send(); + } + + /** + * Runs the currently registered request filters on the request, calls the + * necessary functions (through the parent's class handle()) and runs the + * response filters. + * + * @param SoapRequest $soapRequest SOAP request object + * + * @return SoapResponse + */ + public function handle2(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(); + + // wrap response data in SoapResponse object + $soapResponse = SoapResponse::create( + $response, + $soapRequest->getLocation(), + $soapRequest->getAction(), + $soapRequest->getVersion() + ); + + // run SoapKernel on SoapResponse + $this->soapKernel->filterResponse($soapResponse); + + return $soapResponse; + } + + /** + * Get SoapKernel instance. + * + * @return \BeSimple\SoapServer\SoapKernel + */ + public function getSoapKernel() + { + 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) + { + if (isset($options['attachment_type']) && 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); + }, + ); + } } } \ No newline at end of file diff --git a/src/BeSimple/SoapServer/XmlMimeFilter.php b/src/BeSimple/SoapServer/XmlMimeFilter.php new file mode 100644 index 0000000..7562745 --- /dev/null +++ b/src/BeSimple/SoapServer/XmlMimeFilter.php @@ -0,0 +1,75 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapServer; + +use BeSimple\SoapCommon\FilterHelper; +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Mime\MultiPart as MimeMultiPart; +use BeSimple\SoapCommon\Mime\Parser as MimeParser; +use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapRequest; +use BeSimple\SoapCommon\SoapRequestFilter; +use BeSimple\SoapCommon\SoapResponse; +use BeSimple\SoapCommon\SoapResponseFilter; + +/** + * XML MIME filter that fixes the namespace of xmime:contentType attribute. + * + * @author Andreas Schamberger + */ +class XmlMimeFilter implements SoapResponseFilter +{ + /** + * Reset all properties to default values. + */ + public function resetFilter() + { + } + + /** + * Modify the given response XML. + * + * @param \BeSimple\SoapCommon\SoapResponse $response SOAP request + * + * @return void + */ + public function filterResponse(SoapResponse $response) + { + // get \DOMDocument from SOAP request + $dom = $response->getContentDocument(); + + // create FilterHelper + $filterHelper = new FilterHelper($dom); + + // add the neccessary namespaces + $filterHelper->addNamespace(Helper::PFX_XMLMIME, Helper::NS_XMLMIME); + + // get xsd:base64binary elements + $xpath = new \DOMXPath($dom); + $xpath->registerNamespace('XOP', Helper::NS_XOP); + $query = '//XOP:Include/..'; + $nodes = $xpath->query($query); + + // exchange attributes + if ($nodes->length > 0) { + foreach ($nodes as $node) { + if ($node->hasAttribute('contentType')) { + $contentType = $node->getAttribute('contentType'); + $node->removeAttribute('contentType'); + $filterHelper->setAttribute($node, Helper::NS_XMLMIME, 'contentType', $contentType); + } + } + } + + } +} \ No newline at end of file From 31838105f052e576827e9ec0fee7f7062dd4361c Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 21 Apr 2012 20:32:02 +0200 Subject: [PATCH 13/14] add phpdoc and configuration of soap attachments --- src/BeSimple/SoapServer/SoapServerBuilder.php | 77 +++++++++++++++---- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index e05d658..365c812 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -13,6 +13,7 @@ namespace BeSimple\SoapServer; use BeSimple\SoapCommon\AbstractSoapBuilder; +use BeSimple\SoapCommon\Helper; /** * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. @@ -28,13 +29,14 @@ class SoapServerBuilder extends AbstractSoapBuilder protected $handlerObject; /** - * @return SoapServerBuilder + * Create new instance with default options. + * + * @return \BeSimple\SoapServer\SoapServerBuilder */ static public function createWithDefaults() { return parent::createWithDefaults() - ->withErrorReporting(false) - ; + ->withErrorReporting(false); } /** @@ -48,6 +50,11 @@ class SoapServerBuilder extends AbstractSoapBuilder $this->withErrorReporting(false); } + /** + * Finally returns a SoapClient instance. + * + * @return \BeSimple\SoapServer\SoapServer + */ public function build() { $this->validateOptions(); @@ -69,6 +76,13 @@ class SoapServerBuilder extends AbstractSoapBuilder return $server; } + /** + * Cofigures the SOAP actor. + * + * @param string $actor Actor name + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ public function withActor($actor) { $this->options['actor'] = $actor; @@ -76,6 +90,11 @@ class SoapServerBuilder extends AbstractSoapBuilder return $this; } + /** + * Enables persistence. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ public function withPersistanceRequest() { $this->persistence = SOAP_PERSISTENCE_REQUEST; @@ -85,6 +104,8 @@ class SoapServerBuilder extends AbstractSoapBuilder /** * Enables the HTTP session. The handler object is persisted between multiple requests in a session. + * + * @return \BeSimple\SoapServer\SoapServerBuilder */ public function withPersistenceSession() { @@ -96,7 +117,9 @@ class SoapServerBuilder extends AbstractSoapBuilder /** * Enables reporting of internal errors to clients. This should only be enabled in development environments. * - * @param boolean $enable + * @param boolean $enable Enable error reporting + * + * @return \BeSimple\SoapServer\SoapServerBuilder */ public function withErrorReporting($enable = true) { @@ -105,25 +128,48 @@ class SoapServerBuilder extends AbstractSoapBuilder return $this; } + /** + * SOAP attachment type Base64. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ public function withBase64Attachments() { - return $this; - } + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_BASE64; - public function withSwaAttachments() - { - return $this; - } - - public function withMtomAttachments() - { 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 SoapServerBuilder + * @return \BeSimple\SoapServer\SoapServerBuilder */ public function withHandler($handler) { @@ -140,6 +186,9 @@ class SoapServerBuilder extends AbstractSoapBuilder return $this; } + /** + * Validate options. + */ protected function validateOptions() { $this->validateWsdl(); From 127d06fcb9b401593203ce9287da14a4986158f4 Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Tue, 15 Jan 2013 22:37:36 +0100 Subject: [PATCH 14/14] Added composer.json --- composer.json | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..5a19a6e --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "besimple/soap-server", + "type": "library", + "description": "Build and consume SOAP Server based web services", + "keywords": [ "soap", "soap-server" ], + "homepage": "https://github.com/BeSimple/BeSimpleSoapServer", + "license": "MIT", + "authors": [ + { + "name": "Francis Besset", + "email": "francis.besset@gmail.com" + }, + { + "name": "Christian Kerl", + "email": "christian-kerl@web.de" + }, + { + "name": "Andreas Schamberger", + "email": "mail@andreass.net" + } + ], + "require": { + "php": ">=5.3.0", + "besimple/soap-common": "dev-master" + }, + "autoload": { + "psr-0": { + "BeSimple\\SoapServer": "BeSimple/SoapServer/src/" + } + }, + "target-dir": "BeSimple/SoapServer" +}