');
/**
* Implementation of hook_autoload_info().
*/
function messaging_autoload_info() {
return array(
'Messaging_Message' => array('file' => 'classes/messaging_message.class.inc'),
'Messaging_Send_Method' => array('file' => 'classes/messaging_method.class.inc'),
'Messaging_Mail_Method' => array('file' => 'classes/messaging_method.class.inc'),
'Messaging_Message_Template' => array('file' => 'classes/messaging_message_template.class.inc'),
);
}
/**
* Implementation of hook_help().
*/
function messaging_help($path, $arg) {
switch ($path) {
case 'admin/help#messaging':
$output = '
' . t('The messaging module is the engine that handles outgoing messages and message queueing for different sending methods.') . '
';
$output .= '' . t('You need to enable one or more of the included plug-ins to be able to actually take advantage of it.') . '
';
return $output;
default:
if ($arg[0] == 'admin') {
if ($arg[1] == 'settings' && $arg[2] == 'filters') {
return ''. t('Filters are used also for messaging. If the input format is to be used only for messaging you don\'t need to allow any role for it.') .'
';
}
if ($arg[1] == 'messaging') {
require_once drupal_get_path('module', 'messaging') .'/messaging.admin.inc';
return messaging_admin_help($path, $arg);
}
}
}
}
/**
* Implementation of hook_menu()
*/
function messaging_menu() {
$items['admin/messaging'] = array(
'title' => 'Messaging',
'access arguments' => array('administer messaging'),
'description' => 'Administer and configure messaging',
'page callback' => 'system_admin_menu_block_page',
'file' => 'system.admin.inc',
'file path' => drupal_get_path('module', 'system'),
);
$items['admin/messaging/settings'] = array(
'title' => 'Messaging settings',
'description' => 'Configuration of messaging framework',
'page callback' => 'drupal_get_form',
'page arguments' => array('messaging_admin_settings'),
'access arguments' => array('administer messaging'),
'file' => 'messaging.admin.inc',
);
$items['admin/messaging/settings/overview'] = array(
'title' => 'Messaging',
'description' => 'Configuration of sending methods',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/messaging/settings/method'] = array(
'title' => 'Send methods',
'description' => 'Configuration of sending methods',
'page callback' => 'drupal_get_form',
'page arguments' => array('messaging_admin_method_settings'),
'access arguments' => array('administer messaging'),
'weight' => -10,
'file' => 'messaging.admin.inc',
'type' => MENU_LOCAL_TASK,
);
$items['admin/messaging/settings/method/overview'] = array(
'title' => 'General',
'description' => 'General settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/messaging/template'] = array(
'title' => 'Message templates',
'description' => 'Configuration of message templates',
'page callback' => 'messaging_admin_template',
'access arguments' => array('administer messaging'),
'file' => 'messaging.admin.inc',
);
$items['admin/messaging/template/edit'] = array(
'title' => 'Message templates',
'page callback' => 'messaging_admin_template_edit',
'type' => MENU_CALLBACK,
'access arguments' => array('administer messaging'),
'file' => 'messaging.admin.inc',
);
return $items;
}
/**
* Implementation of hook_perm()
*/
function messaging_perm() {
return array('administer messaging');
}
/**
* Implementation of hook_user().
*
* Adds fieldset and default sending method setting.
*/
function messaging_user($type, $edit, &$user, $category = NULL) {
switch ($type) {
case 'form':
if ($category == 'account' && ($list = messaging_method_list($user))) {
$form['messaging'] = array(
'#type' => 'fieldset',
'#title' => t('Messaging settings'),
'#weight' => 5,
'#collapsible' => TRUE,
);
$form['messaging']['messaging_default'] = array(
'#type' => 'select',
'#title' => t('Default send method'),
'#default_value' => messaging_method_default($user),
'#options' => $list,
'#description' => t('Default sending method for getting messages from this system.'),
'#disabled' => count($list) == 1,
);
return $form;
}
break;
}
}
/** Messaging API **/
/**
* Send message to user represented by account
*
* We are applying same output filter for everybody, depending on send method
*
* The final rendering of the message depends on send method too. I.e. a mail messaging
* method may want to insert '--' before the body footer.
*
* @ TODO Consider whether it makes sense to allow users decide on formatting
*
* @param $account
* User object to recieve message.
* @param $message
* Array of message parts that will be compiled depending on send method.
* Mandatory message parts, which may have nexted parts are:
* - 'type'
* - 'subject'
* - 'body'. The message body may have 'header', 'content', 'footer', 'etc'
* @param $method
* Optional send method. Defaults to the user account predefined method
*/
function messaging_message_send_user($account, $message, $method = NULL, $queue = 0) {
messaging_debug('Sending message to user', array('account' => $account, 'message' => $message, 'method' => $method));
// Build array of parameters so they can be overridden by callbacks
$method = $method ? $method : messaging_method_default($account);
$message = messaging_message_build($message);
$message->method = $method;
$message->queue = $queue;
// Now check that we have a destination for this user account. If set to FALSE we just don't try anymore
$message->destination = messaging_user_destination($account, $method);
$message->set_user($account);
// Send the message or, if no destination, abort the message sending
if (!empty($message->destination)) {
messaging_debug('Found destination for user, sending message', array('method' => $method, 'destination' => $message->destination));
return $message->send();
} else {
// Save the message, let it there for further reference
messaging_log('Destination not available for user account', array('method' => $method, 'account' => $account));
$message->set_error('Destination not available for user account');
}
return FALSE;
}
/**
* Get destination from user account.
*
* This will handle also anonymous user accounts that should have a 'destination' property
*/
function messaging_user_destination($account, $method) {
if ($send_method = messaging_send_method($method)) {
return $send_method->user_destination($account);
}
}
/**
* Send message to array of destinations using the same method. The message is rendered just once.
*
* The $message array may have the following elements
* 'subject' => Message subject, may be already rendered or not
* 'body' => Message content, may be already rendered or not
* 'params' => Optional message params, indexed by sending method group
* I.e. params for mail methods will be in $message['params']['mail']
* 'render' => Optional flag to mark the message subject and body as rendered
* 'sender' => Optional int to identify message sender, may be $user->uid
* 'sender_account' => Optional user account to use as message sender
* @param $destinations
* Array of destinations for sending.
* The element type depends on sending method so it can be a list of e-mail addresses, user accounts, etc
* @param $message
* Message object or array, not rendered
* @param $method
* Sending method. Unlike for messaging_message_send_user() for which the sending method may be user's default
* it is not an optional parameter for this function.
* @param $queue
* Optional flag, 0 for normal queueing, 1 to force queueing.
* We may want to force queueing for bulk messaging. Otherwise it will depend on the sending method
* wether to queue the messages (for pull methods) or not (push methods)
*/
function messaging_message_send($destinations, $message, $method, $queue = 0) {
messaging_debug('Sending message', array('destinations' => $destinations, 'message' => $message, 'method' => $method, 'queue' => $queue));
// Get default sending method, or default for this user account
$method = $method ? $method : messaging_method_default(NULL);
// Convert into an object and add all the information into the message object
$message = messaging_message_build($message);
$message->method = $method;
$message->type = 'outgoing';
$message->queue = $queue;
if ($send_method = messaging_send_method($method)) {
if ($queue) {
$results = $send_method->queue_multiple($message, $destinations);
}
else {
$results = $send_method->send_multiple($message, $destinations);
}
}
if (empty($results)) {
watchdog('messaging', 'Message could not be delivered for method %method', array('%method' => $method), WATCHDOG_ERROR);
}
return isset($results) ? $results : array();
}
/**
* Send for real, finally invoking method's callback function
*
* This sends messages one by one, so the callback function only need to support a single destination
* Specific parameters for this message group are processed here too
*
* @param $destination
* Single destination, may be email, user account, etc...
* @param $message
* Message object
* @param $method
* Sending method
*
* @return boolean
* Message successfully sent
*/
function messaging_message_send_out($destination, $message, $method) {
$message = messaging_message_build($message);
$message->type = 'outgoing';
$message->destination = $destination;
$message->method = $method;
$result = $message->send();
if ($result === FALSE) {
watchdog('messaging', 'Message could not be delivered for method %method, destination %destination', array('%method' => $method, '%destination' => $destination), WATCHDOG_ERROR);
}
return $result;
}
/**
* Implementation of hook_cron()
*
* Process queued messages for delivery
*/
function messaging_cron() {
messaging_store('queue_process');
messaging_store('queue_cleanup');
}
/**
* Pull pending messages for given methods and user accounts
*
* Each returned message will be an array with the following elements
* - 'uid', destination uid
* - 'sender', originating uid
* - 'subject', message subject to be rendered
* - 'body', message body to be rendered
* @param $method
* Send method
* @param $users
* User id or array of user id's
* @param $limit
* Optional limit for number of messages
* @param $delete
* Optional whether to delete messages when fetching
* @return array()
* Array of pending messages.
*/
function messaging_pull_pending($method, $users = NULL, $limit = 0, $delete = TRUE) {
$params['method'] = $method;
$params['queue'] = 1;
if (isset($users)) {
$params['uid'] = $users;
}
$messages = messaging_store('get', $params);
// Not exactly delete but mark as sent
if ($messages && $delete) {
messaging_store('sent', array_keys($messages));
}
return $messages;
}
/**
* Returns list of messaging methods for a type
*
* I.e. all messaging methods of pull type
*/
function messaging_method_type($type) {
$result = array();
foreach (messaging_method_info() as $method => $info) {
if ($info['type'] & $type) {
$result[$method] = $info;
}
}
return $result;
}
/**
* List sending methods
*
* @param $account
* Optional user account, for checking permissions against this account
*/
function messaging_method_list($account = NULL) {
$info = messaging_method_info(NULL, 'name');
if ($account) {
foreach (array_keys($info) as $method) {
// Check access for each method and check destination
if (!messaging_method_permission($method, $account) || !messaging_user_destination($account, $method)) {
unset($info[$method]);
}
}
}
return $info;
}
/**
* Check permission for method and account
*
* @param $method
* Sending method id
* @param $account
* User account to check permission
*/
function messaging_method_permission($method, $account = NULL) {
$info = messaging_method_info($method);
// This sending method may be disabled
if (!$info) {
return FALSE;
} elseif (!empty($info['access'])) {
return user_access($info['access'], $account);
} else {
return TRUE;
}
}
/**
* Returns default messaging method
*/
function messaging_method_default($account = NULL) {
if ($account && !empty($account->messaging_default) && messaging_method_permission($account->messaging_default, $account)) {
return $account->messaging_default;
}
elseif ($method = variable_get('messaging_default_method', '')) {
return $method;
}
else {
return key(messaging_method_info());
}
}
/**
* Get setting from user account or get default setting if not available
*
* If first checks for a 'messaging_$name' property in the user account
* and returns the value of the variable 'messaging_default_$name' if not set
*
* There's an optional variable 'messaging_peruser_$name' that if true will block
* per user settings and use only global settings.
*
* @param $name
* Option name
* @param $account
* Optional account to check setting for
* @param $default
* Default value if no option set
*/
function messaging_user_setting($name, $account = NULL, $default = NULL) {
$variable = 'messaging_' . $name;
if ($account && isset($account->$variable) && variable_get('messaging_peruser_' . $name, 1)) {
return $account->$variable;
}
else {
return variable_get('messaging_default_' . $name, $default);
}
}
/**
* Returns messaging methods properties
*
* @param $method
* Optional, Method to get properties for, none or NULL for all methods
* @param $property
* Optional, Property to get, none or NULL for all properties
* @param $default
* Optional default value to return when there's not that property for the method
*/
function messaging_method_info($method = NULL, $property = NULL, $default = NULL, $refresh = FALSE) {
$info = &messaging_static(__FUNCTION__);
if (!$info || $refresh) {
$info = module_invoke_all('messaging', 'send methods');
// Merge settings for each enabled method, just default filter if variable not set
$default_settings = array('filter' => variable_get('messaging_default_filter', ''));
foreach (array_keys($info) as $name) {
$info[$name] = array_merge($info[$name], variable_get('messaging_method_' . $name, $default_settings));
}
// Allow altering by other modules
drupal_alter('messaging_methods', $info);
}
return _messaging_info($info, $method, $property, $default);
}
/**
* Returns information about message groups
*
* @param $group
* Optional message group. Returns all groups if null.
* @param $key
* Optional message key inside the group. Returns all keys if null.
* @return array()
* Depending on parameters, may be all message groups and keys or only a specific one.
*/
function messaging_message_group($group = NULL, $key = NULL) {
$info = &messaging_static(__FUNCTION__);
if (!isset($info)) {
$info = module_invoke_all('messaging', 'message groups');
}
return _messaging_info($info, $group, $key);
}
/**
* Composes message from different parts, recursively and applies filter
*
* Filter is applied now only once
*
* @param $text
* Simple string or array of message parts
* It may have named elements like #prefix and #text
* or it may be single strings to render straight forward
* @param $glue
* Text to glue all lines together
* @param $filter
* Input format to apply to the results
*/
function messaging_text_render($text, $glue = '', $filter = NULL) {
$output = '';
if (is_array($text)) {
if (isset($text['#prefix'])) {
$output .= $text['#prefix'].$glue;
unset($text['#prefix']);
}
if (isset($text['#text'])) {
$output .= $text['#text'];
return $output;
}
foreach (element_children($text) as $key) {
// The filter is not passed along
$text[$key] = messaging_text_render($text[$key], $glue);
}
$output .= implode($glue, $text);
} else {
$output .= $text;
}
// The filter is applied now only once
if ($filter) {
$output = check_markup($output, $filter, FALSE);
}
return $output;
}
/**
* Implementation of hook_filter(). Contains a basic set of essential filters.
* - Plain text:
* Strips out all html
* Replaces html entities
* - HTML to text
* Same with some text formatting
* Relies on html_to_text module
*/
function messaging_filter($op, $delta = 0, $format = -1, $text = '') {
switch ($op) {
case 'list':
$info[0] = t('Plain text');
$info[1] = t('HTML to text');
return $info;
case 'description':
switch ($delta) {
case 0:
return t('Filters out all HTML tags and replaces HTML entities by characters, respects HTML line breaks.');
case 1:
return t('Replaces HTML tags and entities with plain text formatting, moving links at the end. This filter is just for text messages and it isn\'t safe for rendering content on a web page.');
}
case 'process':
switch ($delta) {
case 0:
return messaging_check_plain($text, "\n");
case 1:
return drupal_html_to_text($text);
default:
return $text;
}
case 'settings':
return;
default:
return $text;
}
}
/**
* HTML to text simple filtering.
* - Replace some tags with line endings: p, br, hr, li, h1, h2, h3, h4
* Strip out all HTML tags and decode entities
*
* @param $text
* Text to clean up
* @param $break
* Optional character to replace tags for line breaks
*/
function messaging_check_plain($text, $break = NULL) {
// This have to be done before the filtering because tag markers may have been previously parsed with check_plain
$text = str_replace(array('<', '>'), array('<', '>'), $text);
// Clean up the HTML and replace some tags with line endings
if (isset($break)) {
$text = _filter_htmlcorrector($text);
$text = str_replace(array('', '
', '
', '', '', '', '', ''), $break, $text);
}
// Final text clean up
return messaging_text_clean($text);
}
/**
* Converts strings to plain utf-8 single line
*/
function messaging_check_subject($text) {
$text = messaging_check_plain($text);
// taken from _sanitizeHeaders() in PEAR mail() : http://pear.php.net/package/Mail
$text = preg_replace('=((0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', NULL, $text);
return $text;
}
/**
* Entry point for the storage API
*/
function messaging_store() {
static $include;
if (!isset($include)) {
require_once drupal_get_path('module', 'messaging') .'/messaging.store.inc';
$include = TRUE;
}
$args = func_get_args();
$function = 'messaging_store_'. array_shift($args);
return call_user_func_array($function, $args);
}
/**
* Helper user loading function with static caching
*/
function messaging_load_user($uid) {
$cache = &messaging_static(__FUNCTION__);
if (!$cache || !array_key_exists($uid, $cache)) {
$cache[$uid] = user_load(array('uid' => $uid));
}
return $cache[$uid];
}
/**
* Helper function for message loading from the store
*
* @param $mqid
* Message id
*/
function messaging_message_load($mqid) {
$cache = &messaging_static(__FUNCTION__);
if (!isset($cache[$mqid])) {
if ($message = messaging_store('load', $mqid)) {
$cache[$mqid] = $message;
} else {
$cache[$mqid] = FALSE;
}
}
return $cache[$mqid];
}
/**
* Do token replacement.
*
* Uses token_logic if enabled, standard token replacement otherwise
*/
function messaging_text_replace($text, $objects) {
// Add some token types
$objects['global'] = NULL;
// Use token_logic if available, http://code.developmentseed.org/token_logic
// Otherwise use standard contrib token module, http://drupal.org/project/token
if (module_exists('token_logic')) {
return token_logic_replace_multiple($text, $objects);
}
else {
return token_replace_multiple($text, $objects);
}
}
/**
* Build a simple text with message subject and body
*
* This is useful for methods requiring a simple text instead of header and subject
*
* @param $message
* Message object
* @param $glue
* Separator to glue subject and body together
*/
function messaging_text_build($message, $glue = ' ') {
$parts = array(trim($message->subject), trim($message->body));
$parts = array_filter($parts);
if ($parts) {
$text = implode($glue, $parts);
return $text;
}
else {
return '';
}
}
/**
* Clean text of HTML stuff and optionally of line endings
*
* @param $text
* Dirty HTML text to be filtered
* @param $newline
* Optional string to be used as line ending
*/
function messaging_text_clean($text, $newline= NULL) {
// HTML entities to plain text conversion.
$text = decode_entities($text);
// Filters out all remaining HTML tags
$text = filter_xss($text, array());
// Optionally, replace new lines
if (!is_null($newline)) {
$text = str_replace("\n", $newline, $text);
}
// Trim out remaining beginning/ending spaces
$text = trim($text);
return $text;
}
/**
* Truncate messages to given length. Adapted from node_teaser() in node.module
*/
function messaging_text_truncate($text, $length) {
// If we have a short message, return the message
if (drupal_strlen($text) < $length) {
return $text;
}
// Initial slice.
$teaser = truncate_utf8($text, $length);
$position = 0;
// Cache the reverse of the message.
$reversed = strrev($teaser);
// split at paragraph boundaries.
$breakpoints = array('' => 0, '
' => 6, '
' => 4, "\n" => 1);
// We use strpos on the reversed needle and haystack for speed.
foreach ($breakpoints as $point => $offset) {
$length = strpos($reversed, strrev($point));
if ($length !== FALSE) {
$position = - $length - $offset;
return ($position == 0) ? $teaser : substr($teaser, 0, $position);
}
}
// When even the first paragraph is too long, we try to split at the end of
// the last full sentence.
$breakpoints = array('. ' => 1, '! ' => 1, '? ' => 1, ' ' => 0);
$min_length = strlen($reversed);
foreach ($breakpoints as $point => $offset) {
$length = strpos($reversed, strrev($point));
if ($length !== FALSE) {
$min_length = min($length, $min_length);
$position = 0 - $length - $offset;
}
}
return ($position == 0) ? $teaser : substr($teaser, 0, $position);
}
/**
* Process incoming message. This is the entry point for plug-in modules
*
* This is just a wrapper for handling incoming in messaging_incoming module
*/
function messaging_message_in($method, $channel, $message, $params = array()) {
if (function_exists('messaging_incoming_post')) {
return messaging_incoming_post($method, $channel, $message, $params);
} else {
return FALSE;
}
}
/**
* Update messaging method.
*
* When a messaging method is disabled, we need to update current settings for this and other modues
*/
function messaging_method_disable($method) {
module_load_include('install', 'messaging');
if ($replace = messaging_update_method_replace($method)) {
messaging_update_method_disable($method, $replace);
drupal_set_message(t('Disabled messaging sending method %method and replaced by %replace', array('%method' => messaging_method_info($method, 'title'), '%replace' => messaging_method_info($replace, 'title'))));
} else {
// It seems all methods are disabled, print warning
drupal_set_message(t('Disabled messaging sending method but cannot find a replacement. Please, enable some other sending method.'), 'error');
}
}
/**
* Build callback structure to be invoked later
*
* A callback structure will be an array containing the function name to invoke
* and a list of arguments for that function
*
* @param $function
* Function name
* @param $arg1, $arg1, $arg3
*/
function _messaging_callback() {
$args = func_get_args();
if (count($args) > 1) {
// Array with function name, param1, param2..
return $args;
} else {
// Simple string with function name
return array_shift($args);
}
}
/**
* Invoke callback with variable arguments
*
* We don't check whether the function exists so it will crash if it's missing
*
* @param $callback
* Function name or array(function, arg1, arg2..)
* @param $arg1, $arg2...
* Variable number of arguments
*/
function _messaging_callback_invoke() {
$args = func_get_args();
$callback = array_shift($args);
if (is_array($callback)) { // It is an array: function, arg1, arg2...
$function = array_shift($callback);
$params = $callback;
} else { // It is just a function name
$function = $callback;
$params = array();
}
// Merge parameters and go for it
$params = array_merge($params, $args);
return call_user_func_array($function, $params);
}
/**
* Invoke ordered list of callbacks on message
*
* For each callback name this function will search existing callbacks in $info ('[name] callback')
* and if not existing will try the default callback 'messaging_message_[name]'
*
* @see _messaging_callback() for callback structure
*
* @param $callback_keys
* Array of callbacks to invoke, ordered list
* @param $message
* Message object
* @param $info
* Messaging method info which may contain callbacks
*/
function messaging_message_callbacks($callback_keys, $message, $info) {
while (!empty($message->process) && ($key = array_shift($callback_keys))) {
if ($callback = _messaging_callback_get($info, $key)) {
$message = messaging_message_invoke($callback, $message, $info);
} elseif (function_exists('messaging_message_' . $key)) {
$message = call_user_func('messaging_message_' . $key, $message, $info);
}
}
return $message;
}
/**
* Implementation of hook_token_list(). Documents the individual
* tokens handled by the module.
*/
function messaging_token_list($type = 'all') {
$tokens = array();
if ($type == 'message' || $type == 'all') {
$tokens['message']['message-subject'] = t('The message subject.');
$tokens['message']['message-body'] = t('The message body.');
$tokens['message']['message-author-name'] = t('The message\'s author name.');
$tokens['message']['message-method'] = t('The message\'s method name.');
$tokens['message']['message-date'] = t('The message\'s sending date.');
}
return $tokens;
}
/**
* Implementation of hook_token_values()
*/
function messaging_token_values($type, $object = NULL, $options = array()) {
switch ($type) {
case 'message':
if ($message = $object) {
$values['message-subject'] = check_plain($message->subject);
$values['message-body'] = filter_xss($message->body);
$sender = messaging_load_user($message->sender);
$values['message-author-name'] = check_plain($sender->name);
$tokens['message-method'] = messaging_method_info($message->method, 'name');
$tokens['message-date'] = format_date($message->sent);
return $values;
}
break;
}
}
/**
* Implementation of hook_theme()
*/
function messaging_theme() {
return array(
'messaging_admin_method_settings' => array(
'arguments' => array('element' => NULL),
'file' => 'messaging.admin.inc',
),
);
}
/**
* Add a callback to a callback collection
*
* @param $callback_list
* Existing callback list or method info array
* @param $type
* Callback type
* @param $callback
* Callback function name or array('function_name', arg1, arg2...) *
*/
function _messaging_callback_add(&$callback_list, $type, $callback) {
$name = $type . ' callback';
// If the existing callback is a single function name, make it an array
if (!empty($callback_list[$name]) && !is_array($callback_list[$name])) {
$callback_list[$name] = array($callback_list[$name]);
}
$callback_list[$name][] = $callback;
}
/**
* Get a callback from the information array if present
*
* @param $info
* Information array, typically a messaging method info array
* @param $type
* Callback type, the search key will be '[type] callback'
* @param $default
* Default callback to return if not in the $info array
*/
function _messaging_callback_get($info, $type, $default = NULL) {
if (!empty($info[$type . ' callback'])) {
return $info[$type . ' callback'];
} else {
return $default;
}
}
/**
* Helper function to get property from an info array
*
* Depending on method and property, returns the full array or a specific property
*/
function _messaging_info($info, $method = NULL, $property = NULL, $default = NULL) {
if ($method && $property) {
return isset($info[$method][$property]) ? $info[$method][$property] : $default;
} elseif ($method) {
return isset($info[$method]) ? $info[$method] : $default;
} elseif ($property) {
// Get this property as a list indexed by method
$props = array();
foreach($info as $method => $values) {
if (isset($values[$property])) {
$props[$method] = $values[$property];
}
}
return $props;
} else {
return $info;
}
}
/**
* Get information from an array of data
*
* If $type and $field, return $data[$type][$field]
* If $type and not $field, return $data[$type]
* If not $type and $field, return that field indexed by type
*
* @param $data
* Array of arrays with the form
* array(
* type1 => array(
* field1 => value11,
* field2 => value12,
* ),
* type2 => ...
* )
* @param $type
* Main index to check
* @param $field
* Field in $data[$info] to check
* @param $default
* Value to return if no data found
*/
function messaging_array_info($data, $type = NULL, $field = NULL, $default = NULL) {
if ($field && $type) {
return isset($data[$type][$field]) ? $data[$type][$field] : $default;
}
elseif ($field) {
$return = array();
foreach ($data as $key => $info) {
$return[$key] = isset($info[$field]) ? $info[$field] : $default;
}
return $return;
}
elseif ($type) {
// The default for this case will be an array if not specified
return isset($data[$type]) ? $data[$type] : (isset($default) ? $default : array());
}
else {
return $data;
}
}
/**
* Helper function for query builders.
*
* Using schema data get 'field = [placeholder]' and args arrays
*/
function _messaging_query_conditions($table, $params) {
$schema = drupal_get_schema($table);
$conditions = $args = array();
foreach ($params as $field => $value) {
$type = $schema['fields'][$field]['type'];
// For array values, build IN conditions
if (is_array($value)) {
$conditions[] = $field . ' IN (' . db_placeholders($value, $type) . ')';
$args = array_merge($args, $value);
}
elseif (is_null($value)) {
$condtions[] = $field . ' IS NULL';
}
else {
$conditions[] = $field . ' = ' . db_type_placeholder($type);
$args[] = $value;
}
}
return array('conditions' => $conditions, 'args' => $args);
}
/**
* Short hand for info logs
*
* Call messaging_log(TRUE) to enable logging
*/
function messaging_log($txt = NULL, $variables = NULL) {
if (function_exists('messaging_debug_log')) {
return messaging_debug_log($txt, $variables, 'info');
}
else {
return _messaging_log('info', $txt, $variables);
}
}
/**
* Short hand for debug logs
*
* Call messaging_debug(TRUE) to enable logging
*/
function messaging_debug($txt = NULL, $variables = NULL) {
if (function_exists('messaging_debug_log')) {
return messaging_debug_log($txt, $variables);
}
}
/**
* Get logs without formatting
*/
function messaging_log_get() {
if ($logs = _messaging_log('return')) {
_messaging_log('reset');
return $logs;
}
}
/**
* Init logging system so logs are saved from now on
*/
function messaging_log_start() {
return _messaging_log('start');
}
/**
* Format logs
*/
function messaging_log_format($logs) {
$rows = array();
foreach ($logs as $log) {
list($type, $string, $append, $objects) = _messaging_log_prepare($log);
// Full objects/arrays are only rendered when debug module is enabled
if ($objects && function_exists('_messaging_debug_format_log')) {
$text = _messaging_debug_format_log($type, $string, $append, $objects);
}
else {
$text = $string;
if ($append) {
$text .= '
' . implode(' ', $append);
}
}
$rows[] = array(
$type,
$text,
);
}
return theme('table', array(t('Type'), t('Message')), $rows);
}
/**
* Quick logging for debugging and manual queue processing
*/
function _messaging_log($type, $txt = NULL, $variables = NULL, $severity = WATCHDOG_NOTICE) {
static $enabled = FALSE;
switch ($type) {
case 'info':
case 'debug':
if ($enabled) {
$_SESSION['messaging_log'][] = array($type, $txt, $variables, $severity);
}
break;
case 'return':
return isset($_SESSION['messaging_log']) ? $_SESSION['messaging_log'] : NULL;
break;
case 'reset':
unset($_SESSION['messaging_log']);
break;
case 'start':
$enabled = TRUE;
break;
case 'stop':
$enabled = FALSE;
break;
}
}
/**
* Prepare log item for formatting
*
* Each log item has type, string, args, severity
*/
function _messaging_log_prepare($log) {
list($type, $string, $args, $severity) = $log;
$append = $replace = $objects = array();
if ($args) {
// Transform arguments before inserting them.
foreach ($args as $key => $value) {
if (is_string($value) || is_numeric($value)) {
switch ($key[0]) {
case '@':
// Escaped only.
$replace[$key] = check_plain($value);
break;
case '%':
$replace[$key] = theme('placeholder', $value);
break;
case '!':
// Pass-through.
$replace[$key] = $value;
break;
default:
// Append to string a key value pair, different from watchdog format
$append[$key] = '' . $key . '= ' . check_plain($value);
break;
}
}
else {
$objects[$key] = $value;
}
}
$string = strtr($string, $replace);
}
return array($type, $string, $append, $objects);
}
/**
* Get send method object
*
* @param $method
* Method name or Messaging_Method object
*/
function messaging_send_method($method) {
$send_methods = &messaging_static(__FUNCTION__);
if (is_object($method)) {
return $method;
}
if (!isset($send_methods[$method])) {
$info = messaging_method_info($method);
$class = !empty($info['class']) ? $info['class'] : 'Messaging_Send_Method';
$send_methods[$method] = new $class($info, $method);
}
return $send_methods[$method];
}
/**
* Build Message object from message array
*
* The $message array may have the following elements
* 'subject' => Message subject, may be already rendered or not
* 'body' => Message content, may be already rendered or not
* 'params' => Optional message params, indexed by sending method group
* I.e. params for mail methods will be in $message['params']['mail']
* 'sender' => Optional int to identify message sender, may be $user->uid
* 'sender_account' => Optional user account to use as message sender
*/
function messaging_message_build($message) {
if (is_object($message) && $message instanceof Messaging_Message) {
return $message;
}
else {
return new Messaging_Message($message);
}
}
/**
* Central static variable storage, Drupal 7 core backport
*
* See http://api.drupal.org/api/function/drupal_static/7
*/
function &messaging_static($name, $default_value = NULL, $reset = FALSE) {
static $data = array(), $default = array();
if (!isset($name)) {
// All variables are reset. This needs to be done one at a time so that
// references returned by earlier invocations of drupal_static() also get
// reset.
foreach ($default as $name => $value) {
$data[$name] = $value;
}
// As the function returns a reference, the return should always be a
// variable.
return $data;
}
if ($reset) {
// The reset means the default is loaded.
if (array_key_exists($name, $default)) {
$data[$name] = $default[$name];
}
else {
// Reset was called before a default is set and yet a variable must be
// returned.
return $data;
}
}
elseif (!array_key_exists($name, $data)) {
// Store the default value internally and also copy it to the reference to
// be returned.
$default[$name] = $data[$name] = $default_value;
}
return $data[$name];
}