Skip to content

Commit

Permalink
Merge pull request #15 from Ricorocks-Digital-Agency/soap-options
Browse files Browse the repository at this point in the history
Adds auth methods and allows setting options on the client.
  • Loading branch information
lukeraymonddowning authored Mar 23, 2021
2 parents 7786b83 + 326d8b3 commit 31849d7
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 36 deletions.
69 changes: 64 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ A Laravel SOAP client that provides a clean interface for handling requests and
* [Call](#call)
* [Parameters](#parameters)
* [Nodes](#nodes)
- [Tracing](#Tracing)
- [Options](#options)
* [Tracing](#tracing)
* [Authentication](#authentication)
* [Global Options](#global-options)
- [Hooks](#hooks)
- [Faking](#faking)
- [Configuration](#configuration)
Expand Down Expand Up @@ -148,7 +151,21 @@ Now, just by adding or removing a body to the `soap_node()` the outputted array

A node can be made with either the Facade `Soap::node()` or the helper method `soap_node()`.

## Tracing
## Options

You can set custom options for each soap request that will be passed to the Soap Client using the `withOptions` method.

```php
Soap::to('...')->withOptions(['soap_version' => SOAP_1_2])->call('...');
```

See [https://www.php.net/manual/en/soapclient.construct.php](https://www.php.net/manual/en/soapclient.construct.php)
for more details and available options.

Soap also provides a number of methods that add syntactical sugar to the most commonly used options, which are detailed
below.

### Tracing
Soap allows you to easily trace your interactions with the SOAP endpoint being accessed.

To trace all requests, set the following in the register method of your `ServiceProvider`:
Expand All @@ -166,6 +183,37 @@ Now, just this `Response` will have a valid `Trace`.

Tracing is null safe. If `$response->getTrace()` is called when a `Trace` hasn't been set, a new `Trace` is returned. This `Trace`'s properties will all return `null`.

### Authentication

You can authenticate using Basic or Digest by calling `withBasicAuth` and `withDigestAuth` respectively.

```php
Soap::to('...')->withBasicAuth('username', 'password')->call('...');
Soap::to('...')->withDigestAuth('username', 'password')->call('...');
```

### Global Options

Sometimes, you may wish to include the same set of options on every SOAP request. You can do that using the `options`
method on the `Soap` facade:

```php
// Every request will include these options automatically
Soap::options(['login' => 'foo', 'password' => 'bar']);
```

You may also want to include options on every request, but only for a certain endpoint or action:

```php
// Only requests to this endpoint will include these options
Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com');

// Only requests to this endpoint and the method Customers will include these options
Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com', 'Customers');
```

These calls are usually placed in the `boot` method of one of your application's Service Providers.

## Hooks

Hooks allow you to perform actions before and after Soap makes a request.
Expand Down Expand Up @@ -266,18 +314,29 @@ Configuration of Soap is via the `Soap` facade in the `boot()` method in your se

### Include

Parameters can be set to be included with specific endpoints. These can be `arrays` or [nodes](#nodes)
Parameters can be set to be automatically included in all requests. These can be `arrays` or [nodes](#nodes)

```php
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('...');
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])]);
```

You can even use dot syntax on your array keys to permeate deeper into the request body.

```php
Soap::include(['login.credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('...');
Soap::include(['login.credentials' => soap_node(['user' => '...', 'password' => '...'])]);
```

Often, you'll want to target specific endpoints or actions. You can chain the `for` method to achieve this.

```php
// Only requests to https://api.example.com will include this data
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com');

// Only requests to https://api.example.com calling the Customers method will include this data
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com', 'Customers');
```


## Ray Support

This package comes with first party support for Ray, an awesome debugging tool by Spatie! We offer a couple of methods that you
Expand Down
5 changes: 4 additions & 1 deletion src/Facades/Soap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use Closure;
use Illuminate\Support\Facades\Facade;
use RicorocksDigitalAgency\Soap\Inclusion;
use RicorocksDigitalAgency\Soap\OptionSet;
use RicorocksDigitalAgency\Soap\Parameters\Node;
use RicorocksDigitalAgency\Soap\Request\Request;

Expand All @@ -15,7 +17,8 @@
*
* @method static Request to(string $endpoint)
* @method static Node node(array $attributes = [])
* @method static include(array $parameters)
* @method static Inclusion include(array $parameters)
* @method static OptionSet options(array $options)
* @method static \RicorocksDigitalAgency\Soap\Soap beforeRequesting(callable $hook)
* @method static \RicorocksDigitalAgency\Soap\Soap afterRequesting(callable $hook)
* @method static void fake(array|Closure $callable = null)
Expand Down
21 changes: 3 additions & 18 deletions src/Inclusion.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,17 @@

namespace RicorocksDigitalAgency\Soap;

class Inclusion
use RicorocksDigitalAgency\Soap\Support\Scoped;

class Inclusion extends Scoped
{
protected $parameters;
protected $endpoint;
protected $method = null;

public function __construct($parameters)
{
$this->parameters = $parameters;
}

public function for($endpoint, $method = null)
{
$this->endpoint = $endpoint;
$this->method = $method;
}

public function matches(string $endpoint, $method = null)
{
if ($this->endpoint !== $endpoint) {
return false;
}

return empty($this->method) || $this->method === $method;
}

public function getParameters()
{
return $this->parameters;
Expand Down
22 changes: 22 additions & 0 deletions src/OptionSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php


namespace RicorocksDigitalAgency\Soap;


use RicorocksDigitalAgency\Soap\Support\Scoped;

class OptionSet extends Scoped
{
protected $options = [];

public function __construct(array $options)
{
$this->options = $options;
}

public function getOptions()
{
return $this->options;
}
}
8 changes: 8 additions & 0 deletions src/Request/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ public function getMethod();

public function getBody();

public function getOptions(): array;

public function set($key, $value): self;

public function trace($shouldTrace = true): self;

public function withOptions(array $options): self;

public function withBasicAuth($login, $password): self;

public function withDigestAuth($login, $password): self;
}
61 changes: 49 additions & 12 deletions src/Request/SoapClientRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use RicorocksDigitalAgency\Soap\Parameters\Builder;
use RicorocksDigitalAgency\Soap\Response\Response;
use RicorocksDigitalAgency\Soap\Support\Tracing\Trace;
use SoapClient;

class SoapClientRequest implements Request
{
Expand All @@ -15,7 +16,7 @@ class SoapClientRequest implements Request
protected Builder $builder;
protected Response $response;
protected $hooks = [];
protected $shouldTrace = false;
protected $options = [];

public function __construct(Builder $builder)
{
Expand Down Expand Up @@ -56,15 +57,7 @@ protected function getRealResponse()
{
return tap(
Response::new($this->makeRequest()),
fn($response) => $this->shouldTrace ? $this->addTrace($response) : $response
);
}

protected function addTrace($response)
{
return $response->setTrace(
Trace::thisXmlRequest($this->client()->__getLastRequest())
->thisXmlResponse($this->client()->__getLastResponse())
fn($response) => data_get($this->options, 'trace') ? $this->addTrace($response) : $response
);
}

Expand All @@ -75,7 +68,13 @@ protected function makeRequest()

protected function client()
{
return $this->client ??= app(\SoapClient::class, ['wsdl' => $this->endpoint, 'options' => ['trace' => $this->shouldTrace]]);
return $this->client ??= app(
SoapClient::class,
[
'wsdl' => $this->endpoint,
'options' => $this->options
]
);
}

public function getMethod()
Expand All @@ -88,6 +87,14 @@ public function getBody()
return $this->body;
}

protected function addTrace($response)
{
return $response->setTrace(
Trace::thisXmlRequest($this->client()->__getLastRequest())
->thisXmlResponse($this->client()->__getLastResponse())
);
}

public function functions(): array
{
return $this->client()->__getFunctions();
Expand Down Expand Up @@ -128,7 +135,37 @@ public function set($key, $value): Request

public function trace($shouldTrace = true): Request
{
$this->shouldTrace = $shouldTrace;
$this->options['trace'] = $shouldTrace;

return $this;
}

public function withBasicAuth($login, $password): Request
{
$this->options['authentication'] = SOAP_AUTHENTICATION_BASIC;
$this->options['login'] = $login;
$this->options['password'] = $password;

return $this;
}

public function withDigestAuth($login, $password): Request
{
$this->options['authentication'] = SOAP_AUTHENTICATION_DIGEST;
$this->options['login'] = $login;
$this->options['password'] = $password;

return $this;
}

public function getOptions(): array
{
return $this->options;
}

public function withOptions(array $options): Request
{
$this->options = array_merge($this->getOptions(), $options);
return $this;
}
}
19 changes: 19 additions & 0 deletions src/Soap.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ class Soap

protected Fakery $fakery;
protected $inclusions = [];
protected $optionsSets = [];
protected $globalHooks = [];

public function __construct(Fakery $fakery)
{
$this->fakery = $fakery;
$this->beforeRequesting(fn($request) => $request->fakeUsing($this->fakery->mockResponseIfAvailable($request)));
$this->beforeRequesting(fn($request) => $this->mergeInclusionsFor($request));
$this->beforeRequesting(fn($request) => $this->mergeOptionsFor($request));
$this->afterRequesting(fn($request, $response) => $this->record($request, $response));
}

Expand All @@ -47,6 +49,13 @@ public function include($parameters)
return $inclusion;
}

public function options(array $options)
{
$options = new OptionSet($options);
$this->optionsSets[] = $options;
return $options;
}

protected function mergeInclusionsFor(Request $request)
{
collect($this->inclusions)
Expand All @@ -57,6 +66,16 @@ protected function mergeInclusionsFor(Request $request)
->each(fn($value, $key) => $request->set($key, $value));
}

protected function mergeOptionsFor(Request $request)
{
collect($this->optionsSets)
->filter
->matches($request->getEndpoint(), $request->getMethod())
->map
->getOptions()
->each(fn($options) => $request->withOptions($options));
}

public function beforeRequesting(callable $hook)
{
($this->globalHooks['beforeRequesting'] ??= collect())->push($hook);
Expand Down
30 changes: 30 additions & 0 deletions src/Support/Scoped.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php


namespace RicorocksDigitalAgency\Soap\Support;


abstract class Scoped
{
protected $endpoint;
protected $method = null;

public function for($endpoint, $method = null)
{
$this->endpoint = $endpoint;
$this->method = $method;
}

public function matches(string $endpoint, $method = null)
{
if (empty($this->endpoint)) {
return true;
}

if ($this->endpoint !== $endpoint) {
return false;
}

return empty($this->method) || $this->method === $method;
}
}
Loading

0 comments on commit 31849d7

Please sign in to comment.