Objective:
Create a hook that allows other modules to react to different events happening in the privatemsg module. My initial need is simply to act after a new private message has been saved.
I've attached a patch. It is based on how the core user module does its hooks. See #324380: Privatemsg: The road to Damascus comment #23.
I have three initial questions at this point.
1. Should this call: privatemsg_module_invoke('send', $message); go farther up in the pm_send() function, say, before data is saved into the database?
2. Should we use options besides 'send' as the first parameter? Examples might be 'before-save', 'after-save' insead of 'send'. That way we could place two calls inside the pm_send() function if needed. If that's just way over-thinking this, please say so.
3. Should the hook code function privatemsg_module_invoke($type, &$array) go lower in the module code, just for orderly organization?
OK, so please take a look at this patch when you have a chance, and post any other suggestions here. Thank you!
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | hook-3.patch | 1.29 KB | nadavoid |
| #3 | hook-2.patch | 1.34 KB | nadavoid |
| hook-1.patch | 1.29 KB | nadavoid |
Comments
Comment #1
litwol commentedComment #2
litwol commentedComment #3
nadavoid commentedAttaching an updated patch.
Also, removed $type from $function().
Comment #4
nadavoid commentedUpdated the example implementation
Comment #5
litwol commentedI like where this is going. lets make a list for all possible places where we would want to place this API.
I would mind having things like 'pre_send' and 'after_send' but we have to be careful not to go overboard.
Comment #6
berdirI already thought about this in #288183: Provide api function for other modules to send messages. and started to implement it (Haven't touched privatemsg.module, only as part of the api functions)
Is there a reason why "drupal_alter('privatemsg_message_insert', $message); wouldn't work ? => http://api.drupal.org/api/function/drupal_alter/6
Looks like re-inventing the wheel for me....
Some ideas I had about hooks (names are from http://api.drupal.org/api/function/hook_nodeapi)
- presave and insert, obvious...
- validate, I think that would be pretty useful, it would allow generic validation routines to hook in like messaging quota. Could also possibly replace/extend the current user block mechanism which is limited to one user at a time.
- delete, would for example allow to remove added tags. But would need that we have to load the message before deleting it...
Comment #7
litwol commentedI am unsure about the differences between our dedicated API and the use of drupal_alter(...).
Immediate thought that jumps out is that drupal_alter is used to alter data, not to signal an action. we could use drupal_alter before executing some privatemsgAPI.
validate op means different things when validating for display or for insert. deletes we have single message delete, thread delete. we have user blocks/unblocks. filter criterion (not sure about this one). what else?
Comment #8
berdirFrom what I understand, drupal_alter is the same as module_invoke_all but with the ability to manipulate the parameters, meaning they are given by reference, that's the same as the current patch is doing it: privatemsg_module_invoke($op, &$array). All the other code of drupal_alter is just a hack to support more than one by reference parameters. If we don't need by reference, why not simply use module_invoke_all ?
I think, validate should be before the data is saved, handling of data to be displayed is already done with the filter.
Comment #9
berdirSome more...
Naming: My idea was privatemsg_element_op, where element is the thing that is worked on... message, thread, maybe others..
- We (aka nbz) are already using "privatemsg_pm_controls", to add actions to messages like delete/block. Works fine, only thing is maybe to rename it, see above
- maybe we would need to have a hook for message and thread deletion, for example privatemsg_message_delete and privatemsg_thread_delete. However, this would make deleting messages quite expensive because it always needs a query to get the message and a second query to check if it is the last of that thread and if yes, to fire the privatemsg_thread_delete hook.
- validate: This is my current implementation for the API I'm working on...
So a module can hook in, validate whatever it want's and return a string or array (multiple errors). If atleast one error is returned, they are logged (remember, this is api, the form validation could display them via form_set_error ) and false is returned. Problem: Either we can't change $message (module_invoke_all), this would make it impossible to remove some recipients for example or we can't return anyting (drupal_alter), but we could use a specific array key (for example '__validate_errors') to handle validation errors.
Imho, filtering should be done as we are doing it now, by directly changing the sql query via query builder. filtering already loaded message would break paging and it also wouldn't be good for perfomance, if a user filters everything out except the last of his 1000 messages)
Comment #10
litwol commentedI think instead of storing validation errors in watchdog, those errors should be returned. validation api should understand that if a non empty array was returned then it means there are errors. returning those errors would allow user of the api to decide whether to drupal_Set_message or write to watchdog or what ever.
i dont like using watchdog for this case because its not really a thing that should be notified to site admin if some validation returns false, for example if user is blocked and some one is attempting to send message to him.
Comment #11
berdirI'm going to close this one as duplicate of #288183: Provide api function for other modules to send messages..