New hook system with hook_sms() for 2.x

derhasi - April 23, 2009 - 12:31
Project:SMS Framework
Version:6.x-2.x-dev
Component:Core Framework
Category:feature request
Priority:normal
Assigned:Unassigned
Status:needs review
Description

For additional handling of sending messages, the framework should be extended with additional hook-ops.

Some reasons for that were:
* sms validation (check length of message, valid recipients,...)
* Flexible gateway selection per user/scope ( a site could change the gateway due to receiving country)
* Flexible gateway options per user (site could give user opportunity to use its own account)
* SMS limit per user/node/time/group/role/...
* message conversion ( e.g. adding flexible links)
* logging/storage of sent messages
* increase/decrease userpoints (when messaging will be part of a premium account, left messages could be decreased)

In my to come implementation for smscreator there are a lot of modules integrated that need pre and post processing. So for providing this gateway for sms framework, and the other parts independently on the gateway, we should add such additional hooks to the framework.

This would ease integration of additional gateway-independent message handling.

So sms_send() could look like this

*retrieve default gateway
*call hook_send_sms:PRE PROCESS
  **params by ref: $number, $message, $options, $gateway
  **return: ERROR messages (on error skip message sending)
*call hook_send_sms:PROCESS
  **params by ref: $number, $message, $options, $gateway
  **return: <none>
*call GATEWAY SEND function
*call hook_send_sms:POST PROCESS
*call ERROR handling

#1

Will White - April 27, 2009 - 16:50

Hi Derhasi,
Thanks for the request. Looks like what you need could probably with drupal_alter().

Something like:

drupal_alter('sms_send', $message, 'pre process');
drupal_alter('sms_send', $message, 'process');
drupal_alter('sms_send', $message, 'post process');

We would just have to come up with a standard way to store the "message" in a structured array. This would probably work:

$message['number'] => '5555555555';
$message['body'] => 'Body text...';
$message['options'] => <additional options as defined by the gateway>;

#2

derhasi - April 29, 2009 - 21:07

I agree, using a general $message object would be the best method, so any module can add its own necessary information. Besides I also suggest a $gateway object, that will contain the $gateway->type and additional options, like ->uri / ->user / -> password.

So $message could contain

->message
->sender
->recipient
->gateway (object)
->type
->direction (outgoing / incoming)
->...

If this approach should be realized, we should think about legacy to existing sms.module implementations.

#3

derhasi - May 2, 2009 - 16:51
Version:6.x-1.x-dev» 6.x-2.x-dev

Is 2.x-dev the place for adding this functionality?

#4

derhasi - May 5, 2009 - 17:54

I would start tonight with writing some changes to 2.x-dev implementing send:pre process/process/past process

My suggestion for the hook-ops would be:

pre send process
- collect all information for $message (except gateway dependent)
- validate message in basic

send process
- will be performed before the original _send-function of the given gateway
- will only change $message->gateway - information
- will validate only gateway-dependent cases (like, user may not send via gateway A, but may send via gateway B)

post send process
- will handle suffescully sent or failed messages
- may save a message to database
- may fire status messages
- may create new content (like nodes)
- ...

My suggestion for a minimum $message-object would be:

$message ->
type (string)
- type definition (e.g. by module) - like "sms_blast", "node_link", ...
mid (int)
- serial for outgoing AND incoming messages
direction (string)
- either 'out'(sending) or 'in'(receiving)
recipient (integer?)
- the international number for messages (without +, without whitespaces)
sender (integer?)
- the international number of the sender
message (string)
- the to send message
gateway (object)
- the gateway object should at least contain the 'type' attribute

Should be introduced a new hook for legacy reasons?
(1) hook_sms($op,$message)
(2) hook_sms_alter($message,$op)
(3a) hook_sms_incoming($op,$message)
(3b) hook_sms_outgoing($op,$message)

I would favourize (1), so we could secure only gateway may be edited (and maybe recipient & sender).

#5

Will White - May 5, 2009 - 19:02

Hi derhasi,
Sorry for the delay on this. This looks good. Yes these changes should go into 2.x. Will these changes alter the parameters in sms_send() at all. I think we should avoid that if possible because there would be quite a bit of legacy code to update.

We should remove the word 'process' from each of the $ops and instead just have 'pre send', 'send', and 'post send'.

How will we determine $message->type?

Thanks for your work on this!

#6

derhasi - May 5, 2009 - 20:53

I would propose that any module that uses sms.module to send an sms has to define ->type itself, like node_save(), that has to have a $node->type defined.

For legacy I would add the opportunity to internally keep opportunity (1)sms_send($number,$message,$options=array()) but define it as (2)sms_send($message,$a1 = NULL, $a2 = NULL) and switch to (1) if $a1 is given as a string. $message->type then would be set to 'legacy'.

hook_sms($op, $message)

OPs:

  • pre send
  • send
    may call hook_sms_send via sms_legacy_sms("send",$message) in a sms_legacy.module
    after that op the gateway_send will be called
  • post send
  • ---
  • pre receive
    may call hook_sms_incoming("pre process") via sms_legacy_sms("pre receive,$message) in a sms_legacy.module
  • receive
    may call hook_sms_incoming("process") via sms_legacy_sms("receive,$message) in a sms_legacy.module
  • post receive
    may call hook_sms_incoming("post process") via sms_legacy_sms("post receive,$message) in a sms_legacy.module

There could be a sms_gateway.module, that will add the default gateway in sms:pre send, if there's none given. But for the first steps, I try to use the given gateway handling.

If you have any suggestions, you can contact me via IRC ;)

#7

derhasi - May 5, 2009 - 22:17
Status:active» needs review

built a first patch on sms.module and sms_legacy.module

AttachmentSize
smsframework-442748-1.patch 5.34 KB
modules/sms_legacy/sms_legacy.module.txt 1016 bytes
modules/sms_legacy/sms_legacy.info 169 bytes

#8

derhasi - May 6, 2009 - 10:23

Changed $message - object to $sms-object to avoid legacy confusion.

Also changed sms_send_log() to fit in new gateway_send.

AttachmentSize
smsframework-442748-2.patch 5.98 KB

#9

derhasi - May 14, 2009 - 11:40

Changed some minor errors (e.g. an error logs were sent falsely).

Applied the patch on the current dev.

AttachmentSize
smsframework-442748.patch 8.42 KB

#10

derhasi - May 14, 2009 - 11:52
Title:Add hook_sms_send ops - pre process, process, post process» New hook system with hook_sms() for 2.x

#11

derhasi - June 4, 2009 - 16:16

recognized a bug in the patch, please replace $sms->text = $a2; with $sms->text = $a1; in sms_send().

I will include it in a patch file soon, after I've discussed with Will about further steps.

#12

Eric_A - September 19, 2009 - 17:42

messaging_message_send($destinations, &$message, $method, $queue = 0) invokes hooks like the ones mentioned above:

'prepare/message_alter', 'render', 'presend', 'queue', 'afterqueue', 'multisend', 'aftersend'.

Perhaps leveraging the Messaging API is a good idea, i.e. declare a dependency on Messaging.

#13

derhasi - September 21, 2009 - 05:09

Yes, implementing messaging as dependency might be a solution. Personally I have to take a closer look on that module.

#14

Eric_A - September 22, 2009 - 21:28

derhasi, looking at the existing bridge messaging_sms.module first might be helpfull. And perhaps a straight dependency on this one rather than on messaging.module?

EDIT:
In which case the hooks that are currently not declared with a callback would have to be added to the callback list in messaging_sms_messaging(), most notably 'prepare callback', 'presend callback', 'aftersend callback'.
SMS Framework would focus on implementations of these hooks. In order to get the hooks invoked all sending would be done through the messaging API: either messaging_message_send($destinations, &$message, $method, $queue = 0) or messaging_message_send_user($account, &$message, $method = NULL, $queue = 0).

 
 

Drupal is a registered trademark of Dries Buytaert.