-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathprivatemsg.api.php
614 lines (567 loc) · 19.2 KB
/
privatemsg.api.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
<?php
/**
* @file
* Privatemsg API Documentation
*/
/**
* @mainpage Privatemsg API Documentation
* This is the API documentation of Privatemsg.
*
* - Topics:
* - @link api API functions @endlink
* - @link sql Query builder and related hooks @endlink
* - @link message_hooks Message hooks @endlink
* - @link generic_hooks Generic hooks @endlink
* - @link theming Theming @endlink
* - @link types Types of recipients @endlink
*/
/**
* @defgroup sql Query Builder
*
* Query builder and related hooks
*
* Privatemsg uses SelectQuery combined with custom tags to allow to customize
* almost all SELECT queries. For more information about SelectQuery, see
* http://drupal.org/developing/api/database and http://drupal.org/node/310075.
*
* Arguments to a given query is stored in the metadata, with numerical keys
* (arg_%d) according to the position of the argument.
*
*/
/**
* @addtogroup sql
* @{
*/
/**
* Query to search for autocomplete usernames.
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_autocomplete()
* @see hook_query_alter()
*/
function hook_query_privatemsg_autocomplete_alter($query) {
global $user;
$search = $query->getMetaData('arg_1');
$names = $query->getMetaData('arg_2');
// For example, add a join on a table where the user connections are stored
// and specify that only users connected with the current user should be
// loaded.
$query->innerJoin('my_table', 'm', 'm.user1 = u.uid AND m.user2 = :user2', array(':user2' => $user->uid));
}
/**
* Display a list of threads.
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_list()
* @see hook_query_alter()
*/
function hook_query_privatemsg_sql_list_alter($query) {
$account = $query->getMetaData('arg_1');
}
/**
* Query definition to load messages of one or multiple threads.
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_messages()
* @see hook_query_alter()
*/
function hook_query_privatemsg_messages_alter($query) {
$threads = $query->getMetaData('arg_1');
$account = $query->getMetaData('arg_2');
$load_all = $query->getMetaData('arg_3');
}
/**
* Alter the query that loads the participants of a thread.
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_participants()
* @see hook_query_alter()
*/
function hook_query_privatemsg_participants_alter($query) {
$thread_id = $query->getMetaData('arg_1');
$account = $query->getMetaData('arg_2');
}
/**
* Loads all unread messages of a user (only the count query is used).
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_unread_count()
* @see hook_query_alter()
*/
function hook_query_privatemsg_unread_count_alter($query) {
$account = $query->getMetaData('arg_1');
}
/**
* Alter the query that loads deleted messages to flush them.
*
* @param SelectQuery $query
* Query object
*
* @see privatemsg_sql_deleted()
* @see hook_query_alter()
*/
function hook_query_privatemsg_deleted_alter($query) {
$days = $query->getMetaData('arg_1');
$max = $query->getMetaData('arg_2');
}
/**
* @}
*/
/**
* @defgroup api API functions
*
* There are two different functions to send messages.
* Either by starting a @link privatemsg_new_thread new thread @endlink
* or @link privatemsg_reply reply @endlink to an existing thread.
*
* There is also a function which returns a link to the privatemsg new message
* form with the recipient pre-filled if the user is allowed to.
* privatemsg_get_link().
*/
/**
* @defgroup message_hooks Message hooks
* All message-level hooks look like hook_privatemsg_message_op,
* where op is one of the following:
* - @link hook_privatemsg_message_load load @endlink: Called when a full
* message is loaded similar to nodeapi_load, new values can be returned and
* will be added to $message, parameter: $message
* - @link hook_privatemsg_message_validate validate @endlink: Validation,
* before the message is sent/saved. Return validation errors as array,
* parameter: $message, $form = FALSE
* - @link hook_privatemsg_message_presave_alter presave_alter @endlink: Last
* changes to $message before the message is saved, parameter: $message
* - @link hook_privatemsg_message_insert insert @endlink: message has been
* saved, $message has been updated with the mid and thread_id,
* parameter: $message
* - @link hook_privatemsg_message_delete delete @endlink: the message is
* going to be deleted, parameter: $message
* - @link hook_privatemsg_message_view_alter view_alter @endlink: the message
* is going to be displayed, parameter: $vars
* - @link hook_privatemsg_message_recipient_change recipient changed @endlink:
* a recipient is added or removed from/to a message.
*
* In hooks with _alter suffix, $message is by reference.
*
* $message is an array, with all the relevant information about the message.
* The information in there can be changed/extended by modules, but looks
* typically like this:
* @code
* array (
* 'mid' => 3517, // message id, identifies a message
* 'author' => 27, // author id
* 'subject' => 'bla bla', // Message subject
* 'body' => 'bla bla', // Body of the message
* 'timestamp' => 351287003, // unix timestamp, creation time
* 'is_new' => 0, // If the message has been read by the user
* 'thread_id' => 3341, // thread id, this is actually the mid from the first
* message of the thread
* )
* @endcode
*/
/**
* @addtogroup message_hooks
* @{
*/
/**
* Is called when a message is flushed.
*
* The message will be deleted from the database, remove any related data here.
*
* @param Privatemsg_message $message
* Message
*/
function hook_privatemsg_message_flush($message) {
}
/**
* Validate a message before it is sent/saved in the database.
*
* Validation errors can be returned, either as a string or as array when there
* are multiple errors. If the $form flag is set, errors should be reported
* with form_set_error instead.
*
* @todo adapt api return value changes
*
* @param Privatemsg_message $message
* Message
* @param bool $form
*/
function hook_privatemsg_message_validate($message, $form = FALSE) {
global $_privatemsg_invalid_recipients;
$_privatemsg_invalid_recipients = array();
$errors = array();
foreach ($message->recipients as $recipient) {
if ($recipient->name == 'blocked user') {
$_privatemsg_invalid_recipients[] = $recipient->uid;
$errors[] = t('%name has chosen to not receive any more messages from you.', array('%name' => privatemsg_recipient_format($recipient, array('plain' => TRUE))));
}
}
}
/**
* Change the message before it is stored.
*
* Alter the message, for example remove recipients that have been detected as
* invalid or forbidden in the validate hook.
*
* @param Privatemsg_message $message
* Message
*/
function hook_privatemsg_message_presave_alter(&$message) {
// delete recipients which have been marked as invalid
global $_privatemsg_invalid_recipients;
foreach ($_privatemsg_invalid_recipients as $invalid) {
unset($message->recipients[$invalid]);
}
}
/**
* Act on the $vars before a message is displayed.
*
* This is called in the preprocess hook of the privatemsg-view template.
* The $message data is available in $vars['message'].
*
* @param array $vars
* Template variables
*/
function hook_privatemsg_message_view_alter(&$vars) {
// add a link to each message
$vars['message_links'][] = array('title' => t('My link'), 'href' => '/path/to/my/action/' . $vars['message']['mid']);
}
/**
* This hook is executed after the message has been saved.
*
* $message is updated with mid and thread id. Use this hook to store data,
* that needs to point to the saved message for example attachments.
*
* @param Privatemsg_message $message
* Message
*/
function hook_privatemsg_message_insert($message) {
_mymodule_save_data($message->mid);
}
/**
* Allows response to a deleted change.
*
* Modules implementing this hook should be aware that messages are only
* marked as deleted and not removed from the database. They will only
* eventually be deleted by the flushing.
*
* Therefore, modules should not delete data in this hook but in
* hook_privatemsg_message_flush().
*
* @param $mid
* Message id.
* @param $deleted
* TRUE when the message was marked as deleted, FALSE when marked as not
* deleted.
* @param $account
* User object, if NULL then the message was marked as deleted for all users.
*
* @see privatemsg_message_change_delete()
* @see privatemsg_thread_change_delete()
*
*/
function hook_privatemsg_message_status_deleted($mid, $deleted, $account) {}
/**
* This hook is invoked when a recipient is added to a message.
*
* Since the hook might be invoked hundreds of times during batch or cron, only
* ids are passed and not complete user/message objects.
*
* @param int $mid
* Id of the message.
* @param int $thread_id
* Id of the thread the message belongs to.
* @param int|string $recipient
* Recipient id, a user id if type is user or hidden.
* @param string $type
* Type of the recipient.
* @param bool $added
* TRUE if the recipient is added, FALSE if they are removed.
*/
function hook_privatemsg_message_recipient_changed($mid, $thread_id, $recipient, $type, $added) {
if ($added && ($type == 'user' || $type == 'hidden')) {
privatemsg_filter_add_tags(array($thread_id), config_get('privatemsg_filter.settings', 'inbox_tag'), (object)array('uid' => $recipient));
}
}
/**
* @}
*/
/**
* @defgroup generic_hooks Generic Hooks
* @{
*
* Some generic hooks that can't be categorized.
*/
/**
* Check if the author can send a message to the recipients.
*
* This can be used to limit who can write whom based on other modules and/or
* settings.
*
* @param User $author
* Author of the message to be sent
* @param array $recipients
* Recipient of the message
* @param array $context
* Additional information. Can contain the thread_id to indicate that this is
* a reply on an existing thread.
* @return array
* An indexed array of arrays with the keys recipient ({type}_{key}) and
* message (The reason why the recipient has been blocked).
*/
function hook_privatemsg_block_message($author, $recipients, $context = array()) {
$blocked = array();
foreach ($recipients as $recipient_id => $recipient) {
// Deny/block if the recipient type is role and the account does not have
// the necessary permission.
if ($recipient->type == 'role' && $recipient->recipient == 2) {
$blocked[] = array(
'recipient' => $recipient_id,
'message' => t('Not allowed to write private messages to the role authenticated user'),
);
}
}
return $blocked;
}
/**
* Add content to the view thread page.
*
* @param array $content
* Renderable array, contains the thread object in #thread.
*/
function hook_privatemsg_view_alter($content) {
if (privatemsg_user_access('tag private messages')) {
$content['tags'] = privatemsg_filter_show_tags($content['#thread']['thread_id'], !empty($_GET['show_tags_form']));
}
}
/**
* List of possible templates.
*/
function hook_privatemsg_view_template() {
}
/**
* Expose operations/actions which can be executed on threads.
*
* Return an array of operations to privatemsg, the key of each operation is the
* operation key or name.
*
* @see _privatemsg_action_form()
* @see privatemsg_list_submit()
*/
function hook_privatemsg_thread_operations() {
return array(
'operation key' => array(
'label' => 'Label of the operation. Only use this if the operation
should be displayed automatically in the action form',
'callback' => 'privatemsg_thread_change_status', // Function callback that will be executed.
'callback arguments' => array('status' => PRIVATEMSG_READ), // Additional arguments to above function
'undo callback' => 'privatemsg_thread_change_status', // Provide a function which can "undo" the operation. Optional.
'undo callback arguments' => array('status' => PRIVATEMSG_UNREAD), // Additional arguments to above function.
),
);
}
/**
* Allows response to a status change.
*
* @param int $pmid
* Message id.
* @param int $status
* Either PRIVATEMSG_READ or PRIVATEMSG_UNREAD.
* @param User $account
* User object, defaults to the current user.
*
* @see privatemsg_message_change_status()
*/
function hook_privatemsg_message_status_changed($pmid, $status, $account) {
}
/**
* @}
*/
/**
* @defgroup types Types of recipients
*
* It is possible to define other types of recipients than the usual single
* user. These types are defined through a hook and a few callbacks and are
* stored in the {pm_index} table for each recipient entry.
*
* Because of that, only the combination of type and recipient (was uid in older
* versions) defines a unique recipient.
*
* This feature is usually used to define groups of recipients. Privatemsg
* comes with the privatemsg_roles sub-module, which allows to send messages to
* all members of a specific group.
*
* When sending a new message with a recipient type other than user, Privatemsg
* only inserts a single entry for that recipient type. However, when looking
* for messages for a user, Privatemsg only looks for recipient types user and
* hidden. To fill the gap, Privatemsg defines three ways how a non-user
* type is converted to hidden recipient entries.
*
* - For small recipient types (by default <100 recipients, configurable), the
* entries are added directly after saving the original private message.
* - When sending messages through the UI, bigger recipient types are handled
* with batch API.
* - For messages sent by the API, the hidden recipients are generated during
* cron runs.
*
* Once all hidden recipients are added, the original recipient type is marked
* as read so Privatemsg knows that they have been processed.
*
* Privatemsg defines the following types:
*
* - user: This is the default recipient type which is used for a single user.
* - hidden: Used to add internal recipient entries for other recipient types.
* - role: The sub-module privatemsg_roles defines an additional type called
* role. This allows to send messages to all members of a role.
*
* To implement a new type, the following hooks need to be implemented. Note
* that most of these hooks can also be used alone for other functionality than
* defining recipient types.
*
* - hook_privatemsg_recipient_type_info() - Tell Privatemsg about your
* recipient type(s).
* - hook_privatemsg_name_lookup() - Convert a string to an
* recipient object
*
* Additionally, there is also a hook_privatemsg_recipient_type_info_alter() that
* allows to alter recipient type definitions.
*/
/**
* @addtogroup types
* @{
*/
/**
* This hook is used to tell privatemsg about the recipient types defined by a
* module. Each type consists of an array keyed by the internal recipient type
* name and the following keys must be defined.
*
* * name: Translated name of the recipient type.
* * description: A short description of how to send messages to to that
* recipient type. This is displayed below the To: field when sending a
* message.
* * load: A callback function that can load recipients based on their id,
* example: privatemsg_roles_load_multiple().
* * format: Theme function to format the recipient before displaying. Must be
* defined with hook_theme(), example: theme_privatemsg_roles_format().
* * autocomplete: Function callback to return possible autocomplete matches,
* example: privatemsg_roles_autocomplete().
* * generate recipients: Function callback to return user ids which belong to a
* recipient type, example: privatemsg_roles_load_recipients().
* * max: Function callback to return the highest user id of a recipient type,
* example: privatemsg_roles_count_recipients().
* * write access: Optionally define a permission which controls write access
* to that recipient type.
* * write callback: Optionally define a callback function that returns an
* access decision (allow = TRUE, deny = FALSE) for whether the current user
* can write to recipients of the given recipient type.
* * view access: Optionally define a permission which controls if the user is
* able to see the recipient when they are looking at a thread.
* * view callback: Optionally define a callback function that returns an
* access decision (allow = TRUE, deny = FALSE) for whether the current user
* can see recipients of the given recipient type.
*/
function hook_privatemsg_recipient_type_info() {
return array(
'role' => array(
'name' => t('Role'),
'description' => t('Enter the name of a role to write a message to all users which have that role. Example: authenticated user.'),
'load' => 'privatemsg_roles_load_multiple',
'format' => 'privatemsg_roles_format',
'autocomplete' => 'privatemsg_roles_autocomplete',
'generate recipients' => 'privatemsg_roles_load_recipients',
'count' => 'privatemsg_roles_count_recipients',
'write callback' => 'privatemsg_roles_write_access',
'view access' => 'view roles recipients',
),
);
}
/**
* Hook which allows to look up a user object.
*
* You can try to look up a user object based on the information passed to the
* hook. The first hook that successfully looks up a specific string wins.
*
* Therefore, it is important to only return something if you can actually look
* up the string.
*
* @param string $string
*
* @return object
*/
function hook_privatemsg_name_lookup($string) {
$result = db_query("SELECT *, rid AS recipient FROM {role} WHERE name = '%s'", array(trim($string)));
if ($role = db_fetch_object($result)) {
$role->type = 'role';
return $role;
}
}
/**
* Allows to alter the defined recipient types.
*
* @param array $types
* Array with the recipient types.
*
* @see hook_privatemsg_recipient_type_info()
*/
function hook_privatemsg_recipient_type_info_alter(&$types) {
}
/**
* Allows to alter the found autocomplete suggestions.
*
* @param array $matches
* Array of matching recipient objects.
* @param array $names
* Array of names that are already in the list.
* @param string $fragment
* Fragment that is currently searched for.
*/
function hook_privatemsg_autocomplete_alter(&$matches, $names, $fragment) {
// Remove all types other than user if accessed through
// messages/user/autocomplete.
if (arg(1) == 'user') {
foreach ($matches as $id => $match) {
if ($match->type != 'user') {
unset($matches[$id]);
}
}
}
}
/**
* Allows to alter found recipient types for a given string.
*
* @param array $matches
* Array of matching recipient objects.
* @param string $string
* String representation of the recipient.
*/
function hook_privatemsg_name_lookup_matches(&$matches, $string) {
}
/**
* Allows response to a successful operation.
*
* @param string $operation
* The operation that was executed.
* @param array $threads
* An array which contains the thread ids on which the operation
* has been executed.
* @param User|null $account
* An user account object if an other user than the currently logged in is
* affected.
*
* @see privatemsg_operation_execute()
* @see hook_privatemsg_thread_operations()
*/
function hook_privatemsg_operation_executed($operation, $threads, $account = NULL) {
}
/**
* @}
*/