12 Commits

Author SHA1 Message Date
a8bc834077 Mime/PartHeaders now handle both Content-ID and Content-id according to W3 specs 2017-06-12 15:14:28 +02:00
f74e4b08ce Mime Parser: throws Exception with MimePartMessage contents 2017-06-12 00:28:27 +02:00
dcd5ff5234 Travis now run only PHP 7.x builds, phpstan requirements will fail on 5.6.x or previous 2017-06-07 17:10:10 +02:00
7bd8481a4e Travis CI - test fixes
1. Travis has to run PHP build-in server separately, 2. SoapFault message expectations are now Couldn't/Could not
2017-06-07 17:05:03 +02:00
c82288d641 Travis deployment fixed 2017-06-07 16:23:47 +02:00
bb20882ade Readme updated 2017-06-07 16:18:46 +02:00
2264e329a1 Added phing for running tests & fixed issues in order to pass the tests 2017-06-07 15:50:04 +02:00
b9e36b4900 Fix notice: attribute soapClientOptions defined in Trait and Client class 2017-06-05 10:50:53 +02:00
d495f22413 SoapFaultWithTracingData now provides request / response information from Server SoapFaults 2017-05-30 18:29:51 +02:00
8db9b374e4 SoapFault handling refactored: client now returns server fault codes + more details in message 2017-05-26 10:53:41 +02:00
f669c18c7f Merge pull request #3 from ceesco53/patch-1
composer.json refers to upstream not this fork (README.md fix)
2017-05-25 19:07:26 +02:00
524d1f3fd7 composer.json refers to upstream not this fork
Using the composer.json instructions as is will cause the rest of your instructions to fail.  It points to upstream package.  I've got some other changes coming soon.  Happy to help.
2017-05-25 12:13:58 -04:00
58 changed files with 2139 additions and 662 deletions

View File

@ -1,25 +1,14 @@
language: php
php:
- 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"
- 7.0
- 7.1
before_script:
- composer self-update
- 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
- composer install
- cp phpunit.xml.dist phpunit.xml
- php -S localhost:8000 > /dev/null 2>&1 &
script:
- phpunit --coverage-text
matrix:
allow_failures:
- env: SYMFONY_VERSION="dev-master symfony/debug:~2.7@dev symfony/http-kernel:~2.7@dev"
- vendor/phing/phing/bin/phing -f build.xml

View File

@ -47,7 +47,7 @@ Create a `composer.json` file:
```json
{
"require": {
"besimple/soap": "0.2.*@dev"
"tuscanicz/soap": "^4.2"
}
}
```
@ -144,4 +144,12 @@ See a simplified implementation of ``dummyServiceMethod`` to get a clue:
}
```
For further information and getting inspiration for your implementation, see the unit tests in ``tests`` dir.
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.

54
build.xml Normal file
View File

@ -0,0 +1,54 @@
<project name="be-simple-soap" default="build">
<property environment="env"/>
<fileset id="src" dir="${project.basedir}/src">
<include name="**/*.php"/>
<exclude name="BeSimple/SoapBundle/**/*.php"/>
<exclude name="BeSimple/SoapCommon/Type/**/*.php"/>
</fileset>
<fileset id="tests" dir="${project.basedir}/tests">
<include name="**/*.php"/>
</fileset>
<target name="cleanup" description="Workspace cleanup">
<delete>
<fileset dir="${project.basedir}/cache">
<include name="**/*"/>
<exclude name=".gitkeep"/>
</fileset>
</delete>
</target>
<target name="prepare" depends="cleanup" description="Workspace preparation">
<echo>project.basedir: ${project.basedir}</echo>
<property name="buildOutputPath" value="${project.basedir}/cache"/>
<echo>buildOutputPath: ${buildOutputPath}</echo>
</target>
<target name="lint" depends="prepare" description="PHP Lint check">
<phplint haltonfailure="true" level="debug" deprecatedAsError="true" tofile="${buildOutputPath}/phplint-outfile.txt">
<fileset refid="src"/>
</phplint>
</target>
<target name="varDump" depends="prepare" description="Check for forgotten var_dumps">
<exec command="${project.basedir}/vendor/bin/var-dump-check --exclude app --exclude vendor ." passthru="true" checkreturn="true"/>
</target>
<target name="phpcs" depends="prepare" description="PHP_CodeSniffer checks">
<exec command="php vendor/squizlabs/php_codesniffer/bin/phpcs --ignore=BeSimple/SoapBundle/,BeSimple/SoapCommon/Type/ --standard=${project.basedir}/codesniffer-ruleset.xml --report=checkstyle --report-file=${buildOutputPath}/phpcs-checkstyle-outfile.xml src tests" passthru="true" checkreturn="true"/>
</target>
<target name="phpstan" depends="prepare" description="phpstan checks">
<exec command="php vendor/bin/phpstan analyse src/BeSimple/SoapClient src/BeSimple/SoapServer > cache/phpstan-output.txt" passthru="true" checkreturn="true"/>
</target>
<target name="phpUnitTests" description="Run unit tests">
<exec command="php vendor/phpunit/phpunit/phpunit --configuration=phpunit.xml --testsuite=BeSimpleSoapTestSuite" passthru="true" checkreturn="true"/>
</target>
<target name="build" depends="prepare, varDump, lint, phpcs, phpstan, phpUnitTests" description="Meta target"/>
</project>

52
codesniffer-ruleset.xml Normal file
View File

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<ruleset name="WSCBE">
<description>Coding standards</description>
<rule ref="Generic.Classes">
<exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine"/>
</rule>
<rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
<rule ref="Generic.Files">
<properties>
<property name="eolChar" value="\n"/>
<property name="lineLimit" value="200"/>
<property name="absoluteLineLimit" value="220"/>
</properties>
<exclude name="Generic.Files.LowercasedFilename.NotFound"/>
<exclude name="Generic.Files.EndFileNoNewline.Found"/>
</rule>
<rule ref="Generic.PHP">
<exclude name="Generic.PHP.UpperCaseConstant.Found"/>
<exclude name="Generic.PHP.ClosingPHPTag.NotFound"/>
<exclude name="Generic.PHP.NoSilencedErrors.Discouraged"/> <!-- unfortunately, the only way to make native SoapClient work correctly -->
</rule>
<rule ref="Generic.NamingConventions"/>
<rule ref="Generic.Functions">
<exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine"/>
<exclude name="Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine"/>
</rule>
<rule ref="PSR1.Classes"/>
<rule ref="PSR1.Files"/>
<rule ref="PSR1.Methods"/>
<rule ref="PSR2.Classes"/>
<rule ref="PSR2.ControlStructures"/>
<rule ref="PSR2.Files"/>
<rule ref="PSR2.Methods"/>
<rule ref="PSR2.Namespaces"/>
<rule ref="Squiz.Classes">
<exclude name="Squiz.Classes.ClassDeclaration.EndFileAfterCloseBrace"/>
</rule>
<rule ref="Squiz.Functions">
<exclude name="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpaceAfterDefault"/>
<exclude name="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpaceBeforeEquals"/>
</rule>
<!--<rule ref="Squiz.PHP"/>-->
<rule ref="Squiz.Objects">
<exclude name="Squiz.Objects.ObjectInstantiation.NotAssigned"/>
</rule>
<rule ref="Squiz.Scope"/>
</ruleset>

View File

@ -39,7 +39,11 @@
"require-dev": {
"ext-mcrypt": "*",
"mikey179/vfsStream": "~1.0",
"phpunit/phpunit": "~4.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"
},
"autoload": {
"psr-0": { "BeSimple\\": "src/" }
@ -53,5 +57,11 @@
"branch-alias": {
"dev-master": "0.4-dev"
}
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/tuscanicz/phpstan.git"
}
]
}

1084
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "7601f1ec280c086361e1deaf021f8ca1",
"content-hash": "59372f34124af17d5c35938dfffc6075",
"hash": "635c398afa1d5c217b5b8679b348ddc7",
"content-hash": "08f419455dd969e9145b8adfc84a03e9",
"packages": [
{
"name": "ass/xmlsecurity",
@ -229,6 +229,52 @@
],
"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",
@ -275,6 +321,643 @@
"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",
@ -484,6 +1167,68 @@
],
"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",
@ -855,6 +1600,53 @@
],
"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",
@ -1227,6 +2019,290 @@
"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",
@ -1335,7 +2411,9 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"phpstan/phpstan": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {

6
phing Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env php
<?php
putenv("PHING_HOME=" . realpath(dirname(__FILE__)));
require_once __DIR__ . '/vendor/phing/phing/bin/phing.php';

View File

@ -20,4 +20,9 @@
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true" showOnlySummary="true"/>
<log type="coverage-clover" target="cache/clover.xml"/>
</logging>
</phpunit>

View File

@ -12,7 +12,7 @@ namespace BeSimple\SoapBundle\Converter;
use BeSimple\SoapBundle\Soap\SoapRequest;
use BeSimple\SoapBundle\Soap\SoapResponse;
use BeSimple\SoapBundle\Util\String;
use BeSimple\SoapBundle\Util\StringUtility;
use BeSimple\SoapCommon\Converter\TypeConverterInterface;
/**
@ -40,7 +40,7 @@ class XopIncludeTypeConverter implements TypeConverterInterface
$ref = $include->getAttribute('href');
if (String::startsWith($ref, 'cid:')) {
if (StringUtility::startsWith($ref, 'cid:')) {
$cid = urldecode(substr($ref, 4));
return $request->getSoapAttachments()->get($cid)->getContent();

View File

@ -12,7 +12,7 @@
namespace BeSimple\SoapBundle\Handler;
use BeSimple\SoapServer\Exception\ReceiverSoapFault;
use SoapFault;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Response;
@ -44,7 +44,8 @@ class ExceptionHandler
$code = $this->exception->getStatusCode();
throw new ReceiverSoapFault(
throw new SoapFault(
'receiver',
isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
null,
$this->details

View File

@ -7,7 +7,7 @@ Pre-existent Type
+------------------------------------------------+-----------------+
| Php Type | Value Type |
+================================================+=================+
| BeSimple\\SoapCommon\\Type\\KeyValue\\String | String |
| BeSimple\\SoapCommon\\Type\\KeyValue\\StringUtility | StringUtility |
+------------------------------------------------+-----------------+
| BeSimple\\SoapCommon\\Type\\KeyValue\\Boolean | Boolean |
+------------------------------------------------+-----------------+
@ -34,7 +34,7 @@ Controller
{
/**
* @Soap\Method("returnAssocArray")
* @Soap\Result(phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
* @Soap\Result(phpType = "BeSimple\SoapCommon\Type\KeyValue\StringUtility[]")
*/
public function assocArrayOfStringAction()
{
@ -46,8 +46,8 @@ Controller
/**
* @Soap\Method("sendAssocArray")
* @Soap\Param("assocArray", phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
* @Soap\Result(phpType = "BeSimple\SoapCommon\Type\KeyValue\String[]")
* @Soap\Param("assocArray", phpType = "BeSimple\SoapCommon\Type\KeyValue\StringUtility[]")
* @Soap\Result(phpType = "BeSimple\SoapCommon\Type\KeyValue\StringUtility[]")
*/
public function sendAssocArrayOfStringAction(array $assocArray)
{

View File

@ -11,11 +11,11 @@
namespace BeSimple\SoapBundle\Util;
/**
* String provides utility methods for strings.
* StringUtility provides utility methods for strings.
*
* @author Christian Kerl <christian-kerl@web.de>
*/
class String
class StringUtility
{
/**
* Checks if a string starts with a given string.

View File

@ -92,7 +92,7 @@ class Curl
curl_setopt($curlSession, CURLOPT_URL, $location);
curl_setopt($curlSession, CURLOPT_HEADER, true);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER, true);
if (!is_null($request)) {
if ($request !== null) {
curl_setopt($curlSession, CURLOPT_POST, true);
curl_setopt($curlSession, CURLOPT_POSTFIELDS, $request);
} else {
@ -120,7 +120,7 @@ class Curl
$httpAuthenticationBasic = $options->getHttpAuthentication();
curl_setopt($curlSession, CURLOPT_HTTPAUTH, $httpAuthenticationBasic->getAuthenticationType());
curl_setopt($curlSession, CURLOPT_USERPWD, $httpAuthenticationBasic->getUsername() . ':' . $httpAuthenticationBasic->getPassword());
} else if ($options->hasHttpAuthenticationDigest()) {
} elseif ($options->hasHttpAuthenticationDigest()) {
/** @var HttpAuthenticationDigestOptions $httpAuthenticationDigest */
$httpAuthenticationDigest = $options->getHttpAuthentication();
curl_setopt($curlSession, CURLOPT_HTTPAUTH, $httpAuthenticationDigest->getAuthenticationType());
@ -152,34 +152,35 @@ class Curl
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',
'Curl error "%s" with message: %s occurred while connecting to %s with HTTP response code %s',
curl_errno($curlSession),
curl_error($curlSession),
$location
$location,
$httpResponseCode
);
if (!is_integer($httpResponseCode) || $httpResponseCode >= 400 || $httpResponseCode === 0) {
return new CurlResponse(
$httpRequestHeadersAsString,
$this->normalizeStringOrFalse($httpRequestHeadersAsString),
$httpResponseCode,
$httpResponseMessage,
$httpResponseContentType,
self::CURL_FAILED,
$responseHeaders,
$responseBody,
$this->normalizeStringOrFalse($responseHeaders),
$this->normalizeStringOrFalse($responseBody),
$curlErrorMessage
);
}
return new CurlResponse(
$httpRequestHeadersAsString,
$this->normalizeStringOrFalse($httpRequestHeadersAsString),
$httpResponseCode,
$httpResponseMessage,
$httpResponseContentType,
self::CURL_SUCCESS,
$responseHeaders,
$responseBody
$this->normalizeStringOrFalse($responseHeaders),
$this->normalizeStringOrFalse($responseBody)
);
}
@ -234,4 +235,13 @@ class Curl
throw new Exception('Cannot parse WSDL url redirect: ' . $url);
}
private function normalizeStringOrFalse($string)
{
if ($string === false || $string === '') {
$string = null;
}
return $string;
}
}

View File

@ -50,13 +50,14 @@ class CurlOptionsBuilder
$basicAuthentication->getPassword()
);
} else if ($soapClientOptions->hasAuthenticationDigest()) {
}
if ($soapClientOptions->hasAuthenticationDigest()) {
return new HttpAuthenticationDigestOptions();
} else {
throw new Exception('Unresolved authentication type: '.get_class($soapClientOptions->getAuthentication()));
}
throw new Exception('Unresolved authentication type: '.get_class($soapClientOptions->getAuthentication()));
}
return null;

View File

@ -19,6 +19,7 @@ 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;
@ -40,16 +41,12 @@ use SoapFault;
*/
class SoapClient extends \SoapClient
{
/** @var SoapClientOptions */
protected $soapClientOptions;
use SoapClientNativeMethodsTrait;
/** @var SoapOptions */
protected $soapOptions;
/** @var Curl */
private $curl;
/** @var SoapAttachment[] */
private $soapAttachmentsOnRequestStorage;
/** @var SoapResponse */
private $soapResponseStorage;
public function __construct(SoapClientOptions $soapClientOptions, SoapOptions $soapOptions)
{
@ -76,33 +73,6 @@ class SoapClient extends \SoapClient
@parent::__construct($wsdlPath, $soapClientOptions->toArray() + $soapOptions->toArray());
}
/**
* Avoid using __call directly, it's deprecated even in \SoapClient.
*
* @deprecated
*/
public function __call($function_name, $arguments)
{
throw new Exception(
'The __call method is deprecated. Use __soapCall/soapCall instead.'
);
}
/**
* Using __soapCall returns only response string, use soapCall instead.
*
* @param string $function_name
* @param array $arguments
* @param array|null $options
* @param null $input_headers
* @param array|null $output_headers
* @return string
*/
public function __soapCall($function_name, $arguments, $options = null, $input_headers = null, &$output_headers = null)
{
return $this->soapCall($function_name, $arguments, $options, $input_headers, $output_headers)->getResponseContent();
}
/**
* @param string $functionName
* @param array $arguments
@ -125,95 +95,13 @@ class SoapClient extends \SoapClient
} catch (SoapFault $soapFault) {
if (SoapFaultSourceGetter::isNativeSoapFault($soapFault)) {
$soapResponse = $this->getSoapResponseFromStorage();
if ($soapResponse instanceof SoapResponse) {
$soapFault = $this->throwSoapFaultByTracing(
SoapFaultPrefixEnum::PREFIX_PHP . '-' . $soapFault->getCode(),
$soapFault->getMessage(),
new SoapResponseTracingData(
'Content-Type: ' . $soapResponse->getRequest()->getContentType(),
$soapResponse->getRequest()->getContent(),
'Content-Type: ' . $soapResponse->getContentType(),
$soapResponse->getResponseContent()
)
);
} else {
$soapFault = new SoapFault(
SoapFaultPrefixEnum::PREFIX_PHP . '-unresolved',
'Got SoapFault message with no response: '.$soapFault->getMessage()
);
}
$soapFault = $this->decorateNativeSoapFault($soapFault);
}
throw $soapFault;
}
}
/**
* 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.'
);
}
/**
* Custom request method to be able to modify the SOAP messages.
* $oneWay parameter is not used at the moment.
@ -226,13 +114,23 @@ class SoapClient extends \SoapClient
*
* @return SoapResponse
*/
private function performSoapRequest($request, $location, $action, $version, array $soapAttachments = [])
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
@ -273,22 +171,10 @@ class SoapClient extends \SoapClient
*/
private function performHttpSoapRequest(SoapRequest $soapRequest)
{
if ($soapRequest->getVersion() === SOAP_1_1) {
$headers = [
'Content-Type: ' . $soapRequest->getContentType(),
'SOAPAction: "' . $soapRequest->getAction() . '"',
'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'),
];
} else {
$headers = [
'Content-Type: ' . $soapRequest->getContentType() . '; action="' . $soapRequest->getAction() . '"',
'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'),
];
}
$curlResponse = $this->curl->executeCurlWithCachedSession(
$soapRequest->getLocation(),
$soapRequest->getContent(),
$headers
$this->getHttpHeadersBySoapVersion($soapRequest)
);
$soapResponseTracingData = new SoapResponseTracingData(
$curlResponse->getHttpRequestHeaders(),
@ -310,26 +196,42 @@ class SoapClient extends \SoapClient
$this->getAttachmentFilters(),
$this->soapOptions->getAttachmentType()
);
} else {
return $soapResponse;
}
} else if ($curlResponse->curlStatusFailed()) {
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
);
} else {
return $this->throwSoapFaultByTracing(
SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR,
'Cannot process curl response with unresolved status: ' . $curlResponse->getCurlStatus(),
$soapResponseTracingData
);
}
return $this->throwSoapFaultByTracing(
SoapFaultEnum::SOAP_FAULT_SOAP_CLIENT_ERROR,
'Cannot process curl response with unresolved status: ' . $curlResponse->getCurlStatus(),
$soapResponseTracingData
);
}
/**
@ -383,18 +285,16 @@ class SoapClient extends \SoapClient
$soapResponseTracingData,
$soapAttachments
);
} else {
return SoapResponseFactory::create(
$curlResponse->getResponseBody(),
$soapRequest->getLocation(),
$soapRequest->getAction(),
$soapRequest->getVersion(),
$curlResponse->getHttpResponseContentType(),
$soapAttachments
);
}
return SoapResponseFactory::create(
$curlResponse->getResponseBody(),
$soapRequest->getLocation(),
$soapRequest->getAction(),
$soapRequest->getVersion(),
$curlResponse->getHttpResponseContentType(),
$soapAttachments
);
}
/**
@ -412,49 +312,76 @@ class SoapClient extends \SoapClient
$soapFaultMessage,
$soapResponseTracingData
);
}
throw new SoapFault(
$soapFaultCode,
$soapFaultMessage
);
}
private function decorateNativeSoapFault(SoapFault $nativePhpSoapFault)
{
$soapResponse = $this->getSoapResponseFromStorage();
if ($soapResponse instanceof SoapResponse) {
$soapFault = $this->throwSoapFaultByTracing(
SoapFaultPrefixEnum::PREFIX_PHP . '-' . $nativePhpSoapFault->getCode(),
$nativePhpSoapFault->getMessage(),
$this->getSoapResponseTracingDataFromNativeSoapFault(
$nativePhpSoapFault,
new SoapResponseTracingData(
'Content-Type: '.$soapResponse->getRequest()->getContentType(),
$soapResponse->getRequest()->getContent(),
'Content-Type: '.$soapResponse->getContentType(),
$soapResponse->getResponseContent()
)
)
);
} else {
throw new SoapFault(
$soapFaultCode,
$soapFaultMessage
$soapFault = $this->throwSoapFaultByTracing(
$nativePhpSoapFault->faultcode,
$nativePhpSoapFault->getMessage(),
$this->getSoapResponseTracingDataFromNativeSoapFault(
$nativePhpSoapFault,
new SoapResponseTracingData(
null,
null,
null,
null
)
)
);
}
return $soapFault;
}
private function checkTracing()
{
if ($this->soapClientOptions->getTrace() === false) {
throw new Exception('SoapClientOptions tracing disabled, turn on trace attribute');
private function getSoapResponseTracingDataFromNativeSoapFault(
SoapFault $nativePhpSoapFault,
SoapResponseTracingData $defaultSoapFaultTracingData
) {
if ($nativePhpSoapFault instanceof SoapFaultWithTracingData) {
return $nativePhpSoapFault->getSoapResponseTracingData();
}
return $defaultSoapFaultTracingData;
}
private function setSoapResponseToStorage(SoapResponse $soapResponseStorage)
private function getHttpHeadersBySoapVersion(SoapRequest $soapRequest)
{
$this->soapResponseStorage = $soapResponseStorage;
}
if ($soapRequest->getVersion() === SOAP_1_1) {
/**
* @param SoapAttachment[] $soapAttachments
*/
private function setSoapAttachmentsOnRequestToStorage(array $soapAttachments)
{
$this->soapAttachmentsOnRequestStorage = $soapAttachments;
}
return [
'Content-Type: ' . $soapRequest->getContentType(),
'SOAPAction: "' . $soapRequest->getAction() . '"',
'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'),
];
}
private function getSoapAttachmentsOnRequestFromStorage()
{
$soapAttachmentsOnRequest = $this->soapAttachmentsOnRequestStorage;
$this->soapAttachmentsOnRequestStorage = null;
return $soapAttachmentsOnRequest;
}
private function getSoapResponseFromStorage()
{
$soapResponse = $this->soapResponseStorage;
$this->soapResponseStorage = null;
return $soapResponse;
return [
'Content-Type: ' . $soapRequest->getContentType() . '; action="' . $soapRequest->getAction() . '"',
'Connection: ' . ($this->soapOptions->isConnectionKeepAlive() ? 'Keep-Alive' : 'close'),
];
}
}

View File

@ -0,0 +1,176 @@
<?php
namespace BeSimple\SoapClient;
use BeSimple\SoapBundle\Soap\SoapAttachment;
use BeSimple\SoapClient\SoapOptions\SoapClientOptions;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use Exception;
trait SoapClientNativeMethodsTrait
{
protected $soapClientOptions;
/** @var SoapAttachment[] */
private $soapAttachmentsOnRequestStorage;
/** @var SoapResponse */
private $soapResponseStorage;
/**
* @param string $functionName
* @param array $arguments
* @param array|null $options
* @param SoapAttachment[] $soapAttachments
* @param null $inputHeaders
* @param array|null $outputHeaders
* @return SoapResponse
*/
abstract public function soapCall($functionName, array $arguments, array $soapAttachments = [], array $options = null, $inputHeaders = null, array &$outputHeaders = null);
/**
* @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
*/
abstract protected function performSoapRequest($request, $location, $action, $version, array $soapAttachments = []);
/**
* @return SoapClientOptions
*/
abstract protected function getSoapClientOptions();
/**
* @return SoapOptions
*/
abstract protected function getSoapOptions();
/**
* Avoid using __call directly, it's deprecated even in \SoapClient.
*
* @deprecated
*/
public function __call($function_name, $arguments)
{
throw new Exception(
'The __call method is deprecated. Use __soapCall/soapCall instead.'
);
}
/**
* Using __soapCall returns only response string, use soapCall instead.
*
* @param string $function_name
* @param array $arguments
* @param array|null $options
* @param null $input_headers
* @param array|null $output_headers
* @return string
*/
public function __soapCall($function_name, $arguments, $options = null, $input_headers = null, &$output_headers = null)
{
return $this->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;
}
}

View File

@ -94,16 +94,16 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter
/**
* List of reference parameters associated with this soap message.
*
* @var unknown_type
* @var array
*/
protected $referenceParametersSet = array();
protected $referenceParametersSet;
/**
* List of reference parameters recieved with this soap message.
*
* @var unknown_type
* @var array
*/
protected $referenceParametersRecieved = array();
protected $referenceParametersRecieved;
/**
* 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)
public function filterRequest(CommonSoapRequest $request, $attachmentType)
{
// get \DOMDocument from SOAP request
$dom = $request->getContentDocument();
@ -328,7 +328,7 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter
*
* @return void
*/
public function filterResponse(CommonSoapResponse $response)
public function filterResponse(CommonSoapResponse $response, $attachmentType)
{
// get \DOMDocument from SOAP response
$dom = $response->getContentDocument();
@ -344,4 +344,4 @@ class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter
}
}
}
}
}

View File

@ -104,10 +104,11 @@ 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)
public function filterRequest(CommonSoapRequest $request, $attachmentType)
{
// get \DOMDocument from SOAP request
$dom = $request->getContentDocument();
@ -174,7 +175,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) {
@ -200,7 +201,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) {
@ -226,10 +227,11 @@ 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)
public function filterResponse(CommonSoapResponse $response, $attachmentType)
{
// get \DOMDocument from SOAP response
$dom = $response->getContentDocument();

View File

@ -78,8 +78,8 @@ class WsdlDownloader
throw new Exception('Could not write WSDL cache file: empty curl response from: '.$wsdlPath);
}
if ($resolveRemoteIncludes === true) {
$document = $this->getXmlFileDOMDocument($curl, $cacheType, $curlResponse->getResponseBody(), $wsdlPath);
$this->saveXmlDOMDocument($document, $cacheFilePath);
$document = $this->getXmlFileDomDocument($curl, $cacheType, $curlResponse->getResponseBody(), $wsdlPath);
$this->saveXmlDomDocument($document, $cacheFilePath);
} else {
file_put_contents($cacheFilePath, $curlResponse->getResponseBody());
}
@ -88,8 +88,8 @@ class WsdlDownloader
}
} else {
if (file_exists($wsdlPath)) {
$document = $this->getXmlFileDOMDocument($curl, $cacheType, file_get_contents($wsdlPath));
$this->saveXmlDOMDocument($document, $cacheFilePath);
$document = $this->getXmlFileDomDocument($curl, $cacheType, file_get_contents($wsdlPath));
$this->saveXmlDomDocument($document, $cacheFilePath);
} else {
throw new Exception('Could write WSDL cache file: local file does not exist: '.$wsdlPath);
}
@ -102,9 +102,9 @@ class WsdlDownloader
return realpath($wsdlPath);
} else {
throw new Exception('Could not download WSDL: local file does not exist: '.$wsdlPath);
}
throw new Exception('Could not download WSDL: local file does not exist: '.$wsdlPath);
}
/**
@ -118,11 +118,9 @@ class WsdlDownloader
if (isset($parsedUrlOrFalse['scheme']) && substr($parsedUrlOrFalse['scheme'], 0, 4) === 'http') {
return true;
} else {
return false;
}
return false;
}
throw new Exception('Could not determine wsdlPath is remote: '.$wsdlPath);
@ -137,7 +135,7 @@ class WsdlDownloader
* @param boolean $parentFilePath Parent file name
* @return DOMDocument
*/
private function getXmlFileDOMDocument(Curl $curl, $cacheType, $xmlFileSource, $parentFilePath = null)
private function getXmlFileDomDocument(Curl $curl, $cacheType, $xmlFileSource, $parentFilePath = null)
{
$document = new DOMDocument('1.0', 'utf-8');
if ($document->loadXML($xmlFileSource) === false) {
@ -151,7 +149,7 @@ class WsdlDownloader
return $document;
}
private function saveXmlDOMDocument(DOMDocument $document, $cacheFilePath)
private function saveXmlDomDocument(DOMDocument $document, $cacheFilePath)
{
try {
$xmlContents = $document->saveXML();
@ -191,7 +189,7 @@ class WsdlDownloader
true
)
);
} else if ($parentFilePath !== null) {
} elseif ($parentFilePath !== null) {
$node->setAttribute(
$locationAttributeName,
$this->getWsdlPath(

View File

@ -113,4 +113,4 @@ class Cache
{
ini_set($key, $value);
}
}
}

View File

@ -44,4 +44,3 @@ class DateTimeTypeConverter implements TypeConverterInterface
return sprintf('<%1$s>%2$s</%1$s>', $this->getTypeName(), $data->format('Y-m-d\TH:i:sP'));
}
}

View File

@ -44,4 +44,3 @@ class DateTypeConverter implements TypeConverterInterface
return sprintf('<%1$s>%2$s</%1$s>', $this->getTypeName(), $data->format('Y-m-d'));
}
}

View File

@ -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);
},
);

View File

@ -24,14 +24,14 @@ interface TypeConverterInterface
*
* @return string
*/
function getTypeNamespace();
public function getTypeNamespace();
/**
* Get type name.
*
* @return string
*/
function getTypeName();
public function getTypeName();
/**
* Convert given XML string to PHP type.
@ -40,7 +40,7 @@ interface TypeConverterInterface
*
* @return mixed
*/
function convertXmlToPhp($data);
public function convertXmlToPhp($data);
/**
* Convert PHP type to XML string.
@ -49,5 +49,5 @@ interface TypeConverterInterface
*
* @return string
*/
function convertPhpToXml($data);
}
public function convertPhpToXml($data);
}

View File

@ -0,0 +1,31 @@
<?php
namespace BeSimple\SoapCommon\Fault;
use SimpleXMLElement;
use SoapFault;
class SoapFaultParser
{
/**
* @param string $soapFaultXmlSource
* @return SoapFault
*/
public static function parseSoapFault($soapFaultXmlSource)
{
$simpleXMLElement = new SimpleXMLElement($soapFaultXmlSource);
$faultCode = $simpleXMLElement->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]
);
}
}

View File

@ -175,4 +175,4 @@ class FilterHelper
$this->namespaces[$namespaceURI] = $prefix;
}
}
}
}

View File

@ -167,12 +167,13 @@ 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",
@ -183,7 +184,9 @@ 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)
);
}
@ -198,9 +201,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;
}
/**
@ -214,8 +217,8 @@ class Helper
{
if ($namespace === self::NS_SOAP_1_2) {
return SOAP_1_2;
} else {
return SOAP_1_1;
}
return SOAP_1_1;
}
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace BeSimple\SoapCommon\Mime;
use Exception;
class CouldNotParseMimeMessageException extends Exception
{
private $mimePartMessage;
private $headers;
public function __construct($message, $mimePartMessage, array $headers)
{
$this->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;
}
}

View File

@ -31,21 +31,17 @@ class MultiPart extends PartHeader
{
/**
* Content-ID of main part.
*
* @var string
*/
protected $mainPartContentId;
/**
* Mime parts.
*
* @var \BeSimple\SoapCommon\Mime\Part[]
*/
protected $parts = [];
protected $parts;
/**
* Construct new mime object.
*
* @param string $boundary
*/
public function __construct($boundary = null)
@ -63,7 +59,6 @@ class MultiPart extends PartHeader
* Get mime message of this object (without headers).
*
* @param boolean $withHeaders Returned mime message contains headers
*
* @return string
*/
public function getMimeMessage($withHeaders = false)
@ -79,30 +74,6 @@ class MultiPart extends PartHeader
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 string[]
*/
public function getHeadersForHttp()
{
$allowedHeaders = [
'Content-Type',
'Content-Description',
];
$headers = [];
foreach ($this->headers as $fieldName => $value) {
if (in_array($fieldName, $allowedHeaders)) {
$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.
*
@ -179,11 +150,11 @@ class MultiPart extends PartHeader
*/
public function generateBoundary()
{
return 'multipart-boundary-' . Helper::generateUUID() . '@response.info';
return 'multipart-boundary-' . Helper::generateUuid() . '@response.info';
}
public function getMainPartContentId()
{
return $this->mainPartContentId;
}
}
}

View File

@ -16,7 +16,6 @@ use BeSimple\SoapCommon\Mime\Boundary\MimeBoundaryAnalyser;
use BeSimple\SoapCommon\Mime\Parser\ContentTypeParser;
use BeSimple\SoapCommon\Mime\Parser\ParsedPartList;
use BeSimple\SoapCommon\Mime\Parser\ParsedPartsGetter;
use Exception;
/**
* Simple Multipart-Mime parser.
@ -48,12 +47,14 @@ class Parser
}
if (MimeBoundaryAnalyser::hasMessageBoundary($mimeMessageLines) === true) {
if ($mimeMessageLineCount <= 1) {
throw new Exception(
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
);
}
$parsedPartList = ParsedPartsGetter::getPartsFromMimeMessageLines(
@ -62,18 +63,22 @@ class Parser
$hasHttpRequestHeaders
);
if ($parsedPartList->hasParts() === false) {
throw new Exception(
'Could not parse MimeMessage: no Parts for MultiPart given'
throw new CouldNotParseMimeMessageException(
'Could not parse MimeMessage: no Parts for MultiPart given',
$mimeMessage,
$headers
);
}
if ($parsedPartList->hasExactlyOneMainPart() === false) {
throw new Exception(
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
);
}
self::appendPartsToMultiPart(

View File

@ -113,7 +113,7 @@ class ParsedPartsGetter
$hitFirstBoundary = true;
$inHeader = true;
$messagePartStringContent = '';
} else if (MimeBoundaryAnalyser::isMessageLineLastBoundary($mimeMessageLine, $contentTypeBoundary)) {
} elseif (MimeBoundaryAnalyser::isMessageLineLastBoundary($mimeMessageLine, $contentTypeBoundary)) {
$currentPartContent = self::decodeContent(
$currentPart,
substr($messagePartStringContent, 0, -1)
@ -166,7 +166,7 @@ class ParsedPartsGetter
if ($encoding === Part::ENCODING_BASE64) {
$partStringContent = base64_decode($partStringContent);
} else if ($encoding === Part::ENCODING_QUOTED_PRINTABLE) {
} elseif ($encoding === Part::ENCODING_QUOTED_PRINTABLE) {
$partStringContent = quoted_printable_decode($partStringContent);
}

View File

@ -68,9 +68,7 @@ class Part extends PartHeader
}
/**
* __toString.
*
* @return mixed
* @return string
*/
public function __toString()
{
@ -98,11 +96,7 @@ class Part extends PartHeader
}
/**
* Set mime content.
*
* @param mixed $content Content to set
*
* @return void
* @param string $content
*/
public function setContent($content)
{
@ -111,7 +105,6 @@ class Part extends PartHeader
/**
* Get complete mime message of this object.
*
* @return string
*/
public function getMessagePart()
@ -121,7 +114,6 @@ class Part extends PartHeader
/**
* Generate body.
*
* @return string
*/
protected function generateBody()
@ -154,6 +146,6 @@ class Part extends PartHeader
*/
protected function generateContentId()
{
return 'part-' . Helper::generateUUID() . '@response.info';
return 'part-' . Helper::generateUuid() . '@response.info';
}
}
}

View File

@ -19,7 +19,10 @@ namespace BeSimple\SoapCommon\Mime;
*/
abstract class PartHeader
{
protected $headers = [];
/** @var string[] array of headers with lower-cased keys */
private $headers;
/** @var string[] array of lower-cased keys and their original variants */
private $headersOriginalKeys;
/**
* Add a new header to the mime part.
@ -32,19 +35,21 @@ abstract class PartHeader
*/
public function setHeader($name, $value, $subValue = null)
{
if (isset($this->headers[$name]) && !is_null($subValue)) {
if (!is_array($this->headers[$name])) {
$this->headers[$name] = [
'@' => $this->headers[$name],
$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],
$value => $subValue,
];
} else {
$this->headers[$name][$value] = $subValue;
$this->headers[$lowerCaseName][$value] = $subValue;
}
} elseif (isset($this->headers[$name]) && is_array($this->headers[$name]) && isset($this->headers[$name]['@'])) {
$this->headers[$name]['@'] = $value;
} elseif (isset($this->headers[$lowerCaseName]) && is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName]['@'])) {
$this->headers[$lowerCaseName]['@'] = $value;
} else {
$this->headers[$name] = $value;
$this->headers[$lowerCaseName] = $value;
}
}
@ -58,17 +63,18 @@ abstract class PartHeader
*/
public function getHeader($name, $subValue = null)
{
if (isset($this->headers[$name])) {
$lowerCaseName = mb_strtolower($name);
if (isset($this->headers[$lowerCaseName])) {
if (!is_null($subValue)) {
if (is_array($this->headers[$name]) && isset($this->headers[$name][$subValue])) {
return $this->headers[$name][$subValue];
if (is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName][$subValue])) {
return $this->headers[$lowerCaseName][$subValue];
} else {
return null;
}
} elseif (is_array($this->headers[$name]) && isset($this->headers[$name]['@'])) {
return $this->headers[$name]['@'];
} elseif (is_array($this->headers[$lowerCaseName]) && isset($this->headers[$lowerCaseName]['@'])) {
return $this->headers[$lowerCaseName]['@'];
} else {
return $this->headers[$name];
return $this->headers[$lowerCaseName];
}
}
@ -80,6 +86,30 @@ abstract class PartHeader
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.
*
@ -90,7 +120,7 @@ abstract class PartHeader
$headers = '';
foreach ($this->headers as $fieldName => $value) {
$fieldValue = $this->generateHeaderFieldValue($value);
$headers .= $fieldName . ': ' . $fieldValue . "\n";
$headers .= $this->headersOriginalKeys[$fieldName] . ': ' . $fieldValue . "\n";
}
return $headers;
@ -99,19 +129,18 @@ abstract class PartHeader
/**
* Generates a header field value from the given value paramater.
*
* @param array(string=>string)|string $value Header value
*
* @param string[]|string $value Header value
* @return string
*/
protected function generateHeaderFieldValue($value)
{
$fieldValue = '';
if (is_array($value)) {
if (is_array($value) === true) {
if (isset($value['@'])) {
$fieldValue .= $value['@'];
}
foreach ($value as $subName => $subValue) {
if ($subName != '@') {
if ($subName !== '@') {
$fieldValue .= '; ' . $subName . '=' . $this->quoteValueString($subValue);
}
}
@ -134,8 +163,8 @@ abstract class PartHeader
{
if (preg_match('~[()<>@,;:\\"/\[\]?=]~', $string)) {
return '"' . $string . '"';
} else {
return $string;
}
return $string;
}
}

View File

@ -92,14 +92,14 @@ abstract class SoapMessage
/**
* SOAP version (SOAP_1_1|SOAP_1_2)
*
* @var string
* @var int
*/
protected $version;
/**
* Get content type for given SOAP version.
*
* @param string $version SOAP version constant SOAP_1_1|SOAP_1_2
* @param int $version SOAP version constant SOAP_1_1|SOAP_1_2
*
* @return string
* @throws \InvalidArgumentException
@ -232,9 +232,9 @@ abstract class SoapMessage
}
/**
* Get version.
* Get SOAP version SOAP_1_1|SOAP_1_2
*
* @return string
* @return int
*/
public function getVersion()
{
@ -244,7 +244,7 @@ abstract class SoapMessage
/**
* Set version.
*
* @param string $version SOAP version SOAP_1_1|SOAP_1_2
* @param int $version SOAP version SOAP_1_1|SOAP_1_2
*/
public function setVersion($version)
{

View File

@ -36,7 +36,7 @@ class SoapRequestFactory
*
* @param string $location Location
* @param string $action SOAP action
* @param string $version SOAP version
* @param int $version SOAP version
* @param string $content Content
* @return SoapRequest
*/

View File

@ -27,4 +27,4 @@ interface SoapRequestFilter
* @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64
*/
public function filterRequest(SoapRequest $request, $attachmentType);
}
}

View File

@ -29,4 +29,4 @@ interface SoapResponseFilter
* @param int $attachmentType = SoapOptions::SOAP_ATTACHMENTS_TYPE_SWA|SoapOptions::ATTACHMENTS_TYPE_MTOM|SoapOptions::ATTACHMENTS_TYPE_BASE64
*/
public function filterResponse(SoapResponse $response, $attachmentType);
}
}

View File

@ -1,211 +0,0 @@
<?php
/*
* This file is part of the BeSimpleSoapBundle.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapCommon\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);
}
}

View File

@ -16,7 +16,7 @@ use BeSimple\SoapCommon\Cache;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamWrapper;
class SoapRequestTest extends \PHPUnit_Framework_TestCase
class CacheTest extends \PHPUnit_Framework_TestCase
{
public function testSetEnabled()
{

View File

@ -51,4 +51,3 @@ class DateTimeTypeConverterTest extends \PHPUnit_Framework_TestCase
$this->assertNull($date);
}
}

View File

@ -49,4 +49,3 @@ class DateTypeConverterTest extends \PHPUnit_Framework_TestCase
$this->assertNull($date);
}
}

View File

@ -30,19 +30,19 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$dateTimeTypeConverter = new DateTimeTypeConverter();
$converters->add($dateTimeTypeConverter);
$this->assertSame(array($dateTimeTypeConverter), $converters->getAll());
$this->assertSame([$dateTimeTypeConverter], $converters->getAll());
$dateTypeConverter = new DateTypeConverter();
$converters->add($dateTypeConverter);
$this->assertSame(array($dateTimeTypeConverter, $dateTypeConverter), $converters->getAll());
$this->assertSame([$dateTimeTypeConverter, $dateTypeConverter], $converters->getAll());
}
public function testGetTypemap()
{
$converters = new TypeConverterCollection();
$this->assertEquals(array(), $converters->getTypemap());
$this->assertEquals([], $converters->getTypemap());
$dateTimeTypeConverter = new DateTimeTypeConverter();
$converters->add($dateTimeTypeConverter);
@ -70,7 +70,9 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$dateTimeTypeConverter = new DateTimeTypeConverter();
$converters->add($dateTimeTypeConverter);
$converter = array(new DateTypeConverter);
$converter = [
new DateTypeConverter()
];
$converters->set($converter);
$this->assertSame($converter, $converters->getAll());
@ -85,9 +87,9 @@ class TypeConverterCollectionTest extends \PHPUnit_Framework_TestCase
$converters2->add($dateTimeTypeConverter);
$converters1->addCollection($converters2);
$this->assertSame(array($dateTimeTypeConverter), $converters1->getAll());
$this->assertSame([$dateTimeTypeConverter], $converters1->getAll());
$this->setExpectedException('InvalidArgumentException');
$converters1->addCollection($converters2);
}
}
}

View File

@ -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));
}

View File

@ -115,7 +115,8 @@ class ParserTest extends \PHPUnit_Framework_TestCase
$mimeMessage = file_get_contents($filename);
$headers = array(
'Content-Type' => 'multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:0ca0e16e-feb1-426c-97d8-c4508ada5e82+id=7";start-info="application/soap+xml"',
'Content-Type' =>
'multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";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',

View File

@ -325,7 +325,6 @@ abstract class WsSecurityFilterClientServer
if (Helper::NS_WSS === $key->namespaceURI) {
switch ($key->localName) {
case 'KeyIdentifier':
return $this->serviceSecurityKey->getPublicKey();
case 'Reference':
$uri = $key->getAttribute('URI');
@ -336,7 +335,8 @@ abstract class WsSecurityFilterClientServer
$key = XmlSecurityEnc::decryptEncryptedKey($referencedNode, $this->userSecurityKey->getPrivateKey());
return XmlSecurityKey::factory($algorithm, $key, false, XmlSecurityKey::TYPE_PRIVATE);
} elseif (Helper::NS_WSS === $referencedNode->namespaceURI
}
if (Helper::NS_WSS === $referencedNode->namespaceURI
&& 'BinarySecurityToken' == $referencedNode->localName) {
$key = XmlSecurityPem::formatKeyInPemFormat($referencedNode->textContent);

View File

@ -113,4 +113,4 @@ class WsSecurityKey
{
return null !== $this->publicKey;
}
}
}

View File

@ -1,26 +0,0 @@
<?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
* (c) Andreas Schamberger <mail@andreass.net>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapServer\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);
}
}

View File

@ -1,26 +0,0 @@
<?php
/*
* This file is part of the BeSimpleSoapCommon.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
* (c) Andreas Schamberger <mail@andreass.net>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapServer\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);
}
}

View File

@ -21,6 +21,7 @@ class SoapServerOptions
private $handlerObject;
private $keepAlive;
private $errorReporting;
private $exceptions;
private $persistence;
/**
@ -47,18 +48,20 @@ class SoapServerOptions
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();
} else if ($this->hasHandlerClass()) {
}
if ($this->hasHandlerClass()) {
return $this->getHandlerClass();
} else {
throw new Exception('No HandlerClass or HandlerObject set');
}
throw new Exception('No HandlerClass or HandlerObject set');
}
public function getHandlerInstance()
@ -94,7 +97,7 @@ class SoapServerOptions
public function hasPersistence()
{
return $this->persistence !== SoapServerOptions::SOAP_SERVER_PERSISTENCE_NONE;
return $this->persistence !== self::SOAP_SERVER_PERSISTENCE_NONE;
}
public function getPersistence()
@ -136,14 +139,13 @@ class SoapServerOptions
if (is_string($handler) && class_exists($handler)) {
return null;
} elseif (is_object($handler)) {
}
if (is_object($handler)) {
return $handler;
} else {
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
/**
@ -155,13 +157,12 @@ class SoapServerOptions
if (is_string($handler) && class_exists($handler)) {
return $handler;
} elseif (is_object($handler)) {
}
if (is_object($handler)) {
return null;
} else {
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
throw new \InvalidArgumentException('The handler has to be a class name or an object');
}
}

View File

@ -14,6 +14,7 @@ namespace BeSimple\SoapServer;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapServer\SoapOptions\SoapServerOptions;
use Exception;
/**
* SoapServerBuilder provides a SoapServer instance from SoapServerOptions and SoapOptions.
@ -40,9 +41,16 @@ class SoapServerBuilder
}
if ($soapServerOptions->hasHandlerClass()) {
$server->setClass($soapServerOptions->getHandlerClass());
} else if ($soapServerOptions->hasHandlerObject()) {
}
if ($soapServerOptions->hasHandlerObject()) {
$server->setObject($soapServerOptions->getHandlerObject());
}
if ($soapServerOptions->hasHandlerClass() && $soapServerOptions->hasHandlerObject()) {
throw new Exception(
'Could not create SoapServer: HandlerClass and HandlerObject are set: please specify only one'
);
}
return $server;
}

View File

@ -67,10 +67,11 @@ 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)
public function filterRequest(CommonSoapRequest $request, $attachmentType)
{
// get \DOMDocument from SOAP request
$dom = $request->getContentDocument();
@ -152,10 +153,11 @@ 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)
public function filterResponse(CommonSoapResponse $response, $attachmentType)
{
// get \DOMDocument from SOAP response
$dom = $response->getContentDocument();
@ -190,7 +192,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) {
@ -216,7 +218,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) {

View File

@ -75,7 +75,7 @@ class SoapClientTest extends PHPUnit_Framework_TestCase
public function testSoapCallWithCustomEndpointInvalidShouldFail()
{
$this->setExpectedException(Exception::class, 'Could not resolve host');
$this->setExpectedException(Exception::class, 't resolve host');
$soapClient = $this->getSoapBuilder()->build(
SoapClientOptionsBuilder::createWithEndpointLocation(self::TEST_REMOTE_ENDPOINT_NOT_WORKING),

View File

@ -0,0 +1,33 @@
<?php
namespace BeSimple\SoapCommon\Fault;
use PHPUnit_Framework_TestCase;
use SoapFault;
class SoapFaultParserTest extends PHPUnit_Framework_TestCase
{
public function testParse()
{
$soapFaultXml = '<?xml version="1.0" encoding="UTF-8"?>'.
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'.
'<SOAP-ENV:Body>'.
'<SOAP-ENV:Fault>'.
'<faultcode>911</faultcode>'.
'<faultstring>This is a dummy SoapFault.</faultstring>'.
'</SOAP-ENV:Fault>'.
'</SOAP-ENV:Body>'.
'</SOAP-ENV:Envelope>';
$soapFault = SoapFaultParser::parseSoapFault($soapFaultXml);
self::assertInstanceOf(SoapFault::class, $soapFault);
self::assertEquals(
'911',
$soapFault->faultcode
);
self::assertEquals(
'This is a dummy SoapFault.',
$soapFault->getMessage()
);
}
}

View File

@ -115,6 +115,35 @@ class SoapServerTest extends PHPUnit_Framework_TestCase
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="<rootpart@soapui.org>"; 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();

View File

@ -0,0 +1,216 @@
<?php
namespace BeSimple;
use BeSimple\SoapClient\SoapClientBuilder;
use BeSimple\SoapClient\SoapClientOptionsBuilder;
use BeSimple\SoapClient\SoapFaultWithTracingData;
use BeSimple\SoapCommon\ClassMap;
use BeSimple\SoapCommon\SoapOptions\SoapOptions;
use BeSimple\SoapCommon\SoapOptionsBuilder;
use BeSimple\SoapServer\SoapServerBuilder;
use Fixtures\GenerateTestRequest;
use PHPUnit_Framework_TestCase;
use SoapFault;
use SoapHeader;
class SoapServerAndSoapClientCommunicationSoapFaultsTest extends PHPUnit_Framework_TestCase
{
const CACHE_DIR = __DIR__ . '/../../cache';
const FIXTURES_DIR = __DIR__ . '/../Fixtures';
const TEST_HTTP_URL = 'http://localhost:8000/tests';
const TEST_HTTP_URL_INVALID = 'http://nosuchserverexists1234.com:9911';
const LARGE_SWA_FILE = self::FIXTURES_DIR.'/large-test-file.docx';
private $localWebServerProcess;
public function setUp()
{
$this->localWebServerProcess = popen('php -S localhost:8000 > /dev/null 2>&1 &', 'r');
}
public function tearDown()
{
pclose($this->localWebServerProcess);
}
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
);
/** @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(
'<faultcode>911</faultcode>',
$e->getSoapResponseTracingData()->getLastResponse()
);
self::assertContains(
'<request/>',
$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(
'<request/>',
$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(
'<request/>',
$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();
}
}

View File

@ -4,7 +4,6 @@ namespace BeSimple;
use BeSimple\SoapBundle\Soap\SoapAttachment;
use BeSimple\SoapClient\SoapClientBuilder;
use BeSimple\SoapClient\SoapClientBuilderTest;
use BeSimple\SoapClient\SoapClientOptionsBuilder;
use BeSimple\SoapClient\SoapFaultWithTracingData;
use BeSimple\SoapCommon\ClassMap;
@ -24,6 +23,7 @@ class SoapServerAndSoapClientCommunicationTest extends PHPUnit_Framework_TestCas
const CACHE_DIR = __DIR__ . '/../../cache';
const FIXTURES_DIR = __DIR__ . '/../Fixtures';
const TEST_HTTP_URL = 'http://localhost:8000/tests';
const TEST_HTTP_URL_INVALID = 'http://nosuchserverexists1234.com:9911';
const LARGE_SWA_FILE = self::FIXTURES_DIR.'/large-test-file.docx';
private $localWebServerProcess;

View File

@ -0,0 +1,62 @@
------=_Part_6_2094841787.1482231370463
Content-type: text/xml; charset=UTF-8
Content-transfer-Encoding: 8bit
Content-id: <rootpart@soapui.org>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://schema.testcase">
<soapenv:Header>
<sch:SoapHeader>
<user>admin</user>
</sch:SoapHeader>
</soapenv:Header>
<soapenv:Body>
<sch:dummyServiceMethodWithAttachments>
<request>
<dummyAttribute>3</dummyAttribute>
<includeAttachments>true</includeAttachments>
</request>
</sch:dummyServiceMethodWithAttachments>
</soapenv:Body>
</soapenv:Envelope>
------=_Part_6_2094841787.1482231370463
Content-type: text/html; charset=us-ascii; name=test-page.html
Content-transfer-Encoding: 7bit
Content-id: <test-page.html>
Content-disposition: attachment; name="test-page.html"; filename="test-page.html"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Test file page</title>
<style type="text/css">
<!--
h1 {
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
}
-->
</style>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
------=_Part_6_2094841787.1482231370463
Content-type: application/x-sh; name=testscript.sh
Content-transfer-Encoding: binary
Content-id: <testscript.sh>
Content-disposition: attachment; name="testscript.sh"; filename="testscript.sh"
#!/bin/sh
### ====================================================================== ###
## ##
## Test Script ##
## ##
### ====================================================================== ###
------=_Part_6_2094841787.1482231370463--

View File

@ -0,0 +1,9 @@
<?php
const FIXTURES_DIR = __DIR__.'/Fixtures';
$soapServer = new \SoapServer(FIXTURES_DIR.'/DummyService.wsdl');
$soapServer->fault(
911,
'This is a dummy SoapFault.'
);