'); /** * Implementation of hook_autoload_info(). */ function messaging_autoload_info() { return array( 'Messaging_Object' => array('file' => 'includes/messaging_object.class.inc'), 'Messaging_Cached_Object' => array('file' => 'includes/messaging_object.class.inc'), 'Messaging_Destination' => array('file' => 'includes/messaging_destination.class.inc'), 'Messaging_Message' => array('file' => 'includes/messaging_message.class.inc'), 'Messaging_Send_Method' => array('file' => 'includes/messaging_method.class.inc'), 'Messaging_Method_Mail' => array('file' => 'includes/messaging_method_mail.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; case 'admin/messaging/settings/method': $output = '

' . t('Depending on your content format and the tokens you are using for messages it is important that you use the right filtering for the message body. Set up the filters you need using the Input formats page', array('@input_formats' => url('admin/settings/filters'))) . '

'; return $output; } } /** * 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, ); 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 'delete': // Delete user data from tables Messaging_Destination::delete_multiple(array('uid' => $user->uid)); db_query("DELETE FROM {messaging_store} WHERE uid = %d", $user->uid); break; case 'update': // Claim user mail address if in destinations table if (function_exists('messaging_mail_update_user')) { messaging_mail_update_user($user); } break; 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 **/ /** * Get send method object * * @param $method * Method name or Messaging_Method object * @param $method_info * Array of properties to build a custom send method */ function messaging_send_method($method, $method_info = array()) { $send_methods = &messaging_static(__FUNCTION__); if (is_object($method)) { return $method; } if (!isset($send_methods[$method])) { if ($info = messaging_method_info($method)) { $class = !empty($info['class']) ? $info['class'] : 'Messaging_Send_Method'; $send_methods[$method] = new $class($method, $info); } else { // No info available from modules. This is a custom method or a disabled one $send_methods[$method] = new Messaging_Send_Method($method, $method_info); } } return $send_methods[$method]; } /** * Build message object from object or array */ function messaging_message_build($message) { if(is_object($message) && is_a($message, 'Messaging_Message')) { return $message; } else { return new Messaging_Message($message); } } /** * Send message to destination object * * @param $destination * Messaging Destination 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 $queue * Optional send method. Defaults to the user account predefined method */ function messaging_message_send_destination($destination, $message, $queue = FALSE) { messaging_debug('Sending message to destination', array('destination' => $destination, 'message' => $message)); // Build array of parameters so they can be overridden by callbacks $message = messaging_message_build($message); $message->uid = $destination->uid; $message->method = $destination->method; $message->destination = $destination->address; $message->acccount = $destination->get_account(); if ($queue) { return $message->queue(); } else { return $message->send(); } } /** * 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 = FALSE) { messaging_debug('Sending message to user', array('account' => $account, 'message' => $message, 'method' => $method)); // Build array of parameters so they can be overridden by callbacks $message = messaging_message_build($message); $message->method = $method ? $method : messaging_method_default($account); $message->queue = $queue ? 1 : 0; // Log in case it cannot be delivered. This can be overridden by user callback //$message->log = TRUE; $message->set_user($account); // Check user and availability if there's a callback for that. Depending on the sending method, // when user is not available it may just be discarded / queued / redirected through other method $message->process = TRUE; $message->discard = FALSE; // This can go through multiple redirections, when done $process should be FALSE while (!$message->queue && $message->method && !$message->discard && $message->process && ($callback = messaging_method_info($message->method, 'user callback'))) { $params = _messaging_callback_invoke($callback, $message); } // The sending method may have decided the message is to be discarded. if ($message->discard) { return FALSE; } if ($message->method && empty($message->destination)) { $message->destination = messaging_user_destination($account, $message->method, $message); } // Now check that we have a destination for this user account. If set to FALSE we just don't try anymore // Send the message or, if no destination, abort the message sending if ($message->method && $message->destination) { messaging_debug('Found destination for user, sending message', array('method' => $message->method, 'destination' => $message->destination)); $message->send(); } elseif (!empty($message->log)) { // Save the message, let it there for further reference messaging_log('Destination not available for user account', array('method' => $method, 'account' => $account)); $message->destination = 'ERROR'; $message->cron = $message->queue = 0; $message->log = 1; $message->success = FALSE; $message->store(); } return $message->success; } /** * Build destination object from user account (and create destination if not exists) */ function messaging_account_build_destination($account, $method = NULL, $address = NULL) { if ($account->uid) { if ($method && !$address) { $address = messaging_user_destination($account, $method); } if ($method && $address) { return Messaging_Destination::create($method, $address, $account->uid); } elseif (($fallback = messaging_method_default($account)) && $fallback != $method) { // Retry with new method return messaging_account_build_destination($account, $fallback); } } elseif ($method && $address) { // Anonymous users // @todo check the address doesn't belong to any user ??? return Messaging_Destination::create($method, $address, 0); } } /** * Get destination from user account. * * This will handle also anonymous user accounts that should have a 'destination' property */ function messaging_user_destination($account, $method, $message = NULL) { return messaging_send_method($method)->get_user_address($account); } /** * Send message to array of destinations. 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)); // Convert into an object and add all the information into the message object $message = messaging_message_build($message); $message->method = $method ? $method : messaging_method_default(NULL); $message->source['type'] = 'outgoing'; $message->destinations = $destinations; $message->queue = $queue ? 1 : 0; $message->sent = $message->queued = 0; if ($queue) { $message->queue(); } else { $message->send_multiple(); } // This will return true if the message was sent or queued for delivery if (!isset($message->success)) { $message->success = $message->sent || $message->queued; } return $message->success; } /** * Test sending, just log message */ function messaging_message_test($message, $destinations = array()) { $message->prepare(); $message->render(); messaging_log('Emulating message sending (test run)', array('summary' => (string)$message, 'message' => $message, 'destinations' => $destinations)); return $message->success = TRUE; } /** * Message default callback: preprocessing */ function messaging_message_prepare($message, $info) { Messaging_Send_Method::default_prepare($message, $info); } /** * 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 $address * 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($address, $message, $method) { $message = messaging_message_build($message); $message->method = $method; if ($send_method = messaging_send_method($method)) { return $send_method->send_address($address, $message); } else { watchdog('messaging', 'Message could not be delivered for method %method', array('%method' => $method), WATCHDOG_ERROR); return FALSE; } } /** * Implementation of hook_cron() * * Process queued messages for delivery */ function messaging_cron() { messaging_store('queue_process'); messaging_store('queue_cleanup'); } /** * 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]); } else { $info[$method] = messaging_translate("method:$method:name", $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) { $send_method = messaging_send_method($method); return $send_method && $send_method->user_access($account); } /** * 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 from variable for each enabled method foreach (array_keys($info) as $name) { $info[$name] = array_merge($info[$name], variable_get('messaging_method_' . $name, array())); } // Allow altering by other modules drupal_alter('messaging_methods', $info); } return messaging_array_info($info, $method, $property, $default); } /** * 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) { return Messaging_Send_Method::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() { messaging_include('messaging_store.inc'); $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] = $uid ? user_load($uid) : drupal_anonymous_user(); } return $cache[$uid]; } /** * Helper function for message loading from the store * * @param $mqid * Message id */ function messaging_message_load($mqid, $refresh = FALSE) { static $cache; if (!isset($cache[$mqid]) || $refresh) { if ($message = messaging_store('load', $mqid)) { $cache[$mqid] = $message; } else { $cache[$mqid] = FALSE; } } return $cache[$mqid]; } /** * Renders full message with header and body */ function messaging_message_render($message, $info) { return Messaging_Send_Method::default_render($message, $info); } /** * Composes message from different parts, recursively and applies filter */ function messaging_text_render($text, $glue = '', $filter = NULL) { return Messaging_Send_Method::text_render($text, $glue, $filter); } /** * Build a simple text with message subject and body */ function messaging_text_build($message, $glue = ' ') { return Messaging_Send_Method::text_build($message, $glue); } /** * Clean text of HTML stuff and optionally of line endings */ function messaging_text_clean($text, $newline= NULL) { return Messaging_Send_Method::text_clean($text, $newline); } /** * Truncate messages to given length. Adapted from node_teaser() in node.module */ function messaging_text_truncate($text, $length) { return Messaging_Send_Method::text_truncate($text, $length); } /** * Implementation of hook_requirements() */ function messaging_requirements($phase) { $requirements = array(); // Ensure translations don't break at install time $t = get_t(); if ($phase == 'runtime') { $methods = messaging_method_list(); // Ensure that we have some sending methods available if (!$methods) { $requirements['messaging'] = array( 'title' => $t('Messaging sending methods'), 'value' => $t('No sending method plug-ins available. Please enable some Sending Method on the !admin-modules page.', array('!admin-modules' => l($t('Modules administration'), 'admin/build/modules'))), 'severity' => REQUIREMENT_ERROR, ); } } return $requirements; } /** * 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)) { messaging_message_invoke($callback, $message, $info); } elseif (function_exists('messaging_message_' . $key)) { 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.'); } if ($type == 'destination' || $type == 'all') { $tokens['destination']['destination-address'] = t('Destination address.'); $tokens['destination']['destination-address-name'] = t('Destination address name.'); $tokens['destination']['destination-method-name'] = t('Destination method name.'); } 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->get_subject()); $values['message-body'] = filter_xss($message->get_body()); $values['message-author-name'] = check_plain($message->get_sender_name()); $tokens['message-method'] = messaging_method_info($message->method, 'name'); $tokens['message-date'] = format_date($message->sent); return $values; } break; case 'destination': // Messaging destinations if ($destination = $object) { $values['destination-address'] = $destination->format_address(FALSE); $values['destination-address-name'] = $destination->address_name(); $values['destination-method-name'] = $destination->method_name(); } 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_array_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; } } /** * Helper function for query builders. * * Using schema data get 'field = [placeholder]' and args arrays * * @param $table * Table name (to be prefixed) * @param $params * Array of field => value conditions * @param $table_alias * Optional table alias to prefix fields in conditions */ function _messaging_query_conditions($table, $params, $table_alias = NULL) { $schema = drupal_get_schema($table); $conditions = $args = array(); foreach ($params as $field => $value) { $type = $schema['fields'][$field]['type']; $field_name = $table_alias ? "$table_alias.$field" : $field; // For array values, build IN conditions if (is_array($value)) { $conditions[] = $field_name . ' IN (' . db_placeholders($value, $type) . ')'; $args = array_merge($args, $value); } elseif (is_null($value)) { $condtions[] = $field_name . ' IS NULL'; } else { $conditions[] = $field_name . ' = ' . db_type_placeholder($type); $args[] = $value; } } // Return arrwy with conditions and arguments. Also full where clause. return array('conditions' => $conditions, 'args' => $args, 'where' => implode(' AND ', $conditions)); } /** * Short hand for info logs */ function messaging_log($txt = NULL, $variables = NULL) { return _messaging_log('info', $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'); } /** * Short hand for debug logs */ function messaging_debug($txt = NULL, $variables = NULL) { if (function_exists('messaging_debug_log')) { return messaging_debug_log($txt, $variables); } } /** * Print formatted logs as table */ function messaging_get_log() { if ($logs = _messaging_log()) { messsaging_log_format($logs); } else { return ''; } } /** * Format logs */ function messaging_log_format($logs) { $rows = array(); foreach ($logs as $log) { list($type, $string, $append, $objects) = _messaging_log_format($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; } } /** * Format messaging / notifications log as single text line */ function _messaging_log_format($log) { list($type, $string, $args, $severity) = $log; if ($args) { // Transform arguments before inserting them. $append = $replace = $objects = array(); foreach ($args as $key => $value) { if (is_numeric($value) || is_string($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; } } elseif (is_array($value) || is_object($value)) { $objects[$key] = $value; } } $string = strtr($string, $replace); } return array($type, $string, $append, $objects); } /** * Wrapper function for 1i8nstrings() if i18nstrings enabled. */ function messaging_translate($name, $string, $langcode = NULL, $textgroup = 'messaging') { return function_exists('i18nstrings') ? i18nstrings($textgroup . ':' . $name, $string, $langcode) : $string; } /** * Implementation of hook_locale(). */ function messaging_locale($op = 'groups') { switch ($op) { case 'groups': return array('messaging' => t('Notifications')); case 'info': $info['messaging']['refresh callback'] = 'messaging_locale_refresh'; $info['messaging']['format'] = TRUE; // Strings may have format return $info; } } /** * Refresh strings for translation system */ function messaging_locale_refresh() { foreach (messaging_method_info() as $name => $info) { i18nstrings_update("messaging:method:$name:name", $info['name']); } return TRUE; } /** * 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]; } /** * Reset static variable. Drupal 7 core backport. * * See http://api.drupal.org/api/function/drupal_static_reset/7 * * @param $name * Name of the static variable to reset. Omit to reset all variables. */ function messaging_static_reset($name = NULL) { messaging_static($name, NULL, TRUE); } /** * Load destination from key. Menu autoloading. */ function messaging_destination_load($mdid) { return Messaging_Destination::load($mdid); } /** * Common library for mail methods * * This is the only non method agnostic functionality in this module. As there are several plug-ins * for mail sending, we add this helper function here so its available for all them. */ /** * Rebuild message in Drupal mail format */ function messaging_mail_prepare($destination, $message, $params, $alter = TRUE) { return Messaging_Method_Mail::mail_prepare($destination, $message, $params, $alter); } /** * Get mail headers. Helper function for mail methods * */ function messaging_mail_headers($message, $params) { return Messaging_Method_Mail::mail_headers($message, $params); } /** * Get list of mail methods */ function messaging_mail_methods() { return Messaging_Method_Mail::mail_methods(); } /** * Update destinations when a user account is updated, created * * The destinations for that mail account will be assigned to the user */ function messaging_mail_update_user($account) { return Messaging_Method_Mail::mail_update_user($account); } /** * Include module files as necessary. * * The files must be in an 'includes' subfolder inside the module folder. */ function messaging_include($file, $module = 'messaging') { static $included = array(); if (!isset($included[$module][$file])) { require_once './' . drupal_get_path('module', $module) . '/includes/' . $file; $included[$module][$file] = TRUE; } }