diff options
Diffstat (limited to 'vendor/clue/soap-react')
-rw-r--r-- | vendor/clue/soap-react/LICENSE | 21 | ||||
-rw-r--r-- | vendor/clue/soap-react/composer.json | 27 | ||||
-rw-r--r-- | vendor/clue/soap-react/src/Client.php | 323 | ||||
-rw-r--r-- | vendor/clue/soap-react/src/Protocol/ClientDecoder.php | 53 | ||||
-rw-r--r-- | vendor/clue/soap-react/src/Protocol/ClientEncoder.php | 69 | ||||
-rw-r--r-- | vendor/clue/soap-react/src/Proxy.php | 50 |
6 files changed, 543 insertions, 0 deletions
diff --git a/vendor/clue/soap-react/LICENSE b/vendor/clue/soap-react/LICENSE new file mode 100644 index 0000000..9426ad3 --- /dev/null +++ b/vendor/clue/soap-react/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Christian Lück + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/clue/soap-react/composer.json b/vendor/clue/soap-react/composer.json new file mode 100644 index 0000000..3b7fc4a --- /dev/null +++ b/vendor/clue/soap-react/composer.json @@ -0,0 +1,27 @@ +{ + "name": "clue/soap-react", + "description": "Simple, async SOAP webservice client library, built on top of ReactPHP", + "keywords": ["SOAP", "SoapClient", "WebService", "WSDL", "ReactPHP"], + "homepage": "https://github.com/clue/reactphp-soap", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "autoload": { + "psr-4": { "Clue\\React\\Soap\\": "src/" } + }, + "require": { + "php": ">=5.3", + "clue/buzz-react": "^2.5", + "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", + "react/promise": "^2.1 || ^1.2", + "ext-soap": "*" + }, + "require-dev": { + "clue/block-react": "^1.0", + "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" + } +} diff --git a/vendor/clue/soap-react/src/Client.php b/vendor/clue/soap-react/src/Client.php new file mode 100644 index 0000000..85ee7af --- /dev/null +++ b/vendor/clue/soap-react/src/Client.php @@ -0,0 +1,323 @@ +<?php + +namespace Clue\React\Soap; + +use Clue\React\Buzz\Browser; +use Clue\React\Soap\Protocol\ClientDecoder; +use Clue\React\Soap\Protocol\ClientEncoder; +use Psr\Http\Message\ResponseInterface; +use React\Promise\Deferred; +use React\Promise\PromiseInterface; + +/** + * The `Client` class is responsible for communication with the remote SOAP + * WebService server. + * + * It requires a [`Browser`](https://github.com/clue/reactphp-buzz#browser) object + * bound to the main [`EventLoop`](https://github.com/reactphp/event-loop#usage) + * in order to handle async requests, the WSDL file contents and an optional + * array of SOAP options: + * + * ```php + * $loop = React\EventLoop\Factory::create(); + * $browser = new Clue\React\Buzz\Browser($loop); + * + * $wsdl = '<?xml …'; + * $options = array(); + * + * $client = new Client($browser, $wsdl, $options); + * ``` + * + * If you need custom connector settings (DNS resolution, TLS parameters, timeouts, + * proxy servers etc.), you can explicitly pass a custom instance of the + * [`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface) + * to the [`Browser`](https://github.com/clue/reactphp-buzz#browser) instance: + * + * ```php + * $connector = new \React\Socket\Connector($loop, array( + * 'dns' => '127.0.0.1', + * 'tcp' => array( + * 'bindto' => '192.168.10.1:0' + * ), + * 'tls' => array( + * 'verify_peer' => false, + * 'verify_peer_name' => false + * ) + * )); + * + * $browser = new Browser($loop, $connector); + * $client = new Client($browser, $wsdl); + * ``` + * + * The `Client` works similar to PHP's `SoapClient` (which it uses under the + * hood), but leaves you the responsibility to load the WSDL file. This allows + * you to use local WSDL files, WSDL files from a cache or the most common form, + * downloading the WSDL file contents from an URL through the `Browser`: + * + * ```php + * $browser = new Browser($loop); + * + * $browser->get($url)->then( + * function (ResponseInterface $response) use ($browser) { + * // WSDL file is ready, create client + * $client = new Client($browser, (string)$response->getBody()); + * + * // do something… + * }, + * function (Exception $e) { + * // an error occured while trying to download the WSDL + * } + * ); + * ``` + * + * The `Client` constructor loads the given WSDL file contents into memory and + * parses its definition. If the given WSDL file is invalid and can not be + * parsed, this will throw a `SoapFault`: + * + * ```php + * try { + * $client = new Client($browser, $wsdl); + * } catch (SoapFault $e) { + * echo 'Error: ' . $e->getMessage() . PHP_EOL; + * } + * ``` + * + * > Note that if you have `ext-xdebug` loaded, this may halt with a fatal + * error instead of throwing a `SoapFault`. It is not recommended to use this + * extension in production, so this should only ever affect test environments. + * + * The `Client` constructor accepts an array of options. All given options will + * be passed through to the underlying `SoapClient`. However, not all options + * make sense in this async implementation and as such may not have the desired + * effect. See also [`SoapClient`](http://php.net/manual/en/soapclient.soapclient.php) + * documentation for more details. + * + * If working in WSDL mode, the `$options` parameter is optional. If working in + * non-WSDL mode, the WSDL parameter must be set to `null` and the options + * parameter must contain the `location` and `uri` options, where `location` is + * the URL of the SOAP server to send the request to, and `uri` is the target + * namespace of the SOAP service: + * + * ```php + * $client = new Client($browser, null, array( + * 'location' => 'http://example.com', + * 'uri' => 'http://ping.example.com', + * )); + * ``` + * + * Similarly, if working in WSDL mode, the `location` option can be used to + * explicitly overwrite the URL of the SOAP server to send the request to: + * + * ```php + * $client = new Client($browser, $wsdl, array( + * 'location' => 'http://example.com' + * )); + * ``` + * + * You can use the `soap_version` option to change from the default SOAP 1.1 to + * use SOAP 1.2 instead: + * + * ```php + * $client = new Client($browser, $wsdl, array( + * 'soap_version' => SOAP_1_2 + * )); + * ``` + * + * You can use the `classmap` option to map certain WSDL types to PHP classes + * like this: + * + * ```php + * $client = new Client($browser, $wsdl, array( + * 'classmap' => array( + * 'getBankResponseType' => BankResponse::class + * ) + * )); + * ``` + * + * The `proxy_host` option (and family) is not supported by this library. As an + * alternative, you can configure the given `$browser` instance to use an + * [HTTP proxy server](https://github.com/clue/reactphp-buzz#http-proxy). + * If you find any other option is missing or not supported here, PRs are much + * appreciated! + * + * All public methods of the `Client` are considered *advanced usage*. + * If you want to call RPC functions, see below for the [`Proxy`](#proxy) class. + */ +class Client +{ + private $browser; + private $encoder; + private $decoder; + + /** + * Instantiate a new SOAP client for the given WSDL contents. + * + * @param Browser $browser + * @param string|null $wsdlContents + * @param array $options + */ + public function __construct(Browser $browser, $wsdlContents, array $options = array()) + { + $wsdl = $wsdlContents !== null ? 'data://text/plain;base64,' . base64_encode($wsdlContents) : null; + + // Accept HTTP responses with error status codes as valid responses. + // This is done in order to process these error responses through the normal SOAP decoder. + // Additionally, we explicitly limit number of redirects to zero because following redirects makes little sense + // because it transforms the POST request to a GET one and hence loses the SOAP request body. + $browser = $browser->withOptions(array( + 'obeySuccessCode' => false, + 'followRedirects' => true, + 'maxRedirects' => 0 + )); + + $this->browser = $browser; + $this->encoder = new ClientEncoder($wsdl, $options); + $this->decoder = new ClientDecoder($wsdl, $options); + } + + /** + * Queue the given function to be sent via SOAP and wait for a response from the remote web service. + * + * ```php + * // advanced usage, see Proxy for recommended alternative + * $promise = $client->soapCall('ping', array('hello', 42)); + * ``` + * + * Note: This is considered *advanced usage*, you may want to look into using the [`Proxy`](#proxy) instead. + * + * ```php + * $proxy = new Proxy($client); + * $promise = $proxy->ping('hello', 42); + * ``` + * + * @param string $name + * @param mixed[] $args + * @return PromiseInterface Returns a Promise<mixed, Exception> + */ + public function soapCall($name, $args) + { + try { + $request = $this->encoder->encode($name, $args); + } catch (\Exception $e) { + $deferred = new Deferred(); + $deferred->reject($e); + return $deferred->promise(); + } + + $decoder = $this->decoder; + + return $this->browser->send($request)->then( + function (ResponseInterface $response) use ($decoder, $name) { + // HTTP response received => decode results for this function call + return $decoder->decode($name, (string)$response->getBody()); + } + ); + } + + /** + * Returns an array of functions defined in the WSDL. + * + * It returns the equivalent of PHP's + * [`SoapClient::__getFunctions()`](http://php.net/manual/en/soapclient.getfunctions.php). + * In non-WSDL mode, this method returns `null`. + * + * @return string[]|null + */ + public function getFunctions() + { + return $this->encoder->__getFunctions(); + } + + /** + * Returns an array of types defined in the WSDL. + * + * It returns the equivalent of PHP's + * [`SoapClient::__getTypes()`](http://php.net/manual/en/soapclient.gettypes.php). + * In non-WSDL mode, this method returns `null`. + * + * @return string[]|null + */ + public function getTypes() + { + return $this->encoder->__getTypes(); + } + + /** + * Returns the location (URI) of the given webservice `$function`. + * + * Note that this is not to be confused with the WSDL file location. + * A WSDL file can contain any number of function definitions. + * It's very common that all of these functions use the same location definition. + * However, technically each function can potentially use a different location. + * + * The `$function` parameter should be a string with the the SOAP function name. + * See also [`getFunctions()`](#getfunctions) for a list of all available functions. + * + * ```php + * assert('http://example.com/soap/service' === $client->getLocation('echo')); + * ``` + * + * For easier access, this function also accepts a numeric function index. + * It then uses [`getFunctions()`](#getfunctions) internally to get the function + * name for the given index. + * This is particularly useful for the very common case where all functions use the + * same location and accessing the first location is sufficient. + * + * ```php + * assert('http://example.com/soap/service' === $client->getLocation(0)); + * ``` + * + * When the `location` option has been set in the `Client` constructor + * (such as when in non-WSDL mode) or via the `withLocation()` method, this + * method returns the value of the given location. + * + * Passing a `$function` not defined in the WSDL file will throw a `SoapFault`. + * + * @param string|int $function + * @return string + * @throws \SoapFault if given function does not exist + * @see self::getFunctions() + */ + public function getLocation($function) + { + if (is_int($function)) { + $functions = $this->getFunctions(); + if (isset($functions[$function]) && preg_match('/^\w+ (\w+)\(/', $functions[$function], $match)) { + $function = $match[1]; + } + } + + // encode request for given $function + return (string)$this->encoder->encode($function, array())->getUri(); + } + + /** + * Returns a new `Client` with the updated location (URI) for all functions. + * + * Note that this is not to be confused with the WSDL file location. + * A WSDL file can contain any number of function definitions. + * It's very common that all of these functions use the same location definition. + * However, technically each function can potentially use a different location. + * + * ```php + * $client = $client->withLocation('http://example.com/soap'); + * + * assert('http://example.com/soap' === $client->getLocation('echo')); + * ``` + * + * As an alternative to this method, you can also set the `location` option + * in the `Client` constructor (such as when in non-WSDL mode). + * + * @param string $location + * @return self + * @see self::getLocation() + */ + public function withLocation($location) + { + $client = clone $this; + $client->encoder = clone $this->encoder; + $client->encoder->__setLocation($location); + + return $client; + } +} diff --git a/vendor/clue/soap-react/src/Protocol/ClientDecoder.php b/vendor/clue/soap-react/src/Protocol/ClientDecoder.php new file mode 100644 index 0000000..39cb745 --- /dev/null +++ b/vendor/clue/soap-react/src/Protocol/ClientDecoder.php @@ -0,0 +1,53 @@ +<?php + +namespace Clue\React\Soap\Protocol; + +use \SoapClient; + +/** + * @internal + */ +final class ClientDecoder extends SoapClient +{ + private $response = null; + + /** + * Decodes the SOAP response / return value from the given SOAP envelope (HTTP response body) + * + * @param string $function + * @param string $response + * @return mixed + * @throws \SoapFault if response indicates a fault (error condition) or is invalid + */ + public function decode($function, $response) + { + // Temporarily save response internally for further processing + $this->response = $response; + + // Let's pretend we just invoked the given SOAP function. + // This won't actually invoke anything (see `__doRequest()`), but this + // requires a valid function name to match its definition in the WSDL. + // Internally, simply use the injected response to parse its results. + $ret = $this->__soapCall($function, array()); + $this->response = null; + + return $ret; + } + + /** + * Overwrites the internal request logic to parse the response + * + * By overwriting this method, we can skip the actual request sending logic + * and still use the internal parsing logic by injecting the response as + * the return code in this method. This will implicitly be invoked by the + * call to `pseudoCall()` in the above `decode()` method. + * + * @see SoapClient::__doRequest() + */ + public function __doRequest($request, $location, $action, $version, $one_way = 0) + { + // the actual result doesn't actually matter, just return the given result + // this will be processed internally and will return the parsed result + return $this->response; + } +} diff --git a/vendor/clue/soap-react/src/Protocol/ClientEncoder.php b/vendor/clue/soap-react/src/Protocol/ClientEncoder.php new file mode 100644 index 0000000..e9d0018 --- /dev/null +++ b/vendor/clue/soap-react/src/Protocol/ClientEncoder.php @@ -0,0 +1,69 @@ +<?php + +namespace Clue\React\Soap\Protocol; + +use \SoapClient; +use RingCentral\Psr7\Request; + +/** + * @internal + */ +final class ClientEncoder extends SoapClient +{ + private $request = null; + + /** + * Encodes the given RPC function name and arguments as a SOAP request + * + * @param string $name + * @param array $args + * @return Request + * @throws \SoapFault if request is invalid according to WSDL + */ + public function encode($name, $args) + { + $this->__soapCall($name, $args); + + $request = $this->request; + $this->request = null; + + return $request; + } + + /** + * Overwrites the internal request logic to build the request message + * + * By overwriting this method, we can skip the actual request sending logic + * and still use the internal request serializing logic by accessing the + * given `$request` parameter and building our custom request object from + * it. We skip/ignore its parsing logic by returing an empty response here. + * This will implicitly be invoked by the call to `__soapCall()` in the + * above `encode()` method. + * + * @see SoapClient::__doRequest() + */ + public function __doRequest($request, $location, $action, $version, $one_way = 0) + { + $headers = array(); + if ($version === SOAP_1_1) { + $headers = array( + 'SOAPAction' => $action, + 'Content-Type' => 'text/xml; charset=utf-8' + ); + } elseif ($version === SOAP_1_2) { + $headers = array( + 'Content-Type' => 'application/soap+xml; charset=utf-8; action=' . $action + ); + } + + $this->request = new Request( + 'POST', + (string)$location, + $headers, + (string)$request + ); + + // do not actually block here, just pretend we're done... + return ''; + } +} diff --git a/vendor/clue/soap-react/src/Proxy.php b/vendor/clue/soap-react/src/Proxy.php new file mode 100644 index 0000000..06d70a0 --- /dev/null +++ b/vendor/clue/soap-react/src/Proxy.php @@ -0,0 +1,50 @@ +<?php + +namespace Clue\React\Soap; + +use React\Promise\PromiseInterface; + +/** + * The `Proxy` class wraps an existing [`Client`](#client) instance in order to ease calling + * SOAP functions. + * + * ```php + * $proxy = new Proxy($client); + * ``` + * + * Each and every method call to the `Proxy` class will be sent via SOAP. + * + * ```php + * $proxy->myMethod($myArg1, $myArg2)->then(function ($response) { + * // result received + * }); + * ``` + * + * Please refer to your WSDL or its accompanying documentation for details + * on which functions and arguments are supported. + * + * > Note that this class is called "Proxy" because it will forward (proxy) all + * method calls to the actual SOAP service via the underlying + * [`Client::soapCall()`](#soapcall) method. This is not to be confused with + * using a proxy server. See [`Client`](#client) documentation for more + * details on how to use an HTTP proxy server. + */ +final class Proxy +{ + private $client; + + public function __construct(Client $client) + { + $this->client = $client; + } + + /** + * @param string $name + * @param mixed[] $args + * @return PromiseInterface + */ + public function __call($name, $args) + { + return $this->client->soapCall($name, $args); + } +} |