From 6ac3493bc223768f666b487e02eca03d21241ec2 Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Mon, 21 Nov 2011 20:21:24 +0100 Subject: [PATCH 01/14] added basic soap processing classes discussed in #2 --- src/BeSimple/SoapCommon/SoapKernel.php | 82 ++++++++++++++++ src/BeSimple/SoapCommon/SoapMessage.php | 97 +++++++++++++++++++ src/BeSimple/SoapCommon/SoapRequest.php | 24 +++++ src/BeSimple/SoapCommon/SoapRequestFilter.php | 24 +++++ src/BeSimple/SoapCommon/SoapResponse.php | 24 +++++ .../SoapCommon/SoapResponseFilter.php | 24 +++++ 6 files changed, 275 insertions(+) create mode 100644 src/BeSimple/SoapCommon/SoapKernel.php create mode 100644 src/BeSimple/SoapCommon/SoapMessage.php create mode 100644 src/BeSimple/SoapCommon/SoapRequest.php create mode 100644 src/BeSimple/SoapCommon/SoapRequestFilter.php create mode 100644 src/BeSimple/SoapCommon/SoapResponse.php create mode 100644 src/BeSimple/SoapCommon/SoapResponseFilter.php diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php new file mode 100644 index 0000000..74c6c7c --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -0,0 +1,82 @@ + + * (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\SoapCommon; + +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 + * chains of SoapRequestFilter and SoapResponseFilter objects (roughly following + * the chain-of-responsibility pattern). + * + * @author Christian Kerl + */ +class SoapKernel +{ + private $requestFilters = array(); + private $responseFilters = array(); + + /** + * 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 + */ + 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. + * + * @param SoapRequest $request + */ + public function filterRequest(SoapRequest $request) + { + foreach($this->requestFilters as $filter) + { + $filter->filterRequest($request); + } + } + + /** + * Applies all registered SoapResponseFilter to the given SoapResponse. + * + * @param SoapResponse $response + */ + public function filterResponse(SoapResponse $response) + { + foreach($this->responseFilters as $filter) + { + $filter->filterRequest($response); + } + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php new file mode 100644 index 0000000..a795139 --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -0,0 +1,97 @@ + + * (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\SoapCommon; + +/** + * @author Christian Kerl + */ +abstract class SoapMessage +{ + const CONTENT_TYPE_HEADER = 'CONTENT_TYPE'; + const ACTION_HEADER = 'HTTP_SOAPACTION'; + + static protected $versionToContentTypeMap = array( + SOAP_1_1 => 'text/xml; charset=%s', + SOAP_1_2 => 'application/soap+xml; charset=%s' + ); + + static public function getContentTypeForVersion($version, $encoding = 'utf-8') + { + if(!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) + { + throw new \InvalidArgumentException("The 'version' argument has to be either 'SOAP_1_1' or 'SOAP_1_2'!"); + } + + return sprintf(self::$versionToContentTypeMap[$version], $encoding); + } + + protected $contentType; + protected $content; + + protected $contentDomDocument = null; + + protected $version; + protected $action; + + public function getContentType() + { + return $this->contentType; + } + + public function setContentType($contentType) + { + $this->contentType = $contentType; + } + + public function getContent() + { + return $this->content; + } + + public function setContent($content) + { + $this->content = $content; + } + + public function getContentDocument() + { + if(null === $this->contentDomDocument) + { + $this->contentDomDocument = new \DOMDocument(); + $this->contentDomDocument->loadXML($this->content); + } + + return $this->contentDomDocument; + } + + public function getVersion() + { + return $this->version; + } + + public function setVersion($version) + { + $this->version = $version; + } + + public function getAction() + { + return $this->action; + } + + public function setAction($action) + { + $this->action = $action; + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapRequest.php b/src/BeSimple/SoapCommon/SoapRequest.php new file mode 100644 index 0000000..24120c4 --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapRequest.php @@ -0,0 +1,24 @@ + + * (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\SoapCommon; + +use BeSimple\SoapCommon\SoapMessage; + +/** + * @author Christian Kerl + */ +class SoapRequest extends SoapMessage +{ + +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapRequestFilter.php b/src/BeSimple/SoapCommon/SoapRequestFilter.php new file mode 100644 index 0000000..8b200ee --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapRequestFilter.php @@ -0,0 +1,24 @@ + + * (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\SoapCommon; + +use BeSimple\SoapCommon\SoapRequest; + +/** + * @author Christian Kerl + */ +interface SoapRequestFilter +{ + public function filterRequest(SoapRequest $request); +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapResponse.php b/src/BeSimple/SoapCommon/SoapResponse.php new file mode 100644 index 0000000..7141917 --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapResponse.php @@ -0,0 +1,24 @@ + + * (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\SoapCommon; + +use BeSimple\SoapCommon\SoapMessage; + +/** + * @author Christian Kerl + */ +class SoapResponse extends SoapMessage +{ + +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapResponseFilter.php b/src/BeSimple/SoapCommon/SoapResponseFilter.php new file mode 100644 index 0000000..ebc4c50 --- /dev/null +++ b/src/BeSimple/SoapCommon/SoapResponseFilter.php @@ -0,0 +1,24 @@ + + * (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\SoapCommon; + +use BeSimple\SoapCommon\SoapResponse; + +/** + * @author Christian Kerl + */ +interface SoapResponseFilter +{ + public function filterResponse(SoapResponse $response); +} \ No newline at end of file From c09a163b90c799c46afe697115d67045983b8d0d Mon Sep 17 00:00:00 2001 From: Christian Kerl Date: Mon, 21 Nov 2011 20:28:31 +0100 Subject: [PATCH 02/14] fixed method call in SoapKernel --- src/BeSimple/SoapCommon/SoapKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index 74c6c7c..5a8f650 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -76,7 +76,7 @@ class SoapKernel { foreach($this->responseFilters as $filter) { - $filter->filterRequest($response); + $filter->filterResponse($response); } } } \ No newline at end of file From 7fab5be555a0f085ef96860229cce3a016b83ce4 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 17 Dec 2011 13:34:34 +0100 Subject: [PATCH 03/14] fix WS --- tests/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f2d913c..67150ad 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -19,7 +19,7 @@ spl_autoload_register(function($class) { return true; } } elseif (0 === strpos($class, 'ass\XmlSecurity\\')) { - $path = __DIR__.'/../vendor/XmlSecurity/src/'.strtr($class, '\\', '/').'.php'; + $path = __DIR__.'/../vendor/XmlSecurity/src/'.strtr($class, '\\', '/').'.php'; if (file_exists($path) && is_readable($path)) { require_once $path; From 099c1542a9353b6ae93cdc8fbc7dcf6197eb5c7d Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 17 Dec 2011 13:45:18 +0100 Subject: [PATCH 04/14] - encoding is always utf-8 - add missing location property - consider domdocument for get/setContent --- src/BeSimple/SoapCommon/SoapMessage.php | 61 +++++++++++++++---------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index a795139..cf3e395 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -20,78 +20,93 @@ abstract class SoapMessage { const CONTENT_TYPE_HEADER = 'CONTENT_TYPE'; const ACTION_HEADER = 'HTTP_SOAPACTION'; - + static protected $versionToContentTypeMap = array( - SOAP_1_1 => 'text/xml; charset=%s', - SOAP_1_2 => 'application/soap+xml; charset=%s' + SOAP_1_1 => 'text/xml; charset=utf-8', + SOAP_1_2 => 'application/soap+xml; charset=utf-8' ); - - static public function getContentTypeForVersion($version, $encoding = 'utf-8') + + static public function getContentTypeForVersion($version) { - if(!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) - { + if(!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) { throw new \InvalidArgumentException("The 'version' argument has to be either 'SOAP_1_1' or 'SOAP_1_2'!"); } - - return sprintf(self::$versionToContentTypeMap[$version], $encoding); + + return self::$versionToContentTypeMap[$version]; } - + protected $contentType; protected $content; - + protected $contentDomDocument = null; - + protected $version; protected $action; + protected $location; public function getContentType() { return $this->contentType; } - + public function setContentType($contentType) { $this->contentType = $contentType; } - + public function getContent() { + if (null !== $this->contentDomDocument) { + $this->content = $this->contentDomDocument->saveXML(); + } return $this->content; } - + public function setContent($content) { $this->content = $content; + if (null !== $this->contentDomDocument) { + $this->contentDomDocument->loadXML($this->content); + } } - + public function getContentDocument() { - if(null === $this->contentDomDocument) - { + if (null === $this->contentDomDocument) { $this->contentDomDocument = new \DOMDocument(); $this->contentDomDocument->loadXML($this->content); } - + return $this->contentDomDocument; } - + public function getVersion() { return $this->version; } - + public function setVersion($version) { $this->version = $version; } - + public function getAction() { return $this->action; } - + public function setAction($action) { $this->action = $action; } + + public function getLocation() + { + return $this->location; + } + + public function setLocation($location) + { + $this->location = $location; + } } \ No newline at end of file From ce30ccb5041c094a9bb8391186206842f0622ba5 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 17 Dec 2011 14:12:31 +0100 Subject: [PATCH 05/14] phpdoc --- src/BeSimple/SoapCommon/SoapMessage.php | 173 ++++++++++++++++++++---- 1 file changed, 143 insertions(+), 30 deletions(-) diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index cf3e395..4c256c0 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -14,46 +14,119 @@ namespace BeSimple\SoapCommon; /** + * Base class for SoapRequest and SoapResponse. + * * @author Christian Kerl + * @author Andreas Schamberger */ abstract class SoapMessage { + /** + * $_SERVER key for 'Content-Type' header. + * + * @var string + */ const CONTENT_TYPE_HEADER = 'CONTENT_TYPE'; - const ACTION_HEADER = 'HTTP_SOAPACTION'; + /** + * $_SERVER key for 'SOAPAction' header. + * + * @var string + */ + const SOAP_ACTION_HEADER = 'HTTP_SOAPACTION'; + + /** + * Content types for SOAP versions. + * + * @var array(string=>string) + */ static protected $versionToContentTypeMap = array( SOAP_1_1 => 'text/xml; charset=utf-8', SOAP_1_2 => 'application/soap+xml; charset=utf-8' ); - static public function getContentTypeForVersion($version) + /** + * SOAP action. + * + * @var string + */ + protected $action; + + /** + * Message content (MIME Message or SOAP Envelope). + * + * @var string + */ + protected $content; + + /** + * + * Enter description here ... + * @var \DOMDocument + */ + protected $contentDomDocument = null; + + /** + * Message content type. + * + * @var string + */ + protected $contentType; + + /** + * Service location. + * + * @var string + */ + protected $location; + + /** + * SOAP version (SOAP_1_1|SOAP_1_2) + * + * @var string + */ + protected $version; + + /** + * Get content type for given SOAP version. + * + * @param string $version SOAP version constant SOAP_1_1|SOAP_1_2 + * @throws \InvalidArgumentException + */ + public static function getContentTypeForVersion($version) { - if(!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) { + if (!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) { throw new \InvalidArgumentException("The 'version' argument has to be either 'SOAP_1_1' or 'SOAP_1_2'!"); } return self::$versionToContentTypeMap[$version]; } - protected $contentType; - protected $content; - - protected $contentDomDocument = null; - - protected $version; - protected $action; - protected $location; - - public function getContentType() + /** + * Get SOAP action. + * + * @return string + */ + public function getAction() { - return $this->contentType; + return $this->action; } - public function setContentType($contentType) + /** + * Set SOAP action. + * + * @param string $action + */ + public function setAction($action) { - $this->contentType = $contentType; + $this->action = $action; } + /** + * Get message content (MIME Message or SOAP Envelope). + * + * @return string + */ public function getContent() { if (null !== $this->contentDomDocument) { @@ -62,6 +135,11 @@ abstract class SoapMessage return $this->content; } + /** + * Set message content (MIME Message or SOAP Envelope). + * + * @param string $content + */ public function setContent($content) { $this->content = $content; @@ -70,6 +148,11 @@ abstract class SoapMessage } } + /** + * Get SOAP message as \DOMDocument + * + * @return \DOMDocument + */ public function getContentDocument() { if (null === $this->contentDomDocument) { @@ -80,33 +163,63 @@ abstract class SoapMessage return $this->contentDomDocument; } - public function getVersion() + /** + * Get content type. + * + * @return string + */ + public function getContentType() { - return $this->version; + return $this->contentType; } - public function setVersion($version) + /** + * Set content type. + * + * @param string $contentType + */ + public function setContentType($contentType) { - $this->version = $version; - } - - public function getAction() - { - return $this->action; - } - - public function setAction($action) - { - $this->action = $action; + $this->contentType = $contentType; } + /** + * Get location. + * + * @return string + */ public function getLocation() { return $this->location; } + /** + * Set location. + * + * @param string $location + */ public function setLocation($location) { $this->location = $location; } + + /** + * Get version. + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Set version. + * + * @param string $version + */ + public function setVersion($version) + { + $this->version = $version; + } } \ No newline at end of file From 7de7ee9c6c4d4d03bb49a91320e173256a7e5e51 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 17 Dec 2011 16:25:49 +0100 Subject: [PATCH 06/14] CS fixes --- src/BeSimple/SoapCommon/Helper.php | 2 + src/BeSimple/SoapCommon/Mime/MultiPart.php | 5 ++ src/BeSimple/SoapCommon/Mime/Parser.php | 3 + src/BeSimple/SoapCommon/Mime/Part.php | 4 +- src/BeSimple/SoapCommon/Mime/PartHeader.php | 4 ++ src/BeSimple/SoapCommon/SoapKernel.php | 63 ++++++++++--------- src/BeSimple/SoapCommon/SoapMessage.php | 12 ++-- src/BeSimple/SoapCommon/SoapRequest.php | 4 +- src/BeSimple/SoapCommon/SoapRequestFilter.php | 7 +++ src/BeSimple/SoapCommon/SoapResponse.php | 4 +- .../SoapCommon/SoapResponseFilter.php | 7 +++ src/BeSimple/SoapCommon/WsSecurityKey.php | 2 + src/BeSimple/SoapCommon/WsdlHandler.php | 2 + 13 files changed, 83 insertions(+), 36 deletions(-) diff --git a/src/BeSimple/SoapCommon/Helper.php b/src/BeSimple/SoapCommon/Helper.php index 19185ed..c33a9df 100644 --- a/src/BeSimple/SoapCommon/Helper.php +++ b/src/BeSimple/SoapCommon/Helper.php @@ -191,6 +191,7 @@ class Helper * Get SOAP namespace for the given $version. * * @param int $version SOAP_1_1|SOAP_1_2 + * * @return string */ public static function getSoapNamespace($version) @@ -206,6 +207,7 @@ class Helper * Get SOAP version from namespace URI. * * @param string $namespace NS_SOAP_1_1|NS_SOAP_1_2 + * * @return int SOAP_1_1|SOAP_1_2 */ public static function getSoapVersionFromNamespace($namespace) diff --git a/src/BeSimple/SoapCommon/Mime/MultiPart.php b/src/BeSimple/SoapCommon/Mime/MultiPart.php index 1a3b7e1..1b8ffa3 100644 --- a/src/BeSimple/SoapCommon/Mime/MultiPart.php +++ b/src/BeSimple/SoapCommon/Mime/MultiPart.php @@ -46,6 +46,7 @@ class MultiPart extends PartHeader * Construct new mime object. * * @param string $boundary Boundary string + * * @return void */ public function __construct($boundary = null) @@ -64,6 +65,7 @@ class MultiPart extends PartHeader * Get mime message of this object (without headers). * * @param boolean $withHeaders Returned mime message contains headers + * * @return string */ public function getMimeMessage($withHeaders = false) @@ -106,6 +108,7 @@ class MultiPart extends PartHeader * * @param \BeSimple\SoapCommon\Mime\Part $part Part that is added * @param boolean $isMain Is the given part the main part of mime message + * * @return void */ public function addPart(Part $part, $isMain = false) @@ -124,6 +127,7 @@ class MultiPart extends PartHeader * parameter. * * @param string $contentId Content id of desired part + * * @return \BeSimple\SoapCommon\Mime\Part|null */ public function getPart($contentId = null) @@ -141,6 +145,7 @@ class MultiPart extends PartHeader * Get all parts. * * @param boolean $includeMainPart Should main part be in result set + * * @return array(\BeSimple\SoapCommon\Mime\Part) */ public function getParts($includeMainPart = false) diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index ab41b97..1c5fe5f 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -24,6 +24,7 @@ class Parser * * @param string $mimeMessage Mime message string * @param array(string=>string) $headers Array of header elements (e.g. coming from http request) + * * @return \BeSimple\SoapCommon\Mime\MultiPart */ public static function parseMimeMessage($mimeMessage, array $headers = array()) @@ -133,6 +134,7 @@ class Parser * @param \BeSimple\SoapCommon\Mime\PartHeader $part Header part * @param string $headerName Header name * @param string $headerValue Header value + * * @return null */ private static function parseContentTypeHeader(PartHeader $part, $headerName, $headerValue) @@ -165,6 +167,7 @@ class Parser * * @param \BeSimple\SoapCommon\Mime\Part $part Part to add content * @param string $content Content to decode + * * @return null */ private static function decodeContent(Part $part, $content) diff --git a/src/BeSimple/SoapCommon/Mime/Part.php b/src/BeSimple/SoapCommon/Mime/Part.php index 88a2ca7..48aa438 100644 --- a/src/BeSimple/SoapCommon/Mime/Part.php +++ b/src/BeSimple/SoapCommon/Mime/Part.php @@ -68,6 +68,7 @@ class Part extends PartHeader * @param string $charset Charset * @param string $encoding Encoding * @param string $contentId Content id + * * @return void */ public function __construct($content = null, $contentType = 'application/octet-stream', $charset = null, $encoding = self::ENCODING_BINARY, $contentId = null) @@ -76,7 +77,7 @@ class Part extends PartHeader $this->setHeader('Content-Type', $contentType); if (!is_null($charset)) { $this->setHeader('Content-Type', 'charset', $charset); - } else { // if (substr($contentType, 0, 4) == 'text') { + } else { $this->setHeader('Content-Type', 'charset', 'utf-8'); } $this->setHeader('Content-Transfer-Encoding', $encoding); @@ -110,6 +111,7 @@ class Part extends PartHeader * Set mime content. * * @param mixed $content Content to set + * * @return void */ public function setContent($content) diff --git a/src/BeSimple/SoapCommon/Mime/PartHeader.php b/src/BeSimple/SoapCommon/Mime/PartHeader.php index 8e78bea..ff0dcfc 100644 --- a/src/BeSimple/SoapCommon/Mime/PartHeader.php +++ b/src/BeSimple/SoapCommon/Mime/PartHeader.php @@ -32,6 +32,7 @@ abstract class PartHeader * @param string $name Header name * @param string $value Header value * @param string $subValue Is sub value? + * * @return void */ public function setHeader($name, $value, $subValue = null) @@ -57,6 +58,7 @@ abstract class PartHeader * * @param string $name Header name * @param string $subValue Sub value name + * * @return mixed|array(mixed) */ public function getHeader($name, $subValue = null) @@ -104,6 +106,7 @@ abstract class PartHeader * Generates a header field value from the given value paramater. * * @param array(string=>string)|string $value Header value + * * @return string */ protected function generateHeaderFieldValue($value) @@ -129,6 +132,7 @@ abstract class PartHeader * "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" / <"> / "/" / "[" / "]" / "?" / "=" * * @param string $string String to quote + * * @return string */ private function quoteValueString($string) diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index 5a8f650..fc349c8 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -21,61 +21,68 @@ use BeSimple\SoapCommon\SoapResponseFilter; /** * SoapKernel provides methods to pre- and post-process SoapRequests and SoapResponses using - * chains of SoapRequestFilter and SoapResponseFilter objects (roughly following + * chains of SoapRequestFilter and SoapResponseFilter objects (roughly following * the chain-of-responsibility pattern). - * + * * @author Christian Kerl */ class SoapKernel { - private $requestFilters = array(); - private $responseFilters = array(); - /** - * Registers the given object either as filter for SoapRequests or as filter for SoapResponses + * Request filters. + * + * @var array(SoapRequestFilter) + */ + private $requestFilters = array(); + + /** + * Response filters. + * + * @var array(SoapResponseFilter) + */ + private $responseFilters = array(); + + /** + * 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 + * 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 + * + * @param SoapRequestFilter|SoapResponseFilter $filter Filter to register */ public function registerFilter($filter) - { - if($filter instanceof SoapRequestFilter) - { + { + if ($filter instanceof SoapRequestFilter) { array_unshift($this->requestFilters, $filter); } - - if($filter instanceof SoapResponseFilter) - { + + if ($filter instanceof SoapResponseFilter) { array_push($this->responseFilters, $filter); } } - + /** - * Applies all registered SoapRequestFilter to the given SoapRequest. - * - * @param SoapRequest $request + * Applies all registered SoapRequestFilter to the given SoapRequest. + * + * @param SoapRequest $request Soap request */ public function filterRequest(SoapRequest $request) { - foreach($this->requestFilters as $filter) - { + foreach ($this->requestFilters as $filter) { $filter->filterRequest($request); } } - + /** - * Applies all registered SoapResponseFilter to the given SoapResponse. - * - * @param SoapResponse $response + * Applies all registered SoapResponseFilter to the given SoapResponse. + * + * @param SoapResponse $response SOAP response */ public function filterResponse(SoapResponse $response) { - foreach($this->responseFilters as $filter) - { + foreach ($this->responseFilters as $filter) { $filter->filterResponse($response); } } diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index 4c256c0..e92baf5 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -91,6 +91,8 @@ abstract class SoapMessage * Get content type for given SOAP version. * * @param string $version SOAP version constant SOAP_1_1|SOAP_1_2 + * + * @return string * @throws \InvalidArgumentException */ public static function getContentTypeForVersion($version) @@ -115,7 +117,7 @@ abstract class SoapMessage /** * Set SOAP action. * - * @param string $action + * @param string $action SOAP action */ public function setAction($action) { @@ -138,7 +140,7 @@ abstract class SoapMessage /** * Set message content (MIME Message or SOAP Envelope). * - * @param string $content + * @param string $content SOAP message */ public function setContent($content) { @@ -176,7 +178,7 @@ abstract class SoapMessage /** * Set content type. * - * @param string $contentType + * @param string $contentType Content type header */ public function setContentType($contentType) { @@ -196,7 +198,7 @@ abstract class SoapMessage /** * Set location. * - * @param string $location + * @param string $location Location string */ public function setLocation($location) { @@ -216,7 +218,7 @@ abstract class SoapMessage /** * Set version. * - * @param string $version + * @param string $version SOAP version SOAP_1_1|SOAP_1_2 */ public function setVersion($version) { diff --git a/src/BeSimple/SoapCommon/SoapRequest.php b/src/BeSimple/SoapCommon/SoapRequest.php index 24120c4..314d157 100644 --- a/src/BeSimple/SoapCommon/SoapRequest.php +++ b/src/BeSimple/SoapCommon/SoapRequest.php @@ -16,9 +16,11 @@ namespace BeSimple\SoapCommon; use BeSimple\SoapCommon\SoapMessage; /** + * SOAP request message. + * * @author Christian Kerl */ class SoapRequest extends SoapMessage { - + } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapRequestFilter.php b/src/BeSimple/SoapCommon/SoapRequestFilter.php index 8b200ee..dbc990c 100644 --- a/src/BeSimple/SoapCommon/SoapRequestFilter.php +++ b/src/BeSimple/SoapCommon/SoapRequestFilter.php @@ -16,9 +16,16 @@ namespace BeSimple\SoapCommon; use BeSimple\SoapCommon\SoapRequest; /** + * SOAP request filter interface. + * * @author Christian Kerl */ interface SoapRequestFilter { + /** + * Modify SOAP response. + * + * @param SoapRequest $request SOAP request + */ public function filterRequest(SoapRequest $request); } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapResponse.php b/src/BeSimple/SoapCommon/SoapResponse.php index 7141917..b6815b2 100644 --- a/src/BeSimple/SoapCommon/SoapResponse.php +++ b/src/BeSimple/SoapCommon/SoapResponse.php @@ -16,9 +16,11 @@ namespace BeSimple\SoapCommon; use BeSimple\SoapCommon\SoapMessage; /** + * SOAP response message. + * * @author Christian Kerl */ class SoapResponse extends SoapMessage { - + } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapResponseFilter.php b/src/BeSimple/SoapCommon/SoapResponseFilter.php index ebc4c50..c7d6bb6 100644 --- a/src/BeSimple/SoapCommon/SoapResponseFilter.php +++ b/src/BeSimple/SoapCommon/SoapResponseFilter.php @@ -16,9 +16,16 @@ namespace BeSimple\SoapCommon; use BeSimple\SoapCommon\SoapResponse; /** + * SOAP response filter interface. + * * @author Christian Kerl */ interface SoapResponseFilter { + /** + * Modify SOAP response. + * + * @param SoapResponse $response SOAP response + */ public function filterResponse(SoapResponse $response); } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/WsSecurityKey.php b/src/BeSimple/SoapCommon/WsSecurityKey.php index 327b521..432e654 100644 --- a/src/BeSimple/SoapCommon/WsSecurityKey.php +++ b/src/BeSimple/SoapCommon/WsSecurityKey.php @@ -42,6 +42,7 @@ class WsSecurityKey * @param string $key Private key * @param boolean $keyIsFile Given key parameter is path to key file * @param string $passphrase Passphrase for key + * * @return void */ public function addPrivateKey($encryptionType, $key = null, $keyIsFile = true, $passphrase = null) @@ -55,6 +56,7 @@ class WsSecurityKey * @param string $encryptionType Encryption type * @param string $key Public key * @param boolean $keyIsFile Given key parameter is path to key file + * * @return void */ public function addPublicKey($encryptionType, $key = null, $keyIsFile = true) diff --git a/src/BeSimple/SoapCommon/WsdlHandler.php b/src/BeSimple/SoapCommon/WsdlHandler.php index f0f533e..6fd044b 100644 --- a/src/BeSimple/SoapCommon/WsdlHandler.php +++ b/src/BeSimple/SoapCommon/WsdlHandler.php @@ -87,6 +87,7 @@ class WsdlHandler * Gets the mime type information from the WSDL file. * * @param string $soapAction Soap action to analyse + * * @return array(string=>array(string=>array(string))) */ private function getMimeTypesForSoapAction($soapAction) @@ -152,6 +153,7 @@ class WsdlHandler * @param string $operationType Operation type * @param string $part Part name * @param string $currentMimeType Current mime type + * * @return boolean */ public function isValidMimeTypeType($soapAction, $operationType, $part, $currentMimeType) From f0d373f1b8241573052481552f6231b14826f6f0 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 17 Dec 2011 17:52:35 +0100 Subject: [PATCH 07/14] fixed variable name --- src/BeSimple/SoapCommon/SoapMessage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index e92baf5..4bceb21 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -97,7 +97,7 @@ abstract class SoapMessage */ public static function getContentTypeForVersion($version) { - if (!in_array($soapVersion, array(SOAP_1_1, SOAP_1_2))) { + if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) { throw new \InvalidArgumentException("The 'version' argument has to be either 'SOAP_1_1' or 'SOAP_1_2'!"); } From e151d06371686ec4296750219152822bb9cee3b2 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 3 Jan 2012 12:38:58 +0100 Subject: [PATCH 08/14] fix mime parser bug --- src/BeSimple/SoapCommon/Mime/Parser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index 1c5fe5f..92713d8 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -32,6 +32,8 @@ class Parser $boundary = null; $start = null; $multipart = new MultiPart(); + $hitFirstBoundary = false; + $inHeader = true; // add given headers, e.g. coming from HTTP headers if (count($headers) > 0) { foreach ($headers as $name => $value) { @@ -43,9 +45,8 @@ class Parser $multipart->setHeader($name, $value); } } + $inHeader = false; } - $hitFirstBoundary = false; - $inHeader = true; $content = ''; $currentPart = $multipart; $lines = preg_split("/\r\n|\n/", $mimeMessage); From f6ea609f46d40c53c6f14a0aac2b4575f473f340 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 3 Jan 2012 16:38:50 +0100 Subject: [PATCH 09/14] fix parser and add attachment support --- src/BeSimple/SoapCommon/Mime/Parser.php | 7 ++- src/BeSimple/SoapCommon/SoapKernel.php | 47 +++++++++++++++++++ src/BeSimple/SoapCommon/SoapMessage.php | 29 ++++++++++++ .../Tests/SoapCommon/Mime/ParserTest.php | 2 +- 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index 92713d8..5ca618f 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -49,7 +49,7 @@ class Parser } $content = ''; $currentPart = $multipart; - $lines = preg_split("/\r\n|\n/", $mimeMessage); + $lines = preg_split("/(\r\n)/", $mimeMessage); foreach ($lines as $line) { // ignore http status code and POST * if (substr($line, 0, 5) == 'HTTP/' || substr($line, 0, 4) == 'POST') { @@ -74,7 +74,7 @@ class Parser unset($currentHeader); } if ($inHeader) { - if ($line == '') { + if (trim($line) == '') { $inHeader = false; continue; } @@ -111,7 +111,7 @@ class Parser } } else { if ($hitFirstBoundary === false) { - if ($line != '') { + if (trim($line) != '') { $inHeader = true; $currentHeader = $line; continue; @@ -120,7 +120,6 @@ class Parser $content .= $line . "\r\n"; } } - } return $multipart; } diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index fc349c8..2315b69 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -13,6 +13,8 @@ namespace BeSimple\SoapCommon; +use BeSimple\SoapCommon\Mime\Part as MimePart; + use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapResponse; @@ -28,6 +30,13 @@ use BeSimple\SoapCommon\SoapResponseFilter; */ class SoapKernel { + /** + * Mime attachments. + * + * @var array(\BeSimple\SoapCommon\Mime\Part) + */ + protected $attachments = array(); + /** * Request filters. * @@ -42,6 +51,39 @@ class SoapKernel */ private $responseFilters = array(); + /** + * Add attachment. + * + * @param \BeSimple\SoapCommon\Mime\Part $attachment New attachment + * + * @return void + */ + public function addAttachment(MimePart $attachment) + { + $contentId = trim($part->getHeader('Content-ID'), '<>'); + + $this->attachments[$contentId] = $attachment; + } + + /** + * Get attachment and remove from array. + * + * @param string $contentId Content ID of attachment + * + * @return \BeSimple\SoapCommon\Mime\Part|null + */ + public function getAttachment($contentId) + { + if (isset($this->attachments[$contentId])) { + $part = $this->attachments[$contentId]; + unset($this->attachments[$contentId]); + + return $part; + } + + 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 @@ -70,6 +112,9 @@ class SoapKernel */ public function filterRequest(SoapRequest $request) { + $request->setAttachments($this->attachments); + $this->attachments = array(); + foreach ($this->requestFilters as $filter) { $filter->filterRequest($request); } @@ -85,5 +130,7 @@ class SoapKernel foreach ($this->responseFilters as $filter) { $filter->filterResponse($response); } + + $this->attachments = $response->getAttachments(); } } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index 4bceb21..97e0a04 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -13,6 +13,8 @@ namespace BeSimple\SoapCommon; +use BeSimple\SoapCommon\Mime\Part as MimePart; + /** * Base class for SoapRequest and SoapResponse. * @@ -52,6 +54,13 @@ abstract class SoapMessage */ protected $action; + /** + * Mime attachments. + * + * @var array(\BeSimple\SoapCommon\Mime\Part) + */ + protected $attachments = array(); + /** * Message content (MIME Message or SOAP Envelope). * @@ -124,6 +133,26 @@ abstract class SoapMessage $this->action = $action; } + /** + * Get attachments. + * + * @return array(\BeSimple\SoapCommon\Mime\Part) + */ + public function getAttachments() + { + return $this->attachments; + } + + /** + * Set SOAP action. + * + * @param array(\BeSimple\SoapCommon\Mime\Part) $attachments Attachment array + */ + public function setAttachments(array $attachments) + { + $this->attachments = $attachments; + } + /** * Get message content (MIME Message or SOAP Envelope). * diff --git a/tests/BeSimple/Tests/SoapCommon/Mime/ParserTest.php b/tests/BeSimple/Tests/SoapCommon/Mime/ParserTest.php index 8efa1f9..1128325 100644 --- a/tests/BeSimple/Tests/SoapCommon/Mime/ParserTest.php +++ b/tests/BeSimple/Tests/SoapCommon/Mime/ParserTest.php @@ -52,7 +52,7 @@ class ParserTest extends \PHPUnit_Framework_TestCase $p2 = $mp->getPart('0x9d6ad00-0xa19ef48-0x9de7500-0xa4fae78-0xa382698'); $this->assertEquals('binary', $p2->getHeader('Content-Transfer-Encoding')); $this->assertEquals('application/binary', $p2->getHeader('Content-Type')); - $this->assertEquals(81, strlen($p2->getContent())); + $this->assertEquals(79, strlen($p2->getContent())); } public function testParserResponseAxis() From 22665b50ae84eb0fb745c3ac210e0b6fd848fc20 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 3 Jan 2012 18:48:40 +0100 Subject: [PATCH 10/14] fixed variable name --- src/BeSimple/SoapCommon/SoapKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index 2315b69..a49b2b1 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -60,7 +60,7 @@ class SoapKernel */ public function addAttachment(MimePart $attachment) { - $contentId = trim($part->getHeader('Content-ID'), '<>'); + $contentId = trim($attachment->getHeader('Content-ID'), '<>'); $this->attachments[$contentId] = $attachment; } From 67e181fd4f85b3002fcdf48a8ebabe0c4ce9ed24 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Thu, 5 Jan 2012 13:58:35 +0100 Subject: [PATCH 11/14] fixed mime to handle binary data correctly --- src/BeSimple/SoapCommon/Mime/Parser.php | 4 ++-- src/BeSimple/SoapCommon/Mime/Part.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index 5ca618f..c4a8c27 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -85,7 +85,7 @@ class Parser if (strlen($line) > 0 && $line[0] == "-") { if (strcmp(trim($line), '--' . $boundary) === 0) { if ($currentPart instanceof Part) { - $content = iconv_substr($content, 0, -2, 'utf-8'); + $content = substr($content, 0, -2); self::decodeContent($currentPart, $content); // check if there is a start parameter given, if not set first part $isMain = (is_null($start) || $start == $currentPart->getHeader('Content-ID')) ? true : false; @@ -99,7 +99,7 @@ class Parser $inHeader = true; $content = ''; } elseif (strcmp(trim($line), '--' . $boundary . '--') === 0) { - $content = iconv_substr($content, 0, -2, 'utf-8'); + $content = substr($content, 0, -2); self::decodeContent($currentPart, $content); // check if there is a start parameter given, if not set first part $isMain = (is_null($start) || $start == $currentPart->getHeader('Content-ID')) ? true : false; diff --git a/src/BeSimple/SoapCommon/Mime/Part.php b/src/BeSimple/SoapCommon/Mime/Part.php index 48aa438..714f137 100644 --- a/src/BeSimple/SoapCommon/Mime/Part.php +++ b/src/BeSimple/SoapCommon/Mime/Part.php @@ -149,6 +149,7 @@ class Part extends PartHeader case self::ENCODING_QUOTED_PRINTABLE: return quoted_printable_encode($content); case self::ENCODING_BINARY: + return $content; case self::ENCODING_SEVEN_BIT: case self::ENCODING_EIGHT_BIT: default: From 2b2d40b3ac058c65569c93b4e18277c3010f91e6 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sat, 7 Jan 2012 13:19:22 +0100 Subject: [PATCH 12/14] moved code from client to common --- .../InternalTypeConverterInterface.php | 58 ++++++ .../Converter/MtomTypeConverter.php | 96 ++++++++++ .../SoapCommon/Converter/SwaTypeConverter.php | 82 ++++++++ .../Converter/TypeConverterInterface.php | 26 +++ src/BeSimple/SoapCommon/FilterHelper.php | 178 ++++++++++++++++++ src/BeSimple/SoapCommon/MimeFilter.php | 138 ++++++++++++++ src/BeSimple/SoapCommon/SoapKernel.php | 40 +++- 7 files changed, 617 insertions(+), 1 deletion(-) create mode 100644 src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php create mode 100644 src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php create mode 100644 src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php create mode 100644 src/BeSimple/SoapCommon/FilterHelper.php create mode 100644 src/BeSimple/SoapCommon/MimeFilter.php diff --git a/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php b/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php new file mode 100644 index 0000000..9c86b66 --- /dev/null +++ b/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php @@ -0,0 +1,58 @@ + + * (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\SoapCommon\Converter; + +use BeSimple\SoapCommon\SoapKernel; + +/** + * Internal type converter interface. + * + * @author Andreas Schamberger + * @author Christian Kerl + */ +interface InternalTypeConverterInterface +{ + /** + * Get type namespace. + * + * @return string + */ + function getTypeNamespace(); + + /** + * Get type name. + * + * @return string + */ + function getTypeName(); + + /** + * Convert given XML string to PHP type. + * + * @param string $data XML string + * @param \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + * + * @return mixed + */ + function convertXmlToPhp($data, SoapKernel $soapKernel); + + /** + * Convert PHP type to XML string. + * + * @param mixed $data PHP type + * @param \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + * + * @return string + */ + function convertPhpToXml($data, SoapKernel $soapKernel); +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php new file mode 100644 index 0000000..a9709e2 --- /dev/null +++ b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php @@ -0,0 +1,96 @@ + + * (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\SoapCommon\Converter; + +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapKernel; +use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest; +use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; +use BeSimple\SoapCommon\Converter\InternalTypeConverterInterface; + +/** + * MTOM type converter. + * + * @author Andreas Schamberger + */ +class MtomTypeConverter implements InternalTypeConverterInterface +{ + /** + * {@inheritDoc} + */ + public function getTypeNamespace() + { + return 'http://www.w3.org/2001/XMLSchema'; + } + + /** + * {@inheritDoc} + */ + public function getTypeName() + { + return 'base64Binary'; + } + + /** + * {@inheritDoc} + */ + public function convertXmlToPhp($data, SoapKernel $soapKernel) + { + $doc = new \DOMDocument(); + $doc->loadXML($data); + + $includes = $doc->getElementsByTagNameNS(Helper::NS_XOP, 'Include'); + $include = $includes->item(0); + + // 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 + $ref = $include->getAttribute('myhref'); + + if ('cid:' === substr($ref, 0, 4)) { + $contentId = urldecode(substr($ref, 4)); + + if (null !== ($part = $soapKernel->getAttachment($contentId))) { + + return $part->getContent(); + } else { + + return null; + } + } + + return $data; + } + + /** + * {@inheritDoc} + */ + public function convertPhpToXml($data, SoapKernel $soapKernel) + { + $part = new MimePart($data); + $contentId = trim($part->getHeader('Content-ID'), '<>'); + + $soapKernel->addAttachment($part); + + $doc = new \DOMDocument(); + $node = $doc->createElement($this->getTypeName()); + $doc->appendChild($node); + + // add xop:Include element + $xinclude = $doc->createElementNS(Helper::NS_XOP, Helper::PFX_XOP . ':Include'); + $xinclude->setAttribute('href', 'cid:' . $contentId); + $node->appendChild($xinclude); + + return $doc->saveXML(); + } +} diff --git a/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php b/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php new file mode 100644 index 0000000..32ba467 --- /dev/null +++ b/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php @@ -0,0 +1,82 @@ + + * (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\SoapCommon\Converter; + +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapKernel; +use BeSimple\SoapCommon\Converter\InternalTypeConverterInterface; + +/** + * SwA type converter. + * + * @author Andreas Schamberger + */ +class SwaTypeConverter implements InternalTypeConverterInterface +{ + /** + * {@inheritDoc} + */ + public function getTypeNamespace() + { + return 'http://www.w3.org/2001/XMLSchema'; + } + + /** + * {@inheritDoc} + */ + public function getTypeName() + { + return 'base64Binary'; + } + + /** + * {@inheritDoc} + */ + public function convertXmlToPhp($data, SoapKernel $soapKernel) + { + $doc = new \DOMDocument(); + $doc->loadXML($data); + + // 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 + $ref = $doc->documentElement->getAttribute('myhref'); + + if ('cid:' === substr($ref, 0, 4)) { + $contentId = urldecode(substr($ref, 4)); + + if (null !== ($part = $soapKernel->getAttachment($contentId))) { + + return $part->getContent(); + } else { + + return null; + } + } + + return $data; + } + + /** + * {@inheritDoc} + */ + public function convertPhpToXml($data, SoapKernel $soapKernel) + { + $part = new MimePart($data); + $contentId = trim($part->getHeader('Content-ID'), '<>'); + + $soapKernel->addAttachment($part); + + return sprintf('<%s href="%s"/>', $this->getTypeName(), $contentId); + } +} diff --git a/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php b/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php index 4de7d7f..e390963 100644 --- a/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php +++ b/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php @@ -13,15 +13,41 @@ namespace BeSimple\SoapCommon\Converter; /** + * Type converter interface. + * * @author Christian Kerl */ interface TypeConverterInterface { + /** + * Get type namespace. + * + * @return string + */ function getTypeNamespace(); + /** + * Get type name. + * + * @return string + */ function getTypeName(); + /** + * Convert given XML string to PHP type. + * + * @param string $data XML string + * + * @return mixed + */ function convertXmlToPhp($data); + /** + * Convert PHP type to XML string. + * + * @param mixed $data PHP type + * + * @return string + */ function convertPhpToXml($data); } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/FilterHelper.php b/src/BeSimple/SoapCommon/FilterHelper.php new file mode 100644 index 0000000..01a1717 --- /dev/null +++ b/src/BeSimple/SoapCommon/FilterHelper.php @@ -0,0 +1,178 @@ + + * (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\SoapCommon; + +/** + * Soap request/response filter helper for manipulating SOAP messages. + * + * @author Andreas Schamberger + */ +class FilterHelper +{ + /** + * DOMDocument on which the helper functions operate. + * + * @var \DOMDocument + */ + protected $domDocument = null; + + /** + * Namespaces added. + * + * @var array(string=>string) + */ + protected $namespaces = array(); + + /** + * Constructor. + * + * @param \DOMDocument $domDocument SOAP document + */ + public function __construct(\DOMDocument $domDocument) + { + $this->domDocument = $domDocument; + } + + /** + * Add new soap header. + * + * @param \DOMElement $node DOMElement to add + * @param boolean $mustUnderstand SOAP header mustUnderstand attribute + * @param string $actor SOAP actor/role + * @param string $soapVersion SOAP version SOAP_1_1|SOAP_1_2 + * + * @return void + */ + public function addHeaderElement(\DOMElement $node, $mustUnderstand = null, $actor = null, $soapVersion = SOAP_1_1) + { + $root = $this->domDocument->documentElement; + $namespace = $root->namespaceURI; + $prefix = $root->prefix; + if (null !== $mustUnderstand) { + $node->appendChild(new \DOMAttr($prefix . ':mustUnderstand', (int) $mustUnderstand)); + } + if (null !== $actor) { + $attributeName = ($soapVersion == SOAP_1_1) ? 'actor' : 'role'; + $node->appendChild(new \DOMAttr($prefix . ':' . $attributeName, $actor)); + } + $nodeListHeader = $root->getElementsByTagNameNS($namespace, 'Header'); + // add header if not there + if ($nodeListHeader->length == 0) { + // new header element + $header = $this->domDocument->createElementNS($namespace, $prefix . ':Header'); + // try to add it before body + $nodeListBody = $root->getElementsByTagNameNS($namespace, 'Body'); + if ($nodeListBody->length == 0) { + $root->appendChild($header); + } else { + $body = $nodeListBody->item(0); + $header = $body->parentNode->insertBefore($header, $body); + } + $header->appendChild($node); + } else { + $nodeListHeader->item(0)->appendChild($node); + } + } + + /** + * Add new soap body element. + * + * @param \DOMElement $node DOMElement to add + * + * @return void + */ + public function addBodyElement(\DOMElement $node) + { + $root = $this->domDocument->documentElement; + $namespace = $root->namespaceURI; + $prefix = $root->prefix; + $nodeList = $this->domDocument->getElementsByTagNameNS($namespace, 'Body'); + // add body if not there + if ($nodeList->length == 0) { + // new body element + $body = $this->domDocument->createElementNS($namespace, $prefix . ':Body'); + $root->appendChild($body); + $body->appendChild($node); + } else { + $nodeList->item(0)->appendChild($node); + } + } + + /** + * Add new namespace to root tag. + * + * @param string $prefix Namespace prefix + * @param string $namespaceURI Namespace URI + * + * @return void + */ + public function addNamespace($prefix, $namespaceURI) + { + if (!isset($this->namespaces[$namespaceURI])) { + $root = $this->domDocument->documentElement; + $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $prefix, $namespaceURI); + $this->namespaces[$namespaceURI] = $prefix; + } + } + + /** + * Create new element for given namespace. + * + * @param string $namespaceURI Namespace URI + * @param string $name Element name + * @param string $value Element value + * + * @return \DOMElement + */ + public function createElement($namespaceURI, $name, $value = null) + { + $prefix = $this->namespaces[$namespaceURI]; + + return $this->domDocument->createElementNS($namespaceURI, $prefix . ':' . $name, $value); + } + + /** + * Add new attribute to element with given namespace. + * + * @param \DOMElement $element DOMElement to edit + * @param string $namespaceURI Namespace URI + * @param string $name Attribute name + * @param string $value Attribute value + * + * @return void + */ + public function setAttribute(\DOMElement $element, $namespaceURI, $name, $value) + { + if (null !== $namespaceURI) { + $prefix = $this->namespaces[$namespaceURI]; + $element->setAttributeNS($namespaceURI, $prefix . ':' . $name, $value); + } else { + $element->setAttribute($name, $value); + } + } + + /** + * Register namespace. + * + * @param string $prefix Namespace prefix + * @param string $namespaceURI Namespace URI + * + * @return void + */ + public function registerNamespace($prefix, $namespaceURI) + { + if (!isset($this->namespaces[$namespaceURI])) { + $this->namespaces[$namespaceURI] = $prefix; + } + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/MimeFilter.php b/src/BeSimple/SoapCommon/MimeFilter.php new file mode 100644 index 0000000..068deb7 --- /dev/null +++ b/src/BeSimple/SoapCommon/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\SoapCommon; + +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) + { + // get attachments from request object + $attachmentsToSend = $request->getAttachments(); + + // build mime message if we have attachments + if (count($attachmentsToSend) > 0) { + $multipart = new MimeMultiPart(); + $soapPart = new MimePart($request->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); + $soapVersion = $request->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); + } + $request->setContent($multipart->getMimeMessage()); + + // TODO + $headers = $multipart->getHeadersForHttp(); + list($name, $contentType) = explode(': ', $headers[0]); + + $request->setContentType($contentType); + } + } + + /** + * Modify the given response XML. + * + * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response + * + * @return void + */ + public function filterResponse(SoapResponse $response) + { + // array to store attachments + $attachmentsRecieved = array(); + + // check content type if it is a multipart mime message + $responseContentType = $response->getContentType(); + if (false !== stripos($responseContentType, 'multipart/related')) { + // parse mime message + $headers = array( + 'Content-Type' => trim($responseContentType), + ); + $multipart = MimeParser::parseMimeMessage($response->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()); + $response->setContent($content); + $response->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) { + $response->setAttachments($attachmentsRecieved); + } + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index a49b2b1..f0ead8c 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -15,9 +15,10 @@ namespace BeSimple\SoapCommon; use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\Converter\MtomTypeConverter; +use BeSimple\SoapCommon\Converter\SwaTypeConverter; use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapResponse; - use BeSimple\SoapCommon\SoapRequestFilter; use BeSimple\SoapCommon\SoapResponseFilter; @@ -133,4 +134,41 @@ class SoapKernel $this->attachments = $response->getAttachments(); } + + /** + * Configure filter and type converter for SwA/MTOM. + * + * @param array &$options SOAP constructor options array. + * + * @return void + */ + public 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->registerFilter($mimeFilter); + // configure type converter + if (Helper::ATTACHMENTS_TYPE_SWA === $options['attachment_type']) { + $converter = new SwaTypeConverter(); + } elseif (Helper::ATTACHMENTS_TYPE_MTOM === $options['attachment_type']) { + $converter = new MtomTypeConverter(); + } + // configure typemap + if (!isset($options['typemap'])) { + $options['typemap'] = array(); + } + $soapKernel = $this; + $options['typemap'][] = array( + 'type_name' => $converter->getTypeName(), + 'type_ns' => $converter->getTypeNamespace(), + 'from_xml' => function($input) use ($converter, $soapKernel) { + return $converter->convertXmlToPhp($input, $soapKernel); + }, + 'to_xml' => function($input) use ($converter, $soapKernel) { + return $converter->convertPhpToXml($input, $soapKernel); + }, + ); + } + } } \ No newline at end of file From bf8965895ece3a92863a9e49108d2d2340a3b360 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sun, 8 Jan 2012 09:31:01 +0100 Subject: [PATCH 13/14] mime filter is not generic --- src/BeSimple/SoapCommon/MimeFilter.php | 138 ------------------------- 1 file changed, 138 deletions(-) delete mode 100644 src/BeSimple/SoapCommon/MimeFilter.php diff --git a/src/BeSimple/SoapCommon/MimeFilter.php b/src/BeSimple/SoapCommon/MimeFilter.php deleted file mode 100644 index 068deb7..0000000 --- a/src/BeSimple/SoapCommon/MimeFilter.php +++ /dev/null @@ -1,138 +0,0 @@ - - * (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\SoapCommon; - -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) - { - // get attachments from request object - $attachmentsToSend = $request->getAttachments(); - - // build mime message if we have attachments - if (count($attachmentsToSend) > 0) { - $multipart = new MimeMultiPart(); - $soapPart = new MimePart($request->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); - $soapVersion = $request->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); - } - $request->setContent($multipart->getMimeMessage()); - - // TODO - $headers = $multipart->getHeadersForHttp(); - list($name, $contentType) = explode(': ', $headers[0]); - - $request->setContentType($contentType); - } - } - - /** - * Modify the given response XML. - * - * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response - * - * @return void - */ - public function filterResponse(SoapResponse $response) - { - // array to store attachments - $attachmentsRecieved = array(); - - // check content type if it is a multipart mime message - $responseContentType = $response->getContentType(); - if (false !== stripos($responseContentType, 'multipart/related')) { - // parse mime message - $headers = array( - 'Content-Type' => trim($responseContentType), - ); - $multipart = MimeParser::parseMimeMessage($response->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()); - $response->setContent($content); - $response->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) { - $response->setAttachments($attachmentsRecieved); - } - } -} \ No newline at end of file From d633516e1f19d79bae62ebdd356853a65a2c1f3c Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sun, 8 Jan 2012 09:50:11 +0100 Subject: [PATCH 14/14] replace internal type converter interface with cleaner solution --- .../InternalTypeConverterInterface.php | 58 ------------------- .../Converter/MtomTypeConverter.php | 28 ++++++--- .../Converter/SoapKernelAwareInterface.php | 32 ++++++++++ .../SoapCommon/Converter/SwaTypeConverter.php | 26 +++++++-- src/BeSimple/SoapCommon/SoapKernel.php | 37 ------------ 5 files changed, 72 insertions(+), 109 deletions(-) delete mode 100644 src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php create mode 100644 src/BeSimple/SoapCommon/Converter/SoapKernelAwareInterface.php diff --git a/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php b/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php deleted file mode 100644 index 9c86b66..0000000 --- a/src/BeSimple/SoapCommon/Converter/InternalTypeConverterInterface.php +++ /dev/null @@ -1,58 +0,0 @@ - - * (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\SoapCommon\Converter; - -use BeSimple\SoapCommon\SoapKernel; - -/** - * Internal type converter interface. - * - * @author Andreas Schamberger - * @author Christian Kerl - */ -interface InternalTypeConverterInterface -{ - /** - * Get type namespace. - * - * @return string - */ - function getTypeNamespace(); - - /** - * Get type name. - * - * @return string - */ - function getTypeName(); - - /** - * Convert given XML string to PHP type. - * - * @param string $data XML string - * @param \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance - * - * @return mixed - */ - function convertXmlToPhp($data, SoapKernel $soapKernel); - - /** - * Convert PHP type to XML string. - * - * @param mixed $data PHP type - * @param \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance - * - * @return string - */ - function convertPhpToXml($data, SoapKernel $soapKernel); -} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php index a9709e2..52ea961 100644 --- a/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php @@ -15,17 +15,21 @@ namespace BeSimple\SoapCommon\Converter; use BeSimple\SoapCommon\Helper; use BeSimple\SoapCommon\Mime\Part as MimePart; use BeSimple\SoapCommon\SoapKernel; -use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest; -use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; -use BeSimple\SoapCommon\Converter\InternalTypeConverterInterface; +use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; /** * MTOM type converter. * * @author Andreas Schamberger */ -class MtomTypeConverter implements InternalTypeConverterInterface +class MtomTypeConverter implements TypeConverterInterface, SoapKernelAwareInterface { + /** + * @var \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + */ + protected $soapKernel = null; + /** * {@inheritDoc} */ @@ -45,7 +49,7 @@ class MtomTypeConverter implements InternalTypeConverterInterface /** * {@inheritDoc} */ - public function convertXmlToPhp($data, SoapKernel $soapKernel) + public function convertXmlToPhp($data) { $doc = new \DOMDocument(); $doc->loadXML($data); @@ -60,7 +64,7 @@ class MtomTypeConverter implements InternalTypeConverterInterface if ('cid:' === substr($ref, 0, 4)) { $contentId = urldecode(substr($ref, 4)); - if (null !== ($part = $soapKernel->getAttachment($contentId))) { + if (null !== ($part = $this->soapKernel->getAttachment($contentId))) { return $part->getContent(); } else { @@ -75,12 +79,12 @@ class MtomTypeConverter implements InternalTypeConverterInterface /** * {@inheritDoc} */ - public function convertPhpToXml($data, SoapKernel $soapKernel) + public function convertPhpToXml($data) { $part = new MimePart($data); $contentId = trim($part->getHeader('Content-ID'), '<>'); - $soapKernel->addAttachment($part); + $this->soapKernel->addAttachment($part); $doc = new \DOMDocument(); $node = $doc->createElement($this->getTypeName()); @@ -93,4 +97,12 @@ class MtomTypeConverter implements InternalTypeConverterInterface return $doc->saveXML(); } + + /** + * {@inheritDoc} + */ + public function setKernel(SoapKernel $soapKernel) + { + $this->soapKernel = $soapKernel; + } } diff --git a/src/BeSimple/SoapCommon/Converter/SoapKernelAwareInterface.php b/src/BeSimple/SoapCommon/Converter/SoapKernelAwareInterface.php new file mode 100644 index 0000000..655a258 --- /dev/null +++ b/src/BeSimple/SoapCommon/Converter/SoapKernelAwareInterface.php @@ -0,0 +1,32 @@ + + * (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\SoapCommon\Converter; + +use BeSimple\SoapCommon\SoapKernel; + +/** + * Internal type converter interface. + * + * @author Andreas Schamberger + */ +interface SoapKernelAwareInterface +{ + /** + * Set SoapKernel instance. + * + * @param \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + * + * @return void + */ + function setKernel(SoapKernel $soapKernel); +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php b/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php index 32ba467..40d6372 100644 --- a/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php @@ -15,15 +15,21 @@ namespace BeSimple\SoapCommon\Converter; use BeSimple\SoapCommon\Helper; use BeSimple\SoapCommon\Mime\Part as MimePart; use BeSimple\SoapCommon\SoapKernel; -use BeSimple\SoapCommon\Converter\InternalTypeConverterInterface; +use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; /** * SwA type converter. * * @author Andreas Schamberger */ -class SwaTypeConverter implements InternalTypeConverterInterface +class SwaTypeConverter implements TypeConverterInterface, SoapKernelAwareInterface { + /** + * @var \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + */ + protected $soapKernel = null; + /** * {@inheritDoc} */ @@ -43,7 +49,7 @@ class SwaTypeConverter implements InternalTypeConverterInterface /** * {@inheritDoc} */ - public function convertXmlToPhp($data, SoapKernel $soapKernel) + public function convertXmlToPhp($data) { $doc = new \DOMDocument(); $doc->loadXML($data); @@ -55,7 +61,7 @@ class SwaTypeConverter implements InternalTypeConverterInterface if ('cid:' === substr($ref, 0, 4)) { $contentId = urldecode(substr($ref, 4)); - if (null !== ($part = $soapKernel->getAttachment($contentId))) { + if (null !== ($part = $this->soapKernel->getAttachment($contentId))) { return $part->getContent(); } else { @@ -70,13 +76,21 @@ class SwaTypeConverter implements InternalTypeConverterInterface /** * {@inheritDoc} */ - public function convertPhpToXml($data, SoapKernel $soapKernel) + public function convertPhpToXml($data) { $part = new MimePart($data); $contentId = trim($part->getHeader('Content-ID'), '<>'); - $soapKernel->addAttachment($part); + $this->soapKernel->addAttachment($part); return sprintf('<%s href="%s"/>', $this->getTypeName(), $contentId); } + + /** + * {@inheritDoc} + */ + public function setKernel(SoapKernel $soapKernel) + { + $this->soapKernel = $soapKernel; + } } diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index f0ead8c..da57db0 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -134,41 +134,4 @@ class SoapKernel $this->attachments = $response->getAttachments(); } - - /** - * Configure filter and type converter for SwA/MTOM. - * - * @param array &$options SOAP constructor options array. - * - * @return void - */ - public 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->registerFilter($mimeFilter); - // configure type converter - if (Helper::ATTACHMENTS_TYPE_SWA === $options['attachment_type']) { - $converter = new SwaTypeConverter(); - } elseif (Helper::ATTACHMENTS_TYPE_MTOM === $options['attachment_type']) { - $converter = new MtomTypeConverter(); - } - // configure typemap - if (!isset($options['typemap'])) { - $options['typemap'] = array(); - } - $soapKernel = $this; - $options['typemap'][] = array( - 'type_name' => $converter->getTypeName(), - 'type_ns' => $converter->getTypeNamespace(), - 'from_xml' => function($input) use ($converter, $soapKernel) { - return $converter->convertXmlToPhp($input, $soapKernel); - }, - 'to_xml' => function($input) use ($converter, $soapKernel) { - return $converter->convertPhpToXml($input, $soapKernel); - }, - ); - } - } } \ No newline at end of file