Adding a custom action
Rules can fire one or more actions. An action is responsible for sending form data into third party system.
Form Builder provides a number of standard actions, such as:
- Creating a case in Jadu Connect
- Sending an email
- Making a Payment
If you wish to integrate your form with another system, you can create a custom action to handle this.
In order to use an action, Administrators must first build a template. This maps form data, such as variables or form data, into the fields expected by the third party system. Actions therefore have two main tasks:
- Defining how templates should be built
- Sending the data of a given template to the third party system
Deciding which kind of template we need
Jadu Central provides two styles for templates:
-
Simple Mapped
This is useful when the fields to be mapped can never change. When building a template, users will see a simple list of the fields you define.
-
Progress Mapped
This is useful when the fields to be mapped change depending on user input. When building a template, users will see a step-by-step wizard, where each step's field may change based on the user's selections at previous steps.
Example: Sending simple data
Imagine we have a form which needs to submit data to a third party system, called ReceiptingSystem. ReceiptingSystem provides an endpoint accepting three fields (Field A, Field B & Field C), which returns a reference, e.g. REF001, or 'ERR' on failure. This is the most common type of form integration, and is straightforward to build in Jadu Central.
The most appropriate template type is Simple Mapped, as the fields to be mapped are consistent. To use this style of template, we need to create a class at CustomXFormsProBundle/Rules/Actions/ReceiptingSystemActionType.php
which extends SimpleMappedActionType
.
namespace Jadu\Custom\CustomXFormsProBundle\Rules\Actions;
use Jadu\XFormsPro\Form\Rules\Actions\SimpleMappedActionType;
class ReceiptingSystemActionType extends SimpleMappedActionType
{
}
Next, we define some of the abstract's functions:
/**
* Should return the fields to offer mappings for.
*
* @param array $data data populated at previous steps, indexed by field name, if available
*
* @return array
*/
public function getFieldsToMap($data)
{
return [
'fieldA' => [
'options' => self::MAPPING_TYPE_CORE,
'label' => 'Field A',
'help' => 'Data to send in Field A',
'required' => true,
],
'fieldB' => [
'options' => self::MAPPING_TYPE_CORE,
'label' => 'Field B',
'help' => 'Data to send in Field B',
'required' => false,
],
'fieldC' => [
'options' => self::MAPPING_TYPE_CORE,
'label' => 'Field C',
'help' => 'Data to send in Field C',
'required' => false,
],
];
}
/**
* Should return an array of errors, indexed by field name.
* Validates mappings based on the request. Can be overridden if necessary.
*
* @param Request $request
*
* @return string[]
*/
public function validateMappedFields($request)
{
// Abstract handles required fields validation
// nothing extra needed here
return [];
}
Defining fields to map
getFieldsToMap
defines an array of fields that should display to the Administrator. Each field name is determined by its key in this array. Each field is defined as its own array, with the following possible keys:
- options - (Required) the type of the field
- label - (Required) the label of the field when displayed for mapping
- help - Help text to display to the Administrator
- required - Whether this field must be mapped, or can be left empty
- flags - An array of settings that change the behaviour of field
- evaluationType - Useful for defining the type of mapping that is saved when the mapping is a standard dropdown. Defaults to static.
- retraceFunction - Can be used to retrace a mapping. Specifies the name of a public method in this class, which will receive the mapping value as a parameter, and is responsible for translating it to a user friendly string for displaying in the Rules UI.
Supported values for options
are:
| Type | Description |
|-:-|-:-|
| (an array) | Dropdown with set of defined options |
| self::MAPPING_TYPE_CORE
| A Select2 of questions, variables and logics from the form. Also supports manual text entry |
| self::MAPPING_TYPE_TEXT
| A simple text field |
| self::MAPPING_TYPE_TEXTAREA
| A simple text area |
| self::self::MAPPING_TYPE_EDITOR
| A rich text editor |
| self::MAPPING_TYPE_BOOLEAN
| A enabled/disabled switch |
Supported values for flags
are:
| Type | Description |
|-:-|-:-|
| self::MAPPING_OPTION_BUTTON_GROUP
| When used in conjunction with a standard dropdown, displays options as a button group rather than a select box |
| self::MAPPING_OPTION_PLACEHOLDERS
| When used in conjunction with text or textarea, adds a button to insert variable placeholders into the field |
| self::MAPPING_OPTION_SELECT2
| When used in conjunction with a standard dropdown, displays as a Select2 with search box |
| self::MAPPING_OPTION_MULTIPLE
| When used in conjunction with a standard dropdown, displays a dropdown that allows selecting more than one option |
Supported values for evaluationType
are:
| Type | Description |
|-:-|-:-|
| FormDataMappingInterface::TYPE_STATIC
| Mapping will be evaluated to the exact textual value entered. |
| FormDataMappingInterface::TYPE_QUESTION_IDENTIFIER
| Mapping will be evaluated to a Jadu\XFormsPro\Form\Questions\QuestionIdentifier
object. |
In order for TYPE_QUESTION_IDENTIFIER
to work correctly, the options that are loaded into the mapping must have a value of (pageID)-(section name)-(question name)
, e.g. 1-s1231224cabaaa223-q134635cacacbad232
.
It's possible to use specific combinations to build a complex mapping input. For instance, to collect a mapping of multiple static text values:
'fieldA' => [
'options' => [
'option1' => 'Option 1',
'option2' => 'Option 2',
'option3' => 'Option 3'
]
'label' => 'Field A',
'help' => 'Data to send in Field A',
'required' => true,
'evaluationType' => FormDataMappingInterface::TYPE_STATIC,
'flags' => [
self::MAPPING_OPTION_SELECT2,
self::MAPPING_OPTION_MULTIPLE,
]
],
This will render a select2, where it is possible to select one or more values, e.g. 'Option 1' & 'Option 3'. When accessing the data in order to run the action, our fieldA
mapping will be an array, containing the strings option1
and option3
.
The execute() method
The final method to declare in our class is execute
, which will pass data to ReceiptingSystem. It has two parameters: the user form, and an array of mappings. This array contains proper values, against the keys we specified when defining the fields in getFieldsToMap
.
Example:
An Administrator maps:
fieldA
to Question 1 on Page 1fieldB
to Question 2 on Page 1fieldC
to Question 3 on Page 1
User answers:
Red
to Question 1 on Page 1Blue
to Question 2 on Page 1Yellow
to Question 3 on Page 1
The mappings array passed to execute
will be as follows:
[
'fieldA' => 'Red',
'fieldB' => 'Blue',
'fieldC' => 'Yellow',
]
We can implement execute as follows:
/**
* Takes an array of mappings and carries out the integration.
*
* @param array $mappings
* @param UserForm $userForm
*
* @return string the result
*/
public function execute($mappings, $userForm)
{
$log = $this->getNewLog($userForm->getId());
$log->setRequest(
json_encode($mappings)
);
$log->setRequestTime(new \DateTime());
$result = $this->receiptingSystemService->submitData(
$mappings['fieldA'],
$mappings['fieldB'],
$mappings['fieldC']
);
$log->setResponseTime(new \DateTime());
$log->setResult($result);
if ($result != 'ERR') {
$log->setResponse('Successfully sent data to ReceiptingSystem');
} else {
$log->setError('Unable to submit data to ReceiptingSystem');
$log->setResponse('Error');
}
$this->writeLog($log);
return $result;
}
The return statement means this action will return its result, which can be passed into subsequent actions in the rule using (action chaining)[chaining.md].
Determining whether the action is enabled
/**
* Whether to show the action.
*
* @return bool
*/
public function enabled()
{
return true;
}
We can define enabled
in our class. This should return true if the action is enabled, or false otherwise. This can be used to test is the server can connect to the third party system.
Registering the action
We then need to register the action with Jadu Central. To do this, add the following at CustomXFormsProBundle/Resources/config/services.yml
:
services:
custom_xfp.rules.action.receipting_system:
class: Jadu\Custom\CustomXFormsProBundle\Rules\Actions\ReceiptingSystemActionType
arguments:
- "@doctrine.orm.entity_manager"
tags:
- { name: xfp.rule_action, system: 'ReceiptingSystem', label: 'Submit Data' }
The services:
line is only needed once, at the beginning of the services.yml
file.
Actions are grouped by system
. This means it is possible to create multiple different actions for the same system, by specifying different values in label
.
The use of the tag is what tells Jadu Central that this class can be used as an action. Clear the Symfony cache of your development environment.