diff --git a/.gitignore b/.gitignore index 48c3ad1..72bd9c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /vendor/ +composer.lock phpunit.xml -.idea/ diff --git a/.travis.yml b/.travis.yml index 0f62698..6458c71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,25 @@ language: php php: - - 7.0 - - 7.1 + - 5.3 + - 5.4 + - 5.5 + - 5.6 + +env: + - SYMFONY_VERSION=2.6.* + - SYMFONY_VERSION="dev-master symfony/debug:~2.7@dev symfony/http-kernel:~2.7@dev" before_script: - composer self-update - - composer install - - cp phpunit.xml.dist phpunit.xml - - php -S localhost:8000 > /dev/null 2>&1 & + - composer require symfony/framework-bundle:${SYMFONY_VERSION} --no-update + - composer update --no-interaction --prefer-source + - ./src/BeSimple/SoapClient/Tests/bin/phpwebserver.sh + - ./src/BeSimple/SoapClient/Tests/bin/axis.sh script: - - vendor/phing/phing/bin/phing -f build.xml + - phpunit --coverage-text + +matrix: + allow_failures: + - env: SYMFONY_VERSION="dev-master symfony/debug:~2.7@dev symfony/http-kernel:~2.7@dev" diff --git a/README.md b/README.md index 463860c..e1caac8 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,35 @@ # BeSimpleSoap -Build SOAP and WSDL based web services. -This fork is a refactored version that fixes a lot of errors and provides -better API, robust, stable and modern codebase. -See [How to use](#how-to-use) that will help you to understand the magic. +Build SOAP and WSDL based web services # Components BeSimpleSoap consists of five components ... +## BeSimpleSoapBundle + +The BeSimpleSoapBundle is a Symfony2 bundle to build WSDL and SOAP based web services. +For further information see the [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapBundle/README.md). + ## BeSimpleSoapClient -**Refactored** BeSimpleSoapClient is a component that extends the native PHP SoapClient with further features like SwA and WS-Security. - -## BeSimpleSoapServer - -**Refactored** BeSimpleSoapServer is a component that extends the native PHP SoapServer with further features like SwA and WS-Security. +The BeSimpleSoapClient is a component that extends the native PHP SoapClient with further features like SwA, MTOM and WS-Security. +For further information see the [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapClient/README.md). ## BeSimpleSoapCommon -**Refactored** BeSimpleSoapCommon component contains functionality shared by both the server and client implementations. +The BeSimpleSoapCommon component contains functionylity shared by both the server and client implementations. +For further information see the [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapCommon/README.md). + + +## BeSimpleSoapServer + +The BeSimpleSoapServer is a component that extends the native PHP SoapServer with further features like SwA, MTOM and WS-Security. +For further information see the [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapServer/README.md). ## BeSimpleSoapWsdl -**Untouched!** -The component is not affected by refactoring so it should work properly. -For further information see the original [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapWsdl/README.md). - -## BeSimpleSoapBundle - -**Unsupported!** -The BeSimpleSoapBundle is a Symfony2 bundle to build WSDL and SOAP based web services. -For further information see the the original [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapBundle/README.md). -*Will not work since the Symfony libraries were removed and usages of other components were not refactored. Feel free to fork this repository and fix it!* +For further information see the [README](https://github.com/BeSimple/BeSimpleSoap/blob/master/src/BeSimple/SoapWsdl/README.md). # Installation @@ -47,7 +44,7 @@ Create a `composer.json` file: ```json { "require": { - "tuscanicz/soap": "^4.2" + "besimple/soap": "0.2.*@dev" } } ``` @@ -57,99 +54,3 @@ Now you are ready to install the library: ```sh php /usr/local/bin/composer.phar install ``` - -# How to use - -You can investigate the unit tests dir ``tests`` in order to get a clue. -Forget about associative arrays, vague configurations, multiple extension and silent errors! -This may look a bit more complex at the first sight, -but it will guide you to configure and set up your client or server properly. - -## Example of soap client call - -```php -$soapClientBuilder = new SoapClientBuilder(); -$soapClient = $soapClientBuilder->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults('http://path/to/wsdlfile.wsdl') -); -$myRequest = new MyRequest(); -$myRequest->attribute = 'string value'; -$soapResponse = $soapClient->soapCall('myMethod', [$myRequest]); - -var_dump($soapResponse); // Contains Response, Attachments -``` - -### Something wrong?! -Turn on the tracking and catch `SoapFaultWithTracingData` exception to get some sweets :) - -```php -try { - $soapResponse = $soapClient->soapCall('myMethod', [$myRequest]); -} catch (SoapFaultWithTracingData $fault) { - var_dump($fault->getSoapResponseTracingData()->getLastRequest()); -} -``` -In this example, a ``MyRequest`` object has been used to describe request. -Using a ClassMap, you help SoapClient to turn it into XML request. - -## Example of soap server handling - -Starting a SOAP server is a bit more complex. -I recommend you to inspect SoapServer unit tests for inspiration. - -```php -$dummyService = new DummyService(); -$classMap = new ClassMap(); -foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); -} -$soapServerBuilder = new SoapServerBuilder(); -$soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); -$soapOptions = SoapOptionsBuilder::createWithClassMap($dummyService->getWsdlPath(), $classMap); -$soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - -$request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethod', - 'text/xml;charset=UTF-8', - '' -); -$response = $soapServer->handleRequest($request); - -var_dump($response); // Contains Response, Attachments -``` -In this example, a ``DummyService`` service has been used to handle request. -Using a service can help you create coherent SoapServer endpoints. -Service can hold an endpoint URL, WSDL path and a class map as associative array. -You can hold a class map as ``ClassMap`` object directly in the ``DummyService`` instead of array. - -In the service you should describe SOAP methods from given WSDL. -In the example, the dummyServiceMethod is called. -The method will receive request object and return response object that are matched according to the class map. - -See a simplified implementation of ``dummyServiceMethod`` to get a clue: - -``` - /** - * @param DummyServiceRequest $dummyServiceRequest - * @return DummyServiceResponse - */ - public function dummyServiceMethod(DummyServiceRequest $dummyServiceRequest) - { - $response = new DummyServiceResponse(); - $response->status = true; - - return $response; - } -``` - -For further information and getting inspiration for your implementation, see the unit tests in ``tests`` dir. - -# Contribute - -[![Build Status](https://travis-ci.org/tuscanicz/BeSimpleSoap.svg?branch=master)](https://travis-ci.org/tuscanicz/BeSimpleSoap) - -Feel free to contribute! Please, run the tests via Phing ``php phing -f build.xml``. - -**Warning:** Unit tests may fail under Windows OS, tested under Linux, MacOS. diff --git a/build.xml b/build.xml deleted file mode 100644 index 55b3393..0000000 --- a/build.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - project.basedir: ${project.basedir} - - buildOutputPath: ${buildOutputPath} - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cache/.gitignore b/cache/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/cache/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/codesniffer-ruleset.xml b/codesniffer-ruleset.xml deleted file mode 100644 index ceb782d..0000000 --- a/codesniffer-ruleset.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - Coding standards - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/composer.json b/composer.json index 20d325f..fee4704 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,9 @@ { "name": "cadoles/soap", "type": "library", - "description": "A largely refactored besimple/soap used to build SOAP and WSDL based web services. This fork fixes a lot of errors and provides better API, robust, stable and modern codebase.", - "keywords": ["soap", "soap server", "soap client"], + "description": "Build and consume SOAP and WSDL based web services", + "keywords": ["soap"], + "homepage": "http://besim.pl", "license": "MIT", "authors": [ { @@ -17,20 +18,18 @@ "name": "Andreas Schamberger", "email": "mail@andreass.net" }, - { - "name": "Petr Bechyně", - "email": "mail@petrbechyne.com" - }, { "name": "Ghislain Loaec", "email": "gloaec@cadoles.com" } ], "require": { - "php": ">=5.3.0|>=7.0", + "php": ">=5.3.0", "ext-soap": "*", "ext-curl": "*", "ass/xmlsecurity": "~1.0", + "symfony/framework-bundle": "~2.6", + "symfony/twig-bundle": "~2.6", "zendframework/zend-mime": "2.1.*" }, "replace": { @@ -43,29 +42,15 @@ "require-dev": { "ext-mcrypt": "*", "mikey179/vfsStream": "~1.0", - "phpunit/phpunit": "~4.0", - "phpstan/phpstan": "dev-master", - "phing/phing": "^2.16", - "jakub-onderka/php-var-dump-check": "^0.2.0", - "squizlabs/php_codesniffer": "^3.0" + "symfony/filesystem": "~2.3", + "symfony/process": "~2.3" }, "autoload": { "psr-0": { "BeSimple\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "": "tests/" - } - }, "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "0.3-dev" } - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/tuscanicz/phpstan.git" - } - ] + } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 3b9c1c9..0000000 --- a/composer.lock +++ /dev/null @@ -1,2427 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "hash": "635c398afa1d5c217b5b8679b348ddc7", - "content-hash": "08f419455dd969e9145b8adfc84a03e9", - "packages": [ - { - "name": "ass/xmlsecurity", - "version": "v1.1.1", - "source": { - "type": "git", - "url": "https://github.com/aschamberger/XmlSecurity.git", - "reference": "c8976519ebbf6e4d953cd781d09df44b7f65fbb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/aschamberger/XmlSecurity/zipball/c8976519ebbf6e4d953cd781d09df44b7f65fbb8", - "reference": "c8976519ebbf6e4d953cd781d09df44b7f65fbb8", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "lib-openssl": ">=0.9.0", - "php": ">=5.3.0" - }, - "require-dev": { - "satooshi/php-coveralls": "dev-master" - }, - "suggest": { - "ext-mcrypt": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "ass\\XmlSecurity": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Robert Richards", - "email": "rrichards@cdatazone.org" - }, - { - "name": "Andreas Schamberger", - "email": "mail@andreass.net" - } - ], - "description": "The XmlSecurity library is written in PHP for working with XML Encryption and Signatures", - "homepage": "https://github.com/aschamberger/XmlSecurity", - "keywords": [ - "encryption", - "security", - "signature", - "xml" - ], - "time": "2015-05-31 10:10:35" - }, - { - "name": "zendframework/zend-mime", - "version": "2.1.6", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-mime.git", - "reference": "066d6eecff586a7fb10e8907c032beaf1a9d6104" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-mime/zipball/066d6eecff586a7fb10e8907c032beaf1a9d6104", - "reference": "066d6eecff586a7fb10e8907c032beaf1a9d6104", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "zendframework/zend-stdlib": "self.version" - }, - "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", - "zendframework/zend-mail": "self.version" - }, - "suggest": { - "zendframework/zend-mail": "Zend\\Mail component" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev", - "dev-develop": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Mime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "homepage": "https://github.com/zendframework/zend-mime", - "keywords": [ - "mime", - "zf2" - ], - "time": "2013-04-17 13:32:54" - }, - { - "name": "zendframework/zend-stdlib", - "version": "2.1.6", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "0027339961ad3d49f91ee092e23f7269c18cb470" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/0027339961ad3d49f91ee092e23f7269c18cb470", - "reference": "0027339961ad3d49f91ee092e23f7269c18cb470", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "dev-master", - "zendframework/zend-eventmanager": "self.version", - "zendframework/zend-filter": "self.version", - "zendframework/zend-serializer": "self.version", - "zendframework/zend-servicemanager": "self.version" - }, - "suggest": { - "pecl-weakref": "Implementation of weak references for Stdlib\\CallbackHandler", - "zendframework/zend-eventmanager": "To support aggregate hydrator usage", - "zendframework/zend-filter": "To support naming strategy hydrator usage", - "zendframework/zend-serializer": "Zend\\Serializer component", - "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev", - "dev-develop": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "homepage": "https://github.com/zendframework/zend-stdlib", - "keywords": [ - "stdlib", - "zf2" - ], - "time": "2013-04-17 13:32:54" - } - ], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14 21:17:01" - }, - { - "name": "jakub-onderka/php-var-dump-check", - "version": "v0.2", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Var-Dump-Check.git", - "reference": "c00c52f1503c537a3da394520717a7331eb290a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Var-Dump-Check/zipball/c00c52f1503c537a3da394520717a7331eb290a1", - "reference": "c00c52f1503c537a3da394520717a7331eb290a1", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "jakub-onderka/php-parallel-lint": "~0.8", - "phpunit/phpunit": "~4.5" - }, - "suggest": { - "jakub-onderka/php-console-highlighter": "For colored console output" - }, - "bin": [ - "var-dump-check" - ], - "type": "library", - "autoload": { - "psr-0": { - "JakubOnderka\\PhpVarDumpCheck": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com" - } - ], - "description": "Find forgotten variables dump in PHP source code.", - "time": "2015-03-13 12:02:23" - }, - { - "name": "mikey179/vfsStream", - "version": "v1.6.4", - "source": { - "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", - "reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/0247f57b2245e8ad2e689d7cee754b45fbabd592", - "reference": "0247f57b2245e8ad2e689d7cee754b45fbabd592", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Frank Kleine", - "homepage": "http://frankkleine.de/", - "role": "Developer" - } - ], - "description": "Virtual file system to mock the real file system in unit tests.", - "homepage": "http://vfs.bovigo.org/", - "time": "2016-07-18 14:02:57" - }, - { - "name": "nette/bootstrap", - "version": "v2.4.3", - "source": { - "type": "git", - "url": "https://github.com/nette/bootstrap.git", - "reference": "2c27747f5aff2e436ebf542e0ea566bea1db2d53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/bootstrap/zipball/2c27747f5aff2e436ebf542e0ea566bea1db2d53", - "reference": "2c27747f5aff2e436ebf542e0ea566bea1db2d53", - "shasum": "" - }, - "require": { - "nette/di": "~2.4.7", - "nette/utils": "~2.4", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "latte/latte": "~2.2", - "nette/application": "~2.3", - "nette/caching": "~2.3", - "nette/database": "~2.3", - "nette/forms": "~2.3", - "nette/http": "~2.4.0", - "nette/mail": "~2.3", - "nette/robot-loader": "^2.4.2 || ^3.0", - "nette/safe-stream": "~2.2", - "nette/security": "~2.3", - "nette/tester": "~2.0", - "tracy/tracy": "^2.4.1" - }, - "suggest": { - "nette/robot-loader": "to use Configurator::createRobotLoader()", - "tracy/tracy": "to use Configurator::enableTracy()" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette Bootstrap", - "homepage": "https://nette.org", - "time": "2017-02-19 22:15:02" - }, - { - "name": "nette/caching", - "version": "v2.5.3", - "source": { - "type": "git", - "url": "https://github.com/nette/caching.git", - "reference": "2436e530484a346d0a246733519ceaa40b943bd6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/caching/zipball/2436e530484a346d0a246733519ceaa40b943bd6", - "reference": "2436e530484a346d0a246733519ceaa40b943bd6", - "shasum": "" - }, - "require": { - "nette/finder": "^2.2 || ~3.0.0", - "nette/utils": "^2.4 || ~3.0.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "latte/latte": "^2.4", - "nette/di": "^2.4 || ~3.0.0", - "nette/tester": "^2.0", - "tracy/tracy": "^2.4" - }, - "suggest": { - "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette Caching Component", - "homepage": "https://nette.org", - "time": "2017-01-29 20:40:55" - }, - { - "name": "nette/di", - "version": "v2.4.8", - "source": { - "type": "git", - "url": "https://github.com/nette/di.git", - "reference": "b3fe8551162279216e251e49b406e55cd2d255d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/di/zipball/b3fe8551162279216e251e49b406e55cd2d255d5", - "reference": "b3fe8551162279216e251e49b406e55cd2d255d5", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/neon": "^2.3.3 || ~3.0.0", - "nette/php-generator": "^2.6.1 || ~3.0.0", - "nette/utils": "^2.4.3 || ~3.0.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/bootstrap": "<2.4", - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette Dependency Injection Component", - "homepage": "https://nette.org", - "time": "2017-03-14 17:16:14" - }, - { - "name": "nette/finder", - "version": "v2.4.0", - "source": { - "type": "git", - "url": "https://github.com/nette/finder.git", - "reference": "5cabd5fe89f9903715359a403b820c7f94f9bb5e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/finder/zipball/5cabd5fe89f9903715359a403b820c7f94f9bb5e", - "reference": "5cabd5fe89f9903715359a403b820c7f94f9bb5e", - "shasum": "" - }, - "require": { - "nette/utils": "~2.4", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette Finder: Files Searching", - "homepage": "https://nette.org", - "time": "2016-05-17 15:49:06" - }, - { - "name": "nette/neon", - "version": "v2.4.1", - "source": { - "type": "git", - "url": "https://github.com/nette/neon.git", - "reference": "1a78ff64b1e161ebccc03bdf9366450a69365f5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/1a78ff64b1e161ebccc03bdf9366450a69365f5b", - "reference": "1a78ff64b1e161ebccc03bdf9366450a69365f5b", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "ext-json": "*", - "php": ">=5.6.0" - }, - "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette NEON: parser & generator for Nette Object Notation", - "homepage": "http://ne-on.org", - "time": "2017-01-13 08:00:19" - }, - { - "name": "nette/php-generator", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/php-generator.git", - "reference": "8605fd18857a4beef4aa0afc19eb9a7f876237e8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/8605fd18857a4beef4aa0afc19eb9a7f876237e8", - "reference": "8605fd18857a4beef4aa0afc19eb9a7f876237e8", - "shasum": "" - }, - "require": { - "nette/utils": "^2.4.2 || ~3.0.0", - "php": ">=7.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🐘 Generates neat PHP code for you. Supports new PHP 7.1 features.", - "homepage": "https://nette.org", - "keywords": [ - "code", - "nette", - "php", - "scaffolding" - ], - "time": "2017-03-18 15:20:10" - }, - { - "name": "nette/robot-loader", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/robot-loader.git", - "reference": "459fc6bf08f0fd7f6889897e3acdff523dbf1159" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/459fc6bf08f0fd7f6889897e3acdff523dbf1159", - "reference": "459fc6bf08f0fd7f6889897e3acdff523dbf1159", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/finder": "^2.3 || ^3.0", - "nette/utils": "^2.4 || ^3.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🍀 RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", - "homepage": "https://nette.org", - "keywords": [ - "autoload", - "class", - "interface", - "nette", - "trait" - ], - "time": "2017-02-10 13:44:22" - }, - { - "name": "nette/utils", - "version": "v2.4.6", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "266160aec0d99516e0ea510de1dfa24a0dc1e76e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/266160aec0d99516e0ea510de1dfa24a0dc1e76e", - "reference": "266160aec0d99516e0ea510de1dfa24a0dc1e76e", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize() and toAscii()", - "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "Nette Utility Classes", - "homepage": "https://nette.org", - "time": "2017-04-26 10:04:49" - }, - { - "name": "nikic/php-parser", - "version": "v3.0.5", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2b9e2f71b722f7c53918ab0c25f7646c2013f17d", - "reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "time": "2017-03-05 18:23:57" - }, - { - "name": "phing/phing", - "version": "2.16.0", - "source": { - "type": "git", - "url": "https://github.com/phingofficial/phing.git", - "reference": "151a0f4d8cebf7711eccc62dde3f09bc36a00d7b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phingofficial/phing/zipball/151a0f4d8cebf7711eccc62dde3f09bc36a00d7b", - "reference": "151a0f4d8cebf7711eccc62dde3f09bc36a00d7b", - "shasum": "" - }, - "require": { - "php": ">=5.2.0", - "symfony/yaml": "^3.1" - }, - "require-dev": { - "ext-pdo_sqlite": "*", - "mikey179/vfsstream": "^1.6", - "pdepend/pdepend": "2.x", - "pear/archive_tar": "1.4.x", - "pear/http_request2": "dev-trunk", - "pear/net_growl": "dev-trunk", - "pear/pear-core-minimal": "1.10.1", - "pear/versioncontrol_git": "@dev", - "pear/versioncontrol_svn": "~0.5", - "phpdocumentor/phpdocumentor": "2.x", - "phploc/phploc": "~2.0.6", - "phpmd/phpmd": "~2.2", - "phpunit/phpunit": ">=3.7", - "sebastian/git": "~1.0", - "sebastian/phpcpd": "2.x", - "siad007/versioncontrol_hg": "^1.0", - "simpletest/simpletest": "^1.1", - "squizlabs/php_codesniffer": "~2.2" - }, - "suggest": { - "pdepend/pdepend": "PHP version of JDepend", - "pear/archive_tar": "Tar file management class", - "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository", - "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system", - "phpdocumentor/phpdocumentor": "Documentation Generator for PHP", - "phploc/phploc": "A tool for quickly measuring the size of a PHP project", - "phpmd/phpmd": "PHP version of PMD tool", - "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information", - "phpunit/phpunit": "The PHP Unit Testing Framework", - "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code", - "siad007/versioncontrol_hg": "A library for interfacing with Mercurial repositories.", - "tedivm/jshrink": "Javascript Minifier built in PHP" - }, - "bin": [ - "bin/phing" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.16.x-dev" - } - }, - "autoload": { - "classmap": [ - "classes/phing/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "classes" - ], - "license": [ - "LGPL-3.0" - ], - "authors": [ - { - "name": "Michiel Rook", - "email": "mrook@php.net" - }, - { - "name": "Phing Community", - "homepage": "https://www.phing.info/trac/wiki/Development/Contributors" - } - ], - "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", - "homepage": "https://www.phing.info/", - "keywords": [ - "build", - "phing", - "task", - "tool" - ], - "time": "2016-12-22 20:16:33" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2015-12-27 11:43:31" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "shasum": "" - }, - "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2016-11-25 06:54:22" - }, - { - "name": "phpspec/prophecy", - "version": "v1.6.2", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.0", - "phpunit/phpunit": "^4.8 || ^5.6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2016-11-21 14:58:47" - }, - { - "name": "phpstan/phpstan", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/tuscanicz/phpstan.git", - "reference": "11d705360de768c8f0f9431288228ecd85ac14dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tuscanicz/phpstan/zipball/11d705360de768c8f0f9431288228ecd85ac14dd", - "reference": "11d705360de768c8f0f9431288228ecd85ac14dd", - "shasum": "" - }, - "require": { - "nette/bootstrap": "^2.4 || ^3.0", - "nette/caching": "^2.4 || ^3.0", - "nette/di": "^2.4 || ^3.0", - "nette/robot-loader": "^2.4.2 || ^3.0", - "nette/utils": "^2.4 || ^3.0", - "nikic/php-parser": "^2.1 || ^3.0.2", - "php": "~7.0", - "symfony/console": "~2.7 || ~3.0", - "symfony/finder": "~2.7 || ~3.0" - }, - "require-dev": { - "consistence/coding-standard": "~0.13.0", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "phing/phing": "^2.16.0", - "phpunit/phpunit": "^6.0.7", - "satooshi/php-coveralls": "^1.0", - "slevomat/coding-standard": "^2.0" - }, - "bin": [ - "bin/phpstan" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.7-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "autoload-dev": { - "classmap": [ - "tests/PHPStan", - "tests/TestCase.php" - ] - }, - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "support": { - "source": "https://github.com/tuscanicz/phpstan/tree/master" - }, - "time": "2017-06-07 13:05:16" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06 15:47:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2016-10-03 07:40:28" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21 13:50:34" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4|~5" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2016-05-12 18:03:57" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2016-11-15 14:06:22" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.34", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "7eb45205d27edd94bd2b3614085ea158bd1e2bca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7eb45205d27edd94bd2b3614085ea158bd1e2bca", - "reference": "7eb45205d27edd94bd2b3614085ea158bd1e2bca", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-01-26 16:15:36" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02 06:51:40" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10 12:19:37" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29 09:50:25" - }, - { - "name": "sebastian/diff", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2015-12-08 07:14:41" - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-08-18 05:49:44" - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-06-17 09:04:28" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12 03:26:01" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b95ff2c3b122a3ee4b57d149a57d2afce65522c3", - "reference": "b95ff2c3b122a3ee4b57d149a57d2afce65522c3", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2017-05-04 00:33:04" - }, - { - "name": "symfony/console", - "version": "v3.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "70d2a29b2911cbdc91a7e268046c395278238b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/70d2a29b2911cbdc91a7e268046c395278238b2e", - "reference": "70d2a29b2911cbdc91a7e268046c395278238b2e", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/debug": "~2.8|~3.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3", - "symfony/dependency-injection": "~3.3", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/filesystem": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2017-06-02 19:24:58" - }, - { - "name": "symfony/debug", - "version": "v3.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "e9c50482841ef696e8fa1470d950a79c8921f45d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/e9c50482841ef696e8fa1470d950a79c8921f45d", - "reference": "e9c50482841ef696e8fa1470d950a79c8921f45d", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2017-06-01 21:01:25" - }, - { - "name": "symfony/finder", - "version": "v3.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2017-06-01 21:01:25" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2016-11-14 01:06:16" - }, - { - "name": "symfony/yaml", - "version": "v3.2.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "50eadbd7926e31842893c957eca362b21592a97d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/50eadbd7926e31842893c957eca362b21592a97d", - "reference": "50eadbd7926e31842893c957eca362b21592a97d", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/console": "~2.8|~3.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2017-01-03 13:51:32" - }, - { - "name": "webmozart/assert", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2016-11-23 20:04:58" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.3.0|>=7.0", - "ext-soap": "*", - "ext-curl": "*" - }, - "platform-dev": { - "ext-mcrypt": "*" - } -} diff --git a/phing b/phing deleted file mode 100755 index 6e364ef..0000000 --- a/phing +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env php - + bootstrap="vendor/autoload.php" +> + - - tests + + ./src/BeSimple/*/Tests/ - src + ./src/BeSimple/ - src/BeSimple/SoapBundle - src/BeSimple/SoapCommon/Type + ./src/BeSimple/*/Tests + ./src/BeSimple/*/Resources - - - - - diff --git a/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php b/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php index 293b7e6..29d08c3 100644 --- a/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php +++ b/src/BeSimple/SoapBundle/Controller/SoapWebServiceController.php @@ -16,8 +16,7 @@ use BeSimple\SoapBundle\Handler\ExceptionHandler; use BeSimple\SoapBundle\Soap\SoapRequest; use BeSimple\SoapBundle\Soap\SoapResponse; use BeSimple\SoapServer\SoapServerBuilder; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\FlattenException; @@ -29,13 +28,8 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; * @author Christian Kerl * @author Francis Besset */ -class SoapWebServiceController implements ContainerAwareInterface +class SoapWebServiceController extends ContainerAware { - /** - * @var ContainerInterface - */ - private $container; - /** * @var \SoapServer */ @@ -61,14 +55,6 @@ class SoapWebServiceController implements ContainerAwareInterface */ private $headers = array(); - /** - * {@inheritDoc} - */ - public function setContainer(ContainerInterface $container = null) - { - $this->container = $container; - } - /** * @return \BeSimple\SoapBundle\Soap\SoapResponse */ @@ -78,7 +64,7 @@ class SoapWebServiceController implements ContainerAwareInterface $this->serviceBinder = $webServiceContext->getServiceBinder(); - $this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request_stack')->getCurrentRequest()); + $this->soapRequest = SoapRequest::createFromHttpRequest($this->container->get('request')); $this->soapServer = $webServiceContext ->getServerBuilder() ->withSoapVersion11() diff --git a/src/BeSimple/SoapBundle/Resources/config/routing/webservicecontroller.xml b/src/BeSimple/SoapBundle/Resources/config/routing/webservicecontroller.xml index cd370b9..98e80e4 100644 --- a/src/BeSimple/SoapBundle/Resources/config/routing/webservicecontroller.xml +++ b/src/BeSimple/SoapBundle/Resources/config/routing/webservicecontroller.xml @@ -4,13 +4,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - + BeSimpleSoapBundle:SoapWebService:Call xml POST - + BeSimpleSoapBundle:SoapWebService:Definition xml GET diff --git a/src/BeSimple/SoapBundle/WebServiceContext.php b/src/BeSimple/SoapBundle/WebServiceContext.php index 61c7698..dce81a7 100644 --- a/src/BeSimple/SoapBundle/WebServiceContext.php +++ b/src/BeSimple/SoapBundle/WebServiceContext.php @@ -44,7 +44,7 @@ class WebServiceContext if (null === $this->serviceDefinition) { $cache = new ConfigCache(sprintf('%s/%s.definition.php', $this->options['cache_dir'], $this->options['name']), $this->options['debug']); if ($cache->isFresh()) { - $this->serviceDefinition = include $cache->getPath(); + $this->serviceDefinition = include (string) $cache; } else { if (!$this->loader->supports($this->options['resource'], $this->options['resource_type'])) { throw new \LogicException(sprintf('Cannot load "%s" (%s)', $this->options['resource'], $this->options['resource_type'])); diff --git a/src/BeSimple/SoapClient/Curl.php b/src/BeSimple/SoapClient/Curl.php new file mode 100644 index 0000000..e777fc8 --- /dev/null +++ b/src/BeSimple/SoapClient/Curl.php @@ -0,0 +1,336 @@ + + * (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\SoapClient; + +/** + * cURL wrapper class for doing HTTP requests that uses the soap class options. + * + * @author Andreas Schamberger + */ +class Curl +{ + /** + * HTTP User Agent. + * + * @var string + */ + const USER_AGENT = 'PHP-SOAP/\BeSimple\SoapClient'; + + /** + * Curl resource. + * + * @var resource + */ + private $ch; + + /** + * Maximum number of location headers to follow. + * + * @var int + */ + private $followLocationMaxRedirects; + + /** + * Request response data. + * + * @var string + */ + private $response; + + /** + * Constructor. + * + * @param array $options Options array from SoapClient constructor + * @param int $followLocationMaxRedirects Redirection limit for Location header + */ + public function __construct(array $options = array(), $followLocationMaxRedirects = 10) + { + // set the default HTTP user agent + if (!isset($options['user_agent'])) { + $options['user_agent'] = self::USER_AGENT; + } + $this->followLocationMaxRedirects = $followLocationMaxRedirects; + + // make http request + $this->ch = curl_init(); + $curlOptions = array( + CURLOPT_ENCODING => '', + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_FAILONERROR => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_HEADER => true, + CURLOPT_USERAGENT => $options['user_agent'], + CURLINFO_HEADER_OUT => true, + ); + curl_setopt_array($this->ch, $curlOptions); + if (isset($options['compression']) && !($options['compression'] & SOAP_COMPRESSION_ACCEPT)) { + curl_setopt($this->ch, CURLOPT_ENCODING, 'identity'); + } + if (isset($options['connection_timeout'])) { + curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $options['connection_timeout']); + } + + if (isset($options['proxy_host'])) { + if (false !== $options['proxy_host']) { + $proxyHost = $options['proxy_host'].(isset($options['proxy_port']) ? $options['proxy_port'] : 8080); + } else { + $proxyHost = false; + } + + curl_setopt($this->ch, CURLOPT_PROXY, $proxyHost); + + if (false !== $proxyHost && isset($options['proxy_login'])) { + curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $options['proxy_login'].':'.$options['proxy_password']); + + if (isset($options['proxy_auth'])) { + curl_setopt($this->ch, CURLOPT_PROXYAUTH, $options['proxy_auth']); + } + } + } + + if (isset($options['login'])) { + curl_setopt($this->ch, CURLOPT_HTTPAUTH, isset($options['extra_options']['http_auth']) ? $options['extra_options']['http_auth'] : CURLAUTH_ANY); + curl_setopt($this->ch, CURLOPT_USERPWD, $options['login'].':'.$options['password']); + } + if (isset($options['local_cert'])) { + curl_setopt($this->ch, CURLOPT_SSLCERT, $options['local_cert']); + curl_setopt($this->ch, CURLOPT_SSLCERTPASSWD, $options['passphrase']); + } + if (isset($options['ca_info'])) { + curl_setopt($this->ch, CURLOPT_CAINFO, $options['ca_info']); + } + if (isset($options['ca_path'])) { + curl_setopt($this->ch, CURLOPT_CAPATH, $options['ca_path']); + } + } + + /** + * Destructor. + */ + public function __destruct() + { + curl_close($this->ch); + } + + /** + * Execute HTTP request. + * Returns true if request was successfull. + * + * @param string $location HTTP location + * @param string $request Request body + * @param array $requestHeaders Request header strings + * @param array $requestOptions An array of request options + * + * @return bool + */ + public function exec($location, $request = null, $requestHeaders = array(), $requestOptions = array()) + { + curl_setopt($this->ch, CURLOPT_URL, $location); + + if (!is_null($request)) { + curl_setopt($this->ch, CURLOPT_POST, true); + curl_setopt($this->ch, CURLOPT_POSTFIELDS, $request); + } + + if (count($requestHeaders) > 0) { + curl_setopt($this->ch, CURLOPT_HTTPHEADER, $requestHeaders); + } + + if (count($requestOptions) > 0) { + curl_setopt_array($this->ch, $requestOptions); + } + + $this->response = $this->execManualRedirect(); + + return ($this->response === false) ? false : true; + } + + /** + * Custom curl_exec wrapper that allows to follow redirects when specific + * http response code is set. SOAP only allows 307. + * + * @param int $redirects Current redirection count + * + * @return mixed + */ + private function execManualRedirect($redirects = 0) + { + if ($redirects > $this->followLocationMaxRedirects) { + + // TODO Redirection limit reached, aborting + return false; + } + curl_setopt($this->ch, CURLOPT_HEADER, true); + curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($this->ch); + $httpResponseCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE); + if ($httpResponseCode == 307) { + $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE); + $header = substr($response, 0, $headerSize); + $matches = array(); + preg_match('/Location:(.*?)\n/', $header, $matches); + $url = trim(array_pop($matches)); + // @parse_url to suppress E_WARNING for invalid urls + if (($url = @parse_url($url)) !== false) { + $lastUrl = parse_url(curl_getinfo($this->ch, CURLINFO_EFFECTIVE_URL)); + if (!isset($url['scheme'])) { + $url['scheme'] = $lastUrl['scheme']; + } + if (!isset($url['host'])) { + $url['host'] = $lastUrl['host']; + } + if (!isset($url['path'])) { + $url['path'] = $lastUrl['path']; + } + $newUrl = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query'] ? '?' . $url['query'] : ''); + curl_setopt($this->ch, CURLOPT_URL, $newUrl); + + return $this->execManualRedirect($redirects++); + } + } + + return $response; + } + + /** + * Error code mapping from cURL error codes to PHP ext/soap error messages + * (where applicable) + * + * http://curl.haxx.se/libcurl/c/libcurl-errors.html + * + * @return array(int=>string) + */ + protected function getErrorCodeMapping() + { + return array( + 1 => 'Unknown protocol. Only http and https are allowed.', //CURLE_UNSUPPORTED_PROTOCOL + 3 => 'Unable to parse URL', //CURLE_URL_MALFORMAT + 5 => 'Could not connect to host', //CURLE_COULDNT_RESOLVE_PROXY + 6 => 'Could not connect to host', //CURLE_COULDNT_RESOLVE_HOST + 7 => 'Could not connect to host', //CURLE_COULDNT_CONNECT + 9 => 'Could not connect to host', //CURLE_REMOTE_ACCESS_DENIED + 28 => 'Failed Sending HTTP SOAP request', //CURLE_OPERATION_TIMEDOUT + 35 => 'Could not connect to host', //CURLE_SSL_CONNECT_ERROR + 41 => 'Can\'t uncompress compressed response', //CURLE_FUNCTION_NOT_FOUND + 51 => 'Could not connect to host', //CURLE_PEER_FAILED_VERIFICATION + 52 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_GOT_NOTHING + 53 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_NOTFOUND + 54 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_SETFAILED + 55 => 'Failed Sending HTTP SOAP request', //CURLE_SEND_ERROR + 56 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_RECV_ERROR + 58 => 'Could not connect to host', //CURLE_SSL_CERTPROBLEM + 59 => 'Could not connect to host', //CURLE_SSL_CIPHER + 60 => 'Could not connect to host', //CURLE_SSL_CACERT + 61 => 'Unknown Content-Encoding', //CURLE_BAD_CONTENT_ENCODING + 65 => 'Failed Sending HTTP SOAP request', //CURLE_SEND_FAIL_REWIND + 66 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_INITFAILED + 67 => 'Could not connect to host', //CURLE_LOGIN_DENIED + 77 => 'Could not connect to host', //CURLE_SSL_CACERT_BADFILE + 80 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_SSL_SHUTDOWN_FAILED + ); + } + + /** + * Gets the curl error message. + * + * @return string + */ + public function getErrorMessage() + { + $errorCodeMapping = $this->getErrorCodeMapping(); + $errorNumber = curl_errno($this->ch); + if (isset($errorCodeMapping[$errorNumber])) { + + return $errorCodeMapping[$errorNumber]; + } + + return curl_error($this->ch); + } + + /** + * Gets the request headers as a string. + * + * @return string + */ + public function getRequestHeaders() + { + return curl_getinfo($this->ch, CURLINFO_HEADER_OUT); + } + + /** + * Gets the whole response (including headers) as a string. + * + * @return string + */ + public function getResponse() + { + return $this->response; + } + + /** + * Gets the response body as a string. + * + * @return string + */ + public function getResponseBody() + { + $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE); + + return substr($this->response, $headerSize); + } + + /** + * Gets the response content type. + * + * @return string + */ + public function getResponseContentType() + { + return curl_getinfo($this->ch, CURLINFO_CONTENT_TYPE); + } + + /** + * Gets the response headers as a string. + * + * @return string + */ + public function getResponseHeaders() + { + $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE); + + return substr($this->response, 0, $headerSize); + } + + /** + * Gets the response http status code. + * + * @return string + */ + public function getResponseStatusCode() + { + return curl_getinfo($this->ch, CURLINFO_HTTP_CODE); + } + + /** + * Gets the response http status message. + * + * @return string + */ + public function getResponseStatusMessage() + { + preg_match('/HTTP\/(1\.[0-1]+) ([0-9]{3}) (.*)/', $this->response, $matches); + + return trim(array_pop($matches)); + } +} diff --git a/src/BeSimple/SoapClient/Curl/Curl.php b/src/BeSimple/SoapClient/Curl/Curl.php deleted file mode 100644 index 702df40..0000000 --- a/src/BeSimple/SoapClient/Curl/Curl.php +++ /dev/null @@ -1,251 +0,0 @@ -curlSession = $this->acquireNewCurlSession($options); - $this->options = $options; - } - - public function __destruct() - { - $this->closeCurlSession($this->curlSession); - } - - /** - * @param string $location HTTP location - * @param string $request Request body - * @param array $requestHeaders Request header strings - * @return CurlResponse - */ - public function executeCurlWithCachedSession($location, $request = null, $requestHeaders = []) - { - return $this->executeCurlSession($this->curlSession, $this->options, $location, $request, $requestHeaders); - } - - /** - * @param CurlOptions $options - * @param string $location HTTP location - * @param string $request Request body - * @param array $requestHeaders Request header strings - * @return CurlResponse - */ - public function executeCurl(CurlOptions $options, $location, $request = null, $requestHeaders = []) - { - $curlSession = $this->acquireNewCurlSession($options); - $curlResponse = $this->executeCurlSession($curlSession, $options, $location, $request, $requestHeaders); - $this->closeCurlSession($curlSession); - - return $curlResponse; - } - - private function acquireNewCurlSession(CurlOptions $options) - { - $curlSession = curl_init(); - curl_setopt_array($curlSession, [ - CURLOPT_ENCODING => '', - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_FAILONERROR => false, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, - CURLOPT_HEADER => true, - CURLOPT_USERAGENT => $options->getUserAgent(), - CURLINFO_HEADER_OUT => true, - CURLOPT_CONNECTTIMEOUT => $options->getConnectionTimeout() - ]); - - return $curlSession; - } - - private function closeCurlSession($curlSession) - { - curl_close($curlSession); - } - - /** - * @param mixed $curlSession Result of curl_init() handle - * @param CurlOptions $options - * @param string $location HTTP location - * @param string $request Request body - * @param array $requestHeaders Request header strings - * @return CurlResponse - */ - private function executeCurlSession($curlSession, CurlOptions $options, $location, $request = null, $requestHeaders = []) - { - curl_setopt($curlSession, CURLOPT_URL, $location); - curl_setopt($curlSession, CURLOPT_HEADER, true); - curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true); - if ($request !== null) { - curl_setopt($curlSession, CURLOPT_POST, true); - curl_setopt($curlSession, CURLOPT_POSTFIELDS, $request); - } else { - curl_setopt($curlSession, CURLOPT_POST, false); - } - if (count($requestHeaders) > 0) { - curl_setopt($curlSession, CURLOPT_HTTPHEADER, $requestHeaders); - } - if (!$options->getSoapCompression() & SOAP_COMPRESSION_ACCEPT) { - curl_setopt($curlSession, CURLOPT_ENCODING, 'identity'); - } - if ($options->hasProxy()) { - $proxyHost = $options->getProxy()->getHost() . $options->getProxy()->getPort(); - curl_setopt($curlSession, CURLOPT_PROXY, $proxyHost); - if ($options->getProxy()->hasCredentials()) { - curl_setopt($curlSession, CURLOPT_PROXYUSERPWD, $options->getProxy()->getLogin() . ':' . $options->getProxy()->getPassword()); - if ($options->getProxy()->hasAuthenticationType()) { - curl_setopt($curlSession, CURLOPT_PROXYAUTH, $options->getProxy()->getAuthenticationType()); - } - } - } - if ($options->hasHttpAuthentication()) { - if ($options->hasHttpAuthenticationBasic()) { - /** @var HttpAuthenticationBasicOptions $httpAuthenticationBasic */ - $httpAuthenticationBasic = $options->getHttpAuthentication(); - curl_setopt($curlSession, CURLOPT_HTTPAUTH, $httpAuthenticationBasic->getAuthenticationType()); - curl_setopt($curlSession, CURLOPT_USERPWD, $httpAuthenticationBasic->getUsername() . ':' . $httpAuthenticationBasic->getPassword()); - } elseif ($options->hasHttpAuthenticationDigest()) { - /** @var HttpAuthenticationDigestOptions $httpAuthenticationDigest */ - $httpAuthenticationDigest = $options->getHttpAuthentication(); - curl_setopt($curlSession, CURLOPT_HTTPAUTH, $httpAuthenticationDigest->getAuthenticationType()); - } else { - throw new Exception('Unresolved authentication type: '.get_class($options->getHttpAuthentication())); - } - } - if ($options->hasSslCertificateOptions()) { - $sslCertificateOptions = $options->getSslCertificateOptions(); - curl_setopt($curlSession, CURLOPT_SSLCERT, $sslCertificateOptions->getCertificateLocalPath()); - if ($sslCertificateOptions->hasCertificatePassPhrase()) { - curl_setopt($curlSession, CURLOPT_SSLCERTPASSWD, $sslCertificateOptions->getCertificatePassPhrase()); - } - if ($sslCertificateOptions->hasCertificateAuthorityInfo()) { - curl_setopt($curlSession, CURLOPT_CAINFO, $sslCertificateOptions->getCertificateAuthorityInfo()); - } - if ($sslCertificateOptions->hasCertificateAuthorityPath()) { - curl_setopt($curlSession, CURLOPT_CAPATH, $sslCertificateOptions->hasCertificateAuthorityPath()); - } - } - - if ($options->hasSslVersion()) { - curl_setopt($curlSession, CURLOPT_SSLVERSION, $options->getSslVersion()); - } - - $executeSoapCallResponse = $this->executeHttpCall($curlSession, $options); - - $httpRequestHeadersAsString = curl_getinfo($curlSession, CURLINFO_HEADER_OUT); - $headerSize = curl_getinfo($curlSession, CURLINFO_HEADER_SIZE); - $httpResponseCode = curl_getinfo($curlSession, CURLINFO_HTTP_CODE); - $httpResponseContentType = curl_getinfo($curlSession, CURLINFO_CONTENT_TYPE);; - $responseBody = substr($executeSoapCallResponse, $headerSize); - $responseHeaders = substr($executeSoapCallResponse, 0, $headerSize); - preg_match('/HTTP\/(1\.[0-1]+) ([0-9]{3}) (.*)/', $executeSoapCallResponse, $httpResponseMessages); - $httpResponseMessage = trim(array_pop($httpResponseMessages)); - $curlErrorMessage = sprintf( - 'Curl error "%s" with message: %s occurred while connecting to %s with HTTP response code %s', - curl_errno($curlSession), - curl_error($curlSession), - $location, - $httpResponseCode - ); - - if (!is_int($httpResponseCode) || $httpResponseCode >= 400 || $httpResponseCode === 0) { - - return new CurlResponse( - $this->normalizeStringOrFalse($httpRequestHeadersAsString), - $httpResponseCode, - $httpResponseMessage, - $httpResponseContentType, - self::CURL_FAILED, - $this->normalizeStringOrFalse($responseHeaders), - $this->normalizeStringOrFalse($responseBody), - $curlErrorMessage - ); - } - - return new CurlResponse( - $this->normalizeStringOrFalse($httpRequestHeadersAsString), - $httpResponseCode, - $httpResponseMessage, - $httpResponseContentType, - self::CURL_SUCCESS, - $this->normalizeStringOrFalse($responseHeaders), - $this->normalizeStringOrFalse($responseBody) - ); - } - - /** - * Custom curl_exec wrapper that allows to follow redirects when specific - * http response code is set. SOAP only allows 307. - * - * @param mixed $curlSession Result of curl_init() handle - * @param CurlOptions $options - * @param int $executedRedirects - * @return string|null - * @throws Exception - */ - private function executeHttpCall($curlSession, CurlOptions $options, $executedRedirects = 0) - { - if ($executedRedirects > $options->getFollowLocationMaxRedirects()) { - throw new Exception('Cannot executeHttpCall - too many redirects: ' . $executedRedirects); - } - $curlExecResponse = curl_exec($curlSession); - $httpResponseCode = curl_getinfo($curlSession, CURLINFO_HTTP_CODE); - if ($httpResponseCode === 307) { - $newUrl = $this->getRedirectUrlFromResponseHeaders($curlSession, $curlExecResponse); - curl_setopt($curlSession, CURLOPT_URL, $newUrl); - - return $this->executeHttpCall($curlSession, $options, ++$executedRedirects); - } - - return $curlExecResponse; - } - - private function getRedirectUrlFromResponseHeaders($curlSession, $curlExecResponse) - { - $curlExecResponseHeaders = substr($curlExecResponse, 0, curl_getinfo($curlSession, CURLINFO_HEADER_SIZE)); - $matches = []; - preg_match('/Location:(.*?)\n/', $curlExecResponseHeaders, $matches); - $url = trim(array_pop($matches)); - - if (($url = @parse_url($url)) !== false) { - $lastUrl = parse_url(curl_getinfo($curlSession, CURLINFO_EFFECTIVE_URL)); - if (!isset($url['scheme'])) { - $url['scheme'] = $lastUrl['scheme']; - } - if (!isset($url['host'])) { - $url['host'] = $lastUrl['host']; - } - if (!isset($url['path'])) { - $url['path'] = $lastUrl['path']; - } - - return $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query'] ? '?' . $url['query'] : ''); - } - - throw new Exception('Cannot parse WSDL url redirect: ' . $url); - } - - private function normalizeStringOrFalse($string) - { - if ($string === false || $string === '') { - $string = null; - } - - return $string; - } -} diff --git a/src/BeSimple/SoapClient/Curl/CurlOptions.php b/src/BeSimple/SoapClient/Curl/CurlOptions.php deleted file mode 100644 index a3bd84f..0000000 --- a/src/BeSimple/SoapClient/Curl/CurlOptions.php +++ /dev/null @@ -1,140 +0,0 @@ -userAgent = $userAgent; - $this->followLocationMaxRedirects = $followLocationMaxRedirects; - $this->soapCompression = $soapCompression; - $this->connectionTimeout = $connectionTimeout; - $this->proxy = $proxy; - $this->httpAuthentication = $httpAuthentication; - $this->sslCertificateOptions = $sslCertificateOptions; - $this->sslVersion = $sslVersion; - } - - public function getUserAgent() - { - return $this->userAgent; - } - - public function getFollowLocationMaxRedirects() - { - return $this->followLocationMaxRedirects; - } - - public function getSoapCompression() - { - return $this->soapCompression; - } - - public function getConnectionTimeout() - { - return $this->connectionTimeout; - } - - public function getProxy() - { - return $this->proxy; - } - - public function getHttpAuthentication() - { - return $this->httpAuthentication; - } - - public function getSslCertificateOptions() - { - return $this->sslCertificateOptions; - } - - public function hasProxy() - { - return $this->proxy !== null; - } - - public function hasHttpAuthentication() - { - return $this->httpAuthentication !== null; - } - - public function hasSslCertificateOptions() - { - return $this->sslCertificateOptions !== null; - } - - public function hasHttpAuthenticationBasic() - { - if ($this->hasHttpAuthentication()) { - if ($this->getHttpAuthentication() instanceof HttpAuthenticationBasicOptions) { - - return true; - } - } - - return false; - } - - public function hasHttpAuthenticationDigest() - { - if ($this->hasHttpAuthentication()) { - if ($this->getHttpAuthentication() instanceof HttpAuthenticationDigestOptions) { - - return true; - } - } - - return false; - } - - public function hasSslVersion() - { - return $this->sslVersion !== null; - } - - public function getSslVersion() - { - return $this->sslVersion; - } -} diff --git a/src/BeSimple/SoapClient/Curl/CurlOptionsBuilder.php b/src/BeSimple/SoapClient/Curl/CurlOptionsBuilder.php deleted file mode 100644 index 093c038..0000000 --- a/src/BeSimple/SoapClient/Curl/CurlOptionsBuilder.php +++ /dev/null @@ -1,81 +0,0 @@ -getUserAgent(), - self::DEFAULT_MAX_REDIRECTS, - $soapClientOptions->getCompression(), - self::DEFAULT_CONNECTION_TIMEOUT, - $soapClientOptions->getProxy(), - self::getHttpAuthOptions($soapClientOptions), - self::getSslCertificateOptions($soapClientOptions), - $soapClientOptions->getSslVersion() - ); - } - - private static function getHttpAuthOptions(SoapClientOptions $soapClientOptions) - { - if ($soapClientOptions->hasAuthentication()) { - if ($soapClientOptions->hasAuthenticationBasic()) { - /** @var SoapServerAuthenticationBasic $basicAuthentication */ - $basicAuthentication = $soapClientOptions->getAuthentication(); - - return new HttpAuthenticationBasicOptions( - $basicAuthentication->getLogin(), - $basicAuthentication->getPassword() - ); - - } - if ($soapClientOptions->hasAuthenticationDigest()) { - - return new HttpAuthenticationDigestOptions(); - - } - - throw new Exception('Unresolved authentication type: '.get_class($soapClientOptions->getAuthentication())); - } - - return null; - } - - private static function getSslCertificateOptions(SoapClientOptions $soapClientOptions) - { - if ($soapClientOptions->hasAuthenticationDigest()) { - /** @var SoapServerAuthenticationDigest $digestAuthentication */ - $digestAuthentication = $soapClientOptions->getAuthentication(); - - return new SslCertificateOptions( - $digestAuthentication->getLocalCert(), - $digestAuthentication->getPassPhrase() - ); - } - - return null; - } -} diff --git a/src/BeSimple/SoapClient/Curl/CurlResponse.php b/src/BeSimple/SoapClient/Curl/CurlResponse.php deleted file mode 100644 index 83bfd10..0000000 --- a/src/BeSimple/SoapClient/Curl/CurlResponse.php +++ /dev/null @@ -1,90 +0,0 @@ -httpRequestHeaders = $httpRequestHeaders; - $this->httpResponseStatusCode = $httpResponseStatusCode; - $this->httpResponseStatusMessage = $httpResponseStatusMessage; - $this->httpResponseContentType = $httpResponseContentType; - $this->curlStatus = $curlStatus; - $this->curlErrorMessage = $curlErrorMessage; - $this->responseHeader = $responseHeader; - $this->responseBody = $responseBody; - } - - public function getHttpRequestHeaders() - { - return $this->httpRequestHeaders; - } - - public function getHttpResponseStatusCode() - { - return $this->httpResponseStatusCode; - } - - public function getHttpResponseStatusMessage() - { - return $this->httpResponseStatusMessage; - } - - public function getHttpResponseContentType() - { - return $this->httpResponseContentType; - } - - public function getCurlStatus() - { - return $this->curlStatus; - } - - public function curlStatusSuccess() - { - return $this->curlStatus === Curl::CURL_SUCCESS; - } - - public function curlStatusFailed() - { - return $this->curlStatus === Curl::CURL_FAILED; - } - - public function hasCurlErrorMessage() - { - return $this->curlErrorMessage !== null; - } - - public function getCurlErrorMessage() - { - return $this->curlErrorMessage; - } - - public function getResponseHeader() - { - return $this->responseHeader; - } - - public function getResponseBody() - { - return $this->responseBody; - } -} diff --git a/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationBasicOptions.php b/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationBasicOptions.php deleted file mode 100644 index 9eac23e..0000000 --- a/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationBasicOptions.php +++ /dev/null @@ -1,34 +0,0 @@ -username = $username; - $this->password = $password; - } - - public function getUsername() - { - return $this->username; - } - - public function getPassword() - { - return $this->password; - } - - public function getAuthenticationType() - { - return HttpAuthenticationInterface::AUTHENTICATION_TYPE_BASIC; - } -} diff --git a/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationDigestOptions.php b/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationDigestOptions.php deleted file mode 100644 index bdf04df..0000000 --- a/src/BeSimple/SoapClient/Curl/Http/HttpAuthenticationDigestOptions.php +++ /dev/null @@ -1,11 +0,0 @@ -certificateLocalPath = $certificateLocalPath; - $this->certificatePassPhrase = $certificatePassPhrase; - $this->certificateAuthorityInfo = $certificateAuthorityInfo; - $this->certificateAuthorityPath = $certificateAuthorityPath; - } - - public function getCertificateLocalPath() - { - return $this->certificateLocalPath; - } - - public function getCertificatePassPhrase() - { - return $this->certificatePassPhrase; - } - - public function getCertificateAuthorityInfo() - { - return $this->certificateAuthorityInfo; - } - - public function getCertificateAuthorityPath() - { - return $this->certificateAuthorityPath; - } - - public function hasCertificatePassPhrase() - { - return $this->certificatePassPhrase !== null; - } - - public function hasCertificateAuthorityInfo() - { - return $this->certificateAuthorityInfo !== null; - } - - public function hasCertificateAuthorityPath() - { - return $this->certificateAuthorityPath !== null; - } -} diff --git a/src/BeSimple/SoapClient/MimeFilter.php b/src/BeSimple/SoapClient/MimeFilter.php index d217680..0dd9905 100644 --- a/src/BeSimple/SoapClient/MimeFilter.php +++ b/src/BeSimple/SoapClient/MimeFilter.php @@ -16,10 +16,9 @@ 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\Mime\Part; use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapRequestFilter; -use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; +use BeSimple\SoapCommon\SoapResponse; use BeSimple\SoapCommon\SoapResponseFilter; /** @@ -29,61 +28,111 @@ use BeSimple\SoapCommon\SoapResponseFilter; */ class MimeFilter implements SoapRequestFilter, SoapResponseFilter { - public function filterRequest(SoapRequest $request, $attachmentType) + /** + * 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('Part_' . rand(10, 15) . '_' . uniqid() . '.' . uniqid()); + $multipart = new MimeMultiPart(); $soapPart = new MimePart($request->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); $soapVersion = $request->getVersion(); - - if ($soapVersion === SOAP_1_1 && $attachmentType & Helper::ATTACHMENTS_TYPE_MTOM) { + // 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'); - } elseif ($soapVersion === SOAP_1_2) { + } + // 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(, $contentType) = explode(': ', $headers[0]); $request->setContentType($contentType); } - - return $request; } - public function filterResponse(CommonSoapResponse $response, $attachmentType) + /** + * Modify the given response XML. + * + * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response + * + * @return void + */ + public function filterResponse(SoapResponse $response) { - $multiPartMessage = MimeParser::parseMimeMessage( - $response->getContent(), - ['Content-Type' => trim($response->getContentType())] - ); - $soapPart = $multiPartMessage->getMainPart(); - $attachments = $multiPartMessage->getAttachments(); + // array to store attachments + $attachmentsRecieved = array(); - $response->setContent($soapPart->getContent()); - $response->setContentType($soapPart->getHeader('Content-Type')); - if (count($attachments) > 0) { - $response->setAttachments($attachments); + // 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; + } } - return $response; - } - - private function sanitizePhpExceptionOnHrefs(Part $soapPart) - { - // 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 - return preg_replace('/href=(?!#)/', 'myhref=', $soapPart->getContent()); + // add attachments to response object + if (count($attachmentsRecieved) > 0) { + $response->setAttachments($attachmentsRecieved); + } } } diff --git a/src/BeSimple/SoapClient/SoapClient.php b/src/BeSimple/SoapClient/SoapClient.php index 125ea21..0fa3c7d 100644 --- a/src/BeSimple/SoapClient/SoapClient.php +++ b/src/BeSimple/SoapClient/SoapClient.php @@ -12,23 +12,10 @@ namespace BeSimple\SoapClient; -use BeSimple\SoapBundle\Soap\SoapAttachment; -use BeSimple\SoapBundle\Soap\SoapAttachmentList; -use BeSimple\SoapClient\Curl\Curl; -use BeSimple\SoapClient\Curl\CurlOptionsBuilder; -use BeSimple\SoapClient\Curl\CurlResponse; -use BeSimple\SoapClient\SoapOptions\SoapClientOptions; -use BeSimple\SoapCommon\Fault\SoapFaultEnum; -use BeSimple\SoapCommon\Fault\SoapFaultParser; -use BeSimple\SoapCommon\Fault\SoapFaultPrefixEnum; -use BeSimple\SoapCommon\Fault\SoapFaultSourceGetter; -use BeSimple\SoapCommon\Mime\PartFactory; -use BeSimple\SoapCommon\SoapKernel; -use BeSimple\SoapCommon\SoapOptions\SoapOptions; -use BeSimple\SoapCommon\SoapRequest; -use BeSimple\SoapCommon\SoapRequestFactory; -use Exception; -use SoapFault; +use BeSimple\SoapCommon\Helper; +use BeSimple\SoapCommon\Converter\MtomTypeConverter; +use BeSimple\SoapCommon\Converter\SwaTypeConverter; +use BeSimple\SoapCommon\SoapMessage; /** * Extended SoapClient that uses a a cURL wrapper for all underlying HTTP @@ -37,340 +24,360 @@ use SoapFault; * allows caching of all remote referenced items. * * @author Andreas Schamberger - * @author Petr Bechyně */ class SoapClient extends \SoapClient { - use SoapClientNativeMethodsTrait; - - /** @var SoapOptions */ - protected $soapOptions; - /** @var Curl */ - private $curl; - - public function __construct(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions) - { - $this->soapClientOptions = $soapClientOptions; - $this->soapOptions = $soapOptions; - $this->curl = new Curl( - CurlOptionsBuilder::buildForSoapClient($soapClientOptions) - ); - - try { - $wsdlPath = $this->loadWsdl( - $this->curl, - $soapOptions->getWsdlFile(), - $soapOptions->getWsdlCacheType(), - $soapClientOptions->isResolveRemoteIncludes() - ); - } catch (Exception $e) { - throw new SoapFault( - SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR, - 'Unable to load WsdlPath ('.$soapOptions->getWsdlFile().') with message: '.$e->getMessage().' in file: '.$e->getFile().' (line: '.$e->getLine().')' - ); - } - - @parent::__construct($wsdlPath, $soapClientOptions->toArray() + $soapOptions->toArray()); - } + /** + * Soap version. + * + * @var int + */ + protected $soapVersion = SOAP_1_1; /** - * @param string $functionName - * @param array $arguments - * @param array|null $options - * @param SoapAttachment[] $soapAttachments - * @param null $inputHeaders - * @param array|null $outputHeaders + * Tracing enabled? + * + * @var boolean + */ + protected $tracingEnabled = false; + + /** + * cURL instance. + * + * @var \BeSimple\SoapClient\Curl + */ + protected $curl = null; + + /** + * Last request headers. + * + * @var string + */ + private $lastRequestHeaders = ''; + + /** + * Last request. + * + * @var string + */ + private $lastRequest = ''; + + /** + * Last response headers. + * + * @var string + */ + private $lastResponseHeaders = ''; + + /** + * Last response. + * + * @var string + */ + private $lastResponse = ''; + + /** + * Soap kernel. + * + * @var \BeSimple\SoapClient\SoapKernel + */ + protected $soapKernel = null; + + /** + * Constructor. + * + * @param string $wsdl WSDL file + * @param array(string=>mixed) $options Options array + */ + public function __construct($wsdl, array $options = array()) + { + // tracing enabled: store last request/response header and body + if (isset($options['trace']) && $options['trace'] === true) { + $this->tracingEnabled = true; + } + // store SOAP version + if (isset($options['soap_version'])) { + $this->soapVersion = $options['soap_version']; + } + + $this->curl = new Curl($options); + + if (isset($options['extra_options'])) { + unset($options['extra_options']); + } + + $wsdlFile = $this->loadWsdl($wsdl, $options); + // TODO $wsdlHandler = new WsdlHandler($wsdlFile, $this->soapVersion); + $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; + // disable obsolete trace option for native SoapClient as we need to do our own tracing anyways + $options['trace'] = false; + // disable WSDL caching as we handle WSDL caching for remote URLs ourself + $options['cache_wsdl'] = WSDL_CACHE_NONE; + parent::__construct($wsdlFile, $options); + } + + + /** + * Perform HTTP request with cURL. + * + * @param SoapRequest $soapRequest SoapRequest object + * * @return SoapResponse */ - public function soapCall($functionName, array $arguments, array $soapAttachments = [], array $options = null, $inputHeaders = null, array &$outputHeaders = null) + private function __doHttpRequest(SoapRequest $soapRequest) { - $this->setSoapAttachmentsOnRequestToStorage($soapAttachments); - try { - - $soapResponseAsObject = parent::__soapCall($functionName, $arguments, $options, $inputHeaders, $outputHeaders); - $soapResponse = $this->getSoapResponseFromStorage(); - $soapResponse->setResponseObject($soapResponseAsObject); - - return $soapResponse; - - } catch (SoapFault $soapFault) { - if (SoapFaultSourceGetter::isNativeSoapFault($soapFault)) { - $soapFault = $this->decorateNativeSoapFaultWithSoapResponseTracingData($soapFault); - } - - throw $soapFault; + // HTTP headers + $soapVersion = $soapRequest->getVersion(); + $soapAction = $soapRequest->getAction(); + if (SOAP_1_1 == $soapVersion) { + $headers = array( + 'Content-Type:' . $soapRequest->getContentType(), + 'SOAPAction: "' . $soapAction . '"', + ); + } else { + $headers = array( + 'Content-Type:' . $soapRequest->getContentType() . '; action="' . $soapAction . '"', + ); } + + $location = $soapRequest->getLocation(); + $content = $soapRequest->getContent(); + + $headers = $this->filterRequestHeaders($soapRequest, $headers); + + $options = $this->filterRequestOptions($soapRequest); + + // execute HTTP request with cURL + $responseSuccessfull = $this->curl->exec( + $location, + $content, + $headers, + $options + ); + + // tracing enabled: store last request header and body + if ($this->tracingEnabled === true) { + $this->lastRequestHeaders = $this->curl->getRequestHeaders(); + $this->lastRequest = $soapRequest->getContent(); + } + // in case of an error while making the http request throw a soapFault + if ($responseSuccessfull === false) { + // get error message from curl + $faultstring = $this->curl->getErrorMessage(); + throw new \SoapFault('HTTP', $faultstring); + } + // tracing enabled: store last response header and body + if ($this->tracingEnabled === true) { + $this->lastResponseHeaders = $this->curl->getResponseHeaders(); + $this->lastResponse = $this->curl->getResponseBody(); + } + // wrap response data in SoapResponse object + $soapResponse = SoapResponse::create( + $this->curl->getResponseBody(), + $soapRequest->getLocation(), + $soapRequest->getAction(), + $soapRequest->getVersion(), + $this->curl->getResponseContentType() + ); + + return $soapResponse; } /** * Custom request method to be able to modify the SOAP messages. * $oneWay parameter is not used at the moment. * - * @param mixed $request Request object - * @param string $location Location - * @param string $action SOAP action - * @param int $version SOAP version - * @param SoapAttachment[] $soapAttachments SOAP attachments array - * - * @return SoapResponse - */ - protected function performSoapRequest($request, $location, $action, $version, array $soapAttachments = []) - { - $soapRequest = $this->createSoapRequest($location, $action, $version, $request, $soapAttachments); - - return $this->performHttpSoapRequest($soapRequest); - } - - protected function getSoapClientOptions() - { - return $this->soapClientOptions; - } - - protected function getSoapOptions() - { - return $this->soapOptions; - } - - /** - * @param string $location Location - * @param string $action SOAP action - * @param int $version SOAP version - * @param string $request SOAP request body - * @param SoapAttachment[] $soapAttachments array of SOAP attachments - * - * @return SoapRequest - */ - private function createSoapRequest($location, $action, $version, $request, array $soapAttachments = []) - { - $soapAttachmentList = new SoapAttachmentList($soapAttachments); - $soapRequest = SoapRequestFactory::create($location, $action, $version, $request); - if (count($soapAttachments) > 0) { - if ($this->soapOptions->hasAttachments() === true) { - $soapRequest->setAttachments(PartFactory::createAttachmentParts($soapAttachments)); - $soapRequest = SoapKernel::filterRequest( - $soapRequest, - $this->getAttachmentFilters(), - $this->soapOptions->getAttachmentType() - ); - } else { - throw new Exception( - 'Non SWA SoapClient cannot handle SOAP action '.$action.' with attachments: '.implode(', ', $soapAttachmentList->getSoapAttachmentIds()) - ); - } - } - - return $soapRequest; - } - - /** - * Perform HTTP request with cURL. - * - * @param SoapRequest $soapRequest SoapRequest object - * @return SoapResponse - * @throws SoapFault - */ - private function performHttpSoapRequest(SoapRequest $soapRequest) - { - $curlResponse = $this->curl->executeCurlWithCachedSession( - $soapRequest->getLocation(), - $soapRequest->getContent(), - $this->getHttpHeadersBySoapVersion($soapRequest) - ); - $soapResponseTracingData = new SoapResponseTracingData( - $curlResponse->getHttpRequestHeaders(), - $soapRequest->getContent(), - $curlResponse->getResponseHeader(), - $curlResponse->getResponseBody() - ); - - if ($curlResponse->curlStatusSuccess()) { - $soapResponse = $this->returnSoapResponseByTracing( - $soapRequest, - $curlResponse, - $soapResponseTracingData - ); - if ($this->soapOptions->hasAttachments()) { - - return SoapKernel::filterResponse( - $soapResponse, - $this->getAttachmentFilters(), - $this->soapOptions->getAttachmentType() - ); - } - - return $soapResponse; - - } - if ($curlResponse->curlStatusFailed()) { - - if ($curlResponse->getHttpResponseStatusCode() >= 500) { - $soapFault = SoapFaultParser::parseSoapFault( - $curlResponse->getResponseBody() - ); - - return $this->throwSoapFaultByTracing( - $soapFault->faultcode, - sprintf( - 'SOAP HTTP call failed: %s with Message: %s and Code: %s', - $curlResponse->getCurlErrorMessage(), - $soapFault->getMessage(), - $soapFault->faultcode - ), - $soapResponseTracingData - ); - } - - return $this->throwSoapFaultByTracing( - SoapFaultEnum::SOAP_FAULT_HTTP.'-'.$curlResponse->getHttpResponseStatusCode(), - $curlResponse->getCurlErrorMessage(), - $soapResponseTracingData - ); - } - - return $this->throwSoapFaultByTracing( - SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR, - 'Cannot process curl response with unresolved status: ' . $curlResponse->getCurlStatus(), - $soapResponseTracingData - ); - } - - /** - * @param Curl $curl - * @param string $wsdlPath - * @param int $wsdlCacheType - * @param bool $resolveRemoteIncludes + * @param string $request Request string + * @param string $location Location + * @param string $action SOAP action + * @param int $version SOAP version + * @param int $oneWay 0|1 * * @return string */ - private function loadWsdl(Curl $curl, $wsdlPath, $wsdlCacheType, $resolveRemoteIncludes = true) + public function __doRequest($request, $location, $action, $version, $oneWay = 0) { - $wsdlDownloader = new WsdlDownloader(); - try { - $loadedWsdlFilePath = $wsdlDownloader->getWsdlPath($curl, $wsdlPath, $wsdlCacheType, $resolveRemoteIncludes); - } catch (Exception $e) { - throw new SoapFault( - SoapFaultEnum::SOAP_FAULT_WSDL, - 'Unable to load WsdlPath ('.$wsdlPath.') with message: '.$e->getMessage().' in file: '.$e->getFile().' (line: '.$e->getLine().')' - ); - } + // wrap request data in SoapRequest object + $soapRequest = SoapRequest::create($request, $location, $action, $version); - return $loadedWsdlFilePath; - } + // do actual SOAP request + $soapResponse = $this->__doRequest2($soapRequest); - private function getHttpHeadersBySoapVersion(SoapRequest $soapRequest) - { - if ($soapRequest->getVersion() === SOAP_1_1) { - - return [ - 'Content-Type: ' . $soapRequest->getContentType(), - 'SOAPAction: "' . $soapRequest->getAction() . '"', - 'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'), - ]; - } - - return [ - 'Content-Type: ' . $soapRequest->getContentType() . '; action="' . $soapRequest->getAction() . '"', - 'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'), - ]; - } - - private function getAttachmentFilters() - { - $filters = []; - if ($this->soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) { - $filters[] = new MimeFilter(); - } - if ($this->soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) { - $filters[] = new XmlMimeFilter(); - } - - return $filters; - } - - private function returnSoapResponseByTracing( - SoapRequest $soapRequest, - CurlResponse $curlResponse, - SoapResponseTracingData $soapResponseTracingData, - array $soapAttachments = [] - ) { - if ($this->soapClientOptions->getTrace() === true) { - return SoapResponseFactory::createWithTracingData( - $soapRequest, - $curlResponse->getResponseBody(), - $curlResponse->getHttpResponseContentType(), - $soapResponseTracingData, - $soapAttachments - ); - } - - return SoapResponseFactory::create( - $soapRequest, - $curlResponse->getResponseBody(), - $curlResponse->getHttpResponseContentType(), - $soapAttachments - ); + // return SOAP response to ext/soap + return $soapResponse->getContent(); } /** - * @param string $soapFaultCode - * @param string $soapFaultMessage - * @param SoapResponseTracingData $soapResponseTracingData - * @throws SoapFault + * Runs the currently registered request filters on the request, performs + * the HTTP request and runs the response filters. + * + * @param SoapRequest $soapRequest SOAP request object + * + * @return SoapResponse */ - private function throwSoapFaultByTracing($soapFaultCode, $soapFaultMessage, SoapResponseTracingData $soapResponseTracingData) + protected function __doRequest2(SoapRequest $soapRequest) { - if ($this->soapClientOptions->getTrace() === true) { + // run SoapKernel on SoapRequest + $this->soapKernel->filterRequest($soapRequest); - throw new SoapFaultWithTracingData( - $soapFaultCode, - $soapFaultMessage, - $soapResponseTracingData + // perform HTTP request with cURL + $soapResponse = $this->__doHttpRequest($soapRequest); + + // run SoapKernel on SoapResponse + $this->soapKernel->filterResponse($soapResponse); + + return $soapResponse; + } + + /** + * Filters HTTP headers which will be sent + * + * @param SoapRequest $soapRequest SOAP request object + * @param array $headers An array of HTTP headers + * + * @return array + */ + protected function filterRequestHeaders(SoapRequest $soapRequest, array $headers) + { + return $headers; + } + + /** + * Adds additional cURL options for the request + * + * @param SoapRequest $soapRequest SOAP request object + * + * @return array + */ + protected function filterRequestOptions(SoapRequest $soapRequest) + { + return array(); + } + + /** + * Get last request HTTP headers. + * + * @return string + */ + public function __getLastRequestHeaders() + { + return $this->lastRequestHeaders; + } + + /** + * Get last request HTTP body. + * + * @return string + */ + public function __getLastRequest() + { + return $this->lastRequest; + } + + /** + * Get last response HTTP headers. + * + * @return string + */ + public function __getLastResponseHeaders() + { + return $this->lastResponseHeaders; + } + + /** + * Get last response HTTP body. + * + * @return string + */ + public function __getLastResponse() + { + return $this->lastResponse; + } + + /** + * Get SoapKernel instance. + * + * @return \BeSimple\SoapClient\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); + }, ); } - - throw new SoapFault( - $soapFaultCode, - $soapFaultMessage - ); } - private function decorateNativeSoapFaultWithSoapResponseTracingData(SoapFault $nativePhpSoapFault) + /** + * Downloads WSDL files with cURL. Uses all SoapClient options for + * authentication. Uses the WSDL_CACHE_* constants and the 'soap.wsdl_*' + * ini settings. Does only file caching as SoapClient only supports a file + * name parameter. + * + * @param string $wsdl WSDL file + * @param array(string=>mixed) $options Options array + * + * @return string + */ + protected function loadWsdl($wsdl, array $options) { - return $this->throwSoapFaultByTracing( - $nativePhpSoapFault->faultcode, - $nativePhpSoapFault->getMessage(), - $this->getSoapResponseTracingDataFromNativeSoapFaultOrStorage($nativePhpSoapFault) - ); - } - - private function getSoapResponseTracingDataFromNativeSoapFaultOrStorage(SoapFault $nativePhpSoapFault) - { - if ($nativePhpSoapFault instanceof SoapFaultWithTracingData) { - return $nativePhpSoapFault->getSoapResponseTracingData(); + // option to resolve wsdl/xsd includes + $resolveRemoteIncludes = true; + if (isset($options['resolve_wsdl_remote_includes'])) { + $resolveRemoteIncludes = $options['resolve_wsdl_remote_includes']; + } + // option to enable cache + $wsdlCache = WSDL_CACHE_DISK; + if (isset($options['cache_wsdl'])) { + $wsdlCache = $options['cache_wsdl']; + } + $wsdlDownloader = new WsdlDownloader($this->curl, $resolveRemoteIncludes, $wsdlCache); + try { + $cacheFileName = $wsdlDownloader->download($wsdl); + } catch (\RuntimeException $e) { + throw new \SoapFault('WSDL', "SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl . "' : failed to load external entity \"" . $wsdl . "\""); } - return $this->getSoapResponseTracingDataFromRequestStorage(); + return $cacheFileName; } - - private function getSoapResponseTracingDataFromRequestStorage() - { - $lastResponseHeaders = $lastResponse = $lastRequestHeaders = $lastRequest = null; - $soapResponse = $this->getSoapResponseFromStorage(); - if ($soapResponse instanceof SoapResponse) { - $lastResponseHeaders = 'Content-Type: ' . $soapResponse->getContentType(); - $lastResponse = $soapResponse->getResponseContent(); - - if ($soapResponse->hasRequest() === true) { - $lastRequestHeaders = 'Content-Type: ' . $soapResponse->getRequest()->getContentType(); - $lastRequest = $soapResponse->getRequest()->getContent(); - } - } - - return new SoapResponseTracingData( - $lastRequestHeaders, - $lastRequest, - $lastResponseHeaders, - $lastResponse - ); - } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapClient/SoapClientBuilder.php b/src/BeSimple/SoapClient/SoapClientBuilder.php index 02e4b0a..59b5bba 100644 --- a/src/BeSimple/SoapClient/SoapClientBuilder.php +++ b/src/BeSimple/SoapClient/SoapClientBuilder.php @@ -12,44 +12,237 @@ namespace BeSimple\SoapClient; -use BeSimple\SoapBundle\Cache; -use BeSimple\SoapClient\SoapOptions\SoapClientOptions; -use BeSimple\SoapCommon\SoapOptions\SoapOptions; -use Exception; -use SoapHeader; +use BeSimple\SoapCommon\AbstractSoapBuilder; +use BeSimple\SoapCommon\Helper; /** - * Provides a SoapClient instance. + * Fluent interface builder for SoapClient instance. * * @author Francis Besset * @author Christian Kerl - * @author Petr Bechyně */ -class SoapClientBuilder +class SoapClientBuilder extends AbstractSoapBuilder { - public function build(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions) - { - $cache = new Cache($soapOptions); - $cache->validateSettings($soapOptions); + /** + * Authentication options. + * + * @var array(string=>mixed) + */ + protected $soapOptionAuthentication = array(); - return new SoapClient( - $soapClientOptions, - $soapOptions - ); + /** + * Create new instance with default options. + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public static function createWithDefaults() + { + return parent::createWithDefaults() + ->withUserAgent('BeSimpleSoap'); } - public function buildWithSoapHeader( - SoapClientOptions $soapClientOptions, - SoapOptions $soapOptions, - SoapHeader $soapHeader - ) { - $soapClient = $this->build($soapClientOptions, $soapOptions); - if ($soapClient->__setSoapHeaders($soapHeader) === false) { - throw new Exception( - 'Could not set SoapHeader: '.var_export($soapHeader, true) - ); + /** + * Finally returns a SoapClient instance. + * + * @return \BeSimple\SoapClient\SoapClient + */ + public function build() + { + $this->validateOptions(); + + return new SoapClient($this->wsdl, $this->getSoapOptions()); + } + + /** + * Get final array of SOAP options. + * + * @return array(string=>mixed) + */ + public function getSoapOptions() + { + return parent::getSoapOptions() + $this->soapOptionAuthentication; + } + + /** + * Configure option 'trace'. + * + * @param boolean $trace Enable/Disable + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withTrace($trace = true) + { + $this->soapOptions['trace'] = $trace; + + return $this; + } + + /** + * Configure option 'exceptions'. + * + * @param boolean $exceptions Enable/Disable + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withExceptions($exceptions = true) + { + $this->soapOptions['exceptions'] = $exceptions; + + return $this; + } + + /** + * Configure option 'user_agent'. + * + * @param string $userAgent User agent string + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withUserAgent($userAgent) + { + $this->soapOptions['user_agent'] = $userAgent; + + return $this; + } + + /** + * Enable gzip compression. + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withCompressionGzip() + { + $this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP; + + return $this; + } + + /** + * Enable deflate compression. + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withCompressionDeflate() + { + $this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE; + + return $this; + } + + /** + * Configure basic authentication + * + * @param string $username Username + * @param string $password Password + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withBasicAuthentication($username, $password) + { + $this->soapOptionAuthentication = array( + 'authentication' => SOAP_AUTHENTICATION_BASIC, + 'login' => $username, + 'password' => $password, + ); + + return $this; + } + + /** + * Configure digest authentication. + * + * @param string $certificate Certificate + * @param string $passphrase Passphrase + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withDigestAuthentication($certificate, $passphrase = null) + { + $this->soapOptionAuthentication = array( + 'authentication' => SOAP_AUTHENTICATION_DIGEST, + 'local_cert' => $certificate, + ); + + if ($passphrase) { + $this->soapOptionAuthentication['passphrase'] = $passphrase; } - return $soapClient; + return $this; + } + + /** + * Configure proxy. + * + * @param string $host Host + * @param int $port Port + * @param string $login Login + * @param string $password Password + * @param int $auth Authentication method + * + * @return \BeSimple\SoapClient\SoapClientBuilder + */ + public function withProxy($host, $port, $login = null, $password = null, $auth = null) + { + $this->soapOptions['proxy_host'] = $host; + $this->soapOptions['proxy_port'] = $port; + + if ($login) { + $this->soapOptions['proxy_login'] = $login; + $this->soapOptions['proxy_password'] = $password; + + if ($auth) { + if (!in_array($auth, array(\CURLAUTH_BASIC, \CURLAUTH_NTLM), true)) { + throw new \InvalidArgumentException('Invalid authentication method: CURLAUTH_BASIC or CURLAUTH_NTLM constants are availables.'); + } + + $this->soapOptions['proxy_auth'] = $auth; + } + } + + return $this; + } + + /** + * SOAP attachment type Base64. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withBase64Attachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_BASE64; + + return $this; + } + + /** + * SOAP attachment type SwA. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withSwaAttachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_SWA; + + return $this; + } + + /** + * SOAP attachment type MTOM. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withMtomAttachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_MTOM; + + return $this; + } + + /** + * Validate options. + */ + protected function validateOptions() + { + $this->validateWsdl(); } } diff --git a/src/BeSimple/SoapClient/SoapClientMessageWithAttachments.php b/src/BeSimple/SoapClient/SoapClientMessageWithAttachments.php deleted file mode 100644 index bffe5c4..0000000 --- a/src/BeSimple/SoapClient/SoapClientMessageWithAttachments.php +++ /dev/null @@ -1,7 +0,0 @@ -soapCall($function_name, $arguments, $options, $input_headers, $output_headers)->getResponseContent(); - } - - /** - * This is not performing any HTTP requests, but it is getting data from SoapClient that are needed for this Client - * - * @param string $request Request string - * @param string $location Location - * @param string $action SOAP action - * @param int $version SOAP version - * @param int $oneWay 0|1 - * - * @return string - */ - public function __doRequest($request, $location, $action, $version, $oneWay = 0) - { - $soapResponse = $this->performSoapRequest( - $request, - $location, - $action, - $version, - $this->getSoapAttachmentsOnRequestFromStorage() - ); - $this->setSoapResponseToStorage($soapResponse); - - return $soapResponse->getResponseContent(); - } - - /** @deprecated */ - public function __getLastRequestHeaders() - { - $this->checkTracing(); - - throw new Exception( - 'The __getLastRequestHeaders method is now deprecated. Use callSoapRequest instead and get the tracing information from SoapResponseTracingData.' - ); - } - - /** @deprecated */ - public function __getLastRequest() - { - $this->checkTracing(); - - throw new Exception( - 'The __getLastRequest method is now deprecated. Use callSoapRequest instead and get the tracing information from SoapResponseTracingData.' - ); - } - - /** @deprecated */ - public function __getLastResponseHeaders() - { - $this->checkTracing(); - - throw new Exception( - 'The __getLastResponseHeaders method is now deprecated. Use callSoapRequest instead and get the tracing information from SoapResponseTracingData.' - ); - } - - /** @deprecated */ - public function __getLastResponse() - { - $this->checkTracing(); - - throw new Exception( - 'The __getLastResponse method is now deprecated. Use callSoapRequest instead and get the tracing information from SoapResponseTracingData.' - ); - } - - private function checkTracing() - { - if ($this->getSoapClientOptions()->getTrace() === false) { - throw new Exception('SoapClientOptions tracing disabled, turn on trace attribute'); - } - } - - private function setSoapResponseToStorage(SoapResponse $soapResponseStorage) - { - $this->soapResponseStorage = $soapResponseStorage; - } - - /** - * @param SoapAttachment[] $soapAttachments - */ - private function setSoapAttachmentsOnRequestToStorage(array $soapAttachments) - { - $this->soapAttachmentsOnRequestStorage = $soapAttachments; - } - - private function getSoapAttachmentsOnRequestFromStorage() - { - $soapAttachmentsOnRequest = $this->soapAttachmentsOnRequestStorage; - $this->soapAttachmentsOnRequestStorage = null; - - return $soapAttachmentsOnRequest; - } - - private function getSoapResponseFromStorage() - { - $soapResponse = $this->soapResponseStorage; - $this->soapResponseStorage = null; - - return $soapResponse; - } -} diff --git a/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php b/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php deleted file mode 100644 index 7d93844..0000000 --- a/src/BeSimple/SoapClient/SoapClientOptionsBuilder.php +++ /dev/null @@ -1,139 +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\SoapClient; - -use BeSimple\SoapClient\Curl\CurlOptions; -use BeSimple\SoapClient\SoapOptions\SoapClientOptions; -use BeSimple\SoapClient\SoapServerAuthentication\SoapServerAuthenticationInterface; - -/** - * Provides a SoapClient instance. - * - * @author Francis Besset - * @author Christian Kerl - * @author Petr Bechyně - */ -class SoapClientOptionsBuilder -{ - public static function createWithDefaults() - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE - ); - } - - public static function createWithTracing() - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE - ); - } - - public static function createWithProxy($proxy) - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - SoapClientOptions::SOAP_CLIENT_AUTHENTICATION_NONE, - $proxy - ); - } - - public static function createWithEndpointLocation($endpointLocation) - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - SoapClientOptions::SOAP_CLIENT_AUTHENTICATION_NONE, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - $endpointLocation - ); - } - - public static function createWithAuthentication(SoapServerAuthenticationInterface $authentication) - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - $authentication - ); - } - - public static function createWithAuthenticationAndEndpointLocation($endpointLocation, SoapServerAuthenticationInterface $authentication) - { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - $authentication, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - $endpointLocation - ); - } - - /** - * @param $endpointLocation - * @param SoapServerAuthenticationInterface $authentication - * @return SoapClientOptions - */ - public static function createWithAuthenticationAndEndpointLocationAndSslVersionV3( - $endpointLocation, - SoapServerAuthenticationInterface $authentication - ) { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - $authentication, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - $endpointLocation, - false, - CURL_SSLVERSION_SSLv3 - ); - } - - /** - * @param SoapServerAuthenticationInterface $authentication - * @param bool $resolveRemoteIncludes - * @return SoapClientOptions - */ - public static function createWithAuthenticationAndResolveRemoteIncludes( - SoapServerAuthenticationInterface $authentication, - $resolveRemoteIncludes - ) { - return new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_ON, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - $authentication, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - SoapClientOptions::SOAP_CLIENT_ENDPOINT_LOCATION_NONE, - $resolveRemoteIncludes - ); - } -} diff --git a/src/BeSimple/SoapClient/SoapFaultWithTracingData.php b/src/BeSimple/SoapClient/SoapFaultWithTracingData.php deleted file mode 100644 index d62c762..0000000 --- a/src/BeSimple/SoapClient/SoapFaultWithTracingData.php +++ /dev/null @@ -1,21 +0,0 @@ -soapResponseTracingData = $soapResponseTracingData; - parent::__construct($code, $message); - } - - public function getSoapResponseTracingData() - { - return $this->soapResponseTracingData; - } -} diff --git a/src/BeSimple/SoapClient/SoapKernel.php b/src/BeSimple/SoapClient/SoapKernel.php new file mode 100644 index 0000000..e2e5093 --- /dev/null +++ b/src/BeSimple/SoapClient/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\SoapClient; + +use BeSimple\SoapCommon\SoapKernel as CommonSoapKernel; +use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest; +use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; + +/** + * SoapKernel for Client. + * + * @author Andreas Schamberger + */ +class SoapKernel extends CommonSoapKernel +{ + /** + * {@inheritDoc} + */ + public function filterRequest(CommonSoapRequest $request) + { + $request->setAttachments($this->attachments); + $this->attachments = array(); + + parent::filterRequest($request); + } + + /** + * {@inheritDoc} + */ + public function filterResponse(CommonSoapResponse $response) + { + parent::filterResponse($response); + + $this->attachments = $response->getAttachments(); + } +} diff --git a/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php b/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php deleted file mode 100644 index 664e0b5..0000000 --- a/src/BeSimple/SoapClient/SoapOptions/SoapClientOptions.php +++ /dev/null @@ -1,166 +0,0 @@ -trace = $trace; - $this->exceptions = $exceptions; - $this->userAgent = $userAgent; - $this->compression = $compression; - $this->authentication = $authentication; - $this->proxy = $proxy; - $this->location = $location; - $this->resolveRemoteIncludes = $resolveRemoteIncludes; - $this->sslVersion = $sslVersion; - } - - public function getTrace() - { - return $this->trace; - } - - public function getExceptions() - { - return $this->exceptions; - } - - public function getUserAgent() - { - return $this->userAgent; - } - - public function hasCompression() - { - return $this->compression !== self::SOAP_CLIENT_COMPRESSION_NONE; - } - - public function getCompression() - { - return $this->compression; - } - - public function hasAuthentication() - { - return $this->authentication !== null; - } - - public function hasAuthenticationBasic() - { - return $this->hasAuthentication() && $this->getAuthentication() instanceof SoapServerAuthenticationBasic; - } - - public function hasAuthenticationDigest() - { - return $this->hasAuthentication() && $this->getAuthentication() instanceof SoapServerAuthenticationDigest; - } - - public function hasProxy() - { - return $this->proxy !== null; - } - - public function hasLocation() - { - return $this->location !== null; - } - - public function getAuthentication() - { - return $this->authentication; - } - - public function getProxy() - { - return $this->proxy; - } - - public function getLocation() - { - return $this->location; - } - - public function isResolveRemoteIncludes() - { - return $this->resolveRemoteIncludes; - } - - public function toArray() - { - $optionsAsArray = [ - 'trace' => $this->getTrace(), - 'exceptions' => $this->getExceptions(), - 'user_agent' => $this->getUserAgent(), - ]; - if ($this->hasCompression()) { - $optionsAsArray['compression'] = $this->getCompression(); - } - if ($this->hasAuthentication()) { - $optionsAsArray += $this->getAuthentication()->toArray(); - } - if ($this->hasProxy()) { - $optionsAsArray += $this->getProxy()->toArray(); - } - if ($this->hasLocation()) { - $optionsAsArray['location'] = $this->getLocation(); - } - - return $optionsAsArray; - } - - public function getSslVersion() - { - return $this->sslVersion; - } -} diff --git a/src/BeSimple/SoapClient/SoapRequest.php b/src/BeSimple/SoapClient/SoapRequest.php new file mode 100644 index 0000000..00580cb --- /dev/null +++ b/src/BeSimple/SoapClient/SoapRequest.php @@ -0,0 +1,48 @@ + + * (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\SoapClient; + +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 $location Location + * @param string $action SOAP action + * @param string $version SOAP version + * + * @return BeSimple\SoapClient\SoapRequest + */ + public static function create($content, $location, $action, $version) + { + $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); + $contentType = SoapMessage::getContentTypeForVersion($version); + $request->setContentType($contentType); + + return $request; + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapClient/SoapResponse.php b/src/BeSimple/SoapClient/SoapResponse.php index 34c8b5a..0541f43 100644 --- a/src/BeSimple/SoapClient/SoapResponse.php +++ b/src/BeSimple/SoapClient/SoapResponse.php @@ -1,61 +1,46 @@ + * (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\SoapClient; -use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; +/** + * SoapResponse class for SoapClient. Provides factory function for response object. + * + * @author Andreas Schamberger + */ class SoapResponse extends CommonSoapResponse { - /** @var mixed */ - protected $responseObject; - /** @var SoapResponseTracingData */ - protected $tracingData; - /** @var SoapRequest */ - protected $request; - - public function getResponseContent() + /** + * Factory function for SoapResponse. + * + * @param string $content Content + * @param string $location Location + * @param string $action SOAP action + * @param string $version SOAP version + * @param string $contentType Content type header + * + * @return BeSimple\SoapClient\SoapResponse + */ + public static function create($content, $location, $action, $version, $contentType) { - return $this->getContent(); - } + $response = new SoapResponse(); + $response->setContent($content); + $response->setLocation($location); + $response->setAction($action); + $response->setVersion($version); + $response->setContentType($contentType); - public function getResponseObject() - { - return $this->responseObject; - } - - public function setResponseObject($responseObject) - { - $this->responseObject = $responseObject; - } - - public function hasTracingData() - { - return $this->tracingData !== null; - } - - public function getTracingData() - { - return $this->tracingData; - } - - public function setTracingData(SoapResponseTracingData $tracingData) - { - $this->tracingData = $tracingData; - } - - public function hasRequest() - { - return $this->request !== null; - } - - public function setRequest(SoapRequest $request) - { - $this->request = $request; - } - - public function getRequest() - { - return $this->request; + return $response; } } diff --git a/src/BeSimple/SoapClient/SoapResponseFactory.php b/src/BeSimple/SoapClient/SoapResponseFactory.php deleted file mode 100644 index d4d954d..0000000 --- a/src/BeSimple/SoapClient/SoapResponseFactory.php +++ /dev/null @@ -1,91 +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\SoapClient; - -use BeSimple\SoapBundle\Soap\SoapAttachment; -use BeSimple\SoapCommon\Mime\PartFactory; -use BeSimple\SoapCommon\SoapRequest; - -/** - * SoapResponseFactory for SoapClient. Provides factory function for SoapResponse object. - * - * @author Andreas Schamberger - * @author Petr Bechyně - */ -class SoapResponseFactory -{ - /** - * Factory method for SoapClient\SoapResponse. - * - * @param SoapRequest $soapRequest related request object - * @param string $content Content - * @param string $contentType Content type header - * @param SoapAttachment[] $attachments SOAP attachments - * @return SoapResponse - */ - public static function create( - SoapRequest $soapRequest, - $content, - $contentType, - array $attachments = [] - ) { - $response = new SoapResponse(); - $response->setRequest($soapRequest); - $response->setContent($content); - $response->setLocation($soapRequest->getLocation()); - $response->setAction($soapRequest->getAction()); - $response->setVersion($soapRequest->getVersion()); - $response->setContentType($contentType); - if (count($attachments) > 0) { - $response->setAttachments( - PartFactory::createAttachmentParts($attachments) - ); - } - - return $response; - } - - /** - * Factory method for SoapClient\SoapResponse with SoapResponseTracingData. - * - * @param SoapRequest $soapRequest related request object - * @param string $content Content - * @param string $contentType Content type header - * @param SoapResponseTracingData $tracingData Data value object suitable for tracing SOAP traffic - * @param SoapAttachment[] $attachments SOAP attachments - * @return SoapResponse - */ - public static function createWithTracingData( - SoapRequest $soapRequest, - $content, - $contentType, - SoapResponseTracingData $tracingData, - array $attachments = [] - ) { - $response = new SoapResponse(); - $response->setRequest($soapRequest); - $response->setContent($content); - $response->setLocation($soapRequest->getLocation()); - $response->setAction($soapRequest->getAction()); - $response->setVersion($soapRequest->getVersion()); - $response->setContentType($contentType); - $response->setTracingData($tracingData); - if (count($attachments) > 0) { - $response->setAttachments( - PartFactory::createAttachmentParts($attachments) - ); - } - - return $response; - } -} diff --git a/src/BeSimple/SoapClient/SoapResponseTracingData.php b/src/BeSimple/SoapClient/SoapResponseTracingData.php deleted file mode 100644 index c3f13ac..0000000 --- a/src/BeSimple/SoapClient/SoapResponseTracingData.php +++ /dev/null @@ -1,39 +0,0 @@ -lastRequestHeaders = $lastRequestHeaders; - $this->lastRequest = $lastRequest; - $this->lastResponseHeaders = $lastResponseHeaders; - $this->lastResponse = $lastResponse; - } - - public function getLastRequestHeaders() - { - return $this->lastRequestHeaders; - } - - public function getLastRequest() - { - return $this->lastRequest; - } - - public function getLastResponseHeaders() - { - return $this->lastResponseHeaders; - } - - public function getLastResponse() - { - return $this->lastResponse; - } -} diff --git a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationBasic.php b/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationBasic.php deleted file mode 100644 index 95d2d5d..0000000 --- a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationBasic.php +++ /dev/null @@ -1,39 +0,0 @@ -login = $login; - $this->password = $password; - } - - public function getAuthentication() - { - return \SOAP_AUTHENTICATION_BASIC; - } - - public function getLogin() - { - return $this->login; - } - - public function getPassword() - { - return $this->password; - } - - public function toArray() - { - return [ - 'authentication' => $this->getAuthentication(), - 'login' => $this->getLogin(), - 'password' => $this->getPassword(), - ]; - } -} diff --git a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationDigest.php b/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationDigest.php deleted file mode 100644 index b0ff162..0000000 --- a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationDigest.php +++ /dev/null @@ -1,52 +0,0 @@ -localCert = $localCert; - $this->passPhrase = $passPhrase; - } - - public function getLocalCert() - { - return $this->localCert; - } - - public function hasPassPhrase() - { - return $this->passPhrase !== null; - } - - public function getPassPhrase() - { - return $this->passPhrase; - } - - public function getAuthentication() - { - return \SOAP_AUTHENTICATION_DIGEST; - } - - public function toArray() - { - $authenticationAsArray = [ - 'authentication' => $this->getAuthentication(), - 'local_cert' => $this->getLocalCert() - ]; - if ($this->hasPassPhrase()) { - $authenticationAsArray['passphrase'] = $this->getPassPhrase(); - } - - return $authenticationAsArray; - } -} diff --git a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationInterface.php b/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationInterface.php deleted file mode 100644 index 694d44c..0000000 --- a/src/BeSimple/SoapClient/SoapServerAuthentication/SoapServerAuthenticationInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -host = $host; - $this->port = $port; - $this->login = $login; - $this->password = $password; - $this->authenticationType = $authenticationType; - } - - public function getHost() - { - return $this->host; - } - - public function getPort() - { - return $this->port; - } - - public function hasCredentials() - { - return $this->login !== null; - } - - public function getLogin() - { - return $this->login; - } - - public function getPassword() - { - return $this->password; - } - - public function hasAuthenticationType() - { - return $this->authenticationType !== self::PROXY_AUTHENTICATION_TYPE_NONE; - } - - public function getAuthenticationType() - { - return $this->authenticationType; - } - - public function toArray() - { - $proxyAsArray = [ - 'proxy_host' => $this->getHost(), - 'proxy_port' => $this->getPort(), - ]; - if ($this->hasCredentials()) { - $proxyAsArray['proxy_login'] = $this->getLogin(); - $proxyAsArray['proxy_password'] = $this->getPassword(); - } - if ($this->hasAuthenticationType()) { - $proxyAsArray['proxy_auth'] = $this->getAuthenticationType(); - } - - return $proxyAsArray; - } -} diff --git a/src/BeSimple/SoapClient/Tests/AbstractWebserverTest.php b/src/BeSimple/SoapClient/Tests/AbstractWebserverTest.php new file mode 100644 index 0000000..a7bc6d4 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AbstractWebserverTest.php @@ -0,0 +1,56 @@ + + * (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\SoapClient\Tests; + +use Symfony\Component\Process\PhpExecutableFinder; +use Symfony\Component\Process\ProcessBuilder; + +/** + * @author francis.besset@gmail.com + */ +abstract class AbstractWebServerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ProcessBuilder + */ + static protected $webserver; + static protected $websererPortLength; + + public static function setUpBeforeClass() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + self::markTestSkipped('PHP Webserver is available from PHP 5.4'); + } + + $phpFinder = new PhpExecutableFinder(); + self::$webserver = ProcessBuilder::create(array( + 'exec', // used exec binary (https://github.com/symfony/symfony/issues/5759) + $phpFinder->find(), + '-S', + sprintf('localhost:%d', WEBSERVER_PORT), + '-t', + __DIR__.DIRECTORY_SEPARATOR.'Fixtures', + ))->getProcess(); + + self::$webserver->start(); + usleep(100000); + + self::$websererPortLength = strlen(WEBSERVER_PORT); + } + + public static function tearDownAfterClass() + { + self::$webserver->stop(0); + usleep(100000); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/AttachmentRequest.php b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/AttachmentRequest.php new file mode 100644 index 0000000..e4f0236 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/AttachmentRequest.php @@ -0,0 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/SwA.wsdl b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/SwA.wsdl new file mode 100644 index 0000000..d63fe2d --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/SwA.wsdl @@ -0,0 +1,162 @@ + + + BeSimpleSwaService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecuritySigEnc.wsdl b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecuritySigEnc.wsdl new file mode 100644 index 0000000..620ea51 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecuritySigEnc.wsdl @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecurityUserPass.wsdl b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecurityUserPass.wsdl new file mode 100644 index 0000000..6e72411 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/WsSecurityUserPass.wsdl @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/addBook.php b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/addBook.php new file mode 100644 index 0000000..7a171b0 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/Fixtures/addBook.php @@ -0,0 +1,11 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_MTOM, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'base64Binary' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\base64Binary', + 'AttachmentRequest' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\AttachmentRequest', + ), + 'proxy_host' => false, + ); + + public function testAttachment() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/MTOM.wsdl', $this->options); + + $b64 = new base64Binary(); + $b64->_ = 'This is a test. :)'; + $b64->contentType = 'text/plain'; + + $attachment = new AttachmentRequest(); + $attachment->fileName = 'test123.txt'; + $attachment->binaryData = $b64; + + $this->assertEquals('File saved succesfully.', $sc->attachment($attachment)); + +// $fileCreatedByServer = __DIR__.'/'.$attachment->fileName; +// $this->assertEquals($b64->_, file_get_contents($fileCreatedByServer)); +// unlink($fileCreatedByServer); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/build.xml b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/build.xml new file mode 100644 index 0000000..836bda8 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/build.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/resources/META-INF/services.xml b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/resources/META-INF/services.xml new file mode 100644 index 0000000..8bac2eb --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/resources/META-INF/services.xml @@ -0,0 +1,15 @@ + + + BeSimple test service for SwA. + true + besimple.service.BeSimpleSwaService + + urn:uploadFile + + + + urn:downloadFile + + + + diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/src/besimple/service/BeSimpleSwaService.java b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/src/besimple/service/BeSimpleSwaService.java new file mode 100644 index 0000000..b173e15 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/SwA/src/besimple/service/BeSimpleSwaService.java @@ -0,0 +1,78 @@ +package besimple.service; + +import java.io.File; +import java.io.FileOutputStream; + +import javax.xml.namespace.QName; + +import javax.activation.DataHandler; +import javax.activation.FileDataSource; + +import org.apache.axiom.attachments.Attachments; +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; + +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.context.OperationContext; +import org.apache.axis2.wsdl.WSDLConstants; + +public class BeSimpleSwaService { + + String namespace = "http://service.besimple"; + + public OMElement uploadFile(OMElement element) throws Exception { + OMElement dataElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "data")); + OMAttribute hrefAttribute = dataElement.getAttribute(new QName("href")); + + String contentID = hrefAttribute.getAttributeValue(); + contentID = contentID.trim(); + if (contentID.substring(0, 3).equalsIgnoreCase("cid")) { + contentID = contentID.substring(4); + } + OMElement nameElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "name")); + String name = nameElement.getText(); + + MessageContext msgCtx = MessageContext.getCurrentMessageContext(); + Attachments attachment = msgCtx.getAttachmentMap(); + DataHandler dataHandler = attachment.getDataHandler(contentID); + + File file = new File(name); + FileOutputStream fileOutputStream = new FileOutputStream(file); + dataHandler.writeTo(fileOutputStream); + fileOutputStream.flush(); + fileOutputStream.close(); + + OMFactory factory = OMAbstractFactory.getOMFactory(); + OMNamespace omNs = factory.createOMNamespace(namespace, "swa"); + OMElement wrapperElement = factory.createOMElement("uploadFileResponse", omNs); + OMElement returnElement = factory.createOMElement("return", omNs, wrapperElement); + returnElement.setText("File saved succesfully."); + + return wrapperElement; + } + + public OMElement downloadFile(OMElement element) throws Exception { + OMElement nameElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "name")); + String name = nameElement.getText(); + + MessageContext msgCtxIn = MessageContext.getCurrentMessageContext(); + OperationContext operationContext = msgCtxIn.getOperationContext(); + MessageContext msgCtxOut = operationContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE); + + FileDataSource fileDataSource = new FileDataSource(name); + DataHandler dataHandler = new DataHandler(fileDataSource); + + String contentID = "cid:" + msgCtxOut.addAttachment(dataHandler); + + OMFactory factory = OMAbstractFactory.getOMFactory(); + OMNamespace omNs = factory.createOMNamespace(namespace, "swa"); + OMElement wrapperElement = factory.createOMElement("downloadFileResponse", omNs); + OMElement dataElement = factory.createOMElement("data", omNs, wrapperElement); + dataElement.addAttribute("href", contentID, null); + + return wrapperElement; + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/SwaAxisInteropTest.php b/src/BeSimple/SoapClient/Tests/AxisInterop/SwaAxisInteropTest.php new file mode 100644 index 0000000..d964aa3 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/SwaAxisInteropTest.php @@ -0,0 +1,78 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_SWA, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'downloadFile' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\downloadFile', + 'downloadFileResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\downloadFileResponse', + 'uploadFile' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\uploadFile', + 'uploadFileResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\uploadFileResponse', + ), + 'proxy_host' => false, + ); + + public function testUploadDownloadText() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $this->options); + + $upload = new uploadFile(); + $upload->name = 'upload.txt'; + $upload->data = 'This is a test. :)'; + $result = $sc->uploadFile($upload); + + $this->assertEquals('File saved succesfully.', $result->return); + + $download = new downloadFile(); + $download->name = 'upload.txt'; + $result = $sc->downloadFile($download); + + $this->assertEquals($upload->data, $result->data); + } + + public function testUploadDownloadImage() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $this->options); + + $upload = new uploadFile(); + $upload->name = 'image.jpg'; + $upload->data = file_get_contents(__DIR__.'/Fixtures/image.jpg'); // source: http://www.freeimageslive.com/galleries/light/pics/swirl3768.jpg; + $result = $sc->uploadFile($upload); + + $this->assertEquals('File saved succesfully.', $result->return); + + $download = new downloadFile(); + $download->name = 'image.jpg'; + $result = $sc->downloadFile($download); + + $this->assertEquals($upload->data, $result->data); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/TestCase.php b/src/BeSimple/SoapClient/Tests/AxisInterop/TestCase.php new file mode 100644 index 0000000..eb57435 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/TestCase.php @@ -0,0 +1,23 @@ +markTestSkipped( + 'The Axis server is not started on port 8080.' + ); + } + + curl_close($ch); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/WsAddressingAxisInteropTest.php b/src/BeSimple/SoapClient/Tests/AxisInterop/WsAddressingAxisInteropTest.php new file mode 100644 index 0000000..2310476 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/WsAddressingAxisInteropTest.php @@ -0,0 +1,60 @@ + + * ... + * + * + * build.xml: + * replace version.aar with version2.aar + * + * 2) Run ant build.xml in "$AXIS_HOME/samples/version" + * + */ + +use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient; +use BeSimple\SoapClient\WsAddressingFilter as BeSimpleWsAddressingFilter; + +use BeSimple\SoapClient\Tests\AxisInterop\TestCase; + +class WsAddressingAxisInteropTest extends TestCase +{ + private $options = array( + 'soap_version' => SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'proxy_host' => false, + ); + + public function testSession() + { + $sc = new BeSimpleSoapClient('http://localhost:8080/axis2/services/Version2?wsdl', $this->options); + $soapKernel = $sc->getSoapKernel(); + $wsaFilter = new BeSimpleWsAddressingFilter(); + $soapKernel->registerFilter($wsaFilter); + + $wsaFilter->setReplyTo(BeSimpleWsAddressingFilter::ENDPOINT_REFERENCE_ANONYMOUS); + $wsaFilter->setMessageId(); + + $version = $sc->getVersion(); + + $soapSessionId1 = $wsaFilter->getReferenceParameter('http://ws.apache.org/namespaces/axis2', 'ServiceGroupId'); + + $wsaFilter->addReferenceParameter('http://ws.apache.org/namespaces/axis2', 'axis2', 'ServiceGroupId', $soapSessionId1); + + $version = $sc->getVersion(); + + $soapSessionId2 = $wsaFilter->getReferenceParameter('http://ws.apache.org/namespaces/axis2', 'ServiceGroupId'); + + $this->assertEquals($soapSessionId1, $soapSessionId2); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecuritySigEncAxisInteropTest.php b/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecuritySigEncAxisInteropTest.php new file mode 100644 index 0000000..2d7070e --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecuritySigEncAxisInteropTest.php @@ -0,0 +1,107 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation', + ), + 'proxy_host' => false, + ); + + public function testSigEnc() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecuritySigEnc.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(); + // user key for signature and encryption + $securityKeyUser = new BeSimpleWsSecurityKey(); + $securityKeyUser->addPrivateKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientkey.pem', true); + $securityKeyUser->addPublicKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientcert.pem', true); + $wssFilter->setUserSecurityKeyObject($securityKeyUser); + // service key for encryption + $securityKeyService = new BeSimpleWsSecurityKey(); + $securityKeyService->addPrivateKey(XmlSecurityKey::TRIPLEDES_CBC); + $securityKeyService->addPublicKey(XmlSecurityKey::RSA_1_5, __DIR__.'/Fixtures/servercert.pem', true); + $wssFilter->setServiceSecurityKeyObject($securityKeyService); + // TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | TOKEN_REFERENCE_SECURITY_TOKEN | TOKEN_REFERENCE_THUMBPRINT_SHA1 + $wssFilter->setSecurityOptionsSignature(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_SECURITY_TOKEN); + $wssFilter->setSecurityOptionsEncryption(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_THUMBPRINT_SHA1); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecurityUserPassAxisInteropTest.php b/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecurityUserPassAxisInteropTest.php new file mode 100644 index 0000000..2ee71d6 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/AxisInterop/WsSecurityUserPassAxisInteropTest.php @@ -0,0 +1,97 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation', + ), + 'proxy_host' => false, + ); + + public function testUserPassText() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(true, 600); + $wssFilter->addUserData('libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_TEXT); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } + + public function testUserPassDigest() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(true, 600); + $wssFilter->addUserData( 'libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_DIGEST ); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\AxisInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } +} diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/besimple-swa.aar b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/besimple-swa.aar new file mode 100644 index 0000000..bb41750 Binary files /dev/null and b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/besimple-swa.aar differ diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-signencr.aar b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-signencr.aar new file mode 100644 index 0000000..25ffc2d Binary files /dev/null and b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-signencr.aar differ diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-username-digest.aar b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-username-digest.aar new file mode 100644 index 0000000..f6f8595 Binary files /dev/null and b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/library-username-digest.aar differ diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/sample-mtom.aar b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/sample-mtom.aar new file mode 100644 index 0000000..a215edc Binary files /dev/null and b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/sample-mtom.aar differ diff --git a/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/version2.aar b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/version2.aar new file mode 100644 index 0000000..df76662 Binary files /dev/null and b/src/BeSimple/SoapClient/Tests/AxisInterop/axis_services/version2.aar differ diff --git a/src/BeSimple/SoapClient/Tests/CurlTest.php b/src/BeSimple/SoapClient/Tests/CurlTest.php new file mode 100644 index 0000000..28b6311 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/CurlTest.php @@ -0,0 +1,123 @@ + + * (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\SoapClient\Tests; + +use BeSimple\SoapClient\Curl; + +/** + * @author Andreas Schamberger + */ +class CurlTest extends AbstractWebserverTest +{ + public function testExec() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $this->assertTrue($curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT))); + $this->assertTrue($curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT))); + } + + public function testGetErrorMessage() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec('http://unknown/curl.txt'); + $this->assertEquals('Could not connect to host', $curl->getErrorMessage()); + + $curl->exec(sprintf('xyz://localhost:%d/@404.txt', WEBSERVER_PORT)); + $this->assertEquals('Unknown protocol. Only http and https are allowed.', $curl->getErrorMessage()); + + $curl->exec(''); + $this->assertEquals('Unable to parse URL', $curl->getErrorMessage()); + } + + public function testGetRequestHeaders() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertEquals(132 + self::$websererPortLength, strlen($curl->getRequestHeaders())); + + $curl->exec(sprintf('http://localhost:%s/404.txt', WEBSERVER_PORT)); + $this->assertEquals(131 + self::$websererPortLength, strlen($curl->getRequestHeaders())); + } + + public function testGetResponse() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertSame('OK', $curl->getResponseStatusMessage()); + $this->assertEquals(145 + self::$websererPortLength, strlen($curl->getResponse())); + + $curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT)); + $this->assertSame('Not Found', $curl->getResponseStatusMessage()); + } + + public function testGetResponseBody() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertEquals('This is a testfile for cURL.', $curl->getResponseBody()); + } + + public function testGetResponseContentType() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertEquals('text/plain; charset=UTF-8', $curl->getResponseContentType()); + + $curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT)); + $this->assertEquals('text/html; charset=UTF-8', $curl->getResponseContentType()); + } + + public function testGetResponseHeaders() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertEquals(117 + self::$websererPortLength, strlen($curl->getResponseHeaders())); + + $curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT)); + $this->assertEquals(124 + self::$websererPortLength, strlen($curl->getResponseHeaders())); + } + + public function testGetResponseStatusCode() + { + $curl = new Curl(array( + 'proxy_host' => false, + )); + + $curl->exec(sprintf('http://localhost:%d/curl.txt', WEBSERVER_PORT)); + $this->assertEquals(200, $curl->getResponseStatusCode()); + + $curl->exec(sprintf('http://localhost:%d/404.txt', WEBSERVER_PORT)); + $this->assertEquals(404, $curl->getResponseStatusCode()); + } +} diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/curl.txt b/src/BeSimple/SoapClient/Tests/Fixtures/curl.txt new file mode 100644 index 0000000..070def3 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/curl.txt @@ -0,0 +1 @@ +This is a testfile for cURL. \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/foobar.wsdl b/src/BeSimple/SoapClient/Tests/Fixtures/foobar.wsdl new file mode 100644 index 0000000..a890dd8 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/foobar.wsdl @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/type_include.xsd b/src/BeSimple/SoapClient/Tests/Fixtures/type_include.xsd new file mode 100644 index 0000000..a41dd9a --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/type_include.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/wsdl_include.wsdl b/src/BeSimple/SoapClient/Tests/Fixtures/wsdl_include.wsdl new file mode 100644 index 0000000..775240a --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/wsdl_include.wsdl @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_absolute.xml b/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_absolute.xml new file mode 100644 index 0000000..2f59ba1 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_absolute.xml @@ -0,0 +1,5 @@ + + + wsdlincludetest + + diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_relative.xml b/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_relative.xml new file mode 100644 index 0000000..8148e60 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/wsdlinclude/wsdlinctest_relative.xml @@ -0,0 +1,5 @@ + + + wsdlincludetest + + diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_absolute.xml b/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_absolute.xml new file mode 100644 index 0000000..166e549 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_absolute.xml @@ -0,0 +1,9 @@ + + + xsdinctest + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_relative.xml b/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_relative.xml new file mode 100644 index 0000000..58cea74 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/Fixtures/xsdinclude/xsdinctest_relative.xml @@ -0,0 +1,9 @@ + + + xsdinctest + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/AttachmentRequest.php b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/AttachmentRequest.php new file mode 100644 index 0000000..8be17dc --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/AttachmentRequest.php @@ -0,0 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/SwA.wsdl b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/SwA.wsdl new file mode 100644 index 0000000..46b14b7 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/SwA.wsdl @@ -0,0 +1,162 @@ + + + BeSimpleSwaService + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecuritySigEnc.wsdl b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecuritySigEnc.wsdl new file mode 100644 index 0000000..d329f1f --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecuritySigEnc.wsdl @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecurityUserPass.wsdl b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecurityUserPass.wsdl new file mode 100644 index 0000000..7d4b33f --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/WsSecurityUserPass.wsdl @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/addBook.php b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/addBook.php new file mode 100644 index 0000000..8d22133 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/Fixtures/addBook.php @@ -0,0 +1,11 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_MTOM, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary', + 'AttachmentRequest' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest', + ), + 'connection_timeout' => 1, +); + +$sc = new BeSimpleSoapClient('Fixtures/MTOM.wsdl', $options); + +//var_dump($sc->__getFunctions()); +//var_dump($sc->__getTypes()); + +try { + $b64 = new base64Binary(); + $b64->_ = 'This is a test. :)'; + $b64->contentType = 'text/plain'; + + $attachment = new AttachmentRequest(); + $attachment->fileName = 'test123.txt'; + $attachment->binaryData = $b64; + + var_dump($sc->attachment($attachment)); + +} catch (Exception $e) { + var_dump($e); +} + +// var_dump( +// $sc->__getLastRequestHeaders(), +// $sc->__getLastRequest(), +// $sc->__getLastResponseHeaders(), +// $sc->__getLastResponse() +// ); \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/MTOMServer.php b/src/BeSimple/SoapClient/Tests/ServerInterop/MTOMServer.php new file mode 100644 index 0000000..72e8e19 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/MTOMServer.php @@ -0,0 +1,35 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_MTOM, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary', + 'AttachmentType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest', + ), +); + +class Mtom +{ + public function attachment(Fixtures\AttachmentRequest $attachment) + { + $b64 = $attachment->binaryData; + + file_put_contents(__DIR__.'/'.$attachment->fileName, $b64->_); + + return 'File saved succesfully.'; + } +} + +$ss = new BeSimpleSoapServer(__DIR__.'/Fixtures/MTOM.wsdl', $options); +$ss->setClass('Mtom'); +$ss->handle(); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/MtomServerInteropTest.php b/src/BeSimple/SoapClient/Tests/ServerInterop/MtomServerInteropTest.php new file mode 100644 index 0000000..07d7b48 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/MtomServerInteropTest.php @@ -0,0 +1,44 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_MTOM, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'base64Binary' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\base64Binary', + 'AttachmentRequest' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\AttachmentRequest', + ), + 'proxy_host' => false, + ); + + public function testAttachment() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/MTOM.wsdl', $this->options); + + $b64 = new base64Binary(); + $b64->_ = 'This is a test. :)'; + $b64->contentType = 'text/plain'; + + $attachment = new AttachmentRequest(); + $attachment->fileName = 'test123.txt'; + $attachment->binaryData = $b64; + + $this->assertEquals('File saved succesfully.', $sc->attachment($attachment)); + + $fileCreatedByServer = __DIR__.'/'.$attachment->fileName; + $this->assertEquals($b64->_, file_get_contents($fileCreatedByServer)); + unlink($fileCreatedByServer); + } +} diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/SwAServer.php b/src/BeSimple/SoapClient/Tests/ServerInterop/SwAServer.php new file mode 100644 index 0000000..337a0a0 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/SwAServer.php @@ -0,0 +1,49 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_SWA, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'downloadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFile', + 'downloadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFileResponse', + 'uploadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFile', + 'uploadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFileResponse', + ), +); + +class SwA +{ + public function uploadFile(uploadFile $uploadFile) + { + file_put_contents(__DIR__.'/'.$uploadFile->name, $uploadFile->data); + + $ufr = new uploadFileResponse(); + $ufr->return = 'File saved succesfully.'; + + return $ufr; + } + + public function downloadFile(downloadFile $downloadFile) + { + $dfr = new downloadFileResponse(); + $dfr->data = file_get_contents(__DIR__.'/'.$downloadFile->name); + + return $dfr; + } +} + +$ss = new BeSimpleSoapServer(__DIR__.'/Fixtures/SwA.wsdl', $options); +$ss->setClass('SwA'); +$ss->handle(); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/SwaClient.php b/src/BeSimple/SoapClient/Tests/ServerInterop/SwaClient.php new file mode 100644 index 0000000..96f34fd --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/SwaClient.php @@ -0,0 +1,52 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_SWA, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders + 'classmap' => array( + 'downloadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFile', + 'downloadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFileResponse', + 'uploadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFile', + 'uploadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFileResponse', + ), +); + +$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $options); + +try { + + $upload = new uploadFile(); + $upload->name = 'upload.txt'; + $upload->data = 'This is a test. :)'; + $result = $sc->uploadFile($upload); + + var_dump($result); + + $download = new downloadFile(); + $download->name = 'upload.txt'; + var_dump($sc->downloadFile($download)); +} catch (Exception $e) { + var_dump($e); +} + +// var_dump( +// $sc->__getLastRequestHeaders(), +// $sc->__getLastRequest(), +// $sc->__getLastResponseHeaders(), +// $sc->__getLastResponse() +// ); \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/SwaServerInteropTest.php b/src/BeSimple/SoapClient/Tests/ServerInterop/SwaServerInteropTest.php new file mode 100644 index 0000000..01eaeae --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/SwaServerInteropTest.php @@ -0,0 +1,68 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_SWA, + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'downloadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFile', + 'downloadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\downloadFileResponse', + 'uploadFile' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFile', + 'uploadFileResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\uploadFileResponse', + ), + 'proxy_host' => false, + ); + + public function testUploadDownloadText() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $this->options); + + $upload = new uploadFile(); + $upload->name = 'upload.txt'; + $upload->data = 'This is a test. :)'; + $result = $sc->uploadFile($upload); + + $this->assertEquals('File saved succesfully.', $result->return); + + $download = new downloadFile(); + $download->name = 'upload.txt'; + $result = $sc->downloadFile($download); + + $this->assertEquals($upload->data, $result->data); + + unlink(__DIR__.'/../ServerInterop/'.$download->name); + } + + public function testUploadDownloadImage() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/SwA.wsdl', $this->options); + + $upload = new uploadFile(); + $upload->name = 'image.jpg'; + $upload->data = file_get_contents(__DIR__.'/Fixtures/image.jpg'); // source: http://www.freeimageslive.com/galleries/light/pics/swirl3768.jpg; + $result = $sc->uploadFile($upload); + + $this->assertEquals('File saved succesfully.', $result->return); + + $download = new downloadFile(); + $download->name = 'image.jpg'; + $result = $sc->downloadFile($download); + + $this->assertEquals($upload->data, $result->data); + + unlink(__DIR__.'/../ServerInterop/'.$download->name); + } +} diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/TestCase.php b/src/BeSimple/SoapClient/Tests/ServerInterop/TestCase.php new file mode 100644 index 0000000..b0f1f40 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/TestCase.php @@ -0,0 +1,29 @@ +markTestSkipped( + 'The PHP cli webserver is not available with PHP 5.3.' + ); + } + + $ch = curl_init('http://localhost:8081/'); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_NOBODY, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + if (curl_exec($ch) === false) { + $this->markTestSkipped( + 'The PHP webserver is not started on port 8081.' + ); + } + + curl_close($ch); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServer.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServer.php new file mode 100644 index 0000000..c8b01c6 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServer.php @@ -0,0 +1,82 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), +); + +class WsSecuritySigEncServer +{ + public function getBook(getBook $gb) + { + $bi = new BookInformation(); + $bi->isbn = $gb->isbn; + $bi->title = 'title'; + $bi->author = 'author'; + $bi->type = 'scifi'; + + $br = new getBookResponse(); + $br->getBookReturn = $bi; + + return $br; + } + + public function addBook(addBook $ab) + { + $abr = new addBookResponse(); + $abr->addBookReturn = true; + + return $abr; + } +} + +$ss = new BeSimpleSoapServer(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $options); + +$wssFilter = new BeSimpleWsSecurityFilter(); + +// user key for signature and encryption +$securityKeyUser = new BeSimpleWsSecurityKey(); +$securityKeyUser->addPrivateKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/serverkey.pem', true); +$securityKeyUser->addPublicKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/servercert.pem', true); +$wssFilter->setUserSecurityKeyObject($securityKeyUser); +// service key for encryption +$securityKeyService = new BeSimpleWsSecurityKey(); +$securityKeyService->addPrivateKey(XmlSecurityKey::TRIPLEDES_CBC); +$securityKeyService->addPublicKey(XmlSecurityKey::RSA_1_5, __DIR__.'/Fixtures/clientcert.pem', true); +$wssFilter->setServiceSecurityKeyObject($securityKeyService); +// TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | TOKEN_REFERENCE_SECURITY_TOKEN | TOKEN_REFERENCE_THUMBPRINT_SHA1 +$wssFilter->setSecurityOptionsSignature(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_SECURITY_TOKEN); +$wssFilter->setSecurityOptionsEncryption(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_THUMBPRINT_SHA1); + +$soapKernel = $ss->getSoapKernel(); +$soapKernel->registerFilter($wssFilter); + +$ss->setClass('WsSecuritySigEncServer'); +$ss->handle(); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerClient.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerClient.php new file mode 100644 index 0000000..1d529d6 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerClient.php @@ -0,0 +1,82 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), +); + +$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecuritySigEnc.wsdl', $options); + +//var_dump($sc->__getFunctions()); +//var_dump($sc->__getTypes()); + +try { + $wssFilter = new BeSimpleWsSecurityFilter(); + // user key for signature and encryption + $securityKeyUser = new BeSimpleWsSecurityKey(); + $securityKeyUser->addPrivateKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientkey.pem', true); + $securityKeyUser->addPublicKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientcert.pem', true); + $wssFilter->setUserSecurityKeyObject($securityKeyUser); + // service key for encryption + $securityKeyService = new BeSimpleWsSecurityKey(); + $securityKeyService->addPrivateKey(XmlSecurityKey::TRIPLEDES_CBC); + $securityKeyService->addPublicKey(XmlSecurityKey::RSA_1_5, __DIR__.'/Fixtures/servercert.pem', true); + $wssFilter->setServiceSecurityKeyObject($securityKeyService); + // TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | TOKEN_REFERENCE_SECURITY_TOKEN | TOKEN_REFERENCE_THUMBPRINT_SHA1 + $wssFilter->setSecurityOptionsSignature(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_SECURITY_TOKEN); + $wssFilter->setSecurityOptionsEncryption(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_THUMBPRINT_SHA1); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + var_dump($result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + var_dump($sc->addBook($ab)); + +} catch (Exception $e) { + var_dump($e); +} + +// var_dump( +// $sc->__getLastRequestHeaders(), +// $sc->__getLastRequest(), +// $sc->__getLastResponseHeaders(), +// $sc->__getLastResponse() +// ); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerInteropTest.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerInteropTest.php new file mode 100644 index 0000000..8978fd6 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecuritySigEncServerInteropTest.php @@ -0,0 +1,73 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), + 'proxy_host' => false, + ); + + public function testSigEnc() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecuritySigEnc.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(); + // user key for signature and encryption + $securityKeyUser = new BeSimpleWsSecurityKey(); + $securityKeyUser->addPrivateKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientkey.pem', true); + $securityKeyUser->addPublicKey(XmlSecurityKey::RSA_SHA1, __DIR__.'/Fixtures/clientcert.pem', true); + $wssFilter->setUserSecurityKeyObject($securityKeyUser); + // service key for encryption + $securityKeyService = new BeSimpleWsSecurityKey(); + $securityKeyService->addPrivateKey(XmlSecurityKey::TRIPLEDES_CBC); + $securityKeyService->addPublicKey(XmlSecurityKey::RSA_1_5, __DIR__.'/Fixtures/servercert.pem', true); + $wssFilter->setServiceSecurityKeyObject($securityKeyService); + // TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | TOKEN_REFERENCE_SECURITY_TOKEN | TOKEN_REFERENCE_THUMBPRINT_SHA1 + $wssFilter->setSecurityOptionsSignature(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_SECURITY_TOKEN); + $wssFilter->setSecurityOptionsEncryption(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_THUMBPRINT_SHA1); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } +} diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServer.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServer.php new file mode 100644 index 0000000..8a2e2dc --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServer.php @@ -0,0 +1,78 @@ + SOAP_1_1, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'cache_wsdl' => WSDL_CACHE_NONE, + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), +); + +class Auth +{ + public static function usernamePasswordCallback($user) + { + if ($user == 'libuser') { + return 'books'; + } + + return null; + } +} + +class WsSecurityUserPassServer +{ + public function getBook(getBook $gb) + { + $bi = new BookInformation(); + $bi->isbn = $gb->isbn; + $bi->title = 'title'; + $bi->author = 'author'; + $bi->type = 'scifi'; + + $br = new getBookResponse(); + $br->getBookReturn = $bi; + + return $br; + } + + public function addBook(addBook $ab) + { + $abr = new addBookResponse(); + $abr->addBookReturn = true; + + return $abr; + } +} + +$ss = new BeSimpleSoapServer(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $options); + +$wssFilter = new BeSimpleWsSecurityFilter(); +$wssFilter->setUsernamePasswordCallback(array('Auth', 'usernamePasswordCallback')); + +$soapKernel = $ss->getSoapKernel(); +$soapKernel->registerFilter($wssFilter); + +$ss->setClass('WsSecurityUserPassServer'); +$ss->handle(); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerClient.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerClient.php new file mode 100644 index 0000000..90cf534 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerClient.php @@ -0,0 +1,67 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), +); + +$sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $options); + +//var_dump($sc->__getFunctions()); +//var_dump($sc->__getTypes()); + +try { + $wssFilter = new BeSimpleWsSecurityFilter(true, 600); + $wssFilter->addUserData('libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_DIGEST); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + var_dump($result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + var_dump($sc->addBook($ab)); + +} catch (Exception $e) { + var_dump($e); +} + +// var_dump( +// $sc->__getLastRequestHeaders(), +// $sc->__getLastRequest(), +// $sc->__getLastResponseHeaders(), +// $sc->__getLastResponse() +// ); diff --git a/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerInteropTest.php b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerInteropTest.php new file mode 100644 index 0000000..efe86b5 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/ServerInterop/WsSecurityUserPassServerInteropTest.php @@ -0,0 +1,86 @@ + SOAP_1_2, + 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1 + 'classmap' => array( + 'getBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBook', + 'getBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBookResponse', + 'getBooksByType' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByType', + 'getBooksByTypeResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\getBooksByTypeResponse', + 'addBook' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBook', + 'addBookResponse' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\addBookResponse', + 'BookInformation' => 'BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', + ), + 'proxy_host' => false, + ); + + public function testUserPassText() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(true, 600); + $wssFilter->addUserData('libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_TEXT); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } + + public function testUserPassDigest() + { + $sc = new BeSimpleSoapClient(__DIR__.'/Fixtures/WsSecurityUserPass.wsdl', $this->options); + + $wssFilter = new BeSimpleWsSecurityFilter(true, 600); + $wssFilter->addUserData( 'libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_DIGEST ); + + $soapKernel = $sc->getSoapKernel(); + $soapKernel->registerFilter($wssFilter); + + $gb = new getBook(); + $gb->isbn = '0061020052'; + $result = $sc->getBook($gb); + $this->assertInstanceOf('BeSimple\SoapClient\Tests\ServerInterop\Fixtures\BookInformation', $result->getBookReturn); + + $ab = new addBook(); + $ab->isbn = '0445203498'; + $ab->title = 'The Dragon Never Sleeps'; + $ab->author = 'Cook, Glen'; + $ab->type = 'scifi'; + + $this->assertTrue((bool) $sc->addBook($ab)); + + // getBooksByType("scifi"); + } +} diff --git a/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php b/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php new file mode 100644 index 0000000..e9aecfb --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/SoapClientBuilderTest.php @@ -0,0 +1,133 @@ + + * (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\SoapClient\Tests; + +use BeSimple\SoapClient\SoapClientBuilder; + +class SoapClientBuilderTest extends \PHPUnit_Framework_TestCase +{ + private $defaultOptions = array( + 'features' => 0, + 'classmap' => array(), + 'typemap' => array(), + ); + + public function testContruct() + { + $options = $this + ->getSoapBuilder() + ->getSoapOptions() + ; + + $this->assertEquals($this->mergeOptions(array()), $options); + } + + public function testWithTrace() + { + $builder = $this->getSoapBuilder(); + + $builder->withTrace(); + $this->assertEquals($this->mergeOptions(array('trace' => true)), $builder->getSoapOptions()); + + $builder->withTrace(false); + $this->assertEquals($this->mergeOptions(array('trace' => false)), $builder->getSoapOptions()); + } + + public function testWithExceptions() + { + $builder = $this->getSoapBuilder(); + + $builder->withExceptions(); + $this->assertEquals($this->mergeOptions(array('exceptions' => true)), $builder->getSoapOptions()); + + $builder->withExceptions(false); + $this->assertEquals($this->mergeOptions(array('exceptions' => false)), $builder->getSoapOptions()); + } + + public function testWithUserAgent() + { + $builder = $this->getSoapBuilder(); + + $builder->withUserAgent('BeSimpleSoap Test'); + $this->assertEquals($this->mergeOptions(array('user_agent' => 'BeSimpleSoap Test')), $builder->getSoapOptions()); + } + + public function testWithCompression() + { + $builder = $this->getSoapBuilder(); + + $builder->withCompressionGzip(); + $this->assertEquals($this->mergeOptions(array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP)), $builder->getSoapOptions()); + + $builder->withCompressionDeflate(); + $this->assertEquals($this->mergeOptions(array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE)), $builder->getSoapOptions()); + } + + public function testWithAuthentication() + { + $builder = $this->getSoapBuilder(); + + $builder->withDigestAuthentication(__DIR__.'/Fixtures/cert.pem', 'foobar'); + $this->assertEquals($this->mergeOptions(array('authentication' => SOAP_AUTHENTICATION_DIGEST, 'local_cert' => __DIR__.'/Fixtures/cert.pem', 'passphrase' => 'foobar')), $builder->getSoapOptions()); + + $builder->withDigestAuthentication(__DIR__.'/Fixtures/cert.pem'); + $this->assertEquals($this->mergeOptions(array('authentication' => SOAP_AUTHENTICATION_DIGEST, 'local_cert' => __DIR__.'/Fixtures/cert.pem')), $builder->getSoapOptions()); + + $builder->withBasicAuthentication('foo', 'bar'); + $this->assertEquals($this->mergeOptions(array('authentication' => SOAP_AUTHENTICATION_BASIC, 'login' => 'foo', 'password' => 'bar')), $builder->getSoapOptions()); + } + + public function testWithProxy() + { + $builder = $this->getSoapBuilder(); + + $builder->withProxy('localhost', 8080); + $this->assertEquals($this->mergeOptions(array('proxy_host' => 'localhost', 'proxy_port' => 8080)), $builder->getSoapOptions()); + + $builder->withProxy('127.0.0.1', 8585, 'foo', 'bar'); + $this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar')), $builder->getSoapOptions()); + + $builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', \CURLAUTH_BASIC); + $this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar', 'proxy_auth' => \CURLAUTH_BASIC)), $builder->getSoapOptions()); + + $builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', \CURLAUTH_NTLM); + $this->assertEquals($this->mergeOptions(array('proxy_host' => '127.0.0.1', 'proxy_port' => 8585, 'proxy_login' => 'foo', 'proxy_password' => 'bar', 'proxy_auth' => \CURLAUTH_NTLM)), $builder->getSoapOptions()); + + try { + $builder->withProxy('127.0.0.1', 8585, 'foo', 'bar', -100); + + $this->fail('An expected exception has not been raised.'); + } catch (\Exception $e) { + $this->assertInstanceOf('InvalidArgumentException', $e); + } + } + + public function testCreateWithDefaults() + { + $builder = SoapClientBuilder::createWithDefaults(); + + $this->assertInstanceOf('BeSimple\SoapClient\SoapClientBuilder', $builder); + + $this->assertEquals($this->mergeOptions(array('soap_version' => SOAP_1_2, 'encoding' => 'UTF-8', 'features' => SOAP_SINGLE_ELEMENT_ARRAYS, 'user_agent' => 'BeSimpleSoap')), $builder->getSoapOptions()); + } + + private function getSoapBuilder() + { + return new SoapClientBuilder(); + } + + private function mergeOptions(array $options) + { + return array_merge($this->defaultOptions, $options); + } +} diff --git a/src/BeSimple/SoapClient/Tests/WsdlDownloaderTest.php b/src/BeSimple/SoapClient/Tests/WsdlDownloaderTest.php new file mode 100644 index 0000000..a5e4595 --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/WsdlDownloaderTest.php @@ -0,0 +1,291 @@ + + * (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\SoapClient\Tests; + +use BeSimple\SoapClient\WsdlDownloader; +use BeSimple\SoapCommon\Cache; +use BeSimple\SoapClient\Curl; +use Symfony\Component\Filesystem\Filesystem; +use org\bovigo\vfs\vfsStream; +use org\bovigo\vfs\vfsStreamWrapper; + +/** + * @author Andreas Schamberger + * @author Francis Besset + */ +class WsdlDownloaderTest extends AbstractWebserverTest +{ + static protected $filesystem; + + static protected $fixturesPath; + + /** + * @dataProvider provideDownload + */ + public function testDownload($source, $regexp, $nbDownloads) + { + $wsdlCacheDir = vfsStream::setup('wsdl'); + $wsdlCacheUrl = $wsdlCacheDir->url('wsdl'); + + Cache::setEnabled(Cache::ENABLED); + Cache::setDirectory($wsdlCacheUrl); + $cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#'); + + $wsdlDownloader = new WsdlDownloader(new Curl(array( + 'proxy_host' => false, + ))); + $this->assertCount(0, $wsdlCacheDir->getChildren()); + + $cacheFileName = $wsdlDownloader->download($source); + $this->assertCount($nbDownloads, $wsdlCacheDir->getChildren()); + + $this->assertRegExp('#'.sprintf($regexp, $cacheDirForRegExp).'#', file_get_contents($cacheFileName)); + } + + public function provideDownload() + { + return array( + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/build_include/xsdinctest_absolute.xml', + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_relative.xml', + '\.\./type_include\.xsd', + 1, + ), + array( + sprintf('http://localhost:%d/build_include/xsdinctest_absolute.xml', WEBSERVER_PORT), + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + array( + sprintf('http://localhost:%d/xsdinclude/xsdinctest_relative.xml', WEBSERVER_PORT), + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + ); + } + + public function testIsRemoteFile() + { + $wsdlDownloader = new WsdlDownloader(new Curl()); + + $r = new \ReflectionClass($wsdlDownloader); + $m = $r->getMethod('isRemoteFile'); + $m->setAccessible(true); + + $this->assertTrue($m->invoke($wsdlDownloader, 'http://www.php.net/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'http://localhost/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'http://mylocaldomain/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'http://www.php.net/dir/test.html')); + $this->assertTrue($m->invoke($wsdlDownloader, 'http://localhost/dir/test.html')); + $this->assertTrue($m->invoke($wsdlDownloader, 'http://mylocaldomain/dir/test.html')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://www.php.net/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://localhost/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://mylocaldomain/')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://www.php.net/dir/test.html')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://localhost/dir/test.html')); + $this->assertTrue($m->invoke($wsdlDownloader, 'https://mylocaldomain/dir/test.html')); + $this->assertFalse($m->invoke($wsdlDownloader, 'c:/dir/test.html')); + $this->assertFalse($m->invoke($wsdlDownloader, '/dir/test.html')); + $this->assertFalse($m->invoke($wsdlDownloader, '../dir/test.html')); + } + + /** + * @dataProvider provideResolveWsdlIncludes + */ + public function testResolveWsdlIncludes($source, $cacheFile, $remoteParentUrl, $regexp, $nbDownloads) + { + $wsdlCacheDir = vfsStream::setup('wsdl'); + $wsdlCacheUrl = $wsdlCacheDir->url('wsdl'); + + Cache::setEnabled(Cache::ENABLED); + Cache::setDirectory($wsdlCacheUrl); + $cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#'); + + $wsdlDownloader = new WsdlDownloader(new Curl(array( + 'proxy_host' => false, + ))); + $r = new \ReflectionClass($wsdlDownloader); + $m = $r->getMethod('resolveRemoteIncludes'); + $m->setAccessible(true); + + $this->assertCount(0, $wsdlCacheDir->getChildren()); + + $cacheFile = sprintf($cacheFile, $wsdlCacheUrl); + $m->invoke($wsdlDownloader, file_get_contents($source), $cacheFile, $remoteParentUrl); + $this->assertCount($nbDownloads, $wsdlCacheDir->getChildren()); + + $this->assertRegExp('#'.sprintf($regexp, $cacheDirForRegExp).'#', file_get_contents($cacheFile)); + } + + public function provideResolveWsdlIncludes() + { + $remoteUrlAbsolute = sprintf('http://localhost:%d/build_include/wsdlinctest_absolute.xml', WEBSERVER_PORT); + $remoteUrlRelative = sprintf('http://localhost:%d/wsdlinclude/wsdlinctest_relative.xml', WEBSERVER_PORT); + + return array( + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/build_include/wsdlinctest_absolute.xml', + '%s/cache_local_absolute.xml', + null, + '%s/wsdl_[a-f0-9]{32}.cache', + 2, + ), + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/wsdlinclude/wsdlinctest_relative.xml', + '%s/cache_local_relative.xml', + null, + '\.\./wsdl_include\.wsdl', + 1, + ), + array( + $remoteUrlAbsolute, + '%s/cache_remote_absolute.xml', + $remoteUrlAbsolute, + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + array( + $remoteUrlRelative, + '%s/cache_remote_relative.xml', + $remoteUrlRelative, + '%s/wsdl_[a-f0-9]{32}\.cache', + 2 + ), + ); + } + + /** + * @dataProvider provideResolveXsdIncludes + */ + public function testResolveXsdIncludes($source, $cacheFile, $remoteParentUrl, $regexp, $nbDownloads) + { + $wsdlCacheDir = vfsStream::setup('wsdl'); + $wsdlCacheUrl = $wsdlCacheDir->url('wsdl'); + + Cache::setEnabled(Cache::ENABLED); + Cache::setDirectory($wsdlCacheUrl); + $cacheDirForRegExp = preg_quote($wsdlCacheUrl, '#'); + + $wsdlDownloader = new WsdlDownloader(new Curl(array( + 'proxy_host' => false, + ))); + $r = new \ReflectionClass($wsdlDownloader); + $m = $r->getMethod('resolveRemoteIncludes'); + $m->setAccessible(true); + + $this->assertCount(0, $wsdlCacheDir->getChildren()); + + $cacheFile = sprintf($cacheFile, $wsdlCacheUrl); + $m->invoke($wsdlDownloader, file_get_contents($source), $cacheFile, $remoteParentUrl); + $this->assertCount($nbDownloads, $wsdlCacheDir->getChildren()); + + $this->assertRegExp('#'.sprintf($regexp, $cacheDirForRegExp).'#', file_get_contents($cacheFile)); + } + + public function provideResolveXsdIncludes() + { + $remoteUrlAbsolute = sprintf('http://localhost:%d/build_include/xsdinctest_absolute.xml', WEBSERVER_PORT); + $remoteUrlRelative = sprintf('http://localhost:%d/xsdinclude/xsdinctest_relative.xml', WEBSERVER_PORT); + + return array( + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/build_include/xsdinctest_absolute.xml', + '%s/cache_local_absolute.xml', + null, + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + array( + __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_relative.xml', + '%s/cache_local_relative.xml', + null, + '\.\./type_include\.xsd', + 1, + ), + array( + $remoteUrlAbsolute, + '%s/cache_remote_absolute.xml', + $remoteUrlAbsolute, + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + array( + $remoteUrlRelative, + '%s/cache_remote_relative.xml', + $remoteUrlRelative, + '%s/wsdl_[a-f0-9]{32}\.cache', + 2, + ), + ); + } + + public function testResolveRelativePathInUrl() + { + $wsdlDownloader = new WsdlDownloader(new Curl()); + + $r = new \ReflectionClass($wsdlDownloader); + $m = $r->getMethod('resolveRelativePathInUrl'); + $m->setAccessible(true); + + $this->assertEquals('http://localhost:8080/test', $m->invoke($wsdlDownloader, 'http://localhost:8080/sub', '/test')); + $this->assertEquals('http://localhost:8080/test', $m->invoke($wsdlDownloader, 'http://localhost:8080/sub/', '/test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub', '/test')); + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/', '/test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost', './test')); + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/', './test')); + + $this->assertEquals('http://localhost/sub/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub', './test')); + $this->assertEquals('http://localhost/sub/sub/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/', './test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub', '../test')); + $this->assertEquals('http://localhost/sub/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/', '../test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub', '../../test')); + $this->assertEquals('http://localhost/sub/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub/', '../../test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub/sub', '../../../test')); + $this->assertEquals('http://localhost/sub/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub/sub/', '../../../test')); + + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub', '../../../test')); + $this->assertEquals('http://localhost/test', $m->invoke($wsdlDownloader, 'http://localhost/sub/sub/sub/', '../../../test')); + } + + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + self::$filesystem = new Filesystem(); + self::$fixturesPath = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR; + self::$filesystem->mkdir(self::$fixturesPath.'build_include'); + + foreach (array('wsdlinclude/wsdlinctest_absolute.xml', 'xsdinclude/xsdinctest_absolute.xml') as $file) { + $content = file_get_contents(self::$fixturesPath.$file); + $content = preg_replace('#'.preg_quote('%location%').'#', sprintf('localhost:%d', WEBSERVER_PORT), $content); + + self::$filesystem->dumpFile(self::$fixturesPath.'build_include'.DIRECTORY_SEPARATOR.pathinfo($file, PATHINFO_BASENAME), $content); + } + } + + public static function tearDownAfterClass() + { + parent::tearDownAfterClass(); + + self::$filesystem->remove(self::$fixturesPath.'build_include'); + } +} diff --git a/src/BeSimple/SoapClient/Tests/bin/axis.sh b/src/BeSimple/SoapClient/Tests/bin/axis.sh new file mode 100755 index 0000000..7c9c59d --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/bin/axis.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR + +VERSION_AXIS=1.5.1 +ZIP_AXIS=axis2-$VERSION_AXIS-bin.zip +if [[ "$VERSION_AXIS" > "1.5.1" ]]; then + PATH_AXIS=http://archive.apache.org/dist/axis/axis2/java/core/$VERSION_AXIS/$ZIP_AXIS +else + PATH_AXIS=http://archive.apache.org/dist/ws/axis2/${VERSION_AXIS//./_}/$ZIP_AXIS +fi + +if [ ! -f "$DIR/$ZIP_AXIS" ]; then + curl -O -s $PATH_AXIS +fi + +VERSION_RAMPART=1.5 +ZIP_RAMPART=rampart-dist-$VERSION_RAMPART-bin.zip +PATH_RAMPART=http://archive.apache.org/dist/axis/axis2/java/rampart/$VERSION_RAMPART/$ZIP_RAMPART + +if [ ! -f "$DIR/$ZIP_RAMPART" ]; then + curl -O -s $PATH_RAMPART +fi + +unzip -o -qq "$DIR/$ZIP_AXIS" + +AXIS_DIR=$DIR/axis2-$VERSION_AXIS + +unzip -o -qq -j "$DIR/$ZIP_RAMPART" '*/lib/*.jar' -d $AXIS_DIR/lib +unzip -o -qq -j "$DIR/$ZIP_RAMPART" '*/modules/*.mar' -d $AXIS_DIR/repository/modules + +cp -r $DIR/../AxisInterop/axis_services/* $AXIS_DIR/repository/services + +$AXIS_DIR/bin/axis2server.sh& + +echo "Waiting until Axis is ready on port 8080" +while [[ -z `curl -s 'http://localhost:8080/axis2/services/' ` ]] +do + echo -n "." + sleep 2s +done + +echo "Axis is up" \ No newline at end of file diff --git a/src/BeSimple/SoapClient/Tests/bin/phpwebserver.sh b/src/BeSimple/SoapClient/Tests/bin/phpwebserver.sh new file mode 100755 index 0000000..0d07b8e --- /dev/null +++ b/src/BeSimple/SoapClient/Tests/bin/phpwebserver.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +PHPWEBSERVEROK="$( php -r "if (version_compare(phpversion(), '5.4', '<')) { echo 'nok'; } else { echo 'ok'; }" )" + +if [ "$PHPWEBSERVEROK" != "ok" ]; then + echo "No PHP webserver available before version 5.4..." + exit +fi + +DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $DIR + +php -S localhost:8081 -t "$DIR/.."& + +echo "Waiting until PHP webserver is ready on port 8081" +while [[ -z `curl -s 'http://localhost:8081' ` ]] +do + echo -n "." + sleep 2s +done + +echo "PHP webserver is up" \ No newline at end of file diff --git a/src/BeSimple/SoapClient/WsAddressingFilter.php b/src/BeSimple/SoapClient/WsAddressingFilter.php index 29cd3de..721fe87 100644 --- a/src/BeSimple/SoapClient/WsAddressingFilter.php +++ b/src/BeSimple/SoapClient/WsAddressingFilter.php @@ -94,16 +94,16 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter /** * List of reference parameters associated with this soap message. * - * @var array + * @var unknown_type */ - protected $referenceParametersSet; + protected $referenceParametersSet = array(); /** * List of reference parameters recieved with this soap message. * - * @var array + * @var unknown_type */ - protected $referenceParametersRecieved; + protected $referenceParametersRecieved = array(); /** * RelatesTo. @@ -214,7 +214,7 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter public function setMessageId($messageId = null) { if (null === $messageId) { - $messageId = 'uuid:' . Helper::generateUuid(); + $messageId = 'uuid:' . Helper::generateUUID(); } $this->messageId = $messageId; } @@ -259,7 +259,7 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter * * @return void */ - public function filterRequest(CommonSoapRequest $request, $attachmentType) + public function filterRequest(CommonSoapRequest $request) { // get \DOMDocument from SOAP request $dom = $request->getContentDocument(); @@ -328,7 +328,7 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter * * @return void */ - public function filterResponse(CommonSoapResponse $response, $attachmentType) + public function filterResponse(CommonSoapResponse $response) { // get \DOMDocument from SOAP response $dom = $response->getContentDocument(); @@ -344,4 +344,4 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter } } } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapClient/WsSecurityFilter.php b/src/BeSimple/SoapClient/WsSecurityFilter.php index 965a8cd..af51a62 100644 --- a/src/BeSimple/SoapClient/WsSecurityFilter.php +++ b/src/BeSimple/SoapClient/WsSecurityFilter.php @@ -104,11 +104,10 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque * Modify the given request XML. * * @param \BeSimple\SoapCommon\SoapRequest $request SOAP request - * @param int $attachmentType * * @return void */ - public function filterRequest(CommonSoapRequest $request, $attachmentType) + public function filterRequest(CommonSoapRequest $request) { // get \DOMDocument from SOAP request $dom = $request->getContentDocument(); @@ -175,7 +174,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque } if (null !== $this->userSecurityKey && $this->userSecurityKey->hasKeys()) { - $guid = 'CertId-' . Helper::generateUuid(); + $guid = 'CertId-' . Helper::generateUUID(); // add token references $keyInfo = null; if (null !== $this->tokenReferenceSignature) { @@ -201,7 +200,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque // encrypt soap document if (null !== $this->serviceSecurityKey && $this->serviceSecurityKey->hasKeys()) { - $guid = 'EncKey-' . Helper::generateUuid(); + $guid = 'EncKey-' . Helper::generateUUID(); // add token references $keyInfo = null; if (null !== $this->tokenReferenceEncryption) { @@ -227,11 +226,10 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque * Modify the given request XML. * * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response - * @param int $attachmentType * * @return void */ - public function filterResponse(CommonSoapResponse $response, $attachmentType) + public function filterResponse(CommonSoapResponse $response) { // get \DOMDocument from SOAP response $dom = $response->getContentDocument(); diff --git a/src/BeSimple/SoapClient/WsdlDownloader.php b/src/BeSimple/SoapClient/WsdlDownloader.php index 1c1d413..97a7d67 100644 --- a/src/BeSimple/SoapClient/WsdlDownloader.php +++ b/src/BeSimple/SoapClient/WsdlDownloader.php @@ -12,15 +12,8 @@ namespace BeSimple\SoapClient; -use BeSimple\SoapClient\Curl\Curl; -use BeSimple\SoapClient\Xml\RemoteFileResolver; -use BeSimple\SoapClient\Xml\XmlFileDomDocumentProcessor; use BeSimple\SoapCommon\Cache; use BeSimple\SoapCommon\Helper; -use DOMDocument; -use DOMElement; -use DOMXPath; -use Exception; /** * Downloads WSDL files with cURL. Uses the WSDL_CACHE_* constants and the @@ -32,56 +25,240 @@ use Exception; */ class WsdlDownloader { - public static function instantiateDownloader() + /** + * Cache enabled. + * + * @var bool + */ + protected $cacheEnabled; + + /** + * Cache dir. + * + * @var string + */ + protected $cacheDir; + + /** + * Cache TTL. + * + * @var int + */ + protected $cacheTtl; + + /** + * cURL instance for downloads. + * + * @var unknown_type + */ + protected $curl; + + /** + * Resolve WSDl/XSD includes. + * + * @var boolean + */ + protected $resolveRemoteIncludes = true; + + /** + * Constructor. + * + * @param \BeSimple\SoapClient\Curl $curl Curl instance + * @param boolean $resolveRemoteIncludes WSDL/XSD include enabled? + * @param boolean $cacheWsdl Cache constant + */ + public function __construct(Curl $curl, $resolveRemoteIncludes = true, $cacheWsdl = Cache::TYPE_DISK) { - return new self(); + $this->curl = $curl; + $this->resolveRemoteIncludes = (Boolean) $resolveRemoteIncludes; + + // get current WSDL caching config + $this->cacheEnabled = $cacheWsdl === Cache::TYPE_NONE ? Cache::DISABLED : Cache::ENABLED == Cache::isEnabled(); + $this->cacheDir = Cache::getDirectory(); + $this->cacheTtl = Cache::getLifetime(); } /** - * @param Curl $curl - * @param string $wsdlPath WSDL file URL/path - * @param int $wsdCacheType = Cache::TYPE_NONE|Cache::WSDL_CACHE_DISK|Cache::WSDL_CACHE_BOTH|Cache::WSDL_CACHE_MEMORY - * @param boolean $resolveRemoteIncludes + * Download given WSDL file and return name of cache file. + * + * @param string $wsdl WSDL file URL/path + * * @return string */ - public function getWsdlPath(Curl $curl, $wsdlPath, $wsdCacheType, $resolveRemoteIncludes = true) + public function download($wsdl) { - $isRemoteFile = RemoteFileResolver::instantiateResolver()->isRemoteFile($wsdlPath); - $isCacheEnabled = $wsdCacheType === Cache::TYPE_NONE ? false : Cache::isEnabled(); - if ($isCacheEnabled === true) { - $cacheFilePath = Cache::getDirectory() . DIRECTORY_SEPARATOR . 'wsdl_' . md5($wsdlPath) . '.cache'; - $isCacheExisting = file_exists($cacheFilePath); - if ($isCacheExisting) { - $fileModificationTime = filemtime($cacheFilePath); - if ($fileModificationTime === false) { - throw new Exception('File modification time could not be get for wsdl path: ' . $cacheFilePath); + // download and cache remote WSDL files or local ones where we want to + // resolve remote XSD includes + $isRemoteFile = $this->isRemoteFile($wsdl); + if ($isRemoteFile || $this->resolveRemoteIncludes) { + $cacheFilePath = $this->cacheDir.DIRECTORY_SEPARATOR.'wsdl_'.md5($wsdl).'.cache'; + + if (!$this->cacheEnabled || !file_exists($cacheFilePath) || (filemtime($cacheFilePath) + $this->cacheTtl) < time()) { + if ($isRemoteFile) { + // execute request + $responseSuccessfull = $this->curl->exec($wsdl); + // get content + if ($responseSuccessfull) { + $response = $this->curl->getResponseBody(); + + if ($this->resolveRemoteIncludes) { + $this->resolveRemoteIncludes($response, $cacheFilePath, $wsdl); + } else { + file_put_contents($cacheFilePath, $response); + } + } else { + throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'"); + } + } elseif (file_exists($wsdl)) { + $response = file_get_contents($wsdl); + $this->resolveRemoteIncludes($response, $cacheFilePath); + } else { + throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'"); } - $isCacheValid = ($fileModificationTime + Cache::getLifetime()) >= time(); - } else { - $isCacheExisting = $isCacheValid = false; - } - if ($isCacheExisting === false || $isCacheValid === false) { - XmlFileDomDocumentProcessor::writeCacheFile($curl, $wsdCacheType, $wsdlPath, $cacheFilePath, $resolveRemoteIncludes, $isRemoteFile); } - return $this->getLocalWsdlPath($cacheFilePath); - - } - if ($isRemoteFile === true) { - return $wsdlPath; + return $cacheFilePath; + } elseif (file_exists($wsdl)) { + return realpath($wsdl); } - return $this->getLocalWsdlPath($wsdlPath); + throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'"); } - private function getLocalWsdlPath($wsdlPath) + /** + * Do we have a remote file? + * + * @param string $file File URL/path + * + * @return boolean + */ + private function isRemoteFile($file) { - if (file_exists($wsdlPath)) { - - return realpath($wsdlPath); - + // @parse_url to suppress E_WARNING for invalid urls + if (false !== $url = @parse_url($file)) { + if (isset($url['scheme']) && 'http' === substr($url['scheme'], 0, 4)) { + return true; + } } - throw new Exception('Could not download WSDL: local file does not exist: ' . $wsdlPath); + return false; + } + + /** + * Resolves remote WSDL/XSD includes within the WSDL files. + * + * @param string $xml XML file + * @param string $cacheFilePath Cache file name + * @param boolean $parentFilePath Parent file name + * + * @return void + */ + private function resolveRemoteIncludes($xml, $cacheFilePath, $parentFilePath = null) + { + $doc = new \DOMDocument(); + $doc->loadXML($xml); + + $xpath = new \DOMXPath($doc); + $xpath->registerNamespace(Helper::PFX_XML_SCHEMA, Helper::NS_XML_SCHEMA); + $xpath->registerNamespace(Helper::PFX_WSDL, Helper::NS_WSDL); + + // WSDL include/import + $query = './/'.Helper::PFX_WSDL.':include | .//'.Helper::PFX_WSDL.':import'; + $nodes = $xpath->query($query); + if ($nodes->length > 0) { + foreach ($nodes as $node) { + $location = $node->getAttribute('location'); + if ($this->isRemoteFile($location)) { + $location = $this->download($location); + $node->setAttribute('location', $location); + } elseif (null !== $parentFilePath) { + $location = $this->resolveRelativePathInUrl($parentFilePath, $location); + $location = $this->download($location); + $node->setAttribute('location', $location); + } + } + } + + // XML schema include/import + $query = './/'.Helper::PFX_XML_SCHEMA.':include | .//'.Helper::PFX_XML_SCHEMA.':import'; + $nodes = $xpath->query($query); + if ($nodes->length > 0) { + foreach ($nodes as $node) { + if ($node->hasAttribute('schemaLocation')) { + $schemaLocation = $node->getAttribute('schemaLocation'); + if ($this->isRemoteFile($schemaLocation)) { + $schemaLocation = $this->download($schemaLocation); + $node->setAttribute('schemaLocation', $schemaLocation); + } elseif (null !== $parentFilePath) { + $schemaLocation = $this->resolveRelativePathInUrl($parentFilePath, $schemaLocation); + $schemaLocation = $this->download($schemaLocation); + $node->setAttribute('schemaLocation', $schemaLocation); + } + } + } + } + + $doc->save($cacheFilePath); + } + + /** + * Resolves the relative path to base into an absolute. + * + * @param string $base Base path + * @param string $relative Relative path + * + * @return string + */ + private function resolveRelativePathInUrl($base, $relative) + { + $urlParts = parse_url($base); + + // combine base path with relative path + if (isset($urlParts['path']) && '/' === $relative{0}) { + // $relative is absolute path from domain (starts with /) + $path = $relative; + } elseif (isset($urlParts['path']) && strrpos($urlParts['path'], '/') === (strlen($urlParts['path']) )) { + // base path is directory + $path = $urlParts['path'].$relative; + } elseif (isset($urlParts['path'])) { + // strip filename from base path + $path = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')).'/'.$relative; + } else { + // no base path + $path = '/'.$relative; + } + + // foo/./bar ==> foo/bar + // remove double slashes + $path = preg_replace(array('#/\./#', '#/+#'), '/', $path); + + // split path by '/' + $parts = explode('/', $path); + + // resolve /../ + foreach ($parts as $key => $part) { + if ('..' === $part) { + $keyToDelete = $key - 1; + + while ($keyToDelete > 0) { + if (isset($parts[$keyToDelete])) { + unset($parts[$keyToDelete]); + + break; + } + + $keyToDelete--; + } + + unset($parts[$key]); + } + } + + $hostname = $urlParts['scheme'].'://'.$urlParts['host']; + if (isset($urlParts['port'])) { + $hostname .= ':'.$urlParts['port']; + } + + return $hostname.implode('/', $parts); } } diff --git a/src/BeSimple/SoapClient/Xml/Path/RelativePathResolver.php b/src/BeSimple/SoapClient/Xml/Path/RelativePathResolver.php deleted file mode 100644 index 7d29221..0000000 --- a/src/BeSimple/SoapClient/Xml/Path/RelativePathResolver.php +++ /dev/null @@ -1,75 +0,0 @@ - foo/bar - // remove double slashes - $path = preg_replace(array('#/\./#', '#/+#'), '/', $path); - - // split path by '/' - $parts = explode('/', $path); - - // resolve /../ - foreach ($parts as $key => $part) { - if ($part === '..') { - $keyToDelete = $key - 1; - while ($keyToDelete > 0) { - if (isset($parts[$keyToDelete])) { - unset($parts[$keyToDelete]); - - break; - } - - $keyToDelete--; - } - - unset($parts[$key]); - } - } - - $hostname = $urlParts['scheme'].'://'.$urlParts['host']; - if (isset($urlParts['port'])) { - $hostname .= ':'.$urlParts['port']; - } - $implodedParts = implode('/', $parts); - if (substr($implodedParts, 0, 1) !== '/') { - $implodedParts = '/'.$implodedParts; - } - - return $hostname.$implodedParts; - } -} diff --git a/src/BeSimple/SoapClient/Xml/RemoteFileResolver.php b/src/BeSimple/SoapClient/Xml/RemoteFileResolver.php deleted file mode 100644 index 0f6d0e7..0000000 --- a/src/BeSimple/SoapClient/Xml/RemoteFileResolver.php +++ /dev/null @@ -1,32 +0,0 @@ -registerNamespace($schemaPrefix, $schemaUrl); - $nodes = $xpath->query('.//'.$schemaPrefix.':include | .//'.$schemaPrefix.':import'); - if ($nodes->length > 0) { - foreach ($nodes as $node) { - /** @var DOMElement $node */ - $locationPath = $node->getAttribute($locationAttributeName); - if ($locationPath !== '') { - if (RemoteFileResolver::instantiateResolver()->isRemoteFile($locationPath)) { - $node->setAttribute( - $locationAttributeName, - WsdlDownloader::instantiateDownloader()->getWsdlPath( - $curl, - $locationPath, - $cacheType, - true - ) - ); - } elseif ($parentFilePath !== null) { - $node->setAttribute( - $locationAttributeName, - WsdlDownloader::instantiateDownloader()->getWsdlPath( - $curl, - RelativePathResolver::instantiateResolver() - ->resolveRelativePathInUrl($parentFilePath, $locationPath), - $cacheType, - true - ) - ); - } - } - } - } - } -} diff --git a/src/BeSimple/SoapClient/Xml/XmlFileDomDocumentProcessor.php b/src/BeSimple/SoapClient/Xml/XmlFileDomDocumentProcessor.php deleted file mode 100644 index 1e8f079..0000000 --- a/src/BeSimple/SoapClient/Xml/XmlFileDomDocumentProcessor.php +++ /dev/null @@ -1,77 +0,0 @@ -executeCurlWithCachedSession($wsdlPath); - if ($curlResponse->curlStatusSuccess()) { - if (mb_strlen($curlResponse->getResponseBody()) === 0) { - throw new Exception('Could not write WSDL cache file: empty curl response from: '.$wsdlPath); - } - if ($resolveRemoteIncludes === true) { - $document = self::getXmlFileDomDocument($curl, $cacheType, $curlResponse->getResponseBody(), $wsdlPath); - self::saveXmlDomDocument($document, $cacheFilePath); - } else { - file_put_contents($cacheFilePath, $curlResponse->getResponseBody()); - } - } else { - throw new Exception('Could not write WSDL cache file: Download failed with message: '.$curlResponse->getCurlErrorMessage()); - } - } else { - if (file_exists($wsdlPath)) { - $document = self::getXmlFileDomDocument($curl, $cacheType, file_get_contents($wsdlPath)); - self::saveXmlDomDocument($document, $cacheFilePath); - } else { - throw new Exception('Could write WSDL cache file: local file does not exist: '.$wsdlPath); - } - } - } - - /** - * Resolves remote WSDL/XSD includes within the WSDL files. - * - * @param Curl $curl - * @param int $cacheType - * @param string $xmlFileSource XML file contents - * @param boolean $parentFilePath Parent file name - * @return DOMDocument - */ - private static function getXmlFileDomDocument(Curl $curl, $cacheType, $xmlFileSource, $parentFilePath = null) - { - $document = new DOMDocument('1.0', 'utf-8'); - if ($document->loadXML($xmlFileSource) === false) { - throw new Exception('Could not save downloaded WSDL cache: '.$xmlFileSource); - } - - $xpath = new DOMXPath($document); - $xmlDomDocumentImportReplacer = XmlDomDocumentImportReplacer::instantiateReplacer(); - $xmlDomDocumentImportReplacer->updateXmlDocument($curl, $cacheType, $xpath, Helper::PFX_WSDL, Helper::NS_WSDL, 'location', $parentFilePath); - $xmlDomDocumentImportReplacer->updateXmlDocument($curl, $cacheType, $xpath, Helper::PFX_XML_SCHEMA, Helper::NS_XML_SCHEMA, 'schemaLocation', $parentFilePath); - - return $document; - } - - private static function saveXmlDomDocument(DOMDocument $document, $cacheFilePath) - { - try { - $xmlContents = $document->saveXML(); - if ($xmlContents === '') { - throw new Exception('Could not write WSDL cache file: DOMDocument returned empty XML file'); - } - file_put_contents($cacheFilePath, $xmlContents); - } catch (Exception $e) { - unlink($cacheFilePath); - throw new Exception('Could not write WSDL cache file: save method returned error: ' . $e->getMessage()); - } - } -} diff --git a/src/BeSimple/SoapClient/XmlMimeFilter.php b/src/BeSimple/SoapClient/XmlMimeFilter.php index b34a23a..ae8ed45 100644 --- a/src/BeSimple/SoapClient/XmlMimeFilter.php +++ b/src/BeSimple/SoapClient/XmlMimeFilter.php @@ -1,5 +1,15 @@ + * (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\SoapClient; use BeSimple\SoapCommon\FilterHelper; @@ -14,7 +24,21 @@ use BeSimple\SoapCommon\SoapRequestFilter; */ class XmlMimeFilter implements SoapRequestFilter { - public function filterRequest(SoapRequest $request, $attachmentType) + /** + * Reset all properties to default values. + */ + public function resetFilter() + { + } + + /** + * Modify the given request XML. + * + * @param \BeSimple\SoapCommon\SoapRequest $request SOAP request + * + * @return void + */ + public function filterRequest(SoapRequest $request) { // get \DOMDocument from SOAP request $dom = $request->getContentDocument(); @@ -42,6 +66,5 @@ class XmlMimeFilter implements SoapRequestFilter } } - return $request; } } diff --git a/src/BeSimple/SoapCommon/AbstractSoapBuilder.php b/src/BeSimple/SoapCommon/AbstractSoapBuilder.php new file mode 100644 index 0000000..7c4dfdf --- /dev/null +++ b/src/BeSimple/SoapCommon/AbstractSoapBuilder.php @@ -0,0 +1,246 @@ + + * (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\Converter\TypeConverterCollection; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; + +/** + * @author Christian Kerl + * @author Francis Besset + */ +abstract class AbstractSoapBuilder +{ + protected $wsdl; + protected $soapOptions = array(); + + /** + * @return AbstractSoapBuilder + */ + static public function createWithDefaults() + { + $builder = new static(); + + return $builder + ->withSoapVersion12() + ->withEncoding('UTF-8') + ->withSingleElementArrays() + ; + } + + public function __construct() + { + $this->soapOptions['features'] = 0; + $this->soapOptions['classmap'] = new Classmap(); + $this->soapOptions['typemap'] = new TypeConverterCollection(); + } + + public function getWsdl() + { + return $this->wsdl; + } + + public function getSoapOptions() + { + $options = $this->soapOptions; + + $options['classmap'] = $this->soapOptions['classmap']->all(); + $options['typemap'] = $this->soapOptions['typemap']->getTypemap(); + + return $options; + } + + /** + * @return AbstractSoapBuilder + */ + public function withWsdl($wsdl) + { + $this->wsdl = $wsdl; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withSoapVersion11() + { + $this->soapOptions['soap_version'] = \SOAP_1_1; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withSoapVersion12() + { + $this->soapOptions['soap_version'] = \SOAP_1_2; + + return $this; + } + + public function withEncoding($encoding) + { + $this->soapOptions['encoding'] = $encoding; + + return $this; + } + + public function withWsdlCache($cache) + { + if (!in_array($cache, Cache::getTypes(), true)) { + throw new \InvalidArgumentException(); + } + + $this->soapOptions['cache_wsdl'] = $cache; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withWsdlCacheNone() + { + $this->soapOptions['cache_wsdl'] = Cache::TYPE_NONE; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withWsdlCacheDisk() + { + $this->soapOptions['cache_wsdl'] = Cache::TYPE_DISK; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withWsdlCacheMemory() + { + $this->soapOptions['cache_wsdl'] = Cache::TYPE_MEMORY; + + return $this; + } + + /** + * @return AbstractSoapBuilder + */ + public function withWsdlCacheDiskAndMemory() + { + $this->soapOptions['cache_wsdl'] = Cache::TYPE_DISK_MEMORY; + + 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. + * + * @return AbstractSoapBuilder + */ + public function withSingleElementArrays() + { + $this->soapOptions['features'] |= \SOAP_SINGLE_ELEMENT_ARRAYS; + + return $this; + } + + /** + * Enables the SOAP_WAIT_ONE_WAY_CALLS feature. + * + * @return AbstractSoapBuilder + */ + public function withWaitOneWayCalls() + { + $this->soapOptions['features'] |= \SOAP_WAIT_ONE_WAY_CALLS; + + return $this; + } + + /** + * Enables the SOAP_USE_XSI_ARRAY_TYPE feature. + * + * @return AbstractSoapBuilder + */ + public function withUseXsiArrayType() + { + $this->soapOptions['features'] |= \SOAP_USE_XSI_ARRAY_TYPE; + + return $this; + } + + public function withTypeConverter(TypeConverterInterface $converter) + { + $this->soapOptions['typemap']->add($converter); + + return $this; + } + + public function withTypeConverters(TypeConverterCollection $converters, $merge = true) + { + if ($merge) { + $this->soapOptions['typemap']->addCollection($converters); + } else { + $this->soapOptions['typemap']->set($converters->all()); + } + + return $this; + } + + /** + * Adds a class mapping to the classmap. + * + * @param string $xmlType + * @param string $phpType + * + * @return AbstractSoapBuilder + */ + public function withClassMapping($xmlType, $phpType) + { + $this->soapOptions['classmap']->add($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. + * + * @return AbstractSoapBuilder + */ + public function withClassmap(Classmap $classmap, $merge = true) + { + if ($merge) { + $this->soapOptions['classmap']->addClassmap($classmap); + } else { + $this->soapOptions['classmap']->set($classmap->all()); + } + + return $this; + } + + protected function validateWsdl() + { + if (null === $this->wsdl) { + throw new \InvalidArgumentException('The WSDL has to be configured!'); + } + } +} diff --git a/src/BeSimple/SoapCommon/AttachmentsHandlerInterface.php b/src/BeSimple/SoapCommon/AttachmentsHandlerInterface.php deleted file mode 100644 index 5ffd483..0000000 --- a/src/BeSimple/SoapCommon/AttachmentsHandlerInterface.php +++ /dev/null @@ -1,15 +0,0 @@ - */ @@ -27,29 +25,24 @@ class Cache const TYPE_MEMORY = WSDL_CACHE_MEMORY; const TYPE_DISK_MEMORY = WSDL_CACHE_BOTH; - static protected $types = [ + static protected $types = array( self::TYPE_NONE, self::TYPE_DISK, self::TYPE_MEMORY, self::TYPE_DISK_MEMORY, - ]; + ); - public static function getTypes() + static public function getTypes() { return self::$types; } - public static function hasType($cacheType) + static public function isEnabled() { - return in_array($cacheType, self::$types); + return self::iniGet('soap.wsdl_cache_enabled'); } - public static function isEnabled() - { - return self::iniGet('soap.wsdl_cache_enabled') === '1'; - } - - public static function setEnabled($enabled) + static public function setEnabled($enabled) { if (!in_array($enabled, array(self::ENABLED, self::DISABLED), true)) { throw new \InvalidArgumentException(); @@ -58,59 +51,61 @@ class Cache self::iniSet('soap.wsdl_cache_enabled', $enabled); } - public static function getType() + static public function getType() { return self::iniGet('soap.wsdl_cache'); } - public static function setType($type) + static public function setType($type) { if (!in_array($type, self::getTypes(), true)) { - throw new InvalidArgumentException( - 'The cache type has to be either Cache::TYPE_NONE, Cache::TYPE_DISK, Cache::TYPE_MEMORY or Cache::TYPE_DISK_MEMORY' - ); + throw new \InvalidArgumentException('The cache type has to be either Cache::TYPE_NONE, Cache::TYPE_DISK, Cache::TYPE_MEMORY or Cache::TYPE_DISK_MEMORY'); } self::iniSet('soap.wsdl_cache', $type); } - public static function getDirectory() + static public function getDirectory() { return self::iniGet('soap.wsdl_cache_dir'); } - public static function setDirectory($directory) + static public function setDirectory($directory) { + if (!is_dir($directory)) { + mkdir($directory, 0777, true); + } + self::iniSet('soap.wsdl_cache_dir', $directory); } - public static function getLifetime() + static public function getLifetime() { return self::iniGet('soap.wsdl_cache_ttl'); } - public static function setLifetime($lifetime) + static public function setLifetime($lifetime) { self::iniSet('soap.wsdl_cache_ttl', $lifetime); } - public static function getLimit() + static public function getLimit() { return self::iniGet('soap.wsdl_cache_limit'); } - public static function setLimit($limit) + static public function setLimit($limit) { self::iniSet('soap.wsdl_cache_limit', $limit); } - protected static function iniGet($key) + static protected function iniGet($key) { return ini_get($key); } - protected static function iniSet($key, $value) + static protected function iniSet($key, $value) { ini_set($key, $value); } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/ClassMap.php b/src/BeSimple/SoapCommon/ClassMap.php deleted file mode 100644 index be1c259..0000000 --- a/src/BeSimple/SoapCommon/ClassMap.php +++ /dev/null @@ -1,97 +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; - -/** - * @author Francis Besset - */ -class ClassMap -{ - protected $classMap; - protected $inverseClassMap; - - public function __construct(array $classMap = []) - { - $this->classmap = []; - foreach ($classMap as $type => $className) { - $this->add($type, $className); - } - } - - /** - * @return array - */ - public function getAll() - { - return $this->classMap; - } - - /** - * @param string $type - * @return string - * @throws \InvalidArgumentException - */ - public function get($type) - { - if (!$this->has($type)) { - throw new \InvalidArgumentException(sprintf('The type "%s" does not exists', $type)); - } - - return $this->classMap[$type]; - } - - /** - * @param string $type - * @param string $className - * @throws \InvalidArgumentException - */ - public function add($type, $className) - { - if ($this->has($type)) { - throw new \InvalidArgumentException(sprintf('The type "%s" already exists', $type)); - } - - $this->classMap[$type] = $className; - $this->inverseClassMap[$className] = $type; - } - - /** - * @param string $type - * @return boolean - */ - public function has($type) - { - return isset($this->classmap[$type]); - } - - public function getByClassName($className) - { - if (!$this->hasByClassName($className)) { - throw new \InvalidArgumentException(sprintf('The className "%s" was not found in %s', $className, __CLASS__)); - } - - return $this->inverseClassMap[$className]; - } - - public function hasByClassName($className) - { - return isset($this->inverseClassMap[$className]); - } - - public function addClassMap(ClassMap $classMap) - { - foreach ($classMap->getAll() as $type => $className) { - $this->add($type, $className); - } - } -} diff --git a/src/BeSimple/SoapCommon/Converter/DateTimeTypeConverter.php b/src/BeSimple/SoapCommon/Converter/DateTimeTypeConverter.php index d312182..6b0a729 100644 --- a/src/BeSimple/SoapCommon/Converter/DateTimeTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/DateTimeTypeConverter.php @@ -44,3 +44,4 @@ class DateTimeTypeConverter implements TypeConverterInterface return sprintf('<%1$s>%2$s', $this->getTypeName(), $data->format('Y-m-d\TH:i:sP')); } } + diff --git a/src/BeSimple/SoapCommon/Converter/DateTypeConverter.php b/src/BeSimple/SoapCommon/Converter/DateTypeConverter.php index 66dcbd8..11d5ad2 100644 --- a/src/BeSimple/SoapCommon/Converter/DateTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/DateTypeConverter.php @@ -44,3 +44,4 @@ class DateTypeConverter implements TypeConverterInterface return sprintf('<%1$s>%2$s', $this->getTypeName(), $data->format('Y-m-d')); } } + diff --git a/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php index 23cf184..52ea961 100644 --- a/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/MtomTypeConverter.php @@ -14,14 +14,22 @@ namespace BeSimple\SoapCommon\Converter; use BeSimple\SoapCommon\Helper; use BeSimple\SoapCommon\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapKernel; +use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; /** * MTOM type converter. * * @author Andreas Schamberger */ -class MtomTypeConverter implements TypeConverterInterface +class MtomTypeConverter implements TypeConverterInterface, SoapKernelAwareInterface { + /** + * @var \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + */ + protected $soapKernel = null; + /** * {@inheritDoc} */ @@ -46,6 +54,25 @@ class MtomTypeConverter implements TypeConverterInterface $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 = $this->soapKernel->getAttachment($contentId))) { + + return $part->getContent(); + } else { + + return null; + } + } + return $data; } @@ -57,6 +84,8 @@ class MtomTypeConverter implements TypeConverterInterface $part = new MimePart($data); $contentId = trim($part->getHeader('Content-ID'), '<>'); + $this->soapKernel->addAttachment($part); + $doc = new \DOMDocument(); $node = $doc->createElement($this->getTypeName()); $doc->appendChild($node); @@ -68,4 +97,12 @@ class MtomTypeConverter implements TypeConverterInterface 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 71d31d1..c199e3c 100644 --- a/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php +++ b/src/BeSimple/SoapCommon/Converter/SwaTypeConverter.php @@ -1,16 +1,34 @@ + * (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\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapKernel; +use BeSimple\SoapCommon\Converter\SoapKernelAwareInterface; +use BeSimple\SoapCommon\Converter\TypeConverterInterface; /** * SwA type converter. * * @author Andreas Schamberger */ -class SwaTypeConverter implements TypeConverterInterface +class SwaTypeConverter implements TypeConverterInterface, SoapKernelAwareInterface { + /** + * @var \BeSimple\SoapCommon\SoapKernel $soapKernel SoapKernel instance + */ + protected $soapKernel = null; + /** * {@inheritDoc} */ @@ -35,6 +53,22 @@ class SwaTypeConverter implements TypeConverterInterface $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 = $this->soapKernel->getAttachment($contentId))) { + + return $part->getContent(); + } else { + + return null; + } + } + return $data; } @@ -46,6 +80,16 @@ class SwaTypeConverter implements TypeConverterInterface $part = new MimePart($data); $contentId = trim($part->getHeader('Content-ID'), '<>'); + $this->soapKernel->addAttachment($part); + return sprintf('<%s href="%s"/>', $this->getTypeName(), 'cid:' . $contentId); } + + /** + * {@inheritDoc} + */ + public function setKernel(SoapKernel $soapKernel) + { + $this->soapKernel = $soapKernel; + } } diff --git a/src/BeSimple/SoapCommon/Converter/TypeConverterCollection.php b/src/BeSimple/SoapCommon/Converter/TypeConverterCollection.php index 6d918a0..7f06142 100644 --- a/src/BeSimple/SoapCommon/Converter/TypeConverterCollection.php +++ b/src/BeSimple/SoapCommon/Converter/TypeConverterCollection.php @@ -19,7 +19,7 @@ class TypeConverterCollection { private $converters = array(); - public function getAll() + public function all() { return array_values($this->converters); } @@ -58,7 +58,7 @@ class TypeConverterCollection public function addCollection(TypeConverterCollection $converterCollection) { - foreach ($converterCollection->getAll() as $converter) { + foreach ($converterCollection->all() as $converter) { $this->add($converter); } } @@ -74,10 +74,10 @@ class TypeConverterCollection $typemap[] = array( 'type_name' => $converter->getTypeName(), 'type_ns' => $converter->getTypeNamespace(), - 'from_xml' => function ($input) use ($converter) { + 'from_xml' => function($input) use ($converter) { return $converter->convertXmlToPhp($input); }, - 'to_xml' => function ($input) use ($converter) { + 'to_xml' => function($input) use ($converter) { return $converter->convertPhpToXml($input); }, ); diff --git a/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php b/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php index 50be071..e390963 100644 --- a/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php +++ b/src/BeSimple/SoapCommon/Converter/TypeConverterInterface.php @@ -24,14 +24,14 @@ interface TypeConverterInterface * * @return string */ - public function getTypeNamespace(); + function getTypeNamespace(); /** * Get type name. * * @return string */ - public function getTypeName(); + function getTypeName(); /** * Convert given XML string to PHP type. @@ -40,7 +40,7 @@ interface TypeConverterInterface * * @return mixed */ - public function convertXmlToPhp($data); + function convertXmlToPhp($data); /** * Convert PHP type to XML string. @@ -49,5 +49,5 @@ interface TypeConverterInterface * * @return string */ - public function convertPhpToXml($data); -} + function convertPhpToXml($data); +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Definition/Type/TypeRepository.php b/src/BeSimple/SoapCommon/Definition/Type/TypeRepository.php index 3a47986..38d0f30 100644 --- a/src/BeSimple/SoapCommon/Definition/Type/TypeRepository.php +++ b/src/BeSimple/SoapCommon/Definition/Type/TypeRepository.php @@ -12,7 +12,7 @@ namespace BeSimple\SoapCommon\Definition\Type; -use BeSimple\SoapCommon\ClassMap; +use BeSimple\SoapCommon\Classmap; /** * @author Christian Kerl @@ -27,7 +27,7 @@ class TypeRepository protected $classmap; - public function __construct(ClassMap $classmap = null) + public function __construct(Classmap $classmap = null) { $this->classmap = $classmap; } @@ -77,7 +77,7 @@ class TypeRepository $phpType = $type->getPhpType(); $this->types[$phpType] = $type; - $this->addClassMap($type->getXmlType(), $phpType); + $this->addClassmap($type->getXmlType(), $phpType); } public function hasType($type) @@ -119,12 +119,12 @@ class TypeRepository return $match[1]; } - public function getClassMap() + public function getClassmap() { return $this->classmap; } - protected function addClassMap($xmlType, $phpType) + protected function addClassmap($xmlType, $phpType) { if (!$this->classmap) { return; diff --git a/src/BeSimple/SoapCommon/Fault/SoapFaultEnum.php b/src/BeSimple/SoapCommon/Fault/SoapFaultEnum.php deleted file mode 100644 index 1428513..0000000 --- a/src/BeSimple/SoapCommon/Fault/SoapFaultEnum.php +++ /dev/null @@ -1,10 +0,0 @@ -xpath('//faultcode'); - if ($faultCode === false || count($faultCode) === 0) { - $faultCode = 'Unable to parse faultCode'; - } - $faultString = $simpleXMLElement->xpath('//faultstring'); - if ($faultString === false || count($faultString) === 0) { - $faultString = 'Unable to parse faultString'; - } - - return new SoapFault( - (string)$faultCode[0], - (string)$faultString[0] - ); - } -} diff --git a/src/BeSimple/SoapCommon/Fault/SoapFaultPrefixEnum.php b/src/BeSimple/SoapCommon/Fault/SoapFaultPrefixEnum.php deleted file mode 100644 index a864f79..0000000 --- a/src/BeSimple/SoapCommon/Fault/SoapFaultPrefixEnum.php +++ /dev/null @@ -1,9 +0,0 @@ -faultcode, $nativeSoapFaultPrefix) === 0) { - - return true; - } - - return false; - } -} diff --git a/src/BeSimple/SoapCommon/FilterHelper.php b/src/BeSimple/SoapCommon/FilterHelper.php index 7806617..01a1717 100644 --- a/src/BeSimple/SoapCommon/FilterHelper.php +++ b/src/BeSimple/SoapCommon/FilterHelper.php @@ -175,4 +175,4 @@ class FilterHelper $this->namespaces[$namespaceURI] = $prefix; } } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Helper.php b/src/BeSimple/SoapCommon/Helper.php index 5a340e1..c33a9df 100644 --- a/src/BeSimple/SoapCommon/Helper.php +++ b/src/BeSimple/SoapCommon/Helper.php @@ -167,13 +167,12 @@ class Helper * @see http://de.php.net/manual/en/function.uniqid.php#94959 * @return string */ - public static function generateUuid() + public static function generateUUID() { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', // 32 bits for "time_low" - mt_rand(0, 0xffff), - mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), // 16 bits for "time_mid" mt_rand(0, 0xffff), // 16 bits for "time_hi_and_version", @@ -184,9 +183,7 @@ class Helper // two most significant bits holds zero and one for variant DCE1.1 mt_rand(0, 0x3fff) | 0x8000, // 48 bits for "node" - mt_rand(0, 0xffff), - mt_rand(0, 0xffff), - mt_rand(0, 0xffff) + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); } @@ -201,9 +198,9 @@ class Helper { if ($version === SOAP_1_2) { return self::NS_SOAP_1_2; + } else { + return self::NS_SOAP_1_1; } - - return self::NS_SOAP_1_1; } /** @@ -217,8 +214,8 @@ class Helper { if ($namespace === self::NS_SOAP_1_2) { return SOAP_1_2; + } else { + return SOAP_1_1; } - - return SOAP_1_1; } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php b/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php deleted file mode 100644 index 5ab33fe..0000000 --- a/src/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyser.php +++ /dev/null @@ -1,52 +0,0 @@ -mimePartMessage = $mimePartMessage; - $this->headers = $headers; - parent::__construct($message); - } - - public function getMimePartMessage() - { - return $this->mimePartMessage; - } - - public function hasHeaders() - { - return count($this->headers) > 0; - } - - public function getHeaders() - { - return $this->headers; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/MultiPart.php b/src/BeSimple/SoapCommon/Mime/MultiPart.php index 500264f..1b8ffa3 100644 --- a/src/BeSimple/SoapCommon/Mime/MultiPart.php +++ b/src/BeSimple/SoapCommon/Mime/MultiPart.php @@ -12,7 +12,6 @@ namespace BeSimple\SoapCommon\Mime; -use Exception; use BeSimple\SoapCommon\Helper; /** @@ -31,18 +30,24 @@ class MultiPart extends PartHeader { /** * Content-ID of main part. + * * @var string */ protected $mainPartContentId; /** * Mime parts. - * @var \BeSimple\SoapCommon\Mime\Part[] + * + * @var array(\BeSimple\SoapCommon\Mime\Part) */ - protected $parts; + protected $parts = array(); /** - * @param string $boundary + * Construct new mime object. + * + * @param string $boundary Boundary string + * + * @return void */ public function __construct($boundary = null) { @@ -50,15 +55,17 @@ class MultiPart extends PartHeader $this->setHeader('Content-Type', 'multipart/related'); $this->setHeader('Content-Type', 'type', 'text/xml'); $this->setHeader('Content-Type', 'charset', 'utf-8'); - if ($boundary !== null) { - $this->setHeader('Content-Type', 'boundary', $boundary); + if (is_null($boundary)) { + $boundary = $this->generateBoundary(); } + $this->setHeader('Content-Type', 'boundary', $boundary); } /** * Get mime message of this object (without headers). * * @param boolean $withHeaders Returned mime message contains headers + * * @return string */ public function getMimeMessage($withHeaders = false) @@ -66,14 +73,36 @@ class MultiPart extends PartHeader $message = ($withHeaders === true) ? $this->generateHeaders() : ""; // add parts foreach ($this->parts as $part) { - $message .= "\n" . '--' . $this->getHeader('Content-Type', 'boundary') . "\n"; + $message .= "\r\n" . '--' . $this->getHeader('Content-Type', 'boundary') . "\r\n"; $message .= $part->getMessagePart(); } - $message .= "\n" . '--' . $this->getHeader('Content-Type', 'boundary') . '--'; - + $message .= "\r\n" . '--' . $this->getHeader('Content-Type', 'boundary') . '--'; return $message; } + /** + * Get string array with MIME headers for usage in HTTP header (with CURL). + * Only 'Content-Type' and 'Content-Description' headers are returned. + * + * @return arrray(string) + */ + public function getHeadersForHttp() + { + $allowed = array( + 'Content-Type', + 'Content-Description', + ); + $headers = array(); + foreach ($this->headers as $fieldName => $value) { + if (in_array($fieldName, $allowed)) { + $fieldValue = $this->generateHeaderFieldValue($value); + // for http only ISO-8859-1 + $headers[] = $fieldName . ': '. iconv('utf-8', 'ISO-8859-1//TRANSLIT', $fieldValue); + } + } + return $headers; + } + /** * Add new part to MIME message. * @@ -88,58 +117,49 @@ class MultiPart extends PartHeader if ($isMain === true) { $this->mainPartContentId = $contentId; $this->setHeader('Content-Type', 'start', $part->getHeader('Content-ID')); - } else { - $part->setHeader('Content-Location', $contentId); } $this->parts[$contentId] = $part; } /** - * Get part with given content id. + * Get part with given content id. If there is no content id given it + * returns the main part that is defined through the content-id start + * parameter. * * @param string $contentId Content id of desired part * - * @return \BeSimple\SoapCommon\Mime\Part + * @return \BeSimple\SoapCommon\Mime\Part|null */ - public function getPart($contentId) + public function getPart($contentId = null) { + if (is_null($contentId)) { + $contentId = $this->mainPartContentId; + } if (isset($this->parts[$contentId])) { return $this->parts[$contentId]; } - - throw new Exception('MimePart not found by ID: ' . $contentId); + return null; } /** - * Get main part. + * Get all parts. * - * @return \BeSimple\SoapCommon\Mime\Part + * @param boolean $includeMainPart Should main part be in result set + * + * @return array(\BeSimple\SoapCommon\Mime\Part) */ - public function getMainPart() + public function getParts($includeMainPart = false) { - foreach ($this->parts as $cid => $part) { - if ($cid === $this->mainPartContentId) { - return $part; + if ($includeMainPart === true) { + $parts = $this->parts; + } else { + $parts = array(); + foreach ($this->parts as $cid => $part) { + if ($cid != $this->mainPartContentId) { + $parts[$cid] = $part; + } } } - - throw new Exception('SoapRequest error: main part not found by Id: ' . $this->mainPartContentId); - } - - /** - * Get attachment parts. - * - * @return \BeSimple\SoapCommon\Mime\Part[] - */ - public function getAttachments() - { - $parts = []; - foreach ($this->parts as $cid => $part) { - if ($cid !== $this->mainPartContentId) { - $parts[$cid] = $part; - } - } - return $parts; } @@ -148,13 +168,8 @@ class MultiPart extends PartHeader * * @return string */ - public function generateBoundary() + protected function generateBoundary() { - return 'multipart-boundary-' . Helper::generateUuid() . '@response.info'; + return 'urn:uuid:' . Helper::generateUUID(); } - - public function getMainPartContentId() - { - return $this->mainPartContentId; - } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Mime/Parser.php b/src/BeSimple/SoapCommon/Mime/Parser.php index 71a7440..c4a8c27 100644 --- a/src/BeSimple/SoapCommon/Mime/Parser.php +++ b/src/BeSimple/SoapCommon/Mime/Parser.php @@ -12,120 +12,176 @@ namespace BeSimple\SoapCommon\Mime; -use BeSimple\SoapCommon\Mime\Boundary\MimeBoundaryAnalyser; -use BeSimple\SoapCommon\Mime\Parser\ContentTypeParser; -use BeSimple\SoapCommon\Mime\Parser\ParsedPartList; -use BeSimple\SoapCommon\Mime\Parser\ParsedPartsGetter; - /** * Simple Multipart-Mime parser. * * @author Andreas Schamberger - * @author Petr Bechyne */ class Parser { /** * Parse the given Mime-Message and return a \BeSimple\SoapCommon\Mime\MultiPart object. * - * @param string $mimeMessage Mime message string - * @param string[] $headers array(string=>string) of header elements (e.g. coming from http request) - * @return MultiPart + * @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 = []) + public static function parseMimeMessage($mimeMessage, array $headers = array()) { - $multiPart = new MultiPart(); - $mimeMessageLines = explode("\n", $mimeMessage); - $mimeMessageLineCount = count($mimeMessageLines); - + $boundary = null; + $start = null; + $multipart = new MultiPart(); + $hitFirstBoundary = false; + $inHeader = true; // add given headers, e.g. coming from HTTP headers if (count($headers) > 0) { - self::setMultiPartHeaders($multiPart, $headers); - $hasHttpRequestHeaders = ParsedPartsGetter::HAS_HTTP_REQUEST_HEADERS; - } else { - $hasHttpRequestHeaders = ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS; + foreach ($headers as $name => $value) { + if ($name == 'Content-Type') { + self::parseContentTypeHeader($multipart, $name, $value); + $boundary = $multipart->getHeader('Content-Type', 'boundary'); + $start = $multipart->getHeader('Content-Type', 'start'); + } else { + $multipart->setHeader($name, $value); + } + } + $inHeader = false; } - if (MimeBoundaryAnalyser::hasMessageBoundary($mimeMessageLines) === true) { - if ($mimeMessageLineCount <= 1) { - throw new CouldNotParseMimeMessageException( - sprintf( - 'Cannot parse MultiPart message of %d characters: got unexpectable low number of lines: %s', - mb_strlen($mimeMessage), - (string)$mimeMessageLineCount - ), - $mimeMessage, - $headers - ); + $content = ''; + $currentPart = $multipart; + $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') { + continue; } - $parsedPartList = ParsedPartsGetter::getPartsFromMimeMessageLines( - $multiPart, - $mimeMessageLines, - $hasHttpRequestHeaders - ); - if ($parsedPartList->hasParts() === false) { - throw new CouldNotParseMimeMessageException( - 'Could not parse MimeMessage: no Parts for MultiPart given', - $mimeMessage, - $headers - ); + if (isset($currentHeader)) { + if (isset($line[0]) && ($line[0] === ' ' || $line[0] === "\t")) { + $currentHeader .= $line; + continue; + } + if (strpos($currentHeader, ':') !== false) { + list($headerName, $headerValue) = explode(':', $currentHeader, 2); + $headerValue = iconv_mime_decode($headerValue, 0, 'utf-8'); + if (strpos($headerValue, ';') !== false) { + self::parseContentTypeHeader($currentPart, $headerName, $headerValue); + $boundary = $multipart->getHeader('Content-Type', 'boundary'); + $start = $multipart->getHeader('Content-Type', 'start'); + } else { + $currentPart->setHeader($headerName, trim($headerValue)); + } + } + unset($currentHeader); } - if ($parsedPartList->hasExactlyOneMainPart() === false) { - throw new CouldNotParseMimeMessageException( - sprintf( - 'Could not parse MimeMessage %s HTTP headers: unexpected count of main ParsedParts: %s (total: %d)', - $hasHttpRequestHeaders ? 'with' : 'w/o', - implode(', ', $parsedPartList->getPartContentIds()), - $parsedPartList->getMainPartCount() - ), - $mimeMessage, - $headers - ); + if ($inHeader) { + if (trim($line) == '') { + $inHeader = false; + continue; + } + $currentHeader = $line; + continue; + } else { + // check if we hit any of the boundaries + if (strlen($line) > 0 && $line[0] == "-") { + if (strcmp(trim($line), '--' . $boundary) === 0) { + if ($currentPart instanceof Part) { + $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; + if ($isMain === true) { + $start = $currentPart->getHeader('Content-ID'); + } + $multipart->addPart($currentPart, $isMain); + } + $currentPart = new Part(); + $hitFirstBoundary = true; + $inHeader = true; + $content = ''; + } elseif (strcmp(trim($line), '--' . $boundary . '--') === 0) { + $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; + if ($isMain === true) { + $start = $currentPart->getHeader('Content-ID'); + } + $multipart->addPart($currentPart, $isMain); + $content = ''; + } + } else { + if ($hitFirstBoundary === false) { + if (trim($line) != '') { + $inHeader = true; + $currentHeader = $line; + continue; + } + } + $content .= $line . "\r\n"; + } } - self::appendPartsToMultiPart( - $parsedPartList, - $multiPart - ); - } else { - self::appendSingleMainPartToMultiPart(new Part($mimeMessage), $multiPart); } - - return $multiPart; + return $multipart; } /** - * @param ParsedPartList $parsedPartList - * @param MultiPart $multiPart + * Parse a "Content-Type" header with multiple sub values. + * e.g. Content-Type: multipart/related; boundary=boundary; type=text/xml; + * start="<123@abc>" + * + * Based on: https://labs.omniti.com/alexandria/trunk/OmniTI/Mail/Parser.php + * + * @param \BeSimple\SoapCommon\Mime\PartHeader $part Header part + * @param string $headerName Header name + * @param string $headerValue Header value + * + * @return null */ - private static function appendPartsToMultiPart(ParsedPartList $parsedPartList, MultiPart $multiPart) + private static function parseContentTypeHeader(PartHeader $part, $headerName, $headerValue) { - foreach ($parsedPartList->getParts() as $parsedPart) { - $multiPart->addPart( - $parsedPart->getPart(), - $parsedPart->isMain() - ); - } - } - - private static function appendSingleMainPartToMultiPart(Part $part, MultiPart $multiPart) - { - $multiPart->addPart($part, true); - } - - private static function setMultiPartHeaders(MultiPart $multiPart, $headers) - { - foreach ($headers as $name => $value) { - if ($name === 'Content-Type') { - $parsedMimeHeaders = ContentTypeParser::parseContentTypeHeader($name, $value); - foreach ($parsedMimeHeaders as $parsedMimeHeader) { - $multiPart->setHeader( - $parsedMimeHeader->getName(), - $parsedMimeHeader->getValue(), - $parsedMimeHeader->getSubValue() - ); - } - } else { - $multiPart->setHeader($name, $value); + list($value, $remainder) = explode(';', $headerValue, 2); + $value = trim($value); + $part->setHeader($headerName, $value); + $remainder = trim($remainder); + while (strlen($remainder) > 0) { + if (!preg_match('/^([a-zA-Z0-9_-]+)=(.{1})/', $remainder, $matches)) { + break; } + $name = $matches[1]; + $delimiter = $matches[2]; + $remainder = substr($remainder, strlen($name)+1); + if (!preg_match('/([^;]+)(;)?(\s|$)?/', $remainder, $matches)) { + break; + } + $value = rtrim($matches[1], ';'); + if ($delimiter == "'" || $delimiter == '"') { + $value = trim($value, $delimiter); + } + $part->setHeader($headerName, $name, $value); + $remainder = substr($remainder, strlen($matches[0])); } } -} + + /** + * Decodes the content of a Mime part. + * + * @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) + { + $encoding = strtolower($part->getHeader('Content-Transfer-Encoding')); + $charset = strtolower($part->getHeader('Content-Type', 'charset')); + if ($encoding == Part::ENCODING_BASE64) { + $content = base64_decode($content); + } elseif ($encoding == Part::ENCODING_QUOTED_PRINTABLE) { + $content = quoted_printable_decode($content); + } + if ($charset != 'utf-8') { + $content = iconv($charset, 'utf-8', $content); + } + $part->setContent($content); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Mime/Parser/ContentTypeParser.php b/src/BeSimple/SoapCommon/Mime/Parser/ContentTypeParser.php deleted file mode 100644 index 6e403ff..0000000 --- a/src/BeSimple/SoapCommon/Mime/Parser/ContentTypeParser.php +++ /dev/null @@ -1,64 +0,0 @@ -" - * - * Based on: https://labs.omniti.com/alexandria/trunk/OmniTI/Mail/Parser.php - * - * @param string $headerName Header name - * @param string $headerValue Header value - * @return ParsedMimeHeader[] - */ - public static function parseContentTypeHeader($headerName, $headerValue) - { - if (self::isCompositeHeaderValue($headerValue)) { - $parsedMimeHeaders = self::parseCompositeValue($headerName, $headerValue); - } else { - $parsedMimeHeaders = [ - new ParsedMimeHeader($headerName, trim($headerValue)) - ]; - } - - return $parsedMimeHeaders; - } - - private static function parseCompositeValue($headerName, $headerValue) - { - $parsedMimeHeaders = []; - list($value, $remainder) = explode(';', $headerValue, 2); - $value = trim($value); - $parsedMimeHeaders[] = new ParsedMimeHeader($headerName, $value); - $remainder = trim($remainder); - while (strlen($remainder) > 0) { - if (!preg_match('/^([a-zA-Z0-9_-]+)=(.{1})/', $remainder, $matches)) { - break; - } - $name = $matches[1]; - $delimiter = $matches[2]; - $remainder = substr($remainder, strlen($name) + 1); - // preg_match migrated from https://github.com/progmancod/BeSimpleSoap/commit/6bc8f6a467616c934b0a9792f0efece55054db97 - if (!preg_match('/([^;]+)(;\s*|\s*$)/', $remainder, $matches)) { - break; - } - $value = rtrim($matches[1], ';'); - if ($delimiter == "'" || $delimiter == '"') { - $value = trim($value, $delimiter); - } - $remainder = substr($remainder, strlen($matches[0])); - $parsedMimeHeaders[] = new ParsedMimeHeader($headerName, $name, $value); - } - - return $parsedMimeHeaders; - } - - private static function isCompositeHeaderValue($headerValue) - { - return strpos($headerValue, ';'); - } -} diff --git a/src/BeSimple/SoapCommon/Mime/Parser/ParsedMimeHeader.php b/src/BeSimple/SoapCommon/Mime/Parser/ParsedMimeHeader.php deleted file mode 100644 index 8656873..0000000 --- a/src/BeSimple/SoapCommon/Mime/Parser/ParsedMimeHeader.php +++ /dev/null @@ -1,37 +0,0 @@ -name = $name; - $this->value = $value; - $this->subValue = $subValue; - } - - public function getName() - { - return $this->name; - } - - public function getValue() - { - return $this->value; - } - - public function getSubValue() - { - return $this->subValue; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPart.php b/src/BeSimple/SoapCommon/Mime/Parser/ParsedPart.php deleted file mode 100644 index a9a90d1..0000000 --- a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPart.php +++ /dev/null @@ -1,34 +0,0 @@ -part = $part; - $this->isMain = $isMain; - } - - public function getPart() - { - return $this->part; - } - - public function isMain() - { - return $this->isMain; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartList.php b/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartList.php deleted file mode 100644 index 49cd3d4..0000000 --- a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartList.php +++ /dev/null @@ -1,60 +0,0 @@ -parts = $parts; - } - - public function getMainPartCount() - { - $mainPartsCount = 0; - foreach ($this->getParts() as $parsedPart) { - if ($parsedPart->isMain() === true) { - $mainPartsCount++; - } - } - - return $mainPartsCount; - } - - public function hasExactlyOneMainPart() - { - return $this->getMainPartCount() === 1; - } - - public function getPartContentIds() - { - $partContentIds = []; - foreach ($this->getParts() as $parsedPart) { - $partContentIds[] = $parsedPart->getPart()->getContentId(); - } - - return $partContentIds; - } - - public function getParts() - { - return $this->parts; - } - - public function getPartCount() - { - return count($this->parts); - } - - public function hasParts() - { - return $this->getPartCount() > 0; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartsGetter.php b/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartsGetter.php deleted file mode 100644 index 07a617f..0000000 --- a/src/BeSimple/SoapCommon/Mime/Parser/ParsedPartsGetter.php +++ /dev/null @@ -1,179 +0,0 @@ -getHeader('Content-Type', 'boundary'); - if ($contentTypeBoundary === null) { - throw new Exception( - 'Unable to get Content-Type boundary from given MultiPart: ' . var_export($multiPart->getHeaders(), true) - ); - } - $contentTypeContentIdStart = $multiPart->getHeader('Content-Type', 'start'); - if ($contentTypeContentIdStart === null) { - throw new Exception( - 'Unable to get Content-Type start from given MultiPart: ' . var_export($multiPart->getHeaders(), true) - ); - } - $currentPart = $multiPart; - $messagePartStringContent = ''; - $inHeader = $hasHttpHeaders; - $hitFirstBoundary = false; - foreach ($mimeMessageLines as $mimeMessageLine) { - if (substr($mimeMessageLine, 0, 5) === 'HTTP/' || substr($mimeMessageLine, 0, 4) === 'POST') { - continue; - } - if (isset($currentHeader)) { - if (isset($mimeMessageLine[0]) && ($mimeMessageLine[0] === ' ' || $mimeMessageLine[0] === "\t")) { - $currentHeader .= $mimeMessageLine; - continue; - } - if (strpos($currentHeader, ':') !== false) { - list($headerName, $headerValue) = explode(':', $currentHeader, 2); - $headerValueWithNoCrAtTheEnd = trim($headerValue); - try { - $headerValue = iconv_mime_decode($headerValueWithNoCrAtTheEnd, 0, Part::CHARSET_UTF8); - } catch (Exception $e) { - if ($hitFirstBoundary === false) { - throw new Exception( - 'Unable to parse message: cannot parse headers before hitting the first boundary' - ); - } - throw new Exception( - sprintf( - 'Unable to get header value: possible parsing message contents of %s characters in header parser: %s', - mb_strlen($headerValueWithNoCrAtTheEnd), - $e->getMessage() - ) - ); - } - $parsedMimeHeaders = ContentTypeParser::parseContentTypeHeader($headerName, $headerValue); - foreach ($parsedMimeHeaders as $parsedMimeHeader) { - $currentPart->setHeader( - $parsedMimeHeader->getName(), - $parsedMimeHeader->getValue(), - $parsedMimeHeader->getSubValue() - ); - } - $contentTypeBoundary = $multiPart->getHeader('Content-Type', 'boundary'); - $contentTypeContentIdStart = $multiPart->getHeader('Content-Type', 'start'); - } - unset($currentHeader); - } - if ($inHeader === true) { - if (trim($mimeMessageLine) === '') { - $inHeader = false; - continue; - } - $currentHeader = $mimeMessageLine; - continue; - } else { - if (MimeBoundaryAnalyser::isMessageLineBoundary($mimeMessageLine)) { - if (MimeBoundaryAnalyser::isMessageLineMiddleBoundary($mimeMessageLine, $contentTypeBoundary)) { - if ($currentPart instanceof Part) { - $currentPartContent = self::decodeContent( - $currentPart, - substr($messagePartStringContent, 0, -1) - ); - if ($currentPartContent[strlen($currentPartContent) - 1] === "\r") { - // temporary hack: if there is a CRLF before any middle boundary, then the remaining CR must be removed - $currentPartContent = substr($currentPartContent, 0, -1); - } - $currentPart->setContent($currentPartContent); - // check if there is a start parameter given, if not set first part - if ($contentTypeContentIdStart === null || $currentPart->hasContentId($contentTypeContentIdStart) === true) { - $contentTypeContentIdStart = $currentPart->getHeader('Content-ID'); - $parsedParts[] = new ParsedPart($currentPart, ParsedPart::PART_IS_MAIN); - } else { - $parsedParts[] = new ParsedPart($currentPart, ParsedPart::PART_IS_NOT_MAIN); - } - } - $currentPart = new Part(); - $hitFirstBoundary = true; - $inHeader = true; - $messagePartStringContent = ''; - } elseif (MimeBoundaryAnalyser::isMessageLineLastBoundary($mimeMessageLine, $contentTypeBoundary)) { - $currentPartContent = self::decodeContent( - $currentPart, - substr($messagePartStringContent, 0, -1) - ); - if ($currentPartContent[strlen($currentPartContent) - 1] === "\r") { - // temporary hack: if there is a CRLF before last boundary, then the remaining CR must be removed - $currentPartContent = substr($currentPartContent, 0, -1); - } - $currentPart->setContent($currentPartContent); - // check if there is a start parameter given, if not set first part - if ($contentTypeContentIdStart === null || $currentPart->hasContentId($contentTypeContentIdStart) === true) { - $contentTypeContentIdStart = $currentPart->getHeader('Content-ID'); - $parsedParts[] = new ParsedPart($currentPart, ParsedPart::PART_IS_MAIN); - } else { - $parsedParts[] = new ParsedPart($currentPart, ParsedPart::PART_IS_NOT_MAIN); - } - $messagePartStringContent = ''; - } else { - // else block migrated from https://github.com/progmancod/BeSimpleSoap/commit/bf9437e3bcf35c98c6c2f26aca655ec3d3514694 - // be careful to replace \r\n with \n - $messagePartStringContent .= $mimeMessageLine . "\n"; - } - } else { - if ($hitFirstBoundary === false) { - if (trim($mimeMessageLine) !== '') { - $inHeader = true; - $currentHeader = $mimeMessageLine; - continue; - } - } - $messagePartStringContent .= $mimeMessageLine . "\n"; - } - } - } - - return new ParsedPartList($parsedParts); - } - - /** - * Decodes the content of a Mime part - * - * @param Part $part Part to add content - * @param string $partStringContent Content to decode - * @return string $partStringContent decodedContent - */ - private static function decodeContent(Part $part, $partStringContent) - { - $encoding = strtolower($part->getHeader('Content-Transfer-Encoding')); - $charset = strtolower($part->getHeader('Content-Type', 'charset')); - - if ($encoding === Part::ENCODING_BASE64) { - $partStringContent = base64_decode($partStringContent); - } elseif ($encoding === Part::ENCODING_QUOTED_PRINTABLE) { - $partStringContent = quoted_printable_decode($partStringContent); - } - - if ($charset !== Part::CHARSET_UTF8) { - return iconv($charset, Part::CHARSET_UTF8, $partStringContent); - } - - return $partStringContent; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/Part.php b/src/BeSimple/SoapCommon/Mime/Part.php index b041116..714f137 100644 --- a/src/BeSimple/SoapCommon/Mime/Part.php +++ b/src/BeSimple/SoapCommon/Mime/Part.php @@ -28,38 +28,58 @@ use BeSimple\SoapCommon\Helper; */ class Part extends PartHeader { + /** + * Encoding type base 64 + */ const ENCODING_BASE64 = 'base64'; + + /** + * Encoding type binary + */ const ENCODING_BINARY = 'binary'; + + /** + * Encoding type eight bit + */ const ENCODING_EIGHT_BIT = '8bit'; + + /** + * Encoding type seven bit + */ const ENCODING_SEVEN_BIT = '7bit'; + + /** + * Encoding type quoted printable + */ const ENCODING_QUOTED_PRINTABLE = 'quoted-printable'; - const CHARSET_UTF8 = 'utf-8'; - - const CONTENT_TYPE_STREAM = 'application/octet-stream'; - const CONTENT_TYPE_PDF = 'application/pdf'; - - /** @var mixed */ + /** + * Content. + * + * @var mixed + */ protected $content; /** + * Construct new mime object. + * * @param mixed $content Content * @param string $contentType Content type * @param string $charset Charset * @param string $encoding Encoding * @param string $contentId Content id + * + * @return void */ - public function __construct( - $content = null, - $contentType = self::CONTENT_TYPE_STREAM, - $charset = self::CHARSET_UTF8, - $encoding = self::ENCODING_BINARY, - $contentId = null - ) { + public function __construct($content = null, $contentType = 'application/octet-stream', $charset = null, $encoding = self::ENCODING_BINARY, $contentId = null) + { $this->content = $content; - $this->setHeader('Content-Type', $contentType); - $this->setHeader('Content-Type', 'charset', $charset); + if (!is_null($charset)) { + $this->setHeader('Content-Type', 'charset', $charset); + } else { + $this->setHeader('Content-Type', 'charset', 'utf-8'); + } $this->setHeader('Content-Transfer-Encoding', $encoding); if (is_null($contentId)) { $contentId = $this->generateContentId(); @@ -68,7 +88,9 @@ class Part extends PartHeader } /** - * @return string + * __toString. + * + * @return mixed */ public function __toString() { @@ -85,18 +107,12 @@ class Part extends PartHeader return $this->content; } - public function hasContentId($contentTypeContentId) - { - return $contentTypeContentId === $this->getContentId(); - } - - public function getContentId() - { - return $this->getHeader('Content-ID'); - } - /** - * @param string $content + * Set mime content. + * + * @param mixed $content Content to set + * + * @return void */ public function setContent($content) { @@ -105,25 +121,27 @@ class Part extends PartHeader /** * Get complete mime message of this object. + * * @return string */ public function getMessagePart() { - return $this->generateHeaders() . "\n" . $this->generateBody(); + return $this->generateHeaders() . "\r\n" . $this->generateBody(); } /** * Generate body. + * * @return string */ protected function generateBody() { $encoding = strtolower($this->getHeader('Content-Transfer-Encoding')); $charset = strtolower($this->getHeader('Content-Type', 'charset')); - if ($charset !== self::CHARSET_UTF8) { - $content = iconv(self::CHARSET_UTF8, $charset.'//TRANSLIT', $this->getContent()); + if ($charset != 'utf-8') { + $content = iconv('utf-8', $charset . '//TRANSLIT', $this->content); } else { - $content = $this->getContent(); + $content = $this->content; } switch ($encoding) { case self::ENCODING_BASE64: @@ -135,7 +153,7 @@ class Part extends PartHeader case self::ENCODING_SEVEN_BIT: case self::ENCODING_EIGHT_BIT: default: - return preg_replace("/\r\n|\r|\n/", "\n", $content); + return preg_replace("/\r\n|\r|\n/", "\r\n", $content); } } @@ -146,6 +164,6 @@ class Part extends PartHeader */ protected function generateContentId() { - return 'part-' . Helper::generateUuid() . '@response.info'; + return 'urn:uuid:' . Helper::generateUUID(); } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Mime/PartFactory.php b/src/BeSimple/SoapCommon/Mime/PartFactory.php deleted file mode 100644 index ea9b3fb..0000000 --- a/src/BeSimple/SoapCommon/Mime/PartFactory.php +++ /dev/null @@ -1,33 +0,0 @@ -getContent(), - Part::CONTENT_TYPE_PDF, - Part::CHARSET_UTF8, - Part::ENCODING_BINARY, - $attachment->getId() - ); - } - - /** - * @param SoapAttachment[] $attachments SOAP attachments - * @return Part[] - */ - public static function createAttachmentParts(array $attachments = []) - { - $parts = []; - foreach ($attachments as $attachment) { - $parts[] = self::createFromSoapAttachment($attachment); - } - - return $parts; - } -} diff --git a/src/BeSimple/SoapCommon/Mime/PartHeader.php b/src/BeSimple/SoapCommon/Mime/PartHeader.php index ed26459..ff0dcfc 100644 --- a/src/BeSimple/SoapCommon/Mime/PartHeader.php +++ b/src/BeSimple/SoapCommon/Mime/PartHeader.php @@ -19,10 +19,12 @@ namespace BeSimple\SoapCommon\Mime; */ abstract class PartHeader { - /** @var string[] array of headers with lower-cased keys */ - private $headers; - /** @var string[] array of lower-cased keys and their original variants */ - private $headersOriginalKeys; + /** + * Mime headers. + * + * @var array(string=>mixed|array(mixed)) + */ + protected $headers = array(); /** * Add a new header to the mime part. @@ -35,21 +37,19 @@ abstract class PartHeader */ public function setHeader($name, $value, $subValue = null) { - $lowerCaseName = mb_strtolower($name); - $this->headersOriginalKeys[$lowerCaseName] = $name; - if (isset($this->headers[$lowerCaseName]) && !is_null($subValue)) { - if (!is_array($this->headers[$lowerCaseName])) { - $this->headers[$lowerCaseName] = [ - '@' => $this->headers[$lowerCaseName], + if (isset($this->headers[$name]) && !is_null($subValue)) { + if (!is_array($this->headers[$name])) { + $this->headers[$name] = array( + '@' => $this->headers[$name], $value => $subValue, - ]; + ); } else { - $this->headers[$lowerCaseName][$value] = $subValue; + $this->headers[$name][$value] = $subValue; } - } elseif (isset($this->headers[$lowerCaseName]) && is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName]['@'])) { - $this->headers[$lowerCaseName]['@'] = $value; + } elseif (isset($this->headers[$name]) && is_array($this->headers[$name]) && isset($this->headers[$name]['@'])) { + $this->headers[$name]['@'] = $value; } else { - $this->headers[$lowerCaseName] = $value; + $this->headers[$name] = $value; } } @@ -63,53 +63,22 @@ abstract class PartHeader */ public function getHeader($name, $subValue = null) { - $lowerCaseName = mb_strtolower($name); - if (isset($this->headers[$lowerCaseName])) { + if (isset($this->headers[$name])) { if (!is_null($subValue)) { - if (is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName][$subValue])) { - return $this->headers[$lowerCaseName][$subValue]; + if (is_array($this->headers[$name]) && isset($this->headers[$name][$subValue])) { + return $this->headers[$name][$subValue]; } else { return null; } - } elseif (is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName]['@'])) { - return $this->headers[$lowerCaseName]['@']; + } elseif (is_array($this->headers[$name]) && isset($this->headers[$name]['@'])) { + return $this->headers[$name]['@']; } else { - return $this->headers[$lowerCaseName]; + return $this->headers[$name]; } } - return null; } - public function getHeaders() - { - return $this->headers; - } - - /** - * Get string array with MIME headers for usage in HTTP header (with CURL). - * Only 'Content-Type' and 'Content-Description' headers are returned. - * - * @return string[] - */ - public function getHeadersForHttp() - { - $allowedHeadersLowerCase = [ - 'content-type', - 'content-description', - ]; - $headers = []; - foreach ($this->headers as $fieldName => $value) { - if (in_array($fieldName, $allowedHeadersLowerCase)) { - $fieldValue = $this->generateHeaderFieldValue($value); - // for http only ISO-8859-1 - $headers[] = $this->headersOriginalKeys[$fieldName] . ': '. iconv('utf-8', 'ISO-8859-1//TRANSLIT', $fieldValue); - } - } - - return $headers; - } - /** * Generate headers. * @@ -117,37 +86,44 @@ abstract class PartHeader */ protected function generateHeaders() { + $charset = strtolower($this->getHeader('Content-Type', 'charset')); + $preferences = array( + 'scheme' => 'Q', + 'input-charset' => 'utf-8', + 'output-charset' => $charset, + ); $headers = ''; foreach ($this->headers as $fieldName => $value) { $fieldValue = $this->generateHeaderFieldValue($value); - $headers .= $this->headersOriginalKeys[$fieldName] . ': ' . $fieldValue . "\n"; + // do not use proper encoding as Apache Axis does not understand this + // $headers .= iconv_mime_encode($field_name, $field_value, $preferences) . "\r\n"; + $headers .= $fieldName . ': ' . $fieldValue . "\r\n"; } - return $headers; } /** * Generates a header field value from the given value paramater. * - * @param string[]|string $value Header value + * @param array(string=>string)|string $value Header value + * * @return string */ protected function generateHeaderFieldValue($value) { $fieldValue = ''; - if (is_array($value) === true) { + if (is_array($value)) { if (isset($value['@'])) { $fieldValue .= $value['@']; } foreach ($value as $subName => $subValue) { - if ($subName !== '@') { + if ($subName != '@') { $fieldValue .= '; ' . $subName . '=' . $this->quoteValueString($subValue); } } } else { $fieldValue .= $value; } - return $fieldValue; } @@ -163,8 +139,8 @@ abstract class PartHeader { if (preg_match('~[()<>@,;:\\"/\[\]?=]~', $string)) { return '"' . $string . '"'; + } else { + return $string; } - - return $string; } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapKernel.php b/src/BeSimple/SoapCommon/SoapKernel.php index 0b1a4ec..a6f621d 100644 --- a/src/BeSimple/SoapCommon/SoapKernel.php +++ b/src/BeSimple/SoapCommon/SoapKernel.php @@ -1,52 +1,129 @@ + * (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\Mime\Part as MimePart; +use BeSimple\SoapCommon\SoapRequest; +use BeSimple\SoapCommon\SoapResponse; +use BeSimple\SoapCommon\SoapRequestFilter; +use BeSimple\SoapCommon\SoapResponseFilter; + /** * SoapKernel provides methods to pre- and post-process SoapRequests and SoapResponses using * chains of SoapRequestFilter and SoapResponseFilter objects (roughly following * the chain-of-responsibility pattern). * * @author Christian Kerl - * @author Petr Bechyně */ class SoapKernel { + /** + * Mime attachments. + * + * @var array(\BeSimple\SoapCommon\Mime\Part) + */ + protected $attachments = array(); + + /** + * Request filters. + * + * @var array(SoapRequestFilter) + */ + private $requestFilters = array(); + + /** + * Response filters. + * + * @var array(SoapResponseFilter) + */ + private $responseFilters = array(); + + /** + * Add attachment. + * + * @param \BeSimple\SoapCommon\Mime\Part $attachment New attachment + * + * @return void + */ + public function addAttachment(MimePart $attachment) + { + $contentId = trim($attachment->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 + * before outer filters. This means the order is as follows: RequestFilter2->RequestFilter1 and + * ResponseFilter1->ResponseFilter2. + * + * TODO: add priority mechanism to ensure correct order of filters + * + * @param SoapRequestFilter|SoapResponseFilter $filter Filter to register + */ + public function registerFilter($filter) + { + if ($filter instanceof SoapRequestFilter) { + array_unshift($this->requestFilters, $filter); + } + + if ($filter instanceof SoapResponseFilter) { + array_push($this->responseFilters, $filter); + } + } + /** * Applies all registered SoapRequestFilter to the given SoapRequest. * * @param SoapRequest $request Soap request - * @param SoapRequestFilter[]|SoapResponseFilter[] $filters - * @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64 - * @return SoapRequest */ - public static function filterRequest(SoapRequest $request, array $filters, $attachmentType) + public function filterRequest(SoapRequest $request) { - foreach ($filters as $filter) { - if ($filter instanceof SoapRequestFilter) { - $request = $filter->filterRequest($request, $attachmentType); - } + foreach ($this->requestFilters as $filter) { + $filter->filterRequest($request); } - - return $request; } /** * Applies all registered SoapResponseFilter to the given SoapResponse. * * @param SoapResponse $response SOAP response - * @param SoapRequestFilter[]|SoapResponseFilter[] $filters - * @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64 - * @return \BeSimple\SoapClient\SoapResponse|\BeSimple\SoapServer\SoapResponse */ - public static function filterResponse(SoapResponse $response, array $filters, $attachmentType) + public function filterResponse(SoapResponse $response) { - foreach ($filters as $filter) { - if ($filter instanceof SoapResponseFilter) { - $response = $filter->filterResponse($response, $attachmentType); - } + foreach ($this->responseFilters as $filter) { + $filter->filterResponse($response); } - - return $response; } } diff --git a/src/BeSimple/SoapCommon/SoapMessage.php b/src/BeSimple/SoapCommon/SoapMessage.php index 3682f2b..1b91c1a 100644 --- a/src/BeSimple/SoapCommon/SoapMessage.php +++ b/src/BeSimple/SoapCommon/SoapMessage.php @@ -13,8 +13,6 @@ namespace BeSimple\SoapCommon; -use DOMDocument; - /** * Base class for SoapRequest and SoapResponse. * @@ -47,12 +45,12 @@ abstract class SoapMessage /** * Content types for SOAP versions. * - * @var array (string=>string) + * @var array(string=>string) */ - static protected $versionToContentTypeMap = [ + static protected $versionToContentTypeMap = array( SOAP_1_1 => 'text/xml; charset=utf-8', SOAP_1_2 => 'application/soap+xml; charset=utf-8' - ]; + ); /** * SOAP action. @@ -64,9 +62,9 @@ abstract class SoapMessage /** * Mime attachments. * - * @var \BeSimple\SoapCommon\Mime\Part[] + * @var array(\BeSimple\SoapCommon\Mime\Part) */ - protected $attachments; + protected $attachments = array(); /** * Message content (MIME Message or SOAP Envelope). @@ -75,6 +73,13 @@ abstract class SoapMessage */ protected $content; + /** + * + * Enter description here ... + * @var \DOMDocument + */ + protected $contentDomDocument = null; + /** * Message content type. * @@ -92,22 +97,22 @@ abstract class SoapMessage /** * SOAP version (SOAP_1_1|SOAP_1_2) * - * @var int + * @var string */ protected $version; /** * Get content type for given SOAP version. * - * @param int $version SOAP version constant SOAP_1_1|SOAP_1_2 + * @param string $version SOAP version constant SOAP_1_1|SOAP_1_2 * * @return string * @throws \InvalidArgumentException */ public static function getContentTypeForVersion($version) { - if (!in_array($version, [SOAP_1_1, SOAP_1_2])) { - throw new \InvalidArgumentException('Invalid SOAP version: ' . $version); + 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'!"); } return self::$versionToContentTypeMap[$version]; @@ -133,15 +138,10 @@ abstract class SoapMessage $this->action = $action; } - public function hasAttachments() - { - return $this->attachments !== null; - } - /** * Get attachments. * - * @return \BeSimple\SoapCommon\Mime\Part[] + * @return array(\BeSimple\SoapCommon\Mime\Part) */ public function getAttachments() { @@ -151,7 +151,7 @@ abstract class SoapMessage /** * Set SOAP action. * - * @param \BeSimple\SoapCommon\Mime\Part[] $attachments + * @param array(\BeSimple\SoapCommon\Mime\Part) $attachments Attachment array */ public function setAttachments(array $attachments) { @@ -165,6 +165,10 @@ abstract class SoapMessage */ public function getContent() { + if (null !== $this->contentDomDocument) { + $this->content = $this->contentDomDocument->saveXML(); + $this->contentDomDocument = null; + } return $this->content; } @@ -176,6 +180,9 @@ abstract class SoapMessage public function setContent($content) { $this->content = $content; + if (null !== $this->contentDomDocument) { + $this->contentDomDocument->loadXML($this->content); + } } /** @@ -185,10 +192,12 @@ abstract class SoapMessage */ public function getContentDocument() { - $contentDomDocument = new DOMDocument(); - $contentDomDocument->loadXML($this->content); + if (null === $this->contentDomDocument) { + $this->contentDomDocument = new \DOMDocument(); + $this->contentDomDocument->loadXML($this->content); + } - return $contentDomDocument; + return $this->contentDomDocument; } /** @@ -232,9 +241,9 @@ abstract class SoapMessage } /** - * Get SOAP version SOAP_1_1|SOAP_1_2 + * Get version. * - * @return int + * @return string */ public function getVersion() { @@ -244,7 +253,7 @@ abstract class SoapMessage /** * Set version. * - * @param int $version SOAP version SOAP_1_1|SOAP_1_2 + * @param string $version SOAP version SOAP_1_1|SOAP_1_2 */ public function setVersion($version) { diff --git a/src/BeSimple/SoapCommon/SoapOptions/SoapFeatures/SoapFeatures.php b/src/BeSimple/SoapCommon/SoapOptions/SoapFeatures/SoapFeatures.php deleted file mode 100644 index 7ffd201..0000000 --- a/src/BeSimple/SoapCommon/SoapOptions/SoapFeatures/SoapFeatures.php +++ /dev/null @@ -1,70 +0,0 @@ -resolveFeatures($features); - } - - public function isSingleElementArrays() - { - return $this->singleElementArrays; - } - - public function isOneWayCallsOn() - { - return $this->oneWayCallsOn; - } - - public function isUseXsiArrayType() - { - return $this->useXsiArrayType; - } - - public function getFeaturesSum() - { - return $this->featuresSum; - } - - private function resolveFeatures(array $features) - { - $featuresSum = 0; - foreach ($features as $feature) { - switch ($feature) { - case self::SINGLE_ELEMENT_ARRAYS: - $this->singleElementArrays = true; - $featuresSum += $feature; - break; - case self::WAIT_ONE_WAY_CALLS: - $this->oneWayCallsOn = true; - $featuresSum += $feature; - break; - case self::USE_XSI_ARRAY_TYPE: - $this->useXsiArrayType = true; - $featuresSum += $feature; - break; - default: - throw new Exception('Unknown SOAP feature: ' . $feature); - } - } - $this->featuresSum = $featuresSum; - } -} diff --git a/src/BeSimple/SoapCommon/SoapOptions/SoapOptions.php b/src/BeSimple/SoapCommon/SoapOptions/SoapOptions.php deleted file mode 100644 index 8d46324..0000000 --- a/src/BeSimple/SoapCommon/SoapOptions/SoapOptions.php +++ /dev/null @@ -1,158 +0,0 @@ -soapVersion = $soapVersion; - $this->encoding = $encoding; - $this->connectionKeepAlive = $connectionKeepAlive; - $this->soapFeatures = $features; - $this->wsdlFile = $wsdlFile; - $this->wsdlCacheType = $wsdlCacheType; - $this->wsdlCacheDir = $wsdlCacheDir; - $this->classMap = $classMap; - $this->typeConverterCollection = $typeConverterCollection; - $this->attachmentType = $attachmentType; - } - - public function getSoapVersion() - { - return $this->soapVersion; - } - - public function getEncoding() - { - return $this->encoding; - } - - public function isConnectionKeepAlive() - { - return $this->connectionKeepAlive; - } - - public function getWsdlFile() - { - return $this->wsdlFile; - } - - public function hasWsdlCacheDir() - { - return $this->wsdlCacheDir !== null; - } - - public function getWsdlCacheDir() - { - return $this->wsdlCacheDir; - } - - public function isWsdlCached() - { - return $this->wsdlCacheType !== self::SOAP_CACHE_TYPE_NONE; - } - - public function getWsdlCacheType() - { - return $this->wsdlCacheType; - } - - public function hasAttachments() - { - return $this->attachmentType !== self::SOAP_ATTACHMENTS_OFF; - } - - public function getAttachmentType() - { - return $this->attachmentType; - } - - public function getSoapFeatures() - { - return $this->soapFeatures; - } - - public function getClassMap() - { - return $this->classMap; - } - - public function getTypeConverterCollection() - { - return $this->typeConverterCollection; - } - - public function toArray() - { - $optionsAsArray = [ - 'soap_version' => $this->getSoapVersion(), - 'encoding' => $this->getEncoding(), - 'features' => $this->getSoapFeatures()->getFeaturesSum(), - 'wsdl' => $this->getWsdlFile(), - 'cache_wsdl' => $this->getWsdlCacheType(), - 'classmap' => $this->getClassMap()->getAll(), - 'typemap' => $this->getTypeConverterCollection()->getTypemap(), - 'keep_alive' => $this->isConnectionKeepAlive(), - ]; - if ($this->hasWsdlCacheDir()) { - $optionsAsArray['wsdl_cache_dir'] = $this->getWsdlCacheDir(); - } - - return $optionsAsArray; - } -} diff --git a/src/BeSimple/SoapCommon/SoapOptionsBuilder.php b/src/BeSimple/SoapCommon/SoapOptionsBuilder.php deleted file mode 100644 index a72ec58..0000000 --- a/src/BeSimple/SoapCommon/SoapOptionsBuilder.php +++ /dev/null @@ -1,166 +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\Converter\TypeConverterCollection; -use BeSimple\SoapCommon\SoapOptions\SoapFeatures\SoapFeatures; -use BeSimple\SoapCommon\SoapOptions\SoapOptions; -use InvalidArgumentException; - -/** - * @author Petr Bechyně - */ -class SoapOptionsBuilder -{ - public static function createWithDefaults( - $wsdlFile, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null - ) { - return self::createWithClassMap($wsdlFile, new ClassMap(), $wsdlCacheType, $wsdlCacheDir); - } - - public static function createWithDefaultsKeepAlive( - $wsdlFile, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null - ) { - return self::createWithClassMapKeepAlive($wsdlFile, new ClassMap(), $wsdlCacheType, $wsdlCacheDir); - } - - public static function createSwaWithClassMap( - $wsdlFile, - ClassMap $classMap, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null - ) { - return self::createWithClassMap( - $wsdlFile, - $classMap, - $wsdlCacheType, - $wsdlCacheDir, - SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA - ); - } - - public static function createSwaWithClassMapV11( - $wsdlFile, - ClassMap $classMap, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null - ) { - return self::createWithClassMapV11( - $wsdlFile, - $classMap, - $wsdlCacheType, - $wsdlCacheDir, - SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA - ); - } - - public static function createWithClassMap( - $wsdlFile, - ClassMap $classMap, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null, - $attachmentType = null - ) { - if (!Cache::hasType($wsdlCacheType)) { - throw new InvalidArgumentException('Invalid cache type'); - } - if ($wsdlCacheType !== SoapOptions::SOAP_CACHE_TYPE_NONE) { - if ($wsdlCacheDir === null) { - throw new InvalidArgumentException('Cache dir must be set for this wsdl cache type'); - } - } - - return new SoapOptions( - SoapOptions::SOAP_VERSION_1_2, - SoapOptions::SOAP_ENCODING_UTF8, - SoapOptions::SOAP_CONNECTION_KEEP_ALIVE_OFF, - new SoapFeatures([ - SoapFeatures::SINGLE_ELEMENT_ARRAYS - ]), - $wsdlFile, - $wsdlCacheType, - $wsdlCacheDir, - $classMap, - new TypeConverterCollection(), - $attachmentType - ); - } - - public static function createWithClassMapKeepAlive( - $wsdlFile, - ClassMap $classMap, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null, - $attachmentType = null - ) { - if (!Cache::hasType($wsdlCacheType)) { - throw new InvalidArgumentException('Invalid cache type'); - } - if ($wsdlCacheType !== SoapOptions::SOAP_CACHE_TYPE_NONE) { - if ($wsdlCacheDir === null) { - throw new InvalidArgumentException('Cache dir must be set for this wsdl cache type'); - } - } - - return new SoapOptions( - SoapOptions::SOAP_VERSION_1_2, - SoapOptions::SOAP_ENCODING_UTF8, - SoapOptions::SOAP_CONNECTION_KEEP_ALIVE_ON, - new SoapFeatures([ - SoapFeatures::SINGLE_ELEMENT_ARRAYS - ]), - $wsdlFile, - $wsdlCacheType, - $wsdlCacheDir, - $classMap, - new TypeConverterCollection(), - $attachmentType - ); - } - - public static function createWithClassMapV11( - $wsdlFile, - ClassMap $classMap, - $wsdlCacheType = SoapOptions::SOAP_CACHE_TYPE_NONE, - $wsdlCacheDir = null, - $attachmentType = null - ) { - if (!Cache::hasType($wsdlCacheType)) { - throw new InvalidArgumentException('Invalid cache type'); - } - if ($wsdlCacheType !== SoapOptions::SOAP_CACHE_TYPE_NONE) { - if ($wsdlCacheDir === null) { - throw new InvalidArgumentException('Cache dir must be set for this wsdl cache type'); - } - } - - return new SoapOptions( - SoapOptions::SOAP_VERSION_1_1, - SoapOptions::SOAP_ENCODING_UTF8, - SoapOptions::SOAP_CONNECTION_KEEP_ALIVE_OFF, - new SoapFeatures([ - SoapFeatures::SINGLE_ELEMENT_ARRAYS - ]), - $wsdlFile, - $wsdlCacheType, - $wsdlCacheDir, - $classMap, - new TypeConverterCollection(), - $attachmentType - ); - } -} diff --git a/src/BeSimple/SoapCommon/SoapRequest.php b/src/BeSimple/SoapCommon/SoapRequest.php index b7951f0..314d157 100644 --- a/src/BeSimple/SoapCommon/SoapRequest.php +++ b/src/BeSimple/SoapCommon/SoapRequest.php @@ -1,7 +1,26 @@ + * (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; + +/** + * SOAP request message. + * + * @author Christian Kerl + */ class SoapRequest extends SoapMessage { -} + +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/SoapRequestFactory.php b/src/BeSimple/SoapCommon/SoapRequestFactory.php deleted file mode 100644 index 5e9e45f..0000000 --- a/src/BeSimple/SoapCommon/SoapRequestFactory.php +++ /dev/null @@ -1,58 +0,0 @@ -setContent($content); - $request->setLocation($location); - $request->setAction($action); - $request->setVersion($version); - $request->setContentType($contentType); - - return $request; - } - - /** - * Factory function for SoapRequest. - * - * @param string $location Location - * @param string $action SOAP action - * @param int $version SOAP version - * @param string $content Content - * @return SoapRequest - */ - public static function create( - $location, - $action, - $version, - $content = null - ) { - - return self::createWithContentType( - $location, - $action, - $version, - SoapRequest::getContentTypeForVersion($version), - $content - ); - } -} diff --git a/src/BeSimple/SoapCommon/SoapRequestFilter.php b/src/BeSimple/SoapCommon/SoapRequestFilter.php index c8a5ae4..dbc990c 100644 --- a/src/BeSimple/SoapCommon/SoapRequestFilter.php +++ b/src/BeSimple/SoapCommon/SoapRequestFilter.php @@ -13,6 +13,8 @@ namespace BeSimple\SoapCommon; +use BeSimple\SoapCommon\SoapRequest; + /** * SOAP request filter interface. * @@ -24,7 +26,6 @@ interface SoapRequestFilter * Modify SOAP response. * * @param SoapRequest $request SOAP request - * @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64 */ - public function filterRequest(SoapRequest $request, $attachmentType); -} + 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 ffd3dd3..b6815b2 100644 --- a/src/BeSimple/SoapCommon/SoapResponse.php +++ b/src/BeSimple/SoapCommon/SoapResponse.php @@ -13,12 +13,14 @@ namespace BeSimple\SoapCommon; +use BeSimple\SoapCommon\SoapMessage; + /** * SOAP response message. * * @author Christian Kerl - * @author Petr Bechyně */ 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 ee6efe9..c7d6bb6 100644 --- a/src/BeSimple/SoapCommon/SoapResponseFilter.php +++ b/src/BeSimple/SoapCommon/SoapResponseFilter.php @@ -26,7 +26,6 @@ interface SoapResponseFilter * Modify SOAP response. * * @param SoapResponse $response SOAP response - * @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64 */ - public function filterResponse(SoapResponse $response, $attachmentType); -} + public function filterResponse(SoapResponse $response); +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Storage/AbstractStorage/AbstractStorage.php b/src/BeSimple/SoapCommon/Storage/AbstractStorage/AbstractStorage.php deleted file mode 100644 index 749d400..0000000 --- a/src/BeSimple/SoapCommon/Storage/AbstractStorage/AbstractStorage.php +++ /dev/null @@ -1,26 +0,0 @@ -items; - $this->resetItems(); - - return $items; - } - - protected function setItems(array $items) - { - $this->items = $items; - } - - private function resetItems() - { - $this->items = []; - } -} diff --git a/src/BeSimple/SoapCommon/Storage/RequestHandlerAttachmentsStorage.php b/src/BeSimple/SoapCommon/Storage/RequestHandlerAttachmentsStorage.php deleted file mode 100644 index ea8996d..0000000 --- a/src/BeSimple/SoapCommon/Storage/RequestHandlerAttachmentsStorage.php +++ /dev/null @@ -1,25 +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\Tests; + +use BeSimple\SoapCommon\Cache; +use BeSimple\SoapCommon\Classmap; +use BeSimple\SoapCommon\Converter\DateTimeTypeConverter; +use BeSimple\SoapCommon\Converter\DateTypeConverter; +use BeSimple\SoapCommon\Converter\TypeConverterCollection; +use BeSimple\SoapCommon\Tests\Fixtures\SoapBuilder; + +class AbstractSoapBuilderTest extends \PHPUnit_Framework_TestCase +{ + private $defaultOptions = array( + 'features' => 0, + 'classmap' => array(), + 'typemap' => array(), + ); + + public function testContruct() + { + $options = $this + ->getSoapBuilder() + ->getSoapOptions() + ; + + $this->assertEquals($this->mergeOptions(array()), $options); + } + + public function testWithWsdl() + { + $builder = $this->getSoapBuilder(); + $this->assertNull($builder->getWsdl()); + + $builder->withWsdl('http://myWsdl/?wsdl'); + $this->assertEquals('http://myWsdl/?wsdl', $builder->getWsdl()); + } + + public function testWithSoapVersion() + { + $builder = $this->getSoapBuilder(); + + $builder->withSoapVersion11(); + $this->assertEquals($this->mergeOptions(array('soap_version' => SOAP_1_1)), $builder->getSoapOptions()); + + $builder->withSoapVersion12(); + $this->assertEquals($this->mergeOptions(array('soap_version' => SOAP_1_2)), $builder->getSoapOptions()); + } + + public function testWithEncoding() + { + $builder = $this + ->getSoapBuilder() + ->withEncoding('ISO 8859-15') + ; + + $this->assertEquals($this->mergeOptions(array('encoding' => 'ISO 8859-15')), $builder->getSoapOptions()); + } + + public function testWithWsdlCache() + { + $builder = $this->getSoapBuilder(); + + $builder->withWsdlCache(Cache::TYPE_DISK_MEMORY); + $this->assertEquals($this->mergeOptions(array('cache_wsdl' => Cache::TYPE_DISK_MEMORY)), $builder->getSoapOptions()); + + $builder->withWsdlCacheNone(); + $this->assertEquals($this->mergeOptions(array('cache_wsdl' => Cache::TYPE_NONE)), $builder->getSoapOptions()); + + $builder->withWsdlCacheDisk(); + $this->assertEquals($this->mergeOptions(array('cache_wsdl' => Cache::TYPE_DISK)), $builder->getSoapOptions()); + + $builder->withWsdlCacheMemory(); + $this->assertEquals($this->mergeOptions(array('cache_wsdl' => Cache::TYPE_MEMORY)), $builder->getSoapOptions()); + + $builder->withWsdlCacheDiskAndMemory(); + $this->assertEquals($this->mergeOptions(array('cache_wsdl' => Cache::TYPE_DISK_MEMORY)), $builder->getSoapOptions()); + } + + public function testWithWsdlCacheBadValue() + { + $builder = $this->getSoapBuilder(); + + $this->setExpectedException('InvalidArgumentException'); + $builder->withWsdlCache('foo'); + } + + public function testWithSingleElementArrays() + { + $options = $this + ->getSoapBuilder() + ->withSingleElementArrays() + ->getSoapOptions() + ; + + $this->assertEquals($this->mergeOptions(array('features' => SOAP_SINGLE_ELEMENT_ARRAYS)), $options); + } + + public function testWithWaitOneWayCalls() + { + $options = $this + ->getSoapBuilder() + ->withWaitOneWayCalls() + ->getSoapOptions() + ; + + $this->assertEquals($this->mergeOptions(array('features' => SOAP_WAIT_ONE_WAY_CALLS)), $options); + } + + public function testWithUseXsiArrayType() + { + $options = $this + ->getSoapBuilder() + ->withUseXsiArrayType() + ->getSoapOptions() + ; + + $this->assertEquals($this->mergeOptions(array('features' => SOAP_USE_XSI_ARRAY_TYPE)), $options); + } + + public function testFeatures() + { + $builder = $this->getSoapBuilder(); + $features = 0; + + $builder->withSingleElementArrays(); + $features |= SOAP_SINGLE_ELEMENT_ARRAYS; + $this->assertEquals($this->mergeOptions(array('features' => $features)), $builder->getSoapOptions()); + + $builder->withWaitOneWayCalls(); + $features |= SOAP_WAIT_ONE_WAY_CALLS; + $this->assertEquals($this->mergeOptions(array('features' => $features)), $builder->getSoapOptions()); + + $builder->withUseXsiArrayType(); + $features |= SOAP_USE_XSI_ARRAY_TYPE; + $this->assertEquals($this->mergeOptions(array('features' => $features)), $builder->getSoapOptions()); + } + + public function testWithTypeConverters() + { + $builder = $this->getSoapBuilder(); + + $builder->withTypeConverter(new DateTypeConverter()); + $options = $builder->getSoapOptions(); + + $this->assertEquals(1, count($options['typemap'])); + + $converters = new TypeConverterCollection(); + $converters->add(new DateTimeTypeConverter()); + $builder->withTypeConverters($converters); + $options = $builder->getSoapOptions(); + + $this->assertEquals(2, count($options['typemap'])); + + $builder->withTypeConverters($converters, false); + $options = $builder->getSoapOptions(); + + $this->assertEquals(1, count($options['typemap'])); + } + + public function testClassmap() + { + $builder = $this->getSoapBuilder(); + + $builder->withClassMapping('foo', __CLASS__); + $options = $builder->getSoapOptions(); + + $this->assertEquals(1, count($options['classmap'])); + + $classmap = new Classmap(); + $classmap->add('bar', __CLASS__); + $builder->withClassmap($classmap); + $options = $builder->getSoapOptions(); + + $this->assertEquals(2, count($options['classmap'])); + + $builder->withClassmap($classmap, false); + $options = $builder->getSoapOptions(); + + $this->assertEquals(1, count($options['classmap'])); + } + + public function testCreateWithDefaults() + { + $builder = SoapBuilder::createWithDefaults(); + + $this->assertInstanceOf('BeSimple\SoapCommon\Tests\Fixtures\SoapBuilder', $builder); + + $this->assertEquals($this->mergeOptions(array('soap_version' => SOAP_1_2, 'encoding' => 'UTF-8', 'features' => SOAP_SINGLE_ELEMENT_ARRAYS)), $builder->getSoapOptions()); + } + + private function getSoapBuilder() + { + return new SoapBuilder(); + } + + private function mergeOptions(array $options) + { + return array_merge($this->defaultOptions, $options); + } +} diff --git a/src/BeSimple/SoapCommon/Tests/CacheTest.php b/src/BeSimple/SoapCommon/Tests/CacheTest.php index 307f2d9..291ff42 100644 --- a/src/BeSimple/SoapCommon/Tests/CacheTest.php +++ b/src/BeSimple/SoapCommon/Tests/CacheTest.php @@ -16,7 +16,7 @@ use BeSimple\SoapCommon\Cache; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\vfsStreamWrapper; -class CacheTest extends \PHPUnit_Framework_TestCase +class SoapRequestTest extends \PHPUnit_Framework_TestCase { public function testSetEnabled() { diff --git a/src/BeSimple/SoapCommon/Tests/ClassMapTest.php b/src/BeSimple/SoapCommon/Tests/ClassMapTest.php deleted file mode 100644 index 4c40357..0000000 --- a/src/BeSimple/SoapCommon/Tests/ClassMapTest.php +++ /dev/null @@ -1,65 +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\Tests; - -use BeSimple\SoapCommon\ClassMap; - -/** - * UnitTest for \BeSimple\SoapCommon\ClassMap. - * - * @author Francis Besset - */ -class ClassMapTest extends \PHPUnit_Framework_TestCase -{ - public function testAll() - { - $classMap = new ClassMap(); - - $this->assertSame([], $classMap->getAll()); - } - - public function testAdd() - { - $classMap = new ClassMap(); - - $classMap->add('foobar', 'BeSimple\SoapCommon\ClassMap'); - - $this->setExpectedException('InvalidArgumentException'); - $classMap->add('foobar', 'BeSimple\SoapCommon\ClassMap'); - } - - public function testGet() - { - $classMap = new ClassMap(); - - $classMap->add('foobar', 'BeSimple\SoapCommon\ClassMap'); - $this->assertSame('BeSimple\SoapCommon\ClassMap', $classMap->get('foobar')); - - $this->setExpectedException('Exception'); - $classMap->get('bar'); - } - - public function testAddClassMap() - { - $classMap1 = new ClassMap(); - $classMap2 = new ClassMap(); - - $classMap2->add('foobar', 'BeSimple\SoapCommon\ClassMap'); - $classMap1->addClassMap($classMap2); - - $this->assertEquals(['foobar' => 'BeSimple\SoapCommon\ClassMap'], $classMap1->getAll()); - - $this->setExpectedException('Exception'); - $classMap1->addClassMap($classMap2); - } -} diff --git a/src/BeSimple/SoapCommon/Tests/ClassmapTest.php b/src/BeSimple/SoapCommon/Tests/ClassmapTest.php new file mode 100644 index 0000000..2358244 --- /dev/null +++ b/src/BeSimple/SoapCommon/Tests/ClassmapTest.php @@ -0,0 +1,81 @@ + + * (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\Tests; + +use BeSimple\SoapCommon\Classmap; + +/** + * UnitTest for \BeSimple\SoapCommon\Classmap. + * + * @author Francis Besset + */ +class ClassmapTest extends \PHPUnit_Framework_TestCase +{ + public function testAll() + { + $classmap = new Classmap(); + + $this->assertSame(array(), $classmap->all()); + } + + public function testAdd() + { + $classmap = new Classmap(); + + $classmap->add('foobar', 'BeSimple\SoapCommon\Classmap'); + + $this->setExpectedException('InvalidArgumentException'); + $classmap->add('foobar', 'BeSimple\SoapCommon\Classmap'); + } + + public function testGet() + { + $classmap = new Classmap(); + + $classmap->add('foobar', 'BeSimple\SoapCommon\Classmap'); + $this->assertSame('BeSimple\SoapCommon\Classmap', $classmap->get('foobar')); + + $this->setExpectedException('InvalidArgumentException'); + $classmap->get('bar'); + } + + public function testSet() + { + $classmap = new Classmap(); + + $classmap->add('foobar', 'BeSimple\SoapCommon\Tests\ClassmapTest'); + $classmap->add('foo', 'BeSimple\SoapCommon\Tests\Classmap'); + + $map = array( + 'foobar' => 'BeSimple\SoapCommon\Classmap', + 'barfoo' => 'BeSimple\SoapCommon\Tests\ClassmapTest', + ); + $classmap->set($map); + + $this->assertSame($map, $classmap->all()); + } + + public function testAddClassmap() + { + $classmap1 = new Classmap(); + $classmap2 = new Classmap(); + + $classmap2->add('foobar', 'BeSimple\SoapCommon\Classmap'); + $classmap1->addClassmap($classmap2); + + $this->assertEquals(array('foobar' => 'BeSimple\SoapCommon\Classmap'), $classmap1->all()); + + $this->setExpectedException('InvalidArgumentException'); + $classmap1->addClassmap($classmap2); + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Tests/Converter/DateTimeTypeConverterTest.php b/src/BeSimple/SoapCommon/Tests/Converter/DateTimeTypeConverterTest.php index 44d1ddd..9546722 100644 --- a/src/BeSimple/SoapCommon/Tests/Converter/DateTimeTypeConverterTest.php +++ b/src/BeSimple/SoapCommon/Tests/Converter/DateTimeTypeConverterTest.php @@ -51,3 +51,4 @@ class DateTimeTypeConverterTest extends \PHPUnit_Framework_TestCase $this->assertNull($date); } } + diff --git a/src/BeSimple/SoapCommon/Tests/Converter/DateTypeConverterTest.php b/src/BeSimple/SoapCommon/Tests/Converter/DateTypeConverterTest.php index 6bc4b53..48bddcc 100644 --- a/src/BeSimple/SoapCommon/Tests/Converter/DateTypeConverterTest.php +++ b/src/BeSimple/SoapCommon/Tests/Converter/DateTypeConverterTest.php @@ -49,3 +49,4 @@ class DateTypeConverterTest extends \PHPUnit_Framework_TestCase $this->assertNull($date); } } + diff --git a/src/BeSimple/SoapCommon/Tests/Converter/TypeConverterCollectionTest.php b/src/BeSimple/SoapCommon/Tests/Converter/TypeConverterCollectionTest.php index 39f5bb3..0a955cd 100644 --- a/src/BeSimple/SoapCommon/Tests/Converter/TypeConverterCollectionTest.php +++ b/src/BeSimple/SoapCommon/Tests/Converter/TypeConverterCollectionTest.php @@ -30,19 +30,19 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase $dateTimeTypeConverter = new DateTimeTypeConverter(); $converters->add($dateTimeTypeConverter); - $this->assertSame([$dateTimeTypeConverter], $converters->getAll()); + $this->assertSame(array($dateTimeTypeConverter), $converters->all()); $dateTypeConverter = new DateTypeConverter(); $converters->add($dateTypeConverter); - $this->assertSame([$dateTimeTypeConverter, $dateTypeConverter], $converters->getAll()); + $this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->all()); } public function testGetTypemap() { $converters = new TypeConverterCollection(); - $this->assertEquals([], $converters->getTypemap()); + $this->assertEquals(array(), $converters->getTypemap()); $dateTimeTypeConverter = new DateTimeTypeConverter(); $converters->add($dateTimeTypeConverter); @@ -70,12 +70,10 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase $dateTimeTypeConverter = new DateTimeTypeConverter(); $converters->add($dateTimeTypeConverter); - $converter = [ - new DateTypeConverter() - ]; + $converter = array(new DateTypeConverter); $converters->set($converter); - $this->assertSame($converter, $converters->getAll()); + $this->assertSame($converter, $converters->all()); } public function testAddCollection() @@ -87,9 +85,9 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase $converters2->add($dateTimeTypeConverter); $converters1->addCollection($converters2); - $this->assertSame([$dateTimeTypeConverter], $converters1->getAll()); + $this->assertSame(array($dateTimeTypeConverter), $converters1->all()); $this->setExpectedException('InvalidArgumentException'); $converters1->addCollection($converters2); } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/Tests/Mime/MultiPartTest.php b/src/BeSimple/SoapCommon/Tests/Mime/MultiPartTest.php index e1782c6..fe51190 100644 --- a/src/BeSimple/SoapCommon/Tests/Mime/MultiPartTest.php +++ b/src/BeSimple/SoapCommon/Tests/Mime/MultiPartTest.php @@ -131,13 +131,13 @@ class MultiPartTest extends \PHPUnit_Framework_TestCase $mp->addPart($p2); $withoutMain = array( - trim($p2->getHeader('Content-ID'), '<>') => $p2, + trim($p2->getHeader('Content-ID'),'<>') => $p2, ); $this->assertEquals($withoutMain, $mp->getParts()); $withMain = array( - trim($p1->getHeader('Content-ID'), '<>') => $p1, - trim($p2->getHeader('Content-ID'), '<>') => $p2 + trim($p1->getHeader('Content-ID'),'<>') => $p1, + trim($p2->getHeader('Content-ID'),'<>') => $p2, ); $this->assertEquals($withMain, $mp->getParts(true)); } diff --git a/src/BeSimple/SoapCommon/Tests/Mime/ParserTest.php b/src/BeSimple/SoapCommon/Tests/Mime/ParserTest.php index d584a7a..8ce3a99 100644 --- a/src/BeSimple/SoapCommon/Tests/Mime/ParserTest.php +++ b/src/BeSimple/SoapCommon/Tests/Mime/ParserTest.php @@ -115,8 +115,7 @@ class ParserTest extends \PHPUnit_Framework_TestCase $mimeMessage = file_get_contents($filename); $headers = array( - 'Content-Type' => - 'multipart/related; type="application/xop+xml";start="";boundary="uuid:0ca0e16e-feb1-426c-97d8-c4508ada5e82+id=7";start-info="application/soap+xml"', + 'Content-Type' => 'multipart/related; type="application/xop+xml";start="";boundary="uuid:0ca0e16e-feb1-426c-97d8-c4508ada5e82+id=7";start-info="application/soap+xml"', 'Content-Length' => 1941, 'Host' => '131.107.72.15', 'Expect' => '100-continue', diff --git a/src/BeSimple/SoapCommon/WsSecurityFilterClientServer.php b/src/BeSimple/SoapCommon/WsSecurityFilterClientServer.php index 010d086..15b0d25 100644 --- a/src/BeSimple/SoapCommon/WsSecurityFilterClientServer.php +++ b/src/BeSimple/SoapCommon/WsSecurityFilterClientServer.php @@ -325,6 +325,7 @@ abstract class WsSecurityFilterClientServer if (Helper::NS_WSS === $key->namespaceURI) { switch ($key->localName) { case 'KeyIdentifier': + return $this->serviceSecurityKey->getPublicKey(); case 'Reference': $uri = $key->getAttribute('URI'); @@ -335,8 +336,7 @@ abstract class WsSecurityFilterClientServer $key = XmlSecurityEnc::decryptEncryptedKey($referencedNode, $this->userSecurityKey->getPrivateKey()); return XmlSecurityKey::factory($algorithm, $key, false, XmlSecurityKey::TYPE_PRIVATE); - } - if (Helper::NS_WSS === $referencedNode->namespaceURI + } elseif (Helper::NS_WSS === $referencedNode->namespaceURI && 'BinarySecurityToken' == $referencedNode->localName) { $key = XmlSecurityPem::formatKeyInPemFormat($referencedNode->textContent); diff --git a/src/BeSimple/SoapCommon/WsSecurityKey.php b/src/BeSimple/SoapCommon/WsSecurityKey.php index d6e03e6..432e654 100644 --- a/src/BeSimple/SoapCommon/WsSecurityKey.php +++ b/src/BeSimple/SoapCommon/WsSecurityKey.php @@ -113,4 +113,4 @@ class WsSecurityKey { return null !== $this->publicKey; } -} +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/Exception/ReceiverSoapFault.php b/src/BeSimple/SoapServer/Exception/ReceiverSoapFault.php new file mode 100644 index 0000000..105e3b5 --- /dev/null +++ b/src/BeSimple/SoapServer/Exception/ReceiverSoapFault.php @@ -0,0 +1,26 @@ + + * (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\Exception; + +/** + * ReceiverSoapFault send a "Receiver" fault code to client. + * This fault code is standardized: http://www.w3.org/TR/soap12-part1/#tabsoapfaultcodes + */ +class ReceiverSoapFault extends \SoapFault +{ + public function __construct($faultstring, $faultactor = null, $detail = null, $faultname = null, $headerfault = null) + { + parent::__construct('Receiver', $faultstring, $faultactor, $detail, $faultname, $headerfault); + } +} diff --git a/src/BeSimple/SoapServer/Exception/SenderSoapFault.php b/src/BeSimple/SoapServer/Exception/SenderSoapFault.php new file mode 100644 index 0000000..de9c358 --- /dev/null +++ b/src/BeSimple/SoapServer/Exception/SenderSoapFault.php @@ -0,0 +1,26 @@ + + * (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\Exception; + +/** + * SenderSoapFault send a "Sender" fault code to client. + * This fault code is standardized: http://www.w3.org/TR/soap12-part1/#tabsoapfaultcodes + */ +class SenderSoapFault extends \SoapFault +{ + public function __construct($faultstring, $faultactor = null, $detail = null, $faultname = null, $headerfault = null) + { + parent::__construct('Sender', $faultstring, $faultactor, $detail, $faultname, $headerfault); + } +} diff --git a/src/BeSimple/SoapServer/MimeFilter.php b/src/BeSimple/SoapServer/MimeFilter.php index 1f4e99b..502f3f4 100644 --- a/src/BeSimple/SoapServer/MimeFilter.php +++ b/src/BeSimple/SoapServer/MimeFilter.php @@ -16,10 +16,9 @@ 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\Mime\Part; use BeSimple\SoapCommon\SoapRequest; use BeSimple\SoapCommon\SoapRequestFilter; -use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; +use BeSimple\SoapCommon\SoapResponse; use BeSimple\SoapCommon\SoapResponseFilter; /** @@ -29,61 +28,111 @@ use BeSimple\SoapCommon\SoapResponseFilter; */ class MimeFilter implements SoapRequestFilter, SoapResponseFilter { - public function filterRequest(SoapRequest $request, $attachmentType) + /** + * 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) { - $multiPartMessage = MimeParser::parseMimeMessage( - $request->getContent(), - ['Content-Type' => trim($request->getContentType())] - ); - $soapPart = $multiPartMessage->getMainPart(); - $attachments = $multiPartMessage->getAttachments(); - - $request->setContent($soapPart->getContent()); - $request->setContentType($soapPart->getHeader('Content-Type')); - if (count($attachments) > 0) { - $request->setAttachments($attachments); - } - - return $request; + $this->attachmentType = $attachmentType; } - public function filterResponse(CommonSoapResponse $response, $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('Part_' . rand(10, 15) . '_' . uniqid() . '.' . uniqid()); + $multipart = new MimeMultiPart(); $soapPart = new MimePart($response->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT); $soapVersion = $response->getVersion(); - - if ($soapVersion === SOAP_1_1 && $attachmentType === Helper::ATTACHMENTS_TYPE_MTOM) { + // 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'); - } elseif ($soapVersion === SOAP_1_2) { + } + // 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(, $contentType) = explode(': ', $headers[0]); $response->setContentType($contentType); } - - return $response; - } - - private function sanitizePhpExceptionOnHrefs(Part $soapPart) - { - // 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 - return preg_replace('/href=(?!#)/', 'myhref=', $soapPart->getContent()); } } diff --git a/src/BeSimple/SoapServer/SoapKernel.php b/src/BeSimple/SoapServer/SoapKernel.php new file mode 100644 index 0000000..47808ca --- /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 as CommonSoapRequest; +use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse; + +/** + * SoapKernel for Server. + * + * @author Andreas Schamberger + */ +class SoapKernel extends CommonSoapKernel +{ + /** + * {@inheritDoc} + */ + public function filterRequest(CommonSoapRequest $request) + { + parent::filterRequest($request); + + $this->attachments = $request->getAttachments(); + } + + /** + * {@inheritDoc} + */ + public function filterResponse(CommonSoapResponse $response) + { + $response->setAttachments($this->attachments); + $this->attachments = array(); + + parent::filterResponse($response); + } +} diff --git a/src/BeSimple/SoapServer/SoapOptions/SoapServerOptions.php b/src/BeSimple/SoapServer/SoapOptions/SoapServerOptions.php deleted file mode 100644 index f75a3e7..0000000 --- a/src/BeSimple/SoapServer/SoapOptions/SoapServerOptions.php +++ /dev/null @@ -1,168 +0,0 @@ -handlerClass = $this->resolveHandlerClass($handlerClassOrObject); - $this->handlerObject = $this->resolveHandlerObject($handlerClassOrObject); - $this->keepAlive = $keepAlive; - $this->errorReporting = $errorReporting; - $this->exceptions = $exceptions; - $this->persistence = $persistence; - } - - public function getHandler() - { - if ($this->hasHandlerObject() && $this->hasHandlerClass()) { - - throw new Exception('Both HandlerClass and HandlerObject set: please specify only one'); - } - if ($this->hasHandlerObject()) { - - return $this->getHandlerObject(); - } - if ($this->hasHandlerClass()) { - - return $this->getHandlerClass(); - } - - throw new Exception('No HandlerClass or HandlerObject set'); - } - - public function getHandlerInstance() - { - if ($this->hasHandlerClass()) { - $handlerClassName = $this->handlerClass; - - return new $handlerClassName; - } - - return $this->getHandler(); - } - - public function hasHandlerClass() - { - return $this->handlerClass !== null; - } - - public function getHandlerClass() - { - return $this->handlerClass; - } - - public function hasHandlerObject() - { - return $this->handlerObject !== null; - } - - public function getHandlerObject() - { - return $this->handlerObject; - } - - public function hasPersistence() - { - return $this->persistence !== self::SOAP_SERVER_PERSISTENCE_NONE; - } - - public function getPersistence() - { - return $this->persistence; - } - - public function isErrorReporting() - { - return $this->errorReporting; - } - - public function isExceptions() - { - return $this->exceptions; - } - - public function isKeepAlive() - { - return $this->keepAlive; - } - - public function toArray() - { - $optionsAsArray = [ - 'keep_alive' => $this->isKeepAlive(), - 'exceptions' => $this->isExceptions(), - ]; - - return $optionsAsArray; - } - - /** - * @param mixed $handler - * @return mixed|null - */ - private function resolveHandlerObject($handler) - { - if (is_string($handler) && class_exists($handler)) { - - return null; - } - if (is_object($handler)) { - - return $handler; - } - - throw new \InvalidArgumentException('The handler has to be a class name or an object'); - } - - /** - * @param mixed $handler - * @return mixed|null - */ - private function resolveHandlerClass($handler) - { - if (is_string($handler) && class_exists($handler)) { - - return $handler; - } - if (is_object($handler)) { - - return null; - } - - throw new \InvalidArgumentException('The handler has to be a class name or an object'); - } -} diff --git a/src/BeSimple/SoapServer/SoapRequest.php b/src/BeSimple/SoapServer/SoapRequest.php new file mode 100644 index 0000000..7fae123 --- /dev/null +++ b/src/BeSimple/SoapServer/SoapRequest.php @@ -0,0 +1,72 @@ + + * (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) + { + $request = new SoapRequest(); + + // $content is if unmodified from SoapClient not a php string type! + $request->setContent((string) (null === $content ? file_get_contents("php://input") : $content)); + $request->setLocation(self::getCurrentUrl()); + $request->setAction(isset($_SERVER[SoapMessage::SOAP_ACTION_HEADER]) ? $_SERVER[SoapMessage::SOAP_ACTION_HEADER] : null); + $request->setVersion($version); + + if (isset($_SERVER[SoapMessage::CONTENT_TYPE_HEADER])) { + $request->setContentType($_SERVER[SoapMessage::CONTENT_TYPE_HEADER]); + } elseif (isset($_SERVER[SoapMessage::HTTP_CONTENT_TYPE_HEADER])) { + $request->setContentType($_SERVER[SoapMessage::HTTP_CONTENT_TYPE_HEADER]); + } + + 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; + } +} diff --git a/src/BeSimple/SoapServer/SoapResponse.php b/src/BeSimple/SoapServer/SoapResponse.php index ed6e677..eba70ff 100644 --- a/src/BeSimple/SoapServer/SoapResponse.php +++ b/src/BeSimple/SoapServer/SoapResponse.php @@ -1,13 +1,59 @@ + * (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 { - public function getResponseContent() + /** + * 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) { - return $this->getContent(); + $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()); + + // send content to client + echo $this->getContent(); } } diff --git a/src/BeSimple/SoapServer/SoapResponseFactory.php b/src/BeSimple/SoapServer/SoapResponseFactory.php deleted file mode 100644 index 7c6cdd7..0000000 --- a/src/BeSimple/SoapServer/SoapResponseFactory.php +++ /dev/null @@ -1,92 +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\SoapServer; - -use BeSimple\SoapBundle\Soap\SoapAttachment; -use BeSimple\SoapClient\SoapResponseTracingData; -use BeSimple\SoapCommon\Mime\PartFactory; -use BeSimple\SoapCommon\SoapMessage; - -class SoapResponseFactory -{ - /** - * Factory function for SoapServer\SoapResponse. - * - * @param string $content Content - * @param string $location Location - * @param string $action SOAP action - * @param string $version SOAP version - * @param SoapAttachment[] $attachments SOAP attachments - * - * @return SoapResponse - */ - public static function create( - $content, - $location, - $action, - $version, - array $attachments = [] - ) { - $response = new SoapResponse(); - $response->setContent($content); - $response->setLocation($location); - $response->setAction($action); - $response->setVersion($version); - $contentType = SoapMessage::getContentTypeForVersion($version); - $response->setContentType($contentType); - if (count($attachments) > 0) { - $response->setAttachments( - PartFactory::createAttachmentParts($attachments) - ); - } - - return $response; - } - - /** - * Factory function for SoapServer\SoapResponse. - * - * @param string $content Content - * @param string $location Location - * @param string $action SOAP action - * @param string $version SOAP version - * @param SoapResponseTracingData $tracingData Data value object suitable for tracing SOAP traffic - * @param SoapAttachment[] $attachments SOAP attachments - * - * @return SoapResponse - */ - public static function createWithTracingData( - $content, - $location, - $action, - $version, - SoapResponseTracingData $tracingData, - array $attachments = [] - ) { - $response = new SoapResponse(); - $response->setContent($content); - $response->setLocation($location); - $response->setAction($action); - $response->setVersion($version); - $response->setTracingData($tracingData); - $contentType = SoapMessage::getContentTypeForVersion($version); - $response->setContentType($contentType); - if (count($attachments) > 0) { - $response->setAttachments( - PartFactory::createAttachmentParts($attachments) - ); - } - - return $response; - } -} diff --git a/src/BeSimple/SoapServer/SoapServer.php b/src/BeSimple/SoapServer/SoapServer.php index dcc4eba..9b1deed 100644 --- a/src/BeSimple/SoapServer/SoapServer.php +++ b/src/BeSimple/SoapServer/SoapServer.php @@ -12,123 +12,73 @@ namespace BeSimple\SoapServer; -use BeSimple\SoapBundle\Soap\SoapAttachment; -use BeSimple\SoapCommon\AttachmentsHandlerInterface; -use BeSimple\SoapCommon\SoapKernel; -use BeSimple\SoapCommon\SoapOptions\SoapOptions; -use BeSimple\SoapCommon\SoapRequest; -use BeSimple\SoapCommon\SoapRequestFactory; -use BeSimple\SoapCommon\Storage\RequestHandlerAttachmentsStorage; -use BeSimple\SoapServer\SoapOptions\SoapServerOptions; +use BeSimple\SoapCommon\Helper; use BeSimple\SoapCommon\Converter\MtomTypeConverter; use BeSimple\SoapCommon\Converter\SwaTypeConverter; -use Exception; -use InvalidArgumentException; /** * Extended SoapServer that allows adding filters for SwA, MTOM, ... . * * @author Andreas Schamberger * @author Christian Kerl - * @author Petr Bechyně */ class SoapServer extends \SoapServer { - const SOAP_SERVER_REQUEST_FAILED = false; + /** + * Soap version. + * + * @var int + */ + protected $soapVersion = SOAP_1_1; - protected $soapVersion; - protected $soapServerOptions; - protected $soapOptions; + /** + * Soap kernel. + * + * @var \BeSimple\SoapServer\SoapKernel + */ + protected $soapKernel = null; /** * Constructor. * - * @param SoapServerOptions $soapServerOptions - * @param SoapOptions $soapOptions + * @param string $wsdl WSDL file + * @param array(string=>mixed) $options Options array */ - public function __construct(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions) + public function __construct($wsdl, array $options = array()) { - $this->validateSoapConfigs($soapServerOptions, $soapOptions); - - $this->soapVersion = $soapOptions->getSoapVersion(); - $this->soapServerOptions = $soapServerOptions; - $this->soapOptions = $soapOptions; - - parent::__construct( - $soapOptions->getWsdlFile(), - $soapServerOptions->toArray() + $soapOptions->toArray() - ); + // 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); } /** * Custom handle method to be able to modify the SOAP messages. * - * @deprecated * @param string $request Request string - * @return string */ public function handle($request = null) { - throw new Exception( - 'The handle method is now deprecated, because it accesses $_SERVER, $_POST. Use handleRequest instead' - ); - } + // wrap request data in SoapRequest object + $soapRequest = SoapRequest::create($request, $this->soapVersion); - /** - * Custom handle method to be able to modify the SOAP messages. - * - * @param string $requestUrl - * @param string $soapAction - * @param string $requestContentType - * @param string $requestContent = null - * @return SoapRequest - */ - public function createRequest($requestUrl, $soapAction, $requestContentType, $requestContent = null) - { - $soapRequest = SoapRequestFactory::createWithContentType( - $requestUrl, - $soapAction, - $this->soapVersion, - $requestContentType, - $requestContent - ); - if ($this->soapOptions->hasAttachments()) { - $soapRequest = SoapKernel::filterRequest( - $soapRequest, - $this->getAttachmentFilters(), - $this->soapOptions->getAttachmentType() - ); - } - - return $soapRequest; - } - - public function handleRequest(SoapRequest $soapRequest) - { + // handle actual SOAP request try { - - return $this->handleSoapRequest($soapRequest); - + $soapResponse = $this->handle2($soapRequest); } catch (\SoapFault $fault) { - - $this->fault($fault->faultcode, $fault->faultstring, $fault->faultactor, $fault->detail); - - return self::SOAP_SERVER_REQUEST_FAILED; + // issue an error to the client + $this->fault($fault->faultcode, $fault->faultstring); } - } - public function handleWsdlRequest(SoapRequest $soapRequest) - { - ob_start(); - parent::handle(); - $nativeSoapServerResponse = ob_get_clean(); - - return SoapResponseFactory::create( - $nativeSoapServerResponse, - $soapRequest->getLocation(), - $soapRequest->getAction(), - $soapRequest->getVersion() - ); + // send SOAP response to client + $soapResponse->send(); } /** @@ -140,133 +90,81 @@ class SoapServer extends \SoapServer * * @return SoapResponse */ - private function handleSoapRequest(SoapRequest $soapRequest) + public function handle2(SoapRequest $soapRequest) { - /** @var AttachmentsHandlerInterface $handler */ - $handler = $this->soapServerOptions->getHandler(); - - if ($this->soapOptions->hasAttachments()) { - $this->injectAttachmentStorage($handler, $soapRequest); - } + // run SoapKernel on SoapRequest + $this->soapKernel->filterRequest($soapRequest); + // call parent \SoapServer->handle() and buffer output ob_start(); parent::handle($soapRequest->getContent()); - $nativeSoapServerResponse = ob_get_clean(); - - $attachments = []; - if ($this->soapOptions->hasAttachments()) { - $attachments = $handler->getAttachmentStorage()->getAttachments(); - } + $response = ob_get_clean(); // Remove headers added by SoapServer::handle() method header_remove('Content-Length'); header_remove('Content-Type'); - return $this->createResponse( + // wrap response data in SoapResponse object + $soapResponse = SoapResponse::create( + $response, $soapRequest->getLocation(), $soapRequest->getAction(), - $soapRequest->getVersion(), - $nativeSoapServerResponse, - $attachments + $soapRequest->getVersion() ); - } - /** - * @param string $requestLocation - * @param string $soapAction - * @param string $soapVersion - * @param string|null $responseContent - * @param SoapAttachment[] $attachments - * @return SoapResponse - */ - private function createResponse($requestLocation, $soapAction, $soapVersion, $responseContent = null, array $attachments = []) - { - $soapResponse = SoapResponseFactory::create( - $responseContent, - $requestLocation, - $soapAction, - $soapVersion, - $attachments - ); - if ($this->soapOptions->hasAttachments()) { - $soapResponse = SoapKernel::filterResponse( - $soapResponse, - $this->getAttachmentFilters(), - $this->soapOptions->getAttachmentType() - ); - } + // run SoapKernel on SoapResponse + $this->soapKernel->filterResponse($soapResponse); return $soapResponse; } - private function injectAttachmentStorage(AttachmentsHandlerInterface $handler, SoapRequest $soapRequest) + /** + * Get SoapKernel instance. + * + * @return \BeSimple\SoapServer\SoapKernel + */ + public function getSoapKernel() { - $attachments = []; - if ($soapRequest->hasAttachments()) { - foreach ($soapRequest->getAttachments() as $attachment) { - $fileName = $attachment->getHeader('Content-Disposition', 'filename'); - if ($fileName === null) { - $fileName = basename($attachment->getHeader('Content-Location')); - } - $attachments[] = new SoapAttachment( - $fileName, - $attachment->getHeader('Content-Type'), - $attachment->getContent() - ); - } - } - $handler->addAttachmentStorage(new RequestHandlerAttachmentsStorage($attachments)); + return $this->soapKernel; } /** - * Legacy code: TypeConverters should be resolved in SoapServer::__construct() - * To be removed if all tests pass + * Configure filter and type converter for SwA/MTOM. * - * @deprecated - * @param SoapOptions $soapOptions - * @return SoapOptions + * @param array &$options SOAP constructor options array. + * + * @return void */ - private function configureTypeConverters(SoapOptions $soapOptions) + private function configureMime(array &$options) { - if ($soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) { - if ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA) { - $soapOptions->getTypeConverterCollection()->add(new SwaTypeConverter()); - } elseif ($soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) { - $soapOptions->getTypeConverterCollection()->add(new MtomTypeConverter()); - } else { - throw new InvalidArgumentException('Unresolved SOAP_ATTACHMENTS_TYPE: ' . $soapOptions->getAttachmentType()); + 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); } - } - - return $soapOptions; - } - - private function getAttachmentFilters() - { - $filters = []; - if ($this->soapOptions->getAttachmentType() !== SoapOptions::SOAP_ATTACHMENTS_TYPE_BASE64) { - $filters[] = new MimeFilter(); - } - if ($this->soapOptions->getAttachmentType() === SoapOptions::SOAP_ATTACHMENTS_TYPE_MTOM) { - $filters[] = new XmlMimeFilter(); - } - - return $filters; - } - - private function validateSoapConfigs(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions) - { - if ($soapOptions->hasAttachments()) { - if (!$soapServerOptions->getHandlerInstance() instanceof AttachmentsHandlerInterface) { - throw new InvalidArgumentException( - sprintf( - '%s::handlerObject or handlerClass (instance of %s given) must implement %s in order to handle with attachments', - SoapServerOptions::class, - get_class($soapServerOptions->getHandlerInstance()), - AttachmentsHandlerInterface::class - ) - ); + // 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); + }, + ); } } } diff --git a/src/BeSimple/SoapServer/SoapServerBuilder.php b/src/BeSimple/SoapServer/SoapServerBuilder.php index d7417f4..365c812 100644 --- a/src/BeSimple/SoapServer/SoapServerBuilder.php +++ b/src/BeSimple/SoapServer/SoapServerBuilder.php @@ -12,46 +12,189 @@ namespace BeSimple\SoapServer; -use BeSimple\SoapCommon\SoapOptions\SoapOptions; -use BeSimple\SoapServer\SoapOptions\SoapServerOptions; -use Exception; +use BeSimple\SoapCommon\AbstractSoapBuilder; +use BeSimple\SoapCommon\Helper; /** - * SoapServerBuilder provides a SoapServer instance from SoapServerOptions and SoapOptions. + * SoapServerBuilder provides a fluent interface to configure and create a SoapServer instance. * - * @author Petr Bechyně + * @author Christian Kerl */ -class SoapServerBuilder +class SoapServerBuilder extends AbstractSoapBuilder { + protected $persistence; + protected $errorReporting; + + protected $handlerClass; + protected $handlerObject; + /** - * Builds a SoapServer instance. + * Create new instance with default options. * - * @param SoapServerOptions $soapServerOptions - * @param SoapOptions $soapOptions - * - * @return SoapServer + * @return \BeSimple\SoapServer\SoapServerBuilder */ - public function build(SoapServerOptions $soapServerOptions, SoapOptions $soapOptions) + static public function createWithDefaults() { - use_soap_error_handler($soapServerOptions->isErrorReporting()); + return parent::createWithDefaults() + ->withErrorReporting(false); + } - $server = new SoapServer($soapServerOptions, $soapOptions); - if ($soapServerOptions->hasPersistence()) { - $server->setPersistence($soapServerOptions->getPersistence()); - } - if ($soapServerOptions->hasHandlerClass()) { - $server->setClass($soapServerOptions->getHandlerClass()); - } - if ($soapServerOptions->hasHandlerObject()) { - $server->setObject($soapServerOptions->getHandlerObject()); - } - if ($soapServerOptions->hasHandlerClass() && $soapServerOptions->hasHandlerObject()) { + /** + * Initializes all options with the defaults used in the native SoapServer. + */ + public function __construct() + { + parent::__construct(); - throw new Exception( - 'Could not create SoapServer: HandlerClass and HandlerObject are set: please specify only one' - ); + // TODO: this is not the default, but safer + $this->withErrorReporting(false); + } + + /** + * Finally returns a SoapClient instance. + * + * @return \BeSimple\SoapServer\SoapServer + */ + public function build() + { + $this->validateOptions(); + + use_soap_error_handler($this->errorReporting); + + $server = new SoapServer($this->wsdl, $this->getSoapOptions()); + + if (null !== $this->persistence) { + $server->setPersistence($this->persistence); + } + + if (null !== $this->handlerClass) { + $server->setClass($this->handlerClass); + } elseif (null !== $this->handlerObject) { + $server->setObject($this->handlerObject); } return $server; } -} + + /** + * Cofigures the SOAP actor. + * + * @param string $actor Actor name + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withActor($actor) + { + $this->options['actor'] = $actor; + + return $this; + } + + /** + * Enables persistence. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withPersistanceRequest() + { + $this->persistence = SOAP_PERSISTENCE_REQUEST; + + return $this; + } + + /** + * Enables the HTTP session. The handler object is persisted between multiple requests in a session. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withPersistenceSession() + { + $this->persistence = SOAP_PERSISTENCE_SESSION; + + return $this; + } + + /** + * Enables reporting of internal errors to clients. This should only be enabled in development environments. + * + * @param boolean $enable Enable error reporting + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withErrorReporting($enable = true) + { + $this->errorReporting = $enable; + + return $this; + } + + /** + * SOAP attachment type Base64. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withBase64Attachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_BASE64; + + return $this; + } + + /** + * SOAP attachment type SwA. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withSwaAttachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_SWA; + + return $this; + } + + /** + * SOAP attachment type MTOM. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withMtomAttachments() + { + $this->options['attachment_type'] = Helper::ATTACHMENTS_TYPE_MTOM; + + return $this; + } + + /** + * Configures the handler class or object. + * + * @param mixed $handler Can be either a class name or an object. + * + * @return \BeSimple\SoapServer\SoapServerBuilder + */ + public function withHandler($handler) + { + if (is_string($handler) && class_exists($handler)) { + $this->handlerClass = $handler; + $this->handlerObject = null; + } elseif (is_object($handler)) { + $this->handlerClass = null; + $this->handlerObject = $handler; + } else { + throw new \InvalidArgumentException('The handler has to be a class name or an object'); + } + + return $this; + } + + /** + * Validate options. + */ + protected function validateOptions() + { + $this->validateWsdl(); + + if (null === $this->handlerClass && null === $this->handlerObject) { + throw new \InvalidArgumentException('The handler has to be configured!'); + } + } +} \ No newline at end of file diff --git a/src/BeSimple/SoapServer/SoapServerOptionsBuilder.php b/src/BeSimple/SoapServer/SoapServerOptionsBuilder.php deleted file mode 100644 index f393363..0000000 --- a/src/BeSimple/SoapServer/SoapServerOptionsBuilder.php +++ /dev/null @@ -1,19 +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\SoapServer\Tests; + +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(); + } +} diff --git a/src/BeSimple/SoapServer/WsSecurityFilter.php b/src/BeSimple/SoapServer/WsSecurityFilter.php index 0de19e9..b2e86a0 100644 --- a/src/BeSimple/SoapServer/WsSecurityFilter.php +++ b/src/BeSimple/SoapServer/WsSecurityFilter.php @@ -67,11 +67,10 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque * Modify the given request XML. * * @param \BeSimple\SoapCommon\SoapRequest $request SOAP request - * @param int $attachmentType * * @return void */ - public function filterRequest(CommonSoapRequest $request, $attachmentType) + public function filterRequest(CommonSoapRequest $request) { // get \DOMDocument from SOAP request $dom = $request->getContentDocument(); @@ -153,11 +152,10 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque * Modify the given request XML. * * @param \BeSimple\SoapCommon\SoapResponse $response SOAP response - * @param int $attachmentType * * @return void */ - public function filterResponse(CommonSoapResponse $response, $attachmentType) + public function filterResponse(CommonSoapResponse $response) { // get \DOMDocument from SOAP response $dom = $response->getContentDocument(); @@ -192,7 +190,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque } if (null !== $this->userSecurityKey && $this->userSecurityKey->hasKeys()) { - $guid = 'CertId-' . Helper::generateUuid(); + $guid = 'CertId-' . Helper::generateUUID(); // add token references $keyInfo = null; if (null !== $this->tokenReferenceSignature) { @@ -218,7 +216,7 @@ class WsSecurityFilter extends WsSecurityFilterClientServer implements SoapReque // encrypt soap document if (null !== $this->serviceSecurityKey && $this->serviceSecurityKey->hasKeys()) { - $guid = 'EncKey-' . Helper::generateUuid(); + $guid = 'EncKey-' . Helper::generateUUID(); // add token references $keyInfo = null; if (null !== $this->tokenReferenceEncryption) { diff --git a/src/BeSimple/SoapServer/XmlMimeFilter.php b/src/BeSimple/SoapServer/XmlMimeFilter.php index dd4ccd1..5c41c4f 100644 --- a/src/BeSimple/SoapServer/XmlMimeFilter.php +++ b/src/BeSimple/SoapServer/XmlMimeFilter.php @@ -31,8 +31,16 @@ class XmlMimeFilter implements SoapResponseFilter { } - public function filterResponse(SoapResponse $response, $attachmentType) + /** + * 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 @@ -58,6 +66,5 @@ class XmlMimeFilter implements SoapResponseFilter } } - return $response; } } diff --git a/tests/BeSimple/SoapClient/SoapClientBuilderTest.php b/tests/BeSimple/SoapClient/SoapClientBuilderTest.php deleted file mode 100644 index a37cb5f..0000000 --- a/tests/BeSimple/SoapClient/SoapClientBuilderTest.php +++ /dev/null @@ -1,116 +0,0 @@ -getWsdlFile()); - } - - public function testSoapClientOptionsCreateWithDefaults() - { - $defaultOptions = SoapClientOptionsBuilder::createWithDefaults(); - - self::assertInstanceOf(SoapClientOptions::class, $defaultOptions); - self::assertEquals(CurlOptions::DEFAULT_USER_AGENT, $defaultOptions->getUserAgent()); - } - - public function testConstructSoapClientWithDefaults() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) - ); - - self::assertInstanceOf(SoapClient::class, $soapClient); - } - - public function testConstructSoapClientWithSwaAndClassMapAndCacheDisk() - { - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_REMOTE_WSDL_UK, - new ClassMap(), - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ); - - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - $soapOptions - ); - - self::assertInstanceOf(SoapClient::class, $soapClient); - } - - public function testConstructSoapClientWithDefaultsAndLocalWsdlFile() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults(self::TEST_LOCAL_WSDL_UK) - ); - - self::assertInstanceOf(SoapClient::class, $soapClient); - } - - public function testConstructSoapClientWithSwaAndClassMapAndCacheDiskAndLocalWsdlFile() - { - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_LOCAL_WSDL_UK, - new ClassMap(), - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ); - - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - $soapOptions - ); - - self::assertInstanceOf(SoapClient::class, $soapClient); - } - - public function testCreateOptionsWithAuthenticationAndEndpointLocationAndSslVersionV3() - { - $authentication = new SoapServerAuthenticationBasic('', ''); - $soapClientOptions = SoapClientOptionsBuilder::createWithAuthenticationAndEndpointLocationAndSslVersionV3('', $authentication); - - self::assertSame(CURL_SSLVERSION_SSLv3, $soapClientOptions->getSslVersion()); - } - - public function testConstructSoapClientWithAuthenticationAndEndpointLocationAndSslVersionV3() - { - $authentication = new SoapServerAuthenticationBasic('', ''); - $soapOptions = SoapOptionsBuilder::createWithDefaults(self::TEST_LOCAL_WSDL_UK); - - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithAuthenticationAndEndpointLocationAndSslVersionV3('', $authentication), - $soapOptions - ); - - self::assertInstanceOf(SoapClient::class, $soapClient); - } - - private function getSoapBuilder() - { - return new SoapClientBuilder(); - } -} diff --git a/tests/BeSimple/SoapClient/SoapClientTest.php b/tests/BeSimple/SoapClient/SoapClientTest.php deleted file mode 100644 index 517dc07..0000000 --- a/tests/BeSimple/SoapClient/SoapClientTest.php +++ /dev/null @@ -1,322 +0,0 @@ -localWebServerProcess = popen('php -S localhost:8000 > /dev/null 2>&1 &', 'r'); - } - - public function tearDown() - { - pclose($this->localWebServerProcess); - } - - public function testSoapCall() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - $soapResponse = $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); - - self::assertContains('GetUKLocationByCountyResult', $soapResponse->getContent()); - self::assertContains('', $soapResponse->getContent()); - self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); - } - - public function testSoapCallWithCustomEndpointValid() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_ENDPOINT_UK), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - $soapResponse = $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); - - self::assertContains('Connection: close', $soapResponse->getTracingData()->getLastRequestHeaders()); - self::assertContains('County>LondongetTracingData()->getLastRequest()); - self::assertContains('GetUKLocationByCountyResult', $soapResponse->getContent()); - self::assertContains('', $soapResponse->getContent()); - self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); - } - - public function testSoapCallWithKeepAliveTrue() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_ENDPOINT_UK), - SoapOptionsBuilder::createWithDefaultsKeepAlive(self::TEST_REMOTE_WSDL_UK) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - $soapResponse = $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); - - self::assertContains('Connection: Keep-Alive', $soapResponse->getTracingData()->getLastRequestHeaders()); - self::assertContains('County>LondongetTracingData()->getLastRequest()); - self::assertContains('GetUKLocationByCountyResult', $soapResponse->getContent()); - self::assertContains('', $soapResponse->getContent()); - self::assertEquals(self::TEST_ENDPOINT_UK, $soapResponse->getLocation()); - } - - public function testSoapCallWithCustomEndpointInvalidShouldFail() - { - $this->setExpectedException(Exception::class, 't resolve host'); - - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_REMOTE_ENDPOINT_NOT_WORKING), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - $soapClient->soapCall('GetUKLocationByCounty', [$getUKLocationByCountyRequest]); - } - - public function testSoapCallWithCacheEndpointDownShouldFail() - { - $this->setExpectedException(Exception::class, 'Could not write WSDL cache file: Download failed with message'); - - $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults( - self::TEST_REMOTE_WSDL_NOT_WORKING, - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ) - ); - } - - public function testSoapCallEndpointDownShouldFail() - { - $this->setExpectedException(Exception::class, 'Parsing WSDL: Couldn\'t load from'); - - $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_NOT_WORKING) - ); - } - - public function testSoapCallNoSwaWithAttachmentMustFail() - { - $this->setExpectedException(Exception::class, 'Non SWA SoapClient cannot handle SOAP action'); - - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithDefaults(), - SoapOptionsBuilder::createWithDefaults(self::TEST_REMOTE_WSDL_UK) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - - $soapClient->soapCall( - 'GetUKLocationByCounty', - [$getUKLocationByCountyRequest], - [ - new SoapAttachment( - 'first-file.txt', - 'text/plain', - 'unexpected file - no SWA - must fail' - ), - ] - ); - } - - public function testSoapCallSwaWithTwoAttachments() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithTracing(), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_REMOTE_WSDL_UK, - new ClassMap(), - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - - try { - $soapResponse = $soapClient->soapCall( - 'GetUKLocationByCounty', - [$getUKLocationByCountyRequest], - [ - new SoapAttachment( - 'first-file.txt', - 'text/plain', - 'hello world' - ), - new SoapAttachment( - 'second-file.txt', - 'text/plain', - 'hello world' - ) - ] - ); - $tracingData = $soapResponse->getTracingData(); - } catch (SoapFaultWithTracingData $e) { - $tracingData = $e->getSoapResponseTracingData(); - } - - self::assertEquals( - $this->getContentId($tracingData->getLastRequestHeaders()), - $this->getContentId($tracingData->getLastRequest()), - 'Content ID must match in request XML and Content-Type: ...; start header' - ); - self::assertEquals( - $this->getMultiPartBoundary($tracingData->getLastRequestHeaders()), - $this->getMultiPartBoundary($tracingData->getLastRequest()), - 'MultiPart boundary must match in request XML and Content-Type: ...; boundary header' - ); - self::assertContains('boundary=Part_', $tracingData->getLastRequestHeaders(), 'Headers should link to boundary'); - self::assertContains('start="getLastRequestHeaders(), 'Headers should link to first MultiPart'); - self::assertContains('action="', $tracingData->getLastRequestHeaders(), 'Headers should contain SOAP action'); - self::assertEquals( - $this->removeOneTimeData( - file_get_contents( - self::FIXTURES_DIR.'/Message/Request/GetUKLocationByCounty.request.mimepart.message' - ) - ), - $this->removeOneTimeData( - $tracingData->getLastRequest() - ), - 'Requests must match after onetime data were removed' - ); - } - - public function testSoapCallSwaWithNoAttachments() - { - $soapClient = $this->getSoapBuilder()->build( - SoapClientOptionsBuilder::createWithTracing(), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_REMOTE_WSDL_UK, - new ClassMap(), - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ) - ); - $getUKLocationByCountyRequest = new GetUKLocationByCounty(); - $getUKLocationByCountyRequest->County = 'London'; - - try { - $soapResponse = $soapClient->soapCall( - 'GetUKLocationByCounty', - [$getUKLocationByCountyRequest] - ); - $tracingData = $soapResponse->getTracingData(); - } catch (SoapFaultWithTracingData $e) { - $tracingData = $e->getSoapResponseTracingData(); - } - - self::assertNotContains('boundary=Part_', $tracingData->getLastRequestHeaders(), 'Headers should link to boundary'); - self::assertNotContains('start="getLastRequestHeaders(), 'Headers should link to first MultiPart'); - self::assertContains('action="', $tracingData->getLastRequestHeaders(), 'Headers should contain SOAP action'); - self::assertStringEqualsFile( - self::FIXTURES_DIR.'/Message/Request/GetUKLocationByCounty.request.message', - $tracingData->getLastRequest(), - 'Requests must match' - ); - } - - /** - * @see This test needs to start a mock server first - */ - public function testSoapCallSwaWithAttachmentsOnResponse() - { - $soapClient = $this->getSoapBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithTracing(), - SoapOptionsBuilder::createSwaWithClassMapV11( - self::TEST_HTTP_URL.'/SwaEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_DISK, - self::CACHE_DIR - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - $generateTestRequest = new GenerateTestRequest(); - $generateTestRequest->salutation = 'World'; - - $soapResponse = $soapClient->soapCall('generateTest', [$generateTestRequest]); - $attachments = $soapResponse->getAttachments(); - - self::assertContains('', $soapResponse->getResponseContent()); - self::assertTrue($soapResponse->hasAttachments()); - self::assertCount(1, $attachments); - - $firstAttachment = reset($attachments); - - self::assertEquals('text/plain', $firstAttachment->getHeader('Content-Type')); - - file_put_contents(self::CACHE_DIR . '/testSoapCallSwaWithAttachmentsOnResponse.xml', $soapResponse->getContent()); - file_put_contents(self::CACHE_DIR . '/testSoapCallSwaWithAttachmentsOnResponse.txt', $firstAttachment->getContent()); - } - - public function removeOneTimeData($string) - { - $contentId = $this->getContentId($string); - $multiPartBoundary = $this->getMultiPartBoundary($string); - - return str_replace( - $contentId, - '{content-id-placeholder}', - str_replace( - $multiPartBoundary, - '{multipart-boundary-placeholder}', - $string - ) - ); - } - - private function getMultiPartBoundary($string) - { - $realMultiParts = null; - preg_match('/Part\_[0-9]{2}\_[a-zA-Z0-9]{13}\.[a-zA-Z0-9]{13}/', $string, $realMultiParts); - if (count($realMultiParts) > 0) { - return $realMultiParts[0]; - } - - throw new Exception('Could not find real MultiPart boundary'); - } - - private function getContentId($string) - { - $realContentIds = null; - preg_match('/part\-[0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12}\@response\.info/', $string, $realContentIds); - if (count($realContentIds) > 0) { - return $realContentIds[0]; - } - - throw new Exception('Could not find real contentId'); - } - - private function getSoapBuilder() - { - return new SoapClientBuilder(); - } -} diff --git a/tests/BeSimple/SoapClient/Xml/Path/RelativePathResolverTest.php b/tests/BeSimple/SoapClient/Xml/Path/RelativePathResolverTest.php deleted file mode 100644 index 07d487b..0000000 --- a/tests/BeSimple/SoapClient/Xml/Path/RelativePathResolverTest.php +++ /dev/null @@ -1,70 +0,0 @@ -relativePathResolver = new RelativePathResolver(); - } - - /** - * @param string $base - * @param string $relative - * @param string $assertPath - * @dataProvider providePathInfo - */ - public function testResolveRelativePathInUrl($base, $relative, $assertPath) - { - $path = $this->relativePathResolver->resolveRelativePathInUrl($base, $relative); - - self::assertEquals($assertPath, $path); - } - - public function providePathInfo() - { - return [ - [ - 'http://anyendpoint.tld:9999/path/to/endpoint.wsdl', - '../Schemas/Common/SoapHeader.xsd', - 'http://anyendpoint.tld:9999/path/Schemas/Common/SoapHeader.xsd', - ], - [ - 'http://endpoint-location.ltd/', - 'Document1.xsd', - 'http://endpoint-location.ltd/Document1.xsd', - ], - [ - 'http://endpoint-location.ltd:8080/endpoint/', - '../Schemas/Common/Document2.xsd', - 'http://endpoint-location.ltd:8080/Schemas/Common/Document2.xsd', - ], - [ - 'http://endpoint-location.ltd/', - '../Schemas/Common/Document3.xsd', - 'http://endpoint-location.ltd/Schemas/Common/Document3.xsd', - ], - [ - 'http://endpoint-location.ltd/', - '/Document4.xsd', - 'http://endpoint-location.ltd/Document4.xsd', - ], - [ - 'http://endpoint-location.ltd', - '/Document5.xsd', - 'http://endpoint-location.ltd/Document5.xsd', - ], - [ - 'http://endpoint-location.ltd', - 'Document6.xsd', - 'http://endpoint-location.ltd/Document6.xsd', - ] - ]; - } -} diff --git a/tests/BeSimple/SoapClient/Xml/RemoteFileResolverTest.php b/tests/BeSimple/SoapClient/Xml/RemoteFileResolverTest.php deleted file mode 100644 index 9e80a14..0000000 --- a/tests/BeSimple/SoapClient/Xml/RemoteFileResolverTest.php +++ /dev/null @@ -1,42 +0,0 @@ -remoteFileResolver = new RemoteFileResolver(); - } - - /** - * @param string $wsdlPath - * @param bool $assertIsRemoteFile - * @dataProvider provideWsdlPaths - */ - public function testIsRemoteFile($wsdlPath, $assertIsRemoteFile) - { - $isRemoteFile = $this->remoteFileResolver->isRemoteFile($wsdlPath); - - self::assertEquals($assertIsRemoteFile, $isRemoteFile); - } - - public function provideWsdlPaths() - { - return [ - ['http://endpoint.tld/path/to/wsdl.wsdl', self::FILE_IS_REMOTE], - ['http://endpoint.tld:1944/path/to/wsdl.wsdl', self::FILE_IS_REMOTE], - ['path/to/wsdl.wsdl', self::FILE_IS_NOT_REMOTE], - ['../../path/to/wsdl.wsdl', self::FILE_IS_NOT_REMOTE], - ['/path/to/wsdl.wsdl', self::FILE_IS_NOT_REMOTE], - ]; - } -} diff --git a/tests/BeSimple/SoapClient/Xml/XmlDomDocumentImportReplacerTest.php b/tests/BeSimple/SoapClient/Xml/XmlDomDocumentImportReplacerTest.php deleted file mode 100644 index 11a435d..0000000 --- a/tests/BeSimple/SoapClient/Xml/XmlDomDocumentImportReplacerTest.php +++ /dev/null @@ -1,114 +0,0 @@ -xmlDomDocumentImportReplacer = new XmlDomDocumentImportReplacer(); - } - - /** - * @param string $xmlSource - * @param Curl $curl - * @param string $schemaPrefix - * @param string $schemaUrl - * @param string $locationAttributeName - * @param string|null $parentFilePath - * @param string|null $assertImportXmlSource - * @dataProvider provideXmlDocumentData - */ - public function testUpdateXmlDocument( - $xmlSource, - Curl $curl, - $schemaPrefix, - $schemaUrl, - $locationAttributeName, - $parentFilePath = null, - $assertImportXmlSource = null - ) { - $wsdl = new DOMDocument(); - $wsdl->loadXML($xmlSource); - - $this->xmlDomDocumentImportReplacer->updateXmlDocument( - $curl, - Cache::TYPE_NONE, - new DOMXPath($wsdl), - $schemaPrefix, - $schemaUrl, - $locationAttributeName, - $parentFilePath - ); - $wsdlSource = $wsdl->saveHTML(); - - self::assertContains( - $assertImportXmlSource, - $wsdlSource - ); - } - - public function provideXmlDocumentData() - { - return [ - 'wsdlWithoutParentPath' => [ - file_get_contents(__DIR__.'/testUpdateXmlDocument.wsdl'), - new Curl(CurlOptionsBuilder::buildDefault()), - Helper::PFX_WSDL, - Helper::NS_WSDL, - 'location', - self::NO_PARENT_FILE_PATH, - '' - ], - 'schemaWithoutParentPath' => [ - file_get_contents(__DIR__.'/testUpdateXmlDocument.wsdl'), - new Curl(CurlOptionsBuilder::buildDefault()), - Helper::PFX_XML_SCHEMA, - Helper::NS_XML_SCHEMA, - 'schemaLocation', - self::NO_PARENT_FILE_PATH, - '' - ], - 'wsdlWithParentPath' => [ - file_get_contents(__DIR__.'/testUpdateXmlDocument.wsdl'), - new Curl(CurlOptionsBuilder::buildDefault()), - Helper::PFX_WSDL, - Helper::NS_WSDL, - 'location', - 'http://endpoint-location.ltd:8080/endpoint/', - '' - ], - 'schemaWithParentPath' => [ - file_get_contents(__DIR__.'/testUpdateXmlDocument.wsdl'), - new Curl(CurlOptionsBuilder::buildDefault()), - Helper::PFX_XML_SCHEMA, - Helper::NS_XML_SCHEMA, - 'schemaLocation', - 'http://endpoint-location.ltd:8080/endpoint/wsdl.wsdl', - '' - ], - 'schemaWithParentPathAndSubDir' => [ - file_get_contents(__DIR__.'/testUpdateXmlDocument.wsdl'), - new Curl(CurlOptionsBuilder::buildDefault()), - Helper::PFX_XML_SCHEMA, - Helper::NS_XML_SCHEMA, - 'schemaLocation', - 'http://endpoint-location.ltd:8080/endpoint/subdir/wsdl.wsdl', - '' - ], - ]; - } -} diff --git a/tests/BeSimple/SoapClient/Xml/testUpdateXmlDocument.wsdl b/tests/BeSimple/SoapClient/Xml/testUpdateXmlDocument.wsdl deleted file mode 100644 index 209f0ca..0000000 --- a/tests/BeSimple/SoapClient/Xml/testUpdateXmlDocument.wsdl +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - TEST-OPERATION-1 - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/BeSimple/SoapCommon/Fault/SoapFaultParserTest.php b/tests/BeSimple/SoapCommon/Fault/SoapFaultParserTest.php deleted file mode 100644 index 8270696..0000000 --- a/tests/BeSimple/SoapCommon/Fault/SoapFaultParserTest.php +++ /dev/null @@ -1,33 +0,0 @@ -'. - ''. - ''. - ''. - '911'. - 'This is a dummy SoapFault.'. - ''. - ''. - ''; - $soapFault = SoapFaultParser::parseSoapFault($soapFaultXml); - - self::assertInstanceOf(SoapFault::class, $soapFault); - self::assertEquals( - '911', - $soapFault->faultcode - ); - self::assertEquals( - 'This is a dummy SoapFault.', - $soapFault->getMessage() - ); - } -} diff --git a/tests/BeSimple/SoapCommon/Fault/SoapFaultSourceGetterTest.php b/tests/BeSimple/SoapCommon/Fault/SoapFaultSourceGetterTest.php deleted file mode 100644 index dfed3fd..0000000 --- a/tests/BeSimple/SoapCommon/Fault/SoapFaultSourceGetterTest.php +++ /dev/null @@ -1,64 +0,0 @@ -getNativeSoapFaultFromClient()], - // @todo: add more test cases for Soap Server \SoapFault - ]; - } - - public function provideBeSimpleSoapFaults() - { - return [ - [new SoapFault(SoapFaultEnum::SOAP_FAULT_HTTP, 'HTTP Connection error')], - [new SoapFault(SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR, 'SOAP Client error')], - [new SoapFault(SoapFaultEnum::SOAP_FAULT_WSDL, 'WSDL error')], - ]; - } - - /** - * @return SoapFault - */ - private function getNativeSoapFaultFromClient() - { - try { - $soapClient = @new \SoapClient('non-existing-wsdl-throwing-soapfault'); - $soapClient->__call('no-function', []); - } catch (SoapFault $e) { - - return $e; - } - - self::fail('Cannot generate native PHP SoapFault from Client, please review the test'); - } -} diff --git a/tests/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyserTest.php b/tests/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyserTest.php deleted file mode 100644 index eefe2cf..0000000 --- a/tests/BeSimple/SoapCommon/Mime/Boundary/MimeBoundaryAnalyserTest.php +++ /dev/null @@ -1,77 +0,0 @@ -setExpectedException(Exception::class, $failedTestCaseFailMessage); - } - $parsedPartsList = ParsedPartsGetter::getPartsFromMimeMessageLines( - $multiPart, - $mimeMessageLines, - $hasHttpRequestHeaders - ); - - if ($testCaseShouldFail === false) { - self::assertInstanceOf(ParsedPartList::class, $parsedPartsList); - self::assertGreaterThanOrEqual(3, $parsedPartsList->getPartCount()); - self::assertTrue($parsedPartsList->hasExactlyOneMainPart()); - } - } - - public function provideMimeMessageLines() - { - $mimePartWithHeadersForSwaResponse = new MultiPart(); - $mimePartWithHeadersForSwaResponse->setHeader('Content-Type', 'boundary', 'Part_13_58e3bc35f3743.58e3bc35f376f'); - $mimePartWithHeadersForSwaResponse->setHeader('Content-Type', 'start', ''); - - $mimePartWithWrongHeadersForSwaResponse = new MultiPart(); - $mimePartWithWrongHeadersForSwaResponse->setHeader('Content-Type', 'boundary', 'non-existing'); - $mimePartWithWrongHeadersForSwaResponse->setHeader('Content-Type', 'start', ''); - - $mimePartWithHeadersForSwaRequest = new MultiPart(); - $mimePartWithHeadersForSwaRequest->setHeader('Content-Type', 'boundary', '----=_Part_6_2094841787.1482231370463'); - $mimePartWithHeadersForSwaRequest->setHeader('Content-Type', 'start', ''); - - return [ - 'ParseSwaResponseWith2FilesAnd1BinaryFile' => [ - $mimePartWithHeadersForSwaResponse, - $this->getMessageLinesFromMimeMessage(__DIR__.'/../../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - ParsedPartsGetter::HAS_HTTP_REQUEST_HEADERS, - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithNoHeaders' => [ - new MultiPart(), - $this->getMessageLinesFromMimeMessage(__DIR__.'/../../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS, - self::TEST_CASE_SHOULD_FAIL, - 'Unable to get Content-Type boundary' - ], - 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithWrongHeaders' => [ - $mimePartWithWrongHeadersForSwaResponse, - $this->getMessageLinesFromMimeMessage(__DIR__.'/../../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - ParsedPartsGetter::HAS_HTTP_REQUEST_HEADERS, - self::TEST_CASE_SHOULD_FAIL, - 'cannot parse headers before hitting the first boundary' - ], - 'ParseSwaRequestWith2Files' => [ - $mimePartWithHeadersForSwaRequest, - $this->getMessageLinesFromMimeMessage(__DIR__ . '/../../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), - ParsedPartsGetter::HAS_HTTP_REQUEST_HEADERS, - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseSwaRequestWith2FilesShouldFailWithNoHeaders' => [ - new MultiPart(), - $this->getMessageLinesFromMimeMessage(__DIR__ . '/../../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), - ParsedPartsGetter::HAS_NO_HTTP_REQUEST_HEADERS, - self::TEST_CASE_SHOULD_FAIL, - 'Unable to get Content-Type boundary' - ], - ]; - } - - private function getMessageLinesFromMimeMessage($filePath) - { - if (file_exists($filePath) === false) { - self::fail('Please, update tests data provider - file not found: '.$filePath); - } - - return explode("\n", file_get_contents($filePath)); - } -} diff --git a/tests/BeSimple/SoapCommon/Mime/ParserTest.php b/tests/BeSimple/SoapCommon/Mime/ParserTest.php deleted file mode 100644 index f7ad5a7..0000000 --- a/tests/BeSimple/SoapCommon/Mime/ParserTest.php +++ /dev/null @@ -1,99 +0,0 @@ -setExpectedException(Exception::class, $failedTestCaseFailMessage); - } - - $mimeMessage = Parser::parseMimeMessage($mimeMessage, $headers); - - if ($testCaseShouldFail === false) { - self::assertInstanceOf(MultiPart::class, $mimeMessage); - self::assertInstanceOf(Part::class, $mimeMessage->getMainPart()); - } - } - - public function provideMimeMessages() - { - return [ - 'ParseRequest' => [ - $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.message.request'), - [], - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseRequestOneLiner' => [ - $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request'), - [], - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseSwaResponseWith2FilesAnd1BinaryFile' => [ - $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - [ - 'Content-Type' => 'multipart/related;'. - ' type="application/soap+xml"; charset=utf-8;'. - ' boundary=Part_13_58e3bc35f3743.58e3bc35f376f;'. - ' start=""' - ], - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithNoHeaders' => [ - $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - [], - self::TEST_CASE_SHOULD_FAIL, - 'Unable to get Content-Type boundary' - ], - 'ParseSwaResponseWith2FilesAnd1BinaryFileShouldFailWithWrongHeaders' => [ - $this->getMimeMessageFromFile(__DIR__.'/../../../Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message'), - [ - 'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=DOES_NOT_EXIST; start=""' - ], - self::TEST_CASE_SHOULD_FAIL, - 'cannot parse headers before hitting the first boundary' - ], - 'ParseSwaRequestWith2Files' => [ - $this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), - [ - 'Content-Type' => 'multipart/related; type="application/soap+xml"; charset=utf-8; boundary=----=_Part_6_2094841787.1482231370463; start=""' - ], - self::TEST_CASE_SHOULD_NOT_FAIL - ], - 'ParseSwaRequestWith2FilesShouldFailWithNoHeaders' => [ - $this->getMimeMessageFromFile(__DIR__ . '/../../../Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message'), - [], - self::TEST_CASE_SHOULD_FAIL, - 'Unable to get Content-Type boundary' - ], - ]; - } - - private function getMimeMessageFromFile($filePath) - { - if (file_exists($filePath) === false) { - self::fail('Please, update tests data provider - file not found: '.$filePath); - } - - return file_get_contents($filePath); - } -} diff --git a/tests/BeSimple/SoapServer/SoapServerBuilderTest.php b/tests/BeSimple/SoapServer/SoapServerBuilderTest.php deleted file mode 100644 index 50654bb..0000000 --- a/tests/BeSimple/SoapServer/SoapServerBuilderTest.php +++ /dev/null @@ -1,48 +0,0 @@ -getWsdlFile()); - } - - public function testSoapServerOptionsCreateWithDefaults() - { - $defaultOptions = SoapServerOptionsBuilder::createWithDefaults(new SoapServerHandler()); - - self::assertInstanceOf(SoapServerOptions::class, $defaultOptions); - self::assertInstanceOf(SoapServerHandler::class, $defaultOptions->getHandlerInstance()); - } - - public function testSoapServerBuilderBuild() - { - $soapServer = $this->getSoapServerBuilder()->build( - SoapServerOptionsBuilder::createWithDefaults(new SoapServerHandler()), - SoapOptionsBuilder::createWithDefaults(self::TEST_LOCAL_WSDL_UK) - ); - - self::assertInstanceOf(SoapServer::class, $soapServer); - } - - public function getSoapServerBuilder() - { - return new SoapServerBuilder(); - } -} diff --git a/tests/BeSimple/SoapServer/SoapServerTest.php b/tests/BeSimple/SoapServer/SoapServerTest.php deleted file mode 100644 index 2a012cd..0000000 --- a/tests/BeSimple/SoapServer/SoapServerTest.php +++ /dev/null @@ -1,151 +0,0 @@ -getSoapServerBuilder()->build( - SoapServerOptionsBuilder::createWithDefaults(new SoapServerHandler()), - SoapOptionsBuilder::createWithDefaults(self::TEST_LOCAL_WSDL_UK) - ); - $soapRequest = $soapServer->createRequest('request-url', 'soap-action', 'content/type', 'request-content'); - - self::assertEquals('content/type', $soapRequest->getContentType()); - self::assertEquals('soap-action', $soapRequest->getAction()); - self::assertEquals('request-content', $soapRequest->getContent()); - self::assertFalse($soapRequest->hasAttachments()); - self::assertNull($soapRequest->getAttachments()); - } - - public function testHandleRequest() - { - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethod', - 'text/xml;charset=UTF-8', - file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethod.message.request') - ); - $response = $soapServer->handleRequest($request); - - file_put_contents(self::CACHE_DIR . '/SoapServerTestResponse.xml', $response->getContent()); - - self::assertNotContains("\r\n", $response->getContent(), 'Response cannot contain CRLF line endings'); - self::assertContains('dummyServiceMethodResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethod', $response->getAction()); - self::assertFalse($response->hasAttachments(), 'Response should not contain attachments'); - } - - public function testHandleRequestWithSwa() - { - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithAttachments', - 'text/xml;charset=UTF-8', - file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithAttachments.request.message') - ); - $response = $soapServer->handleRequest($request); - - file_put_contents(self::CACHE_DIR . '/SoapServerTestResponseFromSwaRequestWithNoAttachments.xml', $response->getContent()); - - self::assertNotContains("\r\n", $response->getContent(), 'Response cannot contain CRLF line endings'); - self::assertContains('dummyServiceMethodWithAttachmentsResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithAttachments', $response->getAction()); - self::assertFalse($response->hasAttachments(), 'Response should not contain attachments'); - } - - public function testHandleRequestWithSwaResponse() - { - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithAttachments', - 'multipart/related; type="text/xml"; start=""; boundary="----=_Part_6_2094841787.1482231370463"', - file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message') - ); - $response = $soapServer->handleRequest($request); - - file_put_contents(self::CACHE_DIR . '/SoapServerTestSwaResponseWithAttachments.xml', $response->getContent()); - - self::assertNotContains("\r\n", $response->getContent(), 'Response cannot contain CRLF line endings'); - self::assertContains('dummyServiceMethodWithAttachmentsResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithAttachments', $response->getAction()); - self::assertTrue($response->hasAttachments(), 'Response should contain attachments'); - self::assertCount(2, $response->getAttachments()); - } - - public function testHandleRequestWithSwaResponseAndLowerCaseHeaders() - { - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithAttachments', - 'multipart/related; type="text/xml"; start=""; boundary="----=_Part_6_2094841787.1482231370463"', - file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithAttachmentsAndLowerCaseHeaders.request.mimepart.message') - ); - $response = $soapServer->handleRequest($request); - - file_put_contents(self::CACHE_DIR . '/SoapServerTestSwaResponseWithAttachmentsAndLowerCaseHeaders.xml', $response->getContent()); - - self::assertNotContains("\r\n", $response->getContent(), 'Response cannot contain CRLF line endings'); - self::assertContains('dummyServiceMethodWithAttachmentsResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithAttachments', $response->getAction()); - self::assertTrue($response->hasAttachments(), 'Response should contain attachments'); - self::assertCount(2, $response->getAttachments()); - } - - public function getSoapServerBuilder() - { - return new SoapServerBuilder(); - } -} diff --git a/tests/BeSimple/SoapServerAndSoapClientCommunicationSoapFaultsTest.php b/tests/BeSimple/SoapServerAndSoapClientCommunicationSoapFaultsTest.php deleted file mode 100644 index effd4c6..0000000 --- a/tests/BeSimple/SoapServerAndSoapClientCommunicationSoapFaultsTest.php +++ /dev/null @@ -1,268 +0,0 @@ -localWebServerProcess = popen('php -S localhost:8000 > /dev/null 2>&1 &', 'r'); - } - - public function tearDown() - { - pclose($this->localWebServerProcess); - } - - public function testSoapCallSwaWithLargeSwaResponseWithSoapFaultAndTracingOff() - { - $soapClient = $this->getSoapClientBuilder()->buildWithSoapHeader( - new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_OFF, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - SoapClientOptions::SOAP_CLIENT_AUTHENTICATION_NONE, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - self::TEST_HTTP_URL.'/SwaSenderSoapFaultEndpoint.php' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $this->setExpectedException(SoapFault::class); - - try { - $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', []); - } catch (SoapFault $e) { - self::assertNotInstanceOf( - SoapFaultWithTracingData::class, - $e, - 'SoapClient must not return tracing data when SoapClientOptions::trace is off.' - ); - self::assertEquals( - '911', - $e->faultcode - ); - self::assertContains( - 'with HTTP response code 500 with Message: This is a dummy SoapFault. and Code: 911', - $e->getMessage() - ); - - throw $e; - } - - self::fail('Expected SoapFault was not thrown'); - } - - public function testSoapCallSwaWithLargeSwaResponseWithSoapFault() - { - $soapClient = $this->getSoapClientBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithEndpointLocation( - self::TEST_HTTP_URL.'/SwaSenderSoapFaultEndpoint.php' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $this->setExpectedException(SoapFault::class); - - try { - $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', []); - } catch (SoapFault $e) { - self::assertInstanceOf( - SoapFaultWithTracingData::class, - $e, - 'SoapClient must return tracing data when SoapClientOptions::trace is on.' - ); - /** @var SoapFaultWithTracingData $e */ - self::assertEquals( - '911', - $e->faultcode - ); - self::assertContains( - 'with HTTP response code 500 with Message: This is a dummy SoapFault. and Code: 911', - $e->getMessage() - ); - self::assertContains( - '911', - $e->getSoapResponseTracingData()->getLastResponse() - ); - self::assertContains( - '', - $e->getSoapResponseTracingData()->getLastRequest() - ); - self::assertContains( - 'Content-Type: application/soap+xml; charset=utf-8; action="DummyService.dummyServiceMethodWithOutgoingLargeSwa"', - $e->getSoapResponseTracingData()->getLastRequestHeaders() - ); - - throw $e; - } - - self::fail('Expected SoapFault was not thrown'); - } - - public function testSoapCallSwaWithLargeSwaResponseWithNoResponseFromEndpoint() - { - $soapClient = $this->getSoapClientBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithEndpointLocation( - self::TEST_HTTP_URL.'/NoSuchEndpointExists' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $this->setExpectedException(SoapFault::class); - - try { - $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', []); - } catch (SoapFault $e) { - self::assertInstanceOf( - SoapFaultWithTracingData::class, - $e - ); - /** @var SoapFaultWithTracingData $e */ - self::assertEquals( - 'be-http-404', - $e->faultcode - ); - self::assertContains( - 'with HTTP response code 404', - $e->getMessage() - ); - self::assertContains( - 'not found', - $e->getSoapResponseTracingData()->getLastResponse() - ); - self::assertContains( - '404 Not Found', - $e->getSoapResponseTracingData()->getLastResponseHeaders() - ); - self::assertContains( - '', - $e->getSoapResponseTracingData()->getLastRequest() - ); - self::assertContains( - 'Content-Type: application/soap+xml; charset=utf-8; action="DummyService.dummyServiceMethodWithOutgoingLargeSwa"', - $e->getSoapResponseTracingData()->getLastRequestHeaders() - ); - - throw $e; - } - - self::fail('Expected SoapFault was not thrown'); - } - - public function testSoapCallSwaWithLargeSwaResponseWithNoResponseFromEndpointHost() - { - $soapClient = $this->getSoapClientBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithEndpointLocation( - self::TEST_HTTP_URL_INVALID.'/NoSuchEndpointExists' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $this->setExpectedException(SoapFault::class); - - try { - $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', []); - } catch (SoapFault $e) { - self::assertInstanceOf( - SoapFaultWithTracingData::class, - $e - ); - /** @var SoapFaultWithTracingData $e */ - self::assertEquals( - 'be-http-0', - $e->faultcode - ); - self::assertContains( - 't resolve host', - $e->getMessage() - ); - self::assertNull( - $e->getSoapResponseTracingData()->getLastResponseHeaders() - ); - self::assertNull( - $e->getSoapResponseTracingData()->getLastResponse() - ); - self::assertContains( - '', - $e->getSoapResponseTracingData()->getLastRequest() - ); - self::assertNull( - $e->getSoapResponseTracingData()->getLastRequestHeaders() - ); - - throw $e; - } - - self::fail('Expected SoapFault was not thrown'); - } - - private function getSoapClientBuilder() - { - return new SoapClientBuilder(); - } - - public function getSoapServerBuilder() - { - return new SoapServerBuilder(); - } -} diff --git a/tests/BeSimple/SoapServerAndSoapClientCommunicationTest.php b/tests/BeSimple/SoapServerAndSoapClientCommunicationTest.php deleted file mode 100644 index 566ddf6..0000000 --- a/tests/BeSimple/SoapServerAndSoapClientCommunicationTest.php +++ /dev/null @@ -1,328 +0,0 @@ -localWebServerProcess = popen('php -S localhost:8000 > /dev/null 2>&1 &', 'r'); - } - - public function tearDown() - { - pclose($this->localWebServerProcess); - } - - public function testHandleRequestWithLargeSwaResponse() - { - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithOutgoingLargeSwa', - 'text/xml;charset=UTF-8', - file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithOutgoingLargeSwa.request.message') - ); - $response = $soapServer->handleRequest($request); - - file_put_contents(self::CACHE_DIR . '/content-type-soap-server-response.xml', $response->getContentType()); - file_put_contents(self::CACHE_DIR . '/multipart-message-soap-server-response.xml', $response->getContent()); - if ($response->hasAttachments() === true) { - foreach ($response->getAttachments() as $attachment) { - $fileName = preg_replace('/\<|\>/', '', $attachment->getContentId()); - file_put_contents(self::CACHE_DIR . DIRECTORY_SEPARATOR . 'attachment-server-response-' . $fileName, $attachment->getContent()); - - self::assertRegExp('/filename\.(docx|html|txt)/', $fileName); - } - } else { - self::fail('Response should contain attachments'); - } - - self::assertContains('dummyServiceMethodWithOutgoingLargeSwaResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithOutgoingLargeSwa', $response->getAction()); - - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-server-response-filename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - } - - public function testSoapCallSwaWithLargeSwaResponse() - { - $soapClient = $this->getSoapBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithEndpointLocation( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $request = new DummyServiceMethodWithOutgoingLargeSwaRequest(); - $request->dummyAttribute = 1; - - $soapResponse = $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', [$request]); - $attachments = $soapResponse->getAttachments(); - - self::assertContains('', $soapResponse->getResponseContent()); - self::assertTrue($soapResponse->hasAttachments(), 'Response should contain attachments'); - self::assertCount(3, $attachments); - self::assertInstanceOf( - SoapRequest::class, - $soapResponse->getRequest(), - 'SoapResponse::request must be SoapRequest for SoapClient calls with enabled tracing' - ); - - file_put_contents(self::CACHE_DIR . '/multipart-message-soap-client-response.xml', $soapResponse->getContent()); - foreach ($soapResponse->getAttachments() as $attachment) { - $fileName = preg_replace('/\<|\>/', '', $attachment->getContentId()); - file_put_contents(self::CACHE_DIR . DIRECTORY_SEPARATOR . 'attachment-client-response-' . $fileName, $attachment->getContent()); - - self::assertRegExp('/filename\.(docx|html|txt)/', $fileName); - } - - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-client-response-filename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - } - - public function testSoapCallSwaWithLargeSwaResponseAndTracingOff() - { - $soapClient = $this->getSoapBuilder()->buildWithSoapHeader( - new SoapClientOptions( - SoapClientOptions::SOAP_CLIENT_TRACE_OFF, - SoapClientOptions::SOAP_CLIENT_EXCEPTIONS_ON, - CurlOptions::DEFAULT_USER_AGENT, - SoapClientOptions::SOAP_CLIENT_COMPRESSION_NONE, - SoapClientOptions::SOAP_CLIENT_AUTHENTICATION_NONE, - SoapClientOptions::SOAP_CLIENT_PROXY_NONE, - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaSenderEndpoint.php?wsdl', - new ClassMap([ - 'GenerateTestRequest' => GenerateTestRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $request = new DummyServiceMethodWithOutgoingLargeSwaRequest(); - $request->dummyAttribute = 1; - - $soapResponse = $soapClient->soapCall('dummyServiceMethodWithOutgoingLargeSwa', [$request]); - $attachments = $soapResponse->getAttachments(); - - self::assertContains('', $soapResponse->getResponseContent()); - self::assertTrue($soapResponse->hasAttachments(), 'Response should contain attachments'); - self::assertCount(3, $attachments); - self::assertInstanceOf( - SoapRequest::class, - $soapResponse->getRequest(), - 'SoapResponse::request must be SoapRequest for SoapClient calls with disabled tracing' - ); - - file_put_contents(self::CACHE_DIR . '/multipart-message-soap-client-response.xml', $soapResponse->getContent()); - foreach ($soapResponse->getAttachments() as $attachment) { - $fileName = preg_replace('/\<|\>/', '', $attachment->getContentId()); - file_put_contents(self::CACHE_DIR . DIRECTORY_SEPARATOR . 'attachment-client-response-' . $fileName, $attachment->getContent()); - - self::assertRegExp('/filename\.(docx|html|txt)/', $fileName); - } - - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-client-response-filename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - } - - public function testSoapCallWithLargeSwaRequest() - { - $soapClient = $this->getSoapBuilder()->buildWithSoapHeader( - SoapClientOptionsBuilder::createWithEndpointLocation( - self::TEST_HTTP_URL.'/SwaReceiverEndpoint.php' - ), - SoapOptionsBuilder::createSwaWithClassMap( - self::TEST_HTTP_URL.'/SwaReceiverEndpoint.php?wsdl', - new ClassMap([ - 'DummyServiceMethodWithIncomingLargeSwaRequest' => DummyServiceMethodWithIncomingLargeSwaRequest::class, - ]), - SoapOptions::SOAP_CACHE_TYPE_NONE - ), - new SoapHeader('http://schema.testcase', 'SoapHeader', [ - 'user' => 'admin', - ]) - ); - - $request = new DummyServiceMethodWithIncomingLargeSwaRequest(); - $request->dummyAttribute = 1; - - try { - $soapResponse = $soapClient->soapCall( - 'dummyServiceMethodWithIncomingLargeSwa', - [$request], - [ - new SoapAttachment('filename.txt', 'text/plain', 'plaintext file'), - new SoapAttachment('filename.html', 'text/html', 'Hello world'), - new SoapAttachment( - 'filename.docx', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - file_get_contents(self::LARGE_SWA_FILE) - ), - ] - ); - - self::assertContains('dummyServiceMethodWithIncomingLargeSwa', $soapResponse->getRequest()->getContent()); - self::assertContains('', $soapResponse->getResponseContent()); - self::assertTrue($soapResponse->getRequest()->hasAttachments(), 'Response MUST contain attachments'); - self::assertFalse($soapResponse->hasAttachments(), 'Response MUST NOT contain attachments'); - self::assertInstanceOf(SoapRequest::class, $soapResponse->getRequest()); - - foreach ($soapResponse->getRequest()->getAttachments() as $attachment) { - file_put_contents(self::CACHE_DIR . '/attachment-client-request-'.trim($attachment->getContentId(), '<>'), $attachment->getContent()); - } - file_put_contents(self::CACHE_DIR . '/content-type-soap-client-request.xml', $soapResponse->getRequest()->getContentType()); - file_put_contents(self::CACHE_DIR.'/multipart-message-soap-client-request.xml', $soapResponse->getRequest()->getContent()); - - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-client-request-filename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - - } catch (SoapFaultWithTracingData $e) { - self::fail( - 'Endpoint did not return expected response: '.var_export($e->getSoapResponseTracingData()->getLastResponse(), true) - ); - } - } - - public function testHandleRequestWithLargeSwaRequest() - { - $previousSoapClientCallContentTypeCacheFile = self::CACHE_DIR.'/content-type-soap-client-request.xml'; - $previousSoapClientCallMessageBodyCacheFile = self::CACHE_DIR.'/multipart-message-soap-client-request.xml'; - if (file_exists($previousSoapClientCallContentTypeCacheFile) === false || file_exists($previousSoapClientCallMessageBodyCacheFile) === false) { - self::fail('Cannot load data from cache: run testSoapCallWithLargeSwaRequest to get the data.'); - } - $previousSoapClientCallContentType = file_get_contents($previousSoapClientCallContentTypeCacheFile); - $previousSoapClientCallMessageBody = file_get_contents($previousSoapClientCallMessageBodyCacheFile); - - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithIncomingLargeSwa', - $previousSoapClientCallContentType, - $previousSoapClientCallMessageBody - ); - $response = $soapServer->handleRequest($request); - - self::assertContains('dummyServiceMethodWithIncomingLargeSwaResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithIncomingLargeSwa', $response->getAction()); - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-server-request-filename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - } - - public function testHandleRequestWithLargeSwaRequestAndMixedCrLf() - { - $soapClientCallContentType = file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.contenttypeheaders'); - $soapClientCallMessageBody = file_get_contents(self::FIXTURES_DIR.'/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.request.mimepart.message'); - - $dummyService = new DummyService(); - $classMap = new ClassMap(); - foreach ($dummyService->getClassMap() as $type => $className) { - $classMap->add($type, $className); - } - $soapServerBuilder = new SoapServerBuilder(); - $soapServerOptions = SoapServerOptionsBuilder::createWithDefaults($dummyService); - $soapOptions = SoapOptionsBuilder::createSwaWithClassMap($dummyService->getWsdlPath(), $classMap); - $soapServer = $soapServerBuilder->build($soapServerOptions, $soapOptions); - - $request = $soapServer->createRequest( - $dummyService->getEndpoint(), - 'DummyService.dummyServiceMethodWithIncomingLargeSwa', - $soapClientCallContentType, - $soapClientCallMessageBody - ); - $response = $soapServer->handleRequest($request); - - self::assertContains('dummyServiceMethodWithIncomingLargeSwaResponse', $response->getContent()); - self::assertSame('DummyService.dummyServiceMethodWithIncomingLargeSwa', $response->getAction()); - self::assertEquals( - filesize(self::LARGE_SWA_FILE), - filesize(self::CACHE_DIR.'/attachment-server-request-oldfilename.docx'), - 'File cannot differ after transport from SoapClient to SoapServer' - ); - } - - private function getSoapBuilder() - { - return new SoapClientBuilder(); - } - - public function getSoapServerBuilder() - { - return new SoapServerBuilder(); - } -} diff --git a/tests/Fixtures/Attachment/Attachment.php b/tests/Fixtures/Attachment/Attachment.php deleted file mode 100644 index e722951..0000000 --- a/tests/Fixtures/Attachment/Attachment.php +++ /dev/null @@ -1,35 +0,0 @@ -fileName = $fileName; - $this->contentType = $contentType; - $this->content = $content; - } -} diff --git a/tests/Fixtures/Attachment/AttachmentCollection.php b/tests/Fixtures/Attachment/AttachmentCollection.php deleted file mode 100644 index d7ba0c9..0000000 --- a/tests/Fixtures/Attachment/AttachmentCollection.php +++ /dev/null @@ -1,21 +0,0 @@ -attachments = $attachments; - } - - public function hasAttachments() - { - return $this->attachments !== null && count($this->attachments) > 0; - } -} diff --git a/tests/Fixtures/Attachment/MessageWithAttachmentsTrait.php b/tests/Fixtures/Attachment/MessageWithAttachmentsTrait.php deleted file mode 100644 index 3767947..0000000 --- a/tests/Fixtures/Attachment/MessageWithAttachmentsTrait.php +++ /dev/null @@ -1,16 +0,0 @@ -attachmentCollection !== null && $this->attachmentCollection->hasAttachments(); - } -} diff --git a/tests/Fixtures/DummyService.php b/tests/Fixtures/DummyService.php deleted file mode 100644 index 0981e1e..0000000 --- a/tests/Fixtures/DummyService.php +++ /dev/null @@ -1,158 +0,0 @@ -requestHandlerAttachmentsStorage = $requestHandlerAttachmentsStorage; - } - - public function getAttachmentStorage() - { - return $this->requestHandlerAttachmentsStorage; - } - - /** - * @return string[] - */ - public function getClassMap() - { - return [ - 'DummyServiceResponse' => DummyServiceResponse::class, - 'DummyServiceResponseWithAttachments' => DummyServiceResponseWithAttachments::class, - 'DummyServiceRequest' => DummyServiceRequest::class, - 'DummyServiceRequestWithAttachments' => DummyServiceRequestWithAttachments::class, - 'DummyServiceMethodWithOutgoingLargeSwaRequest' => DummyServiceMethodWithOutgoingLargeSwaRequest::class, - 'DummyServiceMethodWithOutgoingLargeSwaResponse' => DummyServiceMethodWithOutgoingLargeSwaResponse::class, - 'DummyServiceMethodWithIncomingLargeSwaRequest' => DummyServiceMethodWithIncomingLargeSwaRequest::class, - 'DummyServiceMethodWithIncomingLargeSwaResponse' => DummyServiceMethodWithIncomingLargeSwaResponse::class, - ]; - } - - /** - * @exclude - * @return string - */ - public function getWsdlPath() - { - $class = new ReflectionClass(static::class); - - return __DIR__.DIRECTORY_SEPARATOR.$class->getShortName().'.wsdl'; - } - - /** - * @return string - */ - public function getEndpoint() - { - return 'http://my.test/soap/dummyService'; - } - - /** - * @param DummyServiceRequest $dummyServiceRequest - * @return DummyServiceResponse - */ - public function dummyServiceMethod(DummyServiceRequest $dummyServiceRequest) - { - $dummyServiceHandler = new DummyServiceHandler(); - - return $dummyServiceHandler->handle($dummyServiceRequest); - } - - /** - * @param DummyServiceMethodWithOutgoingLargeSwaRequest $dummyServiceRequest - * @return DummyServiceMethodWithOutgoingLargeSwaResponse - */ - public function dummyServiceMethodWithOutgoingLargeSwa(DummyServiceMethodWithOutgoingLargeSwaRequest $dummyServiceRequest) - { - $dummyServiceHandler = new DummyServiceHandlerWithOutgoingLargeSwa(); - - $dummyServiceResponseWithAttachments = $dummyServiceHandler->handle($dummyServiceRequest); - - if ($dummyServiceResponseWithAttachments->hasAttachments() === true) { - $soapAttachments = []; - foreach ($dummyServiceResponseWithAttachments->attachmentCollection->attachments as $attachment) { - $soapAttachments[] = new SoapAttachment( - $attachment->fileName, - $attachment->contentType, - $attachment->content - ); - } - $this->addAttachmentStorage(new RequestHandlerAttachmentsStorage($soapAttachments)); - } - - return $dummyServiceResponseWithAttachments; - } - - /** - * @param DummyServiceMethodWithIncomingLargeSwaRequest $dummyServiceRequest - * @return DummyServiceMethodWithIncomingLargeSwaResponse - */ - public function dummyServiceMethodWithIncomingLargeSwa(DummyServiceMethodWithIncomingLargeSwaRequest $dummyServiceRequest) - { - $dummyServiceHandler = new DummyServiceHandlerWithIncomingLargeSwa(); - $attachmentStorageContents = $this->getAttachmentStorage()->getAttachments(); - if (count($attachmentStorageContents) > 0) { - $attachments = []; - foreach ($attachmentStorageContents as $soapAttachment) { - $attachments[] = new Attachment( - $soapAttachment->getId(), - $soapAttachment->getType(), - $soapAttachment->getContent() - ); - } - $dummyServiceRequest->attachmentCollection = new AttachmentCollection($attachments); - } - - return $dummyServiceHandler->handle($dummyServiceRequest); - } - - /** - * @param DummyServiceRequestWithAttachments $dummyServiceRequestWithAttachments - * @return DummyServiceResponseWithAttachments - */ - public function dummyServiceMethodWithAttachments(DummyServiceRequestWithAttachments $dummyServiceRequestWithAttachments) - { - if ($dummyServiceRequestWithAttachments->hasAttachments() === true) { - $attachmentStorage = $this->getAttachmentStorage(); - $attachments = []; - foreach ($attachmentStorage->getAttachments() as $soapAttachment) { - $attachments[] = new Attachment( - $soapAttachment->getId(), - $soapAttachment->getType(), - $soapAttachment->getContent() - ); - } - $dummyServiceRequestWithAttachments->attachmentCollection = new AttachmentCollection($attachments); - } - - $dummyServiceHandlerWithAttachments = new DummyServiceHandlerWithAttachments(); - $dummyServiceResponseWithAttachments = $dummyServiceHandlerWithAttachments->handle($dummyServiceRequestWithAttachments); - - if ($dummyServiceResponseWithAttachments->hasAttachments() === true) { - $soapAttachments = []; - foreach ($dummyServiceResponseWithAttachments->attachmentCollection->attachments as $attachment) { - $soapAttachments[] = new SoapAttachment( - $attachment->fileName, - $attachment->contentType, - $attachment->content - ); - } - $this->addAttachmentStorage(new RequestHandlerAttachmentsStorage($soapAttachments)); - } - - return $dummyServiceResponseWithAttachments; - } -} diff --git a/tests/Fixtures/DummyService.wsdl b/tests/Fixtures/DummyService.wsdl deleted file mode 100644 index 1d97dfd..0000000 --- a/tests/Fixtures/DummyService.wsdl +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - User name for authorization - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WSDL file for DummyService - - - - - diff --git a/tests/Fixtures/DummyServiceHandler.php b/tests/Fixtures/DummyServiceHandler.php deleted file mode 100644 index 4d508bb..0000000 --- a/tests/Fixtures/DummyServiceHandler.php +++ /dev/null @@ -1,18 +0,0 @@ -status = true; - - return $response; - } -} diff --git a/tests/Fixtures/DummyServiceHandlerWithAttachments.php b/tests/Fixtures/DummyServiceHandlerWithAttachments.php deleted file mode 100644 index ff63250..0000000 --- a/tests/Fixtures/DummyServiceHandlerWithAttachments.php +++ /dev/null @@ -1,30 +0,0 @@ -status = true; - if ($request->includeAttachments === true) { - if ($request->hasAttachments() === true) { - $attachments = []; - foreach ($request->attachmentCollection->attachments as $attachment) { - $attachments[] = new Attachment($attachment->fileName, $attachment->contentType, $attachment->content); - } - $response->attachmentCollection = new AttachmentCollection($attachments); - } - } - - return $response; - } -} diff --git a/tests/Fixtures/DummyServiceHandlerWithIncomingLargeSwa.php b/tests/Fixtures/DummyServiceHandlerWithIncomingLargeSwa.php deleted file mode 100644 index e576304..0000000 --- a/tests/Fixtures/DummyServiceHandlerWithIncomingLargeSwa.php +++ /dev/null @@ -1,27 +0,0 @@ -hasAttachments() === true) { - foreach ($request->attachmentCollection->attachments as $attachment) { - file_put_contents( - __DIR__.'/../../cache/attachment-server-request-'.$attachment->fileName, - $attachment->content - ); - } - } - - $response = new DummyServiceMethodWithIncomingLargeSwaResponse(); - $response->status = true; - - return $response; - } -} diff --git a/tests/Fixtures/DummyServiceHandlerWithOutgoingLargeSwa.php b/tests/Fixtures/DummyServiceHandlerWithOutgoingLargeSwa.php deleted file mode 100644 index f8edc2c..0000000 --- a/tests/Fixtures/DummyServiceHandlerWithOutgoingLargeSwa.php +++ /dev/null @@ -1,32 +0,0 @@ -status = true; - - $response->attachmentCollection = new AttachmentCollection([ - new Attachment('filename.txt', 'text/plain', 'plaintext file'), - new Attachment('filename.html', 'text/html', 'Hello world'), - new Attachment( - 'filename.docx', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - file_get_contents(SoapServerAndSoapClientCommunicationTest::LARGE_SWA_FILE) - ), - ]); - - return $response; - } -} diff --git a/tests/Fixtures/DummyServiceMethodWithIncomingLargeSwaRequest.php b/tests/Fixtures/DummyServiceMethodWithIncomingLargeSwaRequest.php deleted file mode 100644 index bde561f..0000000 --- a/tests/Fixtures/DummyServiceMethodWithIncomingLargeSwaRequest.php +++ /dev/null @@ -1,15 +0,0 @@ - -London diff --git a/tests/Fixtures/Message/Request/GetUKLocationByCounty.request.mimepart.message b/tests/Fixtures/Message/Request/GetUKLocationByCounty.request.mimepart.message deleted file mode 100644 index 4d83591..0000000 --- a/tests/Fixtures/Message/Request/GetUKLocationByCounty.request.mimepart.message +++ /dev/null @@ -1,24 +0,0 @@ - ---Part_10_589b2dcf4f7fb.589b2dcf4f804 -Content-Type: application/soap+xml; charset=utf-8 -Content-Transfer-Encoding: 8bit -Content-ID: - - -London - ---Part_10_589b2dcf4f7fb.589b2dcf4f804 -Content-Type: application/pdf; charset=utf-8 -Content-Transfer-Encoding: binary -Content-ID: -Content-Location: first-file.txt - -hello world ---Part_10_589b2dcf4f7fb.589b2dcf4f804 -Content-Type: application/pdf; charset=utf-8 -Content-Transfer-Encoding: binary -Content-ID: -Content-Location: second-file.txt - -hello world ---Part_10_589b2dcf4f7fb.589b2dcf4f804-- \ No newline at end of file diff --git a/tests/Fixtures/Message/Request/dummyServiceMethod.message.request b/tests/Fixtures/Message/Request/dummyServiceMethod.message.request deleted file mode 100644 index 80c472b..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethod.message.request +++ /dev/null @@ -1,14 +0,0 @@ - - - - admin - - - - - - 1 - - - - diff --git a/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request b/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request deleted file mode 100644 index 8ab0658..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethod.oneliner.message.request +++ /dev/null @@ -1 +0,0 @@ -admin1 \ No newline at end of file diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.message b/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.message deleted file mode 100644 index 70aeaf9..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.message +++ /dev/null @@ -1,15 +0,0 @@ - - - - admin - - - - - - 2 - false - - - - diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message b/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message deleted file mode 100644 index a2b7e76..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachments.request.mimepart.message +++ /dev/null @@ -1,62 +0,0 @@ - -------=_Part_6_2094841787.1482231370463 -Content-Type: text/xml; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Content-ID: - - - - - admin - - - - - - 3 - true - - - - -------=_Part_6_2094841787.1482231370463 -Content-Type: text/html; charset=us-ascii; name=test-page.html -Content-Transfer-Encoding: 7bit -Content-ID: -Content-Disposition: attachment; name="test-page.html"; filename="test-page.html" - - - - - - Test file page - - - - -

Hello World!

- - - -------=_Part_6_2094841787.1482231370463 -Content-Type: application/x-sh; name=testscript.sh -Content-Transfer-Encoding: binary -Content-ID: -Content-Disposition: attachment; name="testscript.sh"; filename="testscript.sh" - -#!/bin/sh -### ====================================================================== ### -## ## -## Test Script ## -## ## -### ====================================================================== ### - -------=_Part_6_2094841787.1482231370463-- diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachmentsAndLowerCaseHeaders.request.mimepart.message b/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachmentsAndLowerCaseHeaders.request.mimepart.message deleted file mode 100644 index c16cd3d..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethodWithAttachmentsAndLowerCaseHeaders.request.mimepart.message +++ /dev/null @@ -1,62 +0,0 @@ - -------=_Part_6_2094841787.1482231370463 -Content-type: text/xml; charset=UTF-8 -Content-transfer-Encoding: 8bit -Content-id: - - - - - admin - - - - - - 3 - true - - - - -------=_Part_6_2094841787.1482231370463 -Content-type: text/html; charset=us-ascii; name=test-page.html -Content-transfer-Encoding: 7bit -Content-id: -Content-disposition: attachment; name="test-page.html"; filename="test-page.html" - - - - - - Test file page - - - - -

Hello World!

- - - -------=_Part_6_2094841787.1482231370463 -Content-type: application/x-sh; name=testscript.sh -Content-transfer-Encoding: binary -Content-id: -Content-disposition: attachment; name="testscript.sh"; filename="testscript.sh" - -#!/bin/sh -### ====================================================================== ### -## ## -## Test Script ## -## ## -### ====================================================================== ### - -------=_Part_6_2094841787.1482231370463-- diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.contenttypeheaders b/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.contenttypeheaders deleted file mode 100644 index 51d09a5..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.contenttypeheaders +++ /dev/null @@ -1 +0,0 @@ -multipart/related; type="application/soap+xml"; charset=utf-8; boundary="urn:uuid:340c4456-d650-4ddb-ae83-b13cf6077326"; start=""; action="DummyService.dummyServiceMethodWithIncomingLargeSwa" \ No newline at end of file diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.request.mimepart.message b/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.request.mimepart.message deleted file mode 100644 index e3b5522..0000000 Binary files a/tests/Fixtures/Message/Request/dummyServiceMethodWithIncomingLargeSwaAndMixedCrLf.request.mimepart.message and /dev/null differ diff --git a/tests/Fixtures/Message/Request/dummyServiceMethodWithOutgoingLargeSwa.request.message b/tests/Fixtures/Message/Request/dummyServiceMethodWithOutgoingLargeSwa.request.message deleted file mode 100644 index ab21b9d..0000000 --- a/tests/Fixtures/Message/Request/dummyServiceMethodWithOutgoingLargeSwa.request.message +++ /dev/null @@ -1,14 +0,0 @@ - - - - admin - - - - - - 1 - - - - diff --git a/tests/Fixtures/Message/Response/dummyServiceMethodWithIncomingLargeSwa.response.message b/tests/Fixtures/Message/Response/dummyServiceMethodWithIncomingLargeSwa.response.message deleted file mode 100644 index e018129..0000000 --- a/tests/Fixtures/Message/Response/dummyServiceMethodWithIncomingLargeSwa.response.message +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - true - - - - diff --git a/tests/Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message b/tests/Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message deleted file mode 100644 index 4ed82a2..0000000 Binary files a/tests/Fixtures/Message/Response/dummyServiceMethodWithOutgoingLargeSwa.response.mimepart.message and /dev/null differ diff --git a/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.response.message b/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.response.message deleted file mode 100644 index 04253fb..0000000 --- a/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.response.message +++ /dev/null @@ -1,17 +0,0 @@ - ---Part_13_58e3bc35f3743.58e3bc35f376f -Content-Type: application/soap+xml; charset=utf-8 -Content-Transfer-Encoding: 8bit -Content-ID: - - -generateTestReturndummy-attachment.txt - ---Part_13_58e3bc35f3743.58e3bc35f376f -Content-Type: text/plain; charset=utf-8 -Content-Transfer-Encoding: binary -Content-ID: -Content-Location: dummy-attachment.txt - -Hello world! ---Part_13_58e3bc35f3743.58e3bc35f376f-- \ No newline at end of file diff --git a/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.wsdl b/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.wsdl deleted file mode 100644 index 76b1e32..0000000 --- a/tests/Fixtures/Message/Response/soapCallWithSwaAttachmentsOnResponse.wsdl +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - User name for authorization - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WSDL file for TestGeneratorService - - - - - diff --git a/tests/Fixtures/SoapServerHandler.php b/tests/Fixtures/SoapServerHandler.php deleted file mode 100644 index 7f51f55..0000000 --- a/tests/Fixtures/SoapServerHandler.php +++ /dev/null @@ -1,7 +0,0 @@ - - - Get UK Postcode,Town,County and Validate UK Address - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Get UK town,Postcode and County by full /partial County - - - - - Get UK town,Postcode and County by full /partial Town - - - - - Get UK town,Postcode and County by Postcode(First Section of Post Code) - - - - - Validate UK address,Use First Section of Poscode for Postcode atribute - - - - - - - Get UK town,Postcode and County by full /partial County - - - - - Get UK town,Postcode and County by full /partial Town - - - - - Get UK town,Postcode and County by Postcode(First Section of Post Code) - - - - - Validate UK address,Use First Section of Poscode for Postcode atribute - - - - - - - Get UK town,Postcode and County by full /partial County - - - - - Get UK town,Postcode and County by full /partial Town - - - - - Get UK town,Postcode and County by Postcode(First Section of Post Code) - - - - - Validate UK address,Use First Section of Poscode for Postcode atribute - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Get UK Postcode,Town,County and Validate UK Address - - - - - - - - - - - - - - diff --git a/tests/SwaEndpoint.php b/tests/SwaEndpoint.php deleted file mode 100644 index e611564..0000000 --- a/tests/SwaEndpoint.php +++ /dev/null @@ -1,13 +0,0 @@ -"'); -echo file_get_contents(FIXTURES_DIR.'/Message/Response/soapCallWithSwaAttachmentsOnResponse.response.message'); diff --git a/tests/SwaReceiverEndpoint.php b/tests/SwaReceiverEndpoint.php deleted file mode 100644 index 5eea081..0000000 --- a/tests/SwaReceiverEndpoint.php +++ /dev/null @@ -1,15 +0,0 @@ -fault( - 911, - 'Cannot load data from cache: run soap server testHandleRequestWithLargeSwaResponse to get the data.' - ); -} - -header('Content-type: '.file_get_contents($contentTypeFromCache)); -echo file_get_contents($multiPartMessageFromCache); diff --git a/tests/SwaSenderSoapFaultEndpoint.php b/tests/SwaSenderSoapFaultEndpoint.php deleted file mode 100644 index ad92e3e..0000000 --- a/tests/SwaSenderSoapFaultEndpoint.php +++ /dev/null @@ -1,9 +0,0 @@ -fault( - 911, - 'This is a dummy SoapFault.' -);