Skip to content

Developers CustomAdapter

Riccardo Tempesta edited this page Mar 6, 2018 · 5 revisions

For Developers: Writing a custom adapter

MSP Notifier comes with a set of ready adapter provided by msp/module-notifier-core-adapters, but if you need to write your own adapter, you can do it and inject it via DI in the main engine.

Check msp/module-notifier-core-adapters and msp/module-notifier-admin-push-adapter for implementation examples.

Click here to see a full working example.

How to write it

When writing a new adapter you will need to define all the following entities:

  • Adapter Engine
  • Form Modifier for custom parameters
  • Message Validator
  • Parameters Validator

Adapter engine

An adapter engine is a simple class implementing MSP\Notifier\Model\AdapterEngine\AdapterEngineInterface.
This class is responsible for taking a message and delivering it to its destination.

It usually has a single execute public method with the following prototype:

public function execute(string $message, array $params = []): bool

Check Telegram Adapter for a working example.

This method MUST do three fundamental tasks:

  • Deliver the message in $message with configuration parameters from $params
  • Return true in case of success
  • Throw an exception in case of failure

Please note: that this method should never return false. In case of failure it MUST throw an exception.

Parameters

The array parameter in $params comes from your channel's configuration specific parameters.

If we take the Telegram adapter as example we can see it requires, other than the message itself, a token and a chat_id. We will find these parameters directly inside $params as hash:

array(
    'token' => 'my_configured_token',
    'chat_id' => 'my_configured_chat_id'
)

Check Channels section for further information on channels configuration.

See the following chapter to understand how to define adapter specific parameters.

Form Modifier for custom parameters

Every adapter may need additional parameters to be configured, for example an email adapter will require a recipient email as well as a telegram adapter will require a token and a chat_id to deliver its message.

In order to make each adapter independent and 100% flexible, we provided a DataProvider modifier mechanism.

Example:

...
<virtualType name="MSP\Notifier\Ui\DataProvider\Form\Channel\Modifier\Pool">
    <arguments>
        <argument name="modifiers" xsi:type="array">
            <item name="my_custom_adapter" xsi:type="array">
                <item name="class"
                      xsi:type="string">My\NameSpace\Ui\DataProvider\Form\Channel\Modifier\MyAdapter</item>
                <item name="sortOrder" xsi:type="number">1000</item>
            </item>
        </argument>
    </arguments>
</virtualType>
...

Your custom DataProvider class must:

  • Implement MSP\Notifier\Model\Channel\ModifierInterface
  • Define a method getAdapterCode returning the code of the adapter you are referring
  • Define a modifyMeta and modifyData as required by Magento Modifiers.

Your parameters specific list and configuration will be provided as UI Form component structure, from modifyMeta method. Check here to see a working example.

Additional parameters will be automatically added to your channel configuration page when your adapter will be selected.

Example for Telegram adapter:

Validators

You may need to check if your adapters parameters are correctly defined when receiving them for a channel. Params validation can be defined both via VirtualType and concrete class. A set of basic validation is provided with the core package, but you are free to write your own validator.

The following example is a check for required message and parameters:

<virtualType name="My\NameSpace\Model\AdapterEngine\ParamsValidator\MyAdapter\Required"
                 type="MSP\Notifier\Model\AdapterEngine\ParamsValidator\Required">
    <arguments>
        <argument name="requiredParams" xsi:type="array">
            <item name="my_required_paramter" xsi:type="string">my_required_paramter</item>
            <item name="my_other_required_paramter" xsi:type="string">my_other_required_paramter</item>
        </argument>
    </arguments>
</virtualType>
...
<virtualType name="My\NameSpace\Model\AdapterEngine\ValidatorChain\MyAdapter"
             type="MSP\Notifier\Model\AdapterEngine\ValidatorChain">
    <arguments>
        <argument name="messageValidators" xsi:type="array">
            <item name="required"
                  xsi:type="object">MSP\Notifier\Model\AdapterEngine\MessageValidator\Required</item>
            <!-- here you can chain more validators if needed -->
        </argument>
        <argument name="paramsValidators" xsi:type="array">
            <item name="required"
                  xsi:type="object">My\NameSpace\Model\AdapterEngine\ParamsValidator\MyAdapter\Required</item>
            <!-- here you can chain more validators if needed -->
        </argument>
    </arguments>
</virtualType>

Write your own validator

If you need to write your own validator check the following files as examples:

Validators MUST:

  • Implement MSP\Notifier\Model\AdapterEngine\ParamsValidatorInterface or MSP\Notifier\Model\AdapterEngine\MessageValidatorInterface
  • Run validation checks
  • Return true on success
  • Throw an InvalidArgumentException on failure

Putting all the pieces together

AdapterEngineInterface classes should never be called directly (unless you know exactly what you are doing). They are handled by MSP\Notifier\Model\AdapterRepository and therefore injected in it via di.xml.

As final step, you must inject this AdapterEngineInterface and validators inside the adapter class via Magento virtual typing. Once done you can inject the new adapter inside the AdapterRepository.

Example:

<virtualType name="My\NameSpace\Model\Adapter\MyAdapter" type="MSP\Notifier\Model\Adapter">
    <arguments>
        <argument name="engine" xsi:type="object">My\NameSpace\Model\AdapterEngine\MyAdapter</argument>
        <argument name="validatorChain" xsi:type="object">My\NameSpace\Model\AdapterEngine\ValidatorChain\MyAdapter</argument>
        <argument name="code" xsi:type="string">my_custom_adapter</argument>
        <argument name="name" xsi:type="string">My Custom adapter</argument>
        <argument name="description" xsi:type="string">My awesome adapter</argument>
    </arguments>
</virtualType>
...
<type name="MSP\Notifier\Model\AdapterRepository">
    <arguments>
        <argument name="adapters" xsi:type="array">
            <item name="my_custom_adapter" xsi:type="object">My\NameSpace\Model\Adapter\MyAdapter</item>
        </argument>
    </arguments>
</type>
...

This will register a new adapter with code my_custom_adapter that will be automatically available in your adapters list.

Check here for a working example.

Clone this wiki locally