privatemsg.api.php in Privatemsg 6
Same filename and directory in other branches
Privatemsg API Documentation
File
privatemsg.api.phpView source
<?php
/**
* @file
* Privatemsg API Documentation
*/
/**
* @mainpage Privatemsg API Documentation
* This is the (currently inofficial) API documentation of the privatemsg 6.x
* API.
*
* - 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
*/
/**
* @defgroup sql Query Builder
* Privatemsg does use its own simple query builder which allows to extend
* SELECT-Queries in an easy way. The function _privatemsg_assemble_query
* creates the query, based on an array $fragments with the following content.
* Except primary_table, each key is an array itself to allow multiple values
*
* - primary_table: The main table to select from
* - select: The fields that should be selected. This can be a simple field, a
* field with alias or even a subquery.
* - inner_join: The tables that should be joined. This is not specific to
* inner joins.
* Example: INNER JOIN pm_index pmi ON (pmi.mid = pm.mid)
* - where: The where conditions. The conditions are always AND, but it is
* possible to use OR inside a condition.
* Example: ⁽pmi.is_new = 1 OR pmi.deleted = 1)
* - order_by: Order By values, example: pm.timestamp ASC
* - query_args: It is possible to use the placeholders like %s in each part of
* the query. The values of query_args are then inserted into these.
* query_args consists of three arrays (join, where, having), one for each
* key that currently supports arguments.
*
* Use _privatemsg_assemble_query
*
* The privatemsg_assemble_query function takes a query_id as first argument
* and optionally one or multiple arguments. query_id can either be a
* string ('some_id') or an array('group_name', 'query_id'), if a string
* is supplied, group_name defaults to 'privatemsg'. Returned is an array
* with the keys 'query' (normal query) and 'count' (count query for pager).
*
* For the actual query data, the function group_name_sql_query_id is executed,
* this functions does have $fragments as first parameter and then the
* optional parameters.
*
* A short example:
* @code
* // First, create the sql function.
* function privatemsg_sql_getsubject(&$fragments, $mid, $uid) {
* // Set the primary table.
* $fragments['primary_table'] = '{pm_message} pm';
*
* // Add a field.
* $fragments['select'][] = 'pm.subject';
*
* // Join another table.
* $fragment['inner_join'][] = 'JOIN {pm_index} pi ON (pi.mid = pm.mid)';
* $fragment['query_args']['join'][] $uid;
*
* // And finally add a condition.
* $fragments['where'][] = 'pm.mid = %d';
* $fragments['query_args']['where'][] = $mid;
* }
*
* // Now we can use that query everywhere.
* $query = _privatemsg_assemble_query('getsubject', 5);
* $result = db_query($query['query']);
* @endcode
* Extend existing queries
*
* To extend a privatemsg query, use hook_group_name_sql_query_id_alter.
* This hook does use the same parameters as the sql function.
*
* Example:
* @code
* function mymodule_privatemsg_sql_getsubject_alter(&$fragments, $mid) {
* // we want to load the body too..
* $fragments['select'][] = 'pm.body';
* }
* @endcode
*
* - List of sql query hooks.
* - list: List of messages, Parameters: $fragments, $accounty
* - list_sent: List of sent messages, Parameters: $fragments, $accounty
* - load: Load a single message, Parameters: $fragments, $pmid, $account
* - messages: Load the messages of a thread,
* Parameters: $fragments, $thread_id, $account
* - autocomplete: Searching usernames for the autocomplete feature,
* Parameters: $fragments, $search, $names
* - participants: Loads all participants of a thread,
* Parameters: $fragments, $thread_id
* - unread_count: Number of unread messages for a user,
* Parameters: $fragments, $account
*
* - The following query_id's are used in pm_block_user
* - threadautors: Return all authors of one or multiple threads,
* Parameters: $fragments, $threads
*/
/**
* @addtogroup sql
* @{
*/
/**
* Query to search for autocomplete usernames.
*
* @param $fragments
* Query fragments
* @param $search
* Search for that username
* @param $names
* Names that are already in the list and are excluded
*/
function hook_privatemsg_sql_autocomplete_alter(&$fragments, $search, $names) {
global $user;
// Extend the query that searches for usernames
// $fragments is explained in the api documentation in detail
// The query is already set up, it's searching for usernames which start with
// $search and are not $names (may be empty)
// the main table is {user} a
// 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.
$fragments['inner_join'] = 'INNER JOIN {my_table} m ON (m.user1 = u.uid AND m.user2 = %d)';
$fragments['query_args'][] = $user->uid;
}
/**
* Display a list of threads.
*
* @param $fragments
* Query fragments
* @param $account
* User object
*/
function hook_privatemsg_sql_list_alter(&$fragment, $account) {
}
/**
* Query definition to load a message.
*
* @param $fragments
* Query fragments array.
* @param $pmid
* the id of the message.
* @param $account
* User object of account for which to load the message.
*/
function hook_privatemsg_sql_load_alter(&$fragments, $pmid, $account = NULL) {
}
/**
* Query definition to load messages of one or multiple threads.
*
* @param $fragments
* Query fragments array.
* @param $threads
* Array with one or multiple thread id's.
* @param $account
* User object for which the messages are being loaded.
* @param $load_all
* Deleted messages are only loaded if this is set to TRUE.
*/
function hook_privatemsg_sql_messages_alter(&$fragments, $threads, $account = NULL, $load_all = FALSE) {
}
/**
* Load the participants of a thread.
*
* @param $fragments
* Query fragments
* @param $thread_id
* Thread id, pmi.thread_id is the same as the mid of the first
* message of that thread
*/
function hook_privatemsg_sql_participants_alter(&$fragment, $thread_id) {
}
/**
* Loads all unread messages of a user (only the count query is used).
*
* @param $fragments
* Query fragments
* @param $account
* User object
*/
function hook_privatemsg_sql_unread_count_alter(&$fragment, $account) {
}
/**
* @}
*/
/**
* @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 similiar 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
*
* 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' => 'raclebugav', // 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 after the message has been loaded.
*
* Return data will be merged with the $message array.
*
* @param $message
* Message array
*/
function hook_privatemsg_message_load($message) {
return array(
'my_key' => 'my_value',
);
}
/**
* Is called when a message is flushed.
*
* The message will be deleted from the database, remove any related data here.
*
* @param $message
* Message array
*/
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 $message
* Message array
*/
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 recieve any more messages from you.', array(
'%name' => $recipient->name,
));
}
}
}
/**
* 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 $message
* Message array
*/
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 aviable in $vars['message'].
*
* @param $var
* Template variables
*/
function hook_privatemsg_message_view_alter(&$var) {
// 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 $message
* Message array
*/
function hook_privatemsg_message_insert($message) {
_mymodule_save_data($message['mid']);
}
/**
* @}
*/
/**
* @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 $author
* Author of the message to be sent
* @param $recipients
* Recipients of the message
* @return
* An indexed array of arrays with the keys uid and
* message (The reason why the recipient has been blocked).
*/
function hook_privatemsg_block_message($author, $recipients) {
$blocked = array();
// Loop through each recipient and ensure there is no rule blocking this
// author from sending them private messages. Use a reference, so when
// user_load() is needed here the array is updated, negating the need for
// further calls to user_load() later in the code.
foreach (array_keys($recipients) as $uid) {
// Ensure we have a recipient user object which includes roles.
if (!isset($recipients[$uid]->roles)) {
$recipients[$uid] = user_load($uid);
}
// Note: this is checked whether the author may send the message (see third
// parameter). Further below is a check whether the recipient may block it.
if (_pm_block_user_rule_exists($author, $recipients[$uid], PM_BLOCK_USER_DISALLOW_SENDING)) {
$blocked[] = array(
'uid' => $uid,
'message' => t('Sorry, private messaging rules forbid sending messages to !name.', array(
'!name' => $recipients[$uid]->name,
)),
);
}
}
$args = array_merge(array(
$author->uid,
), array_keys($recipients));
$result = db_query('SELECT recipient FROM {pm_block_user} WHERE author = %d AND recipient IN (' . db_placeholders($recipients) . ') GROUP BY recipient', $args);
while ($row = db_fetch_array($result)) {
$recipient = $recipients[$row['recipient']];
// If there's a rule disallowing blocking of this message, send it anyway.
if (_pm_block_user_rule_exists($author, $recipient, PM_BLOCK_USER_DISALLOW_BLOCKING)) {
continue;
}
$blocked[] = array(
'uid' => $row['recipient'],
'message' => t('%name has chosen to not recieve any more messages from you.', array(
'%name' => $recipients[$row['recipient']]->name,
)),
);
}
return $blocked;
}
/**
* Add content to the view thread page.
*
* Each element in content contains a 'value' and a '#weight' key, the weight
* is used set the order of the different parts.
*
* @param $content
* Content array
* @param $message_count
* Amount of messages
*/
function hook_privatemsg_view_messages($content, $message_count) {
}
/**
* 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,
),
),
);
}
/**
* 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.
*/
function hook_privatemsg_name_lookup($string) {
if ((int) $string > 0) {
// This is a possible uid, try to load a matching user.
if ($recipient = user_load(array(
'uid' => $string,
))) {
return $recipient;
}
}
}
/**
* @}
*/
Functions
Name | Description |
---|---|
hook_privatemsg_block_message | Check if the author can send a message to the recipients. |
hook_privatemsg_message_flush | Is called when a message is flushed. |
hook_privatemsg_message_insert | This hook is executed after the message has been saved. |
hook_privatemsg_message_load | Is called after the message has been loaded. |
hook_privatemsg_message_presave_alter | Change the message before it is stored. |
hook_privatemsg_message_validate | Validate a message before it is sent/saved in the database. |
hook_privatemsg_message_view_alter | Act on the $vars before a message is displayed. |
hook_privatemsg_name_lookup | Hook which allows to look up a user object. |
hook_privatemsg_sql_autocomplete_alter | Query to search for autocomplete usernames. |
hook_privatemsg_sql_list_alter | Display a list of threads. |
hook_privatemsg_sql_load_alter | Query definition to load a message. |
hook_privatemsg_sql_messages_alter | Query definition to load messages of one or multiple threads. |
hook_privatemsg_sql_participants_alter | Load the participants of a thread. |
hook_privatemsg_sql_unread_count_alter | Loads all unread messages of a user (only the count query is used). |
hook_privatemsg_thread_operations | Expose operations/actions which can be executed on threads. |
hook_privatemsg_view_messages | Add content to the view thread page. |
hook_privatemsg_view_template | List of possible templates. |