Problem/Motivation

Currently gateways are implemented as separate modules with all the code implemented in the foo.module file and callbacks defined in the foo_gateway_info() function. We want to change this approach and implement gateways as D8 Plugins. There are several good reasons to do this:

  1. There is a lot of boiler-plate code and repetition which would be eliminated by implementing gateways as objects, making it easier to write gateways. DX++
  2. Gateway module code is only needed when sending sms via that gateway, but currently is loaded at every page load and kept in memory causing memory bloat. As objects, all that code is lazy-loaded only when needed.
  3. A common interface can be enforced to ensure required methods are implemented.
  4. More than one gateway can be implemented by a single module - less module overhead.
  5. One single gateway plugin can be used to implement multiple gateways.

All the above are the reasons for D8 in the first place and right now is the best practice architecturally.

Proposed resolution

  1. Implement a gateway plugin manager in sms module that uses AnotatedDiscovery to find sms gateway plugins
  2. Implement a base class for gateway plugins that contains all the basic functionality of sms gateways
  3. Retain the current hook_gateway_info based gateways for backward compatibility and convert them to gateway objects

Remaining tasks

Patch
Reviews / Testing
Commit

User interface changes

  1. The SMS Default gateway selection page now has checkboxes for enabling / disabling each gateway. Selecting a disabled gateway as default in the UI automatically enables it. But the default gateway cannot be disabled.
  2. Configurable gateways have to be created as they don't exist by default. Non-configurable gateways exist by default once the plugin exists.

API changes

  1. Added a GatewayManagerInterface to represent services that manage sms gateways.
  2. Added a GatewayManager class implementing GatewayManagerInterface and the corresponding plugin.manager.sms_gateway service.
  3. Added the SmsGateway plugin annotation type for annotating gateway plugins.
  4. Added a GatewayInterface to represent SMS Gateways and implemented a GatewayBase base class.
  5. Moved the log gateway to a LogGateway plugin class.
  6. Added a SmsMessageProviderInterface to represent sms messaging providers.
  7. Added a default SmsMessageProviderInterface implementation called DefaultSmsProvider and the corresponding sms_provider.default service, which does basically what the sms_send(), sms_incoming(), sms_receipt(), etc. used to do. More complex implementations of SMS messaging including multiple-gateway routing and load-balancing systems can subclass this default implementation.
  8. Added a DeliveryReportController for receiving and handling delivery reports.
  9. Added a SmsMessageResultInterface to represent the report / result that is returned by sms gateways for sms send requests. A default implementation SmsMessageResult is also added.

Comments

almaudoh’s picture

Issue summary: View changes
almaudoh’s picture

StatusFileSize
new66.18 KB

First go at this. Tests not included. Also included a BC-shim to allow this patch to work with existing gateways.

almaudoh’s picture

Status: Active » Needs review
StatusFileSize
new67.36 KB

Re-roll

almaudoh’s picture

Priority: Normal » Major
Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 3: gateway_plugins-reroll-2292319-3.patch, failed testing.

almaudoh’s picture

Issue summary: View changes
Status: Needs work » Needs review
StatusFileSize
new80.98 KB
new90.25 KB

The first version did not allow multiple instances of the same type of gateway plugin to be instantiated.

This iteration adds that, making it possible to create a generic gateway that only needs to be configured e.g. https://www.drupal.org/project/sms_simplegateway so only one plugin for multiple gateways.

Also introduced the possibility to enable and disable gateways. This is useful for more advanced use-cases where multiple gateways could be used. Selecting a disabled gateway as default in the UI automatically enables it.

Also fixed some of the test fails, cleaned up functions and moved them to the correct classes, renamed classes and services to more appropriate names.

Status: Needs review » Needs work

The last submitted patch, 6: gateway_plugins-2292319-6.patch, failed testing.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new92.51 KB
new17.96 KB

Fixing the test fails. Corrected hook implementations and some renames.

almaudoh’s picture

Issue summary: View changes
Status: Needs review » Postponed
Parent issue: » #2509560: [Meta] Revamp SMS Framework in D8 - improve flexibility and scalability

Due to the size of this patch, I have split off the aspect of implementing sms messaging providers as services into a different issue and posted a patch there. Will follow through with that aspect and then continue with this when that issue lands. I have also created a meta issue (now called Plan issue) to help track such refactoring efforts #2509560: [Meta] Revamp SMS Framework in D8 - improve flexibility and scalability

almaudoh’s picture

almaudoh’s picture

Status: Postponed » Needs work

#2509566: Convert sms_send() into a service is in so we can now continue work on this...

Edit: corrected wrong issue link.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new77.41 KB

Re-rolled.

Status: Needs review » Needs work

The last submitted patch, 13: convert_sms_gateways-2292319-13.patch, failed testing.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new70.9 KB

Rerolled.

almaudoh’s picture

  1. +++ b/modules/sms_track/sms_track.module
    @@ -60,17 +61,17 @@ function sms_track_sms_send(SmsMessageInterface $sms, array $options, $gateway)
    +function sms_track_sms_send_process($op, SmsMessageInterface $sms, array $options, GatewayInterface $gateway, $result) {
    

    Type-hint $result as array

  2. +++ b/sms.module
    @@ -128,148 +129,78 @@ function sms_incoming($number, $message, array $options = array()) {
     function sms_gateways($op = 'gateways', $gateway = NULL) {
    ...
    +      foreach ($gateway_manager->getAvailableGateways() as $id => $gw) {
    ...
    +      $gw = $gateway_manager->getGateway($gateway);
    

    Might make more sense to name the function argument $gateway_id and then $gw can be correctly named $gateway

  3. +++ b/sms.routing.yml
    @@ -62,3 +70,10 @@ sms.bootstrap_admin:
    +
    +sms.delivery_report:
    +  path: '/sms/deliveryreport/{gateway_id}'
    +  defaults:
    +    _controller: '\Drupal\sms\DeliveryReportController::acknowledgeDelivery'
    +  requirements:
    +    _access: 'TRUE'
    
    +++ b/src/Annotation/SmsGateway.php
    @@ -0,0 +1,39 @@
    diff --git a/src/DeliveryReportController.php b/src/DeliveryReportController.php
    
    diff --git a/src/DeliveryReportController.php b/src/DeliveryReportController.php
    new file mode 100644
    
    new file mode 100644
    index 0000000..fa54056
    
    index 0000000..fa54056
    --- /dev/null
    
    --- /dev/null
    +++ b/src/DeliveryReportController.php
    
    +++ b/src/DeliveryReportController.php
    +++ b/src/DeliveryReportController.php
    @@ -0,0 +1,69 @@
    
    @@ -0,0 +1,69 @@
    +<?php
    +
    +/**
    + * @file
    + * Contains \Drupal\sms\DeliveryReportController
    + */
    +
    +namespace Drupal\sms;
    +
    

    Delivery reports is strictly not in this scope. Would make the patch easier to review if this is removed to another issue...

  4. +++ b/src/Provider/DefaultSmsProvider.php
    @@ -109,12 +119,12 @@ class DefaultSmsProvider implements SmsProviderInterface {
    +  protected function postProcess(SmsMessageInterface $sms, array $options, GatewayInterface $gateway, $result) {
    

    Type-hint $result as array

almaudoh’s picture

StatusFileSize
new3.28 KB
new71.11 KB

Fixed comments in #16.
#16.2: opened #2542790: Implement API for delivery reports for SMS Gateways
Also opened #2542784: Add unit tests for SMS Gateway and Gateway Manager to add unit tests for the new classes.

With those follow-ups I think this can go in.

almaudoh’s picture

  1. +++ b/src/Gateway/GatewayManager.php
    @@ -0,0 +1,220 @@
    +        // @todo Throw exception here???
    +//        throw new \InvalidArgumentException(sprintf('Gateway %s configured without a plugin id.', $id));
    

    ??? Exception should be thrown. And a test should be added for this in the follow-up issue

  2. +++ b/src/Plugin/Gateway/LogGateway.php
    @@ -0,0 +1,56 @@
    +   *
    +   * Log sms message to drupal watchdog().
    

    Comment should be in the body of the function. And logger is the new name now.

Status: Needs review » Needs work

The last submitted patch, 17: gateway_plugins-2292319-17.patch, failed testing.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new6.65 KB
new70.94 KB

1. Some more clean up.
2. Reverted the array type-hinting, causing problems. Opened #2542866: Clarify the API for message results after sms_send() to take care of that.
3. Implemented default methods in GatewayBase

Status: Needs review » Needs work

The last submitted patch, 20: gateway_plugins-2292319-20.patch, failed testing.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new22.02 KB
new76.38 KB

Fixed test fails. Made the implementation of HookGateway more robust and seamless with existing plugin architecture.

Status: Needs review » Needs work

The last submitted patch, 22: gateway_plugins-2292319-22.patch, failed testing.

almaudoh’s picture

+++ b/src/Tests/SmsFrameworkWebTest.php
@@ -7,16 +7,32 @@
+  ¶

Remove extra space

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new1.59 KB
new76.57 KB

Test base classes should be abstract.

almaudoh’s picture

Status: Needs review » Needs work

The last submitted patch, 25: gateway_plugins-2292319-25.patch, failed testing.

almaudoh’s picture

Status: Needs work » Needs review
StatusFileSize
new6.97 KB
new76.75 KB

  • almaudoh committed 32cf8ea on 8.x-1.x
    Issue #2292319 by almaudoh: Convert SMS Gateways into D8 Plugins
    
almaudoh’s picture

Status: Needs review » Fixed

Committed and pushed to 8.x-1.x

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.