diff --git a/CHANGELOG.md b/CHANGELOG.md index f7502ac..da99cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Latest ### Changes * [#20](https://github.com/cleverage/soap-process-bundle/issues/20) Update quality stack: use Rector `withComposerBased()` sets (removed `SYMFONY_64` / `PHPUNIT_100` sets), declare used Symfony packages and PHPUnit range in composer.json, apply quality tools fixes +* [#22](https://github.com/cleverage/soap-process-bundle/issues/22) Add missing documentations: reference pages for Client, RequestTask & RequestTransformer, cookbooks. Harmonize and fix existing documentation. v3.0 ------ diff --git a/README.md b/README.md index b9f3384..2c2aad0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ For usage documentation, see: ## Support & Contribution -For general support and questions, please use [Github](https://github.com/cleverage/rest-process-bundle/issues). +For general support and questions, please use [Github](https://github.com/cleverage/soap-process-bundle/issues). If you think you found a bug or you have a feature idea to propose, feel free to open an issue after looking at the [contributing](CONTRIBUTING.md) guide. ## License diff --git a/docs/cookbooks/soap_call_and_export.md b/docs/cookbooks/soap_call_and_export.md new file mode 100644 index 0000000..3766643 --- /dev/null +++ b/docs/cookbooks/soap_call_and_export.md @@ -0,0 +1,81 @@ +Call a SOAP service and export the response +=========================================== + +This recipe calls a SOAP method returning a list, filters and maps the response, then writes it to a CSV file. +It uses the public [CountryInfoService](http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso) +through the `country_info` client declared in the [client reference](../reference/client.md#examples). + +```yaml +clever_age_process: + configurations: + app.soap_export_european_countries: + description: 'Export the European countries from the CountryInfoService' + tasks: + list_countries: + service: '@CleverAge\SoapProcessBundle\Task\RequestTask' + error_strategy: stop + options: + client: country_info + method: FullCountryInfoAllCountries + outputs: [extract] + + extract: + service: '@CleverAge\ProcessBundle\Task\TransformerTask' + options: + transformers: + property_accessor: # Get the list of countries from the stdClass response + property_path: 'FullCountryInfoAllCountriesResult.tCountryInfo' + array_filter: + condition: + match: + sContinentCode: 'EU' + array_map: + transformers: + cast: # Convert each stdClass to an array + type: array + mapping: + mapping: + iso_code: + code: '[sISOCode]' + name: + code: '[sName]' + capital: + code: '[sCapitalCity]' + phone_code: + code: '[sPhoneCode]' + currency: + code: '[sCurrencyISOCode]' + outputs: [iterate] + + iterate: + service: '@CleverAge\ProcessBundle\Task\InputIteratorTask' + outputs: [write] + + write: + service: '@CleverAge\ProcessBundle\Task\File\Csv\CsvWriterTask' + options: + file_path: '%kernel.project_dir%/var/exports/european_countries_{date}.csv' + headers: [iso_code, name, capital, phone_code, currency] +``` + +How it works: +- The [RequestTask](../reference/tasks/request_task.md) has no input (it is the first task), so the + `FullCountryInfoAllCountries` method is called without argument. The response is a `stdClass` built by `SoapClient`. + With `error_strategy: stop`, a failed call (logged with the last request and response) stops the process. +- The [TransformerTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/transformer_task.md) + reads the list of countries in the response with + [property_accessor](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/property_accessor_transformer.md), + keeps the European ones with + [array_filter](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/array_filter_transformer.md), + then converts each `stdClass` to an array + ([cast](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/cast_transformer.md)) and + renames its keys ([mapping](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/mapping_transformer.md)) + inside [array_map](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/array_map_transformer.md). +- The [InputIteratorTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/input_iterator_task.md) + outputs the countries one by one to the + [CsvWriterTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/csv_writer_task.md). + +Note that the client sets the `SOAP_SINGLE_ELEMENT_ARRAYS` feature: without it, `tCountryInfo` would be a single +`stdClass` instead of a list if the service returned only one country. Also, a failed call stops the process without +marking it as failed (see [RequestTask notes](../reference/tasks/request_task.md#notes)): monitor the error logs of +the `cleverage_process_task` channel. diff --git a/docs/cookbooks/soap_enrich_csv.md b/docs/cookbooks/soap_enrich_csv.md new file mode 100644 index 0000000..dc45fd8 --- /dev/null +++ b/docs/cookbooks/soap_enrich_csv.md @@ -0,0 +1,130 @@ +Enrich a CSV file with a SOAP service +===================================== + +This recipe reads a CSV file of country codes, calls a SOAP method for each line, and writes the enriched lines to +another CSV file. Lines for which the call fails are logged and skipped. It uses the public +[CountryInfoService](http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso) through the +`country_info` client declared in the [client reference](../reference/client.md#examples). + +Source file `var/data/countries.csv`: + +```csv +iso;label +FR;Our label for France +DE;Our label for Germany +``` + +```yaml +clever_age_process: + configurations: + app.soap_enrich_countries: + description: 'Add the capital city and currency of each country' + tasks: + read: + service: '@CleverAge\ProcessBundle\Task\File\Csv\CsvReaderTask' + options: + file_path: '%kernel.project_dir%/var/data/countries.csv' + outputs: [build_arguments] + + build_arguments: + service: '@CleverAge\ProcessBundle\Task\TransformerTask' + options: + transformers: + mapping: # { parameters: { sCountryISOCode: FR } } + mapping: + parameters: + code: '[iso]' + transformers: + wrapper: + wrapper_key: sCountryISOCode + outputs: [get_country] + + get_country: + service: '@CleverAge\SoapProcessBundle\Task\RequestTask' + error_strategy: skip + options: + client: country_info + method: FullCountryInfo + outputs: [map_response] + error_outputs: [log_error] + + log_error: + service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask' + options: + level: warning + message: 'FullCountryInfo call failed, line skipped' + + map_response: + service: '@CleverAge\ProcessBundle\Task\TransformerTask' + options: + transformers: + property_accessor: + property_path: FullCountryInfoResult + cast: + type: array + mapping: + mapping: + iso: + code: '[sISOCode]' + name: + code: '[sName]' + capital: + code: '[sCapitalCity]' + currency: + code: '[sCurrencyISOCode]' + outputs: [write] + + write: + service: '@CleverAge\ProcessBundle\Task\File\Csv\CsvWriterTask' + options: + file_path: '%kernel.project_dir%/var/exports/countries_enriched_{date}.csv' + headers: [iso, name, capital, currency] +``` + +How it works: +- [CsvReaderTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/csv_reader_task.md) is + iterable: each line goes through the following tasks before the next one is read, so one SOAP call is made per line. +- The first [TransformerTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/transformer_task.md) + builds the arguments of the SOAP method with the + [mapping](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/mapping_transformer.md) + and [wrapper](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/wrapper_transformer.md) + transformers: `FullCountryInfo` is a document/literal method expecting a single `parameters` structure. +- The [RequestTask](../reference/tasks/request_task.md) calls `FullCountryInfo` with these arguments. With + `error_strategy: skip`, a failed call is logged by the task, `false` is sent to the + [LoggerTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/logger_task.md) of the + `error_outputs`, and the line is not written. +- The second TransformerTask extracts the result from the `stdClass` response + ([property_accessor](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/property_accessor_transformer.md)), + converts it to an array ([cast](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/cast_transformer.md)) + and maps the columns to write with the + [CsvWriterTask](https://github.com/cleverage/process-bundle/blob/main/docs/reference/tasks/csv_writer_task.md). + +Note that the error output of the RequestTask is `false`, not the CSV line: the details of the failed call (options, +last request and response) are in the log context of the `Empty resultset for query` error logged by the task. + +To add a single value to the line instead of replacing it, the SOAP call can also be done inside a `mapping` with the +[RequestTransformer](../reference/transformers/request_transformer.md) (`soap_request`), e.g. with `keep_input: true`: + +```yaml +# Task configuration level +add_country_name: + service: '@CleverAge\ProcessBundle\Task\TransformerTask' + options: + transformers: + mapping: + keep_input: true + mapping: + name: + code: '[iso]' + transformers: + wrapper: + wrapper_key: sCountryISOCode + wrapper#2: + wrapper_key: parameters + soap_request: + client: country_info + method: CountryName + property_accessor: + property_path: CountryNameResult + outputs: [write] +``` diff --git a/docs/index.md b/docs/index.md index 47d52d3..a59b596 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,7 @@ ## Prerequisite -CleverAge/ProcessBundle must be [installed](https://github.com/cleverage/process-bundle/blob/main/docs/01-quick_start.md#installation. +CleverAge/ProcessBundle must be [installed](https://github.com/cleverage/process-bundle/blob/main/docs/01-quick_start.md#installation). +The PHP [soap](https://www.php.net/manual/en/book.soap.php) extension is required. ## Installation @@ -19,9 +20,36 @@ Remember to add the following line to config/bundles.php (not required if Symfon CleverAge\SoapProcessBundle\CleverAgeSoapProcessBundle::class => ['all' => true], ``` +## Configuration + +The bundle has no configuration. Declare at least one SOAP client as a service tagged `cleverage.soap.client`, its +`code` is then used by the `client` option of the task and the transformer (see [Client](reference/client.md)): + +```yaml +# config/services.yaml +services: + app.cleverage_soap_process.client.country_info: + class: CleverAge\SoapProcessBundle\Client\Client + arguments: + $logger: '@logger' + $code: 'country_info' + $wsdl: 'http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL' + $options: + exceptions: true + features: !php/const SOAP_SINGLE_ELEMENT_ARRAYS + tags: + - { name: cleverage.soap.client } +``` + ## Reference +- [Client](reference/client.md) - Tasks - [RequestTask](reference/tasks/request_task.md) - Transformers - - [RequestTransformer] + - [RequestTransformer](reference/transformers/request_transformer.md) + +## Cookbooks + +- [Call a SOAP service and export the response](cookbooks/soap_call_and_export.md) +- [Enrich a CSV file with a SOAP service](cookbooks/soap_enrich_csv.md) diff --git a/docs/reference/client.md b/docs/reference/client.md new file mode 100644 index 0000000..2f04fbf --- /dev/null +++ b/docs/reference/client.md @@ -0,0 +1,142 @@ +Client +====== + +A SOAP client wraps a PHP [SoapClient](https://www.php.net/manual/en/class.soapclient.php) (a WSDL and its options) +and makes it available to the [RequestTask](tasks/request_task.md) and the +[RequestTransformer](transformers/request_transformer.md) under a short **code**, referenced by their `client` option. + +Client reference +---------------- + +* **Interface**: `CleverAge\SoapProcessBundle\Client\ClientInterface` +* **Base class**: `CleverAge\SoapProcessBundle\Client\Client` +* **Service tag**: `cleverage.soap.client`, every tagged service is registered in the + `cleverage_soap_process.registry.client` registry (`CleverAge\SoapProcessBundle\Registry\ClientRegistry`) + +The bundle does not declare any client: you have to register at least one service, either with the +`CleverAge\SoapProcessBundle\Client\Client` class or with your own implementation of `ClientInterface`. + +Constructor arguments +--------------------- + +Arguments of the `CleverAge\SoapProcessBundle\Client\Client` base class: + +| Code | Type | Required | Default | Description | +|------------|----------------------------|:--------:|---------|----------------------------------------------------------------------------------------------------------------------------------------------| +| `$logger` | `Psr\Log\LoggerInterface` | **X** | | Logger used to trace the calls (see Notes) | +| `$code` | `string` | **X** | | Unique client code, referenced by the `client` option of the task and the transformer. It cannot be empty or `'0'` | +| `$wsdl` | `string\|null` | **X** | | URI of the WSDL file, or `null` to work in non-WSDL mode (the `location` and `uri` options are then required by `SoapClient`) | +| `$options` | `array` | | `[]` | Options of the [SoapClient constructor](https://www.php.net/manual/en/soapclient.construct.php) (`exceptions`, `features`, `login`, …) | + +Setters +------- + +These values can be set with `calls` in the service definition. Note that the [RequestTask](tasks/request_task.md) +overwrites the SOAP call options and headers each time it is executed (see Notes). + +| Method | Description | +|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `setWsdl(?string $wsdl)` | Change the WSDL URI (only before the first call: the `SoapClient` is created once) | +| `setOptions(array $options)` | Change the `SoapClient` constructor options (only before the first call) | +| `setSoapOptions(?array $options)` | Options of [SoapClient::__soapCall()](https://www.php.net/manual/en/soapclient.soapcall.php): `location`, `uri`, `soapaction` | +| `setSoapHeaders(?array $headers)` | List of `\SoapHeader` sent with each call | +| `setSoapClient(\SoapClient $client)` | Inject an already built `SoapClient` (e.g. a subclass), instead of letting the client build it from the WSDL and the options | + +Examples +-------- + +* Client of the public [CountryInfoService](http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso) + (used by the [cookbooks](../index.md#cookbooks)) + - `features` is a `SoapClient` constructor option, so it is set in `$options`. The `!php/const` YAML tag is needed + to get the value of the PHP constant (a plain `SOAP_SINGLE_ELEMENT_ARRAYS` would be a string) + - `SOAP_SINGLE_ELEMENT_ARRAYS` returns an array even when a list contains a single element + +```yaml +# config/services.yaml +services: + app.cleverage_soap_process.client.country_info: + class: CleverAge\SoapProcessBundle\Client\Client + arguments: + $logger: '@logger' + $code: 'country_info' + $wsdl: 'http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL' + $options: + trace: true + exceptions: true + cache_wsdl: !php/const WSDL_CACHE_BOTH + features: !php/const SOAP_SINGLE_ELEMENT_ARRAYS + tags: + - { name: cleverage.soap.client } +``` + +With `autowire: true` in the `_defaults` of your `config/services.yaml`, the `$logger` argument can be omitted. + +* Client in non-WSDL mode, with HTTP basic authentication + +```yaml +# config/services.yaml +services: + app.cleverage_soap_process.client.legacy_erp: + class: CleverAge\SoapProcessBundle\Client\Client + arguments: + $logger: '@logger' + $code: 'legacy_erp' + $wsdl: ~ + $options: + location: '%env(ERP_SOAP_LOCATION)%' + uri: 'urn:erp' + login: '%env(ERP_SOAP_LOGIN)%' + password: '%env(ERP_SOAP_PASSWORD)%' + tags: + - { name: cleverage.soap.client } +``` + +* Custom client, overriding the call of one SOAP method + - `Client::call()` looks for a `soapCall` method (`ucfirst()` of the method name) and uses it instead of + the generic call, which allows to prepare the arguments or post-process the result of one method + +```php + $input + */ + protected function soapCallCountryName(array $input): mixed + { + $result = $this->doSoapCall('CountryName', $input); + + return false === $result ? false : $result->CountryNameResult; + } +} +``` + +Notes +----- + +* Codes must be unique: registering two clients with the same code throws an `\UnexpectedValueException` + (`Client is already defined`) when the registry is instantiated, i.e. when the first SOAP task or + transformer service is built. +* Using a code that is not registered throws a `CleverAge\SoapProcessBundle\Exception\MissingClientException` + (`No Soap client with code : `). +* The `SoapClient` is created lazily, on the first call, and then reused: the WSDL is only loaded once per client. + A WSDL that cannot be loaded throws a `SoapFault` at this moment, which is not caught by the client. +* The `trace` option is always forced to `true` when the `SoapClient` is created, so that the last request and + response are always available (they are added to the log context of a failed call). Setting `trace: true` in + `$options` additionally logs them at `debug` level after each successful call. +* Each generic call is logged at `notice` level (`Soap call '' on ''`). When a `SoapFault` is thrown + (i.e. with `exceptions: true`, the default of `SoapClient`), the error is logged at `alert` level, with the last + request and response in the log context, and `false` is returned instead of throwing. With `exceptions: false`, + `SoapClient` returns the `SoapFault` object, which is then returned as a regular result. +* A client service is shared by default: the SOAP call options and headers set by a [RequestTask](tasks/request_task.md) remain + set on the client for the following calls, including calls made by the + [RequestTransformer](transformers/request_transformer.md). diff --git a/docs/reference/tasks/_template.md b/docs/reference/tasks/_template.md index ed1d4a5..919390a 100644 --- a/docs/reference/tasks/_template.md +++ b/docs/reference/tasks/_template.md @@ -1,44 +1,47 @@ TaskName ======== -_Describe main goal an use cases of the task_ +_Describe the main goal and use cases of the task._ Task reference -------------- -* **Service**: `ClassName` +* **Service**: `Fully\Qualified\ClassName` +* **Iterable task** _(only if it implements `IterableTaskInterface`)_ +* **Blocking task** _(only if it implements `BlockingTaskInterface`)_ +* **Flushable task** _(only if it implements `FlushableTaskInterface`)_ Accepted inputs --------------- -_Description of allowed types_ +_Description of allowed types, or "Input is ignored"._ Possible outputs ---------------- -_Description of possible types_ +_Description of possible types._ Options ------- -| Code | Type | Required | Default | Description | -| ---- | ---- | :------: | ------- | ----------- | -| `code` | `type` | **X** _or nothing_ | `default value` _if available_ | _description_ | +| Code | Type | Required | Default | Description | +|--------|--------|:--------:|-----------------|---------------| +| `code` | `type` | **X** | `default value` | _description_ | + +_If the task has no option, replace the table with "This task has no option."._ Examples -------- -_YAML samples and explanations_ - * Example 1 - details - - details - + ```yaml # Task configuration level code: - service: '@service_ref' - options: - a: 1 - b: 2 + service: '@Fully\Qualified\ClassName' + options: + a: 1 + b: 2 + outputs: [next_task] ``` diff --git a/docs/reference/tasks/request_task.md b/docs/reference/tasks/request_task.md index 028cf06..4b9ce58 100644 --- a/docs/reference/tasks/request_task.md +++ b/docs/reference/tasks/request_task.md @@ -1,77 +1,98 @@ RequestTask -=============== +=========== -Call a SOAP Request and get result. +Call a method of a SOAP service, through a registered [client](../client.md), and output the result. Task reference -------------- -* **Client Service Interface**: `CleverAge\SoapProcessBundle\Client\ClientInterface` -* **Task Service**: `CleverAge\SoapProcessBundle\Task\RequestTask` +* **Service**: `CleverAge\SoapProcessBundle\Task\RequestTask` Accepted inputs --------------- -`array`: list of of the arguments to pass as `$args` to the [SoapClient::__soapCall()](https://www.php.net/manual/en/soapclient.soapcall.php) method. +`array`: list of the arguments passed as `$args` to +[SoapClient::__soapCall()](https://www.php.net/manual/en/soapclient.soapcall.php). An empty input (`null`, `[]`, …) +calls the method without argument. + +For a document/literal service, the arguments of the method are usually wrapped in a single array, e.g. +`{ parameters: { sCountryISOCode: FR } }` (in WSDL mode, the keys of the first level are ignored, only the order +matters). Possible outputs ---------------- -`false|stdClass|array`: the result of the soap call. +`mixed`: the result of the SOAP call, usually a `stdClass` (or an array of `stdClass`) built by `SoapClient` from the +response. + +`false` when the call failed (`SoapFault`), see Notes. Options ------- -### For Client - -| Code | Type | Required | Default | Description | -|-----------------|------------------|:---------:|---------|-------------------------------------------------------------------------------| -| `code` | `string` | **X** | | Service identifier, used by Task client option | -| `wsdl` | `string or null` | | | URI of a WSDL file describing the service | -| `options` | `array` | | [] | An associative array specifying additional options for the SOAP client. | -| `options.trace` | `boolean` | | true | Captures request and response information. Add debug informations into logger | +| Code | Type | Required | Default | Description | +|---------------------|---------------|:--------:|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `client` | `string` | **X** | | Code of the [client](../client.md) to use | +| `method` | `string` | **X** | | Name of the SOAP method to call | +| `soap_call_options` | `array\|null` | | `null` | `$options` of [SoapClient::__soapCall()](https://www.php.net/manual/en/soapclient.soapcall.php): `location`, `uri`, `soapaction` | +| `soap_call_headers` | `array\|null` | | `null` | Headers sent with the request, as a list of `header name => header options` (see below), converted to [SoapHeader](https://www.php.net/manual/en/class.soapheader.php) | -Calls setter methods in `CleverAge\SoapProcessBundle\Client\ClientInterface` to add more options. +Each header of `soap_call_headers` has the following options: -### For Task - -| Code | Type | Required | Default | Description | -|-------------------------------|-----------------------------------------------|:----------------------------------------:|---------|---------------------------------------------------------------------| -| `client` | `string` | **X** | | `ClientInterface` service identifier | -| `method` | `string` | **X** | | The name of the SOAP function to call. | -| `soap_call_options` | `array or null` | | null | An associative array of options to pass to the client. | -| `soap_call_headers` | `array or null` resolved as \SoapHeader array | | null | An array of headers to be sent along with the SOAP request. | -| `soap_call_headers.namespace` | `array or null` | **X** if `soap_call_headers` is not null | | The namespace of the SOAP header element. | -| `soap_call_headers.data` | `array or null` | **X** if `soap_call_headers` is not null | | A SOAP header's content. It can be a PHP value or a SoapVar object. | +| Code | Type | Required | Default | Description | +|-------------|----------|:--------:|---------|------------------------------------------------------------------------------------| +| `namespace` | `string` | **X** | | Namespace of the SOAP header element | +| `data` | `mixed` | **X** | | Content of the SOAP header: a scalar, an array (converted to a structure by PHP) … | Examples -------- -### Client +* Call a method without argument ```yaml -services: - app.cleverage_soap_process.client.domain_sample: - class: CleverAge\SoapProcessBundle\Client\Client - bind: - $code: 'domain_sample' - $wsdl: 'https://domain/sample.wsdl' - $options: - trace: true - exceptions: true - calls: - - [ setSoapOptions, [ { features: SOAP_SINGLE_ELEMENT_ARRAYS} ] ] - tags: - - { name: cleverage.soap.client } -``` - -### Task +# Task configuration level +list_countries: + service: '@CleverAge\SoapProcessBundle\Task\RequestTask' + options: + client: country_info + method: FullCountryInfoAllCountries + outputs: [transform] +``` + +* Call a method with the arguments built by a previous task, sending an authentication header and forcing the + endpoint URL ```yaml # Task configuration level -code: +get_order: service: '@CleverAge\SoapProcessBundle\Task\RequestTask' + error_strategy: skip options: - client: domain_sample - method: 'MethodToCall' + client: legacy_erp + method: GetOrder + soap_call_options: + location: 'https://erp.example.com/soap/orders' + soap_call_headers: + AuthHeader: # Name of the header element + namespace: 'urn:erp' + data: + Username: '%env(ERP_SOAP_LOGIN)%' + Token: '%env(ERP_SOAP_TOKEN)%' + outputs: [transform] + error_outputs: [log_error] ``` + +Notes +----- + +* When the call fails (the client returns `false`, see [client](../client.md)), the task: + - logs an error `Empty resultset for query`, with the options and the last request and response in the log context + - sets `false` as error output, so the `error_outputs` tasks receive `false` (not the input of the task) + - with `error_strategy: skip`, skips the `outputs` tasks + - with `error_strategy: stop`, stops the process. No exception is set on the state, so the process is **not** + marked as failed and the console command does not return an error code +* An exception thrown by the client (e.g. a `SoapFault` when the WSDL cannot be loaded, or a + `MissingClientException` for an unknown `client`) is handled as usual by the `error_strategy`. +* `soap_call_options` and `soap_call_headers` are set on the client each time the task is executed, including when + they are `null`: they overwrite the values configured with `setSoapOptions` / `setSoapHeaders` in the client + service definition. diff --git a/docs/reference/transformers/_template.md b/docs/reference/transformers/_template.md new file mode 100644 index 0000000..74c4b57 --- /dev/null +++ b/docs/reference/transformers/_template.md @@ -0,0 +1,42 @@ +TransformerName +=============== + +_Describe the main goal and use cases of the transformer._ + +Transformer reference +--------------------- + +* **Service**: `Fully\Qualified\ClassName` +* **Transformer code**: `code` + +Accepted inputs +--------------- + +_Description of allowed types._ + +Possible outputs +---------------- + +_Description of possible types._ + +Options +------- + +| Code | Type | Required | Default | Description | +|--------|--------|:--------:|-----------------|---------------| +| `code` | `type` | **X** | `default value` | _description_ | + +_If the transformer has no option, replace the table with "This transformer has no option."._ + +Examples +-------- + +* Example 1 + - details + +```yaml +# Transformer options level +code: + option1: a + option2: b +``` diff --git a/docs/reference/transformers/request_transformer.md b/docs/reference/transformers/request_transformer.md new file mode 100644 index 0000000..a4296e2 --- /dev/null +++ b/docs/reference/transformers/request_transformer.md @@ -0,0 +1,73 @@ +RequestTransformer +================== + +Call a method of a SOAP service, through a registered [client](../client.md), with the input value as arguments, and +return the result. Unlike the [RequestTask](../tasks/request_task.md), it can be used anywhere a transformer is +accepted, e.g. to enrich a single property inside a `mapping`. + +Transformer reference +--------------------- + +* **Service**: `CleverAge\SoapProcessBundle\Transformer\RequestTransformer` +* **Transformer code**: `soap_request` + +Accepted inputs +--------------- + +`array`: list of the arguments passed as `$args` to +[SoapClient::__soapCall()](https://www.php.net/manual/en/soapclient.soapcall.php) (see the +[RequestTask](../tasks/request_task.md#accepted-inputs)). Any other type throws an `\UnexpectedValueException` +(`Expecting an array of value`). + +Possible outputs +---------------- + +`mixed`: the result of the SOAP call, usually a `stdClass` built by `SoapClient` from the response. + +`false` when the call failed (`SoapFault`), see Notes. + +Options +------- + +| Code | Type | Required | Default | Description | +|----------|----------|:--------:|---------|-------------------------------------------| +| `client` | `string` | **X** | | Code of the [client](../client.md) to use | +| `method` | `string` | **X** | | Name of the SOAP method to call | + +Examples +-------- + +* Replace an ISO country code by the country name + - input: `FR` + - the two [wrapper](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/wrapper_transformer.md) + transformers build the arguments `{ parameters: { sCountryISOCode: FR } }` + - the [property_accessor](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/property_accessor_transformer.md) + transformer extracts the value from the `stdClass` response + - output: `France` + +```yaml +# Transformer options level +wrapper: + wrapper_key: sCountryISOCode +wrapper#2: + wrapper_key: parameters +soap_request: + client: country_info + method: CountryName +property_accessor: + property_path: CountryNameResult +``` + +Notes +----- + +* The transformer does not handle any SOAP call option or header: the values currently set on the client are used + (from the `calls` of the client service definition, or from the last [RequestTask](../tasks/request_task.md) + executed with the same client). +* A failed call is logged by the [client](../client.md) and returns `false`, without any exception: check the result + (or chain a transformer that fails on `false`, like `property_accessor` above) if the process must not go on + silently with a `false` value. +* One SOAP call is made each time the transformer is applied: to avoid calling the service several times with the same + arguments, wrap it in the + [cached](https://github.com/cleverage/process-bundle/blob/main/docs/reference/transformers/cached_transformer.md) + transformer.