Index: modules/contact/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v
retrieving revision 1.86
diff -u -r1.86 contact.module
--- modules/contact/contact.module 31 May 2007 12:03:18 -0000 1.86
+++ modules/contact/contact.module 3 Jun 2007 17:40:44 -0000
@@ -360,44 +360,46 @@
* Process the personal contact page form submission.
*/
function contact_mail_user_submit($form, &$form_state, $form_values) {
- global $user;
+ global $user, $language;
$account = user_load(array('uid' => arg(1), 'status' => 1));
- // Compose the body:
- $message[] = "$account->name,";
- $message[] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE)), '!form-url' => url($_GET['q'], array('absolute' => TRUE)), '!site' => variable_get('site_name', 'Drupal')));
- $message[] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE))));
- $message[] = t('Message:');
- $message[] = $form_values['message'];
-
- // Tidy up the body:
- foreach ($message as $key => $value) {
- $message[$key] = wordwrap($value);
- }
-
- // Prepare all fields:
- $to = $account->mail;
- $from = $user->mail;
-
- // Format the subject:
- $subject = '['. variable_get('site_name', 'Drupal') .'] '. $form_values['subject'];
-
- // Prepare the body:
- $body = implode("\n\n", $message);
+
+ // Format the subject
+ $message['#subject'] = text_t('[!site_name] !contact_subject');
+ // Compose the body
+ $message['#body'][] = text("!contact_name_to,");
+ $message['#body'][] = text_t("!contact_name_from (!contact_from_url) has sent you a message via your contact form (!contact_form_url) at !site_name.");
+ $message['#body'][] = text_t("If you don't want to receive such e-mails, you can change your settings at !contact_to_url.");
+ $message['#body'][] = text_t('Message:');
+ $message['#body'][] = $form_values['message'];
+
+ // Add language independent variables and parameters to message
+ // The rest of the variables will be added in contact_mail_alter() once
+ // the language of the e-mail has been decided for each recipient.
+
+ $message['#variables'] = array(
+ '!contact_subject' => $form_values['subject'],
+ '!contact_name_from' => $user->name,
+ '!contact_name_to' => $account->name,
+ );
+ $message['#params'] = array(
+ 'user_from' => $user,
+ 'user_to' => $account,
+ );
+
+ // Send the e-mail to the recipient. The language will be the user's language or the site default
+ $message['#from'] = $user->mail;
+ user_mail('user-contact-mail', $account, $message);
- // Send the e-mail:
- drupal_mail('contact-user-mail', $to, $subject, $body, $from);
-
- // Send a copy if requested:
+ // Send a copy to the user, if requested.
+ // The default language for the copy will be the current page one.
if ($form_values['copy']) {
- drupal_mail('contact-user-copy', $from, $subject, $body, $from);
+ $message['#language'] = $language;
+ user_mail('user-contact-copy', $user, $message);
}
- // Log the operation:
flood_register_event('contact');
watchdog('mail', '%name-from sent %name-to an e-mail.', array('%name-from' => $user->name, '%name-to' => $account->name));
-
- // Set a status message:
drupal_set_message(t('The message has been sent.'));
// Jump to the user's profile page:
@@ -406,6 +408,27 @@
}
/**
+ * Implementation of hook_mail_alter().
+ */
+function contact_mail_alter(&$message) {
+ switch ($message['#mail_id']) {
+ case 'user-contact-mail':
+ case 'user-contact-copy':
+ $user_from = $message['#params']['user_from'];
+ $user_to = $message['#params']['user_to'];
+ $tokens = array(
+ '!contact_from_url' => url("user/$user_from->uid", array('absolute' => TRUE, 'language' => $message['#language'])),
+ '!contact_url' => url("user/$user_to->uid", array('absolute' => TRUE, 'language' => $message['#language'])),
+ );
+ // No break
+ case 'contact-page-mail':
+ $tokens['!contact_form_url'] = url($_GET['q'], array('absolute' => TRUE, 'language' => $message['#language']));
+
+ $message['#variables'] += $tokens;
+ }
+}
+
+/**
* Site-wide contact page
*/
function contact_site_page() {
@@ -509,40 +532,51 @@
* Process the site-wide contact page form submission.
*/
function contact_mail_page_submit($form, &$form_state, $form_values) {
-
+ global $language;
+
// E-mail address of the sender: as the form field is a text field,
// all instances of \r and \n have been automatically stripped from it.
$from = $form_values['mail'];
- // Compose the body:
- $message[] = t("!name sent a message using the contact form at !form.", array('!name' => $form_values['name'], '!form' => url($_GET['q'], array('absolute' => TRUE))));
- $message[] = $form_values['message'];
-
- // Tidy up the body:
- foreach ($message as $key => $value) {
- $message[$key] = wordwrap($value);
- }
-
// Load the category information:
$contact = db_fetch_object(db_query("SELECT * FROM {contact} WHERE cid = %d", $form_values['cid']));
- // Format the category:
- $subject = t('[!category] !subject', array('!category' => $contact->category, '!subject' => $form_values['subject']));
-
- // Prepare the body:
- $body = implode("\n\n", $message);
-
- // Send the e-mail to the recipients:
- drupal_mail('contact-page-mail', $contact->recipients, $subject, $body, $from);
+ // Compose the mail message:
+ $message['#subject'] = text_t('[!contact_category] !contact_subject');
+ $message['#body'][] = text_t("!contact_name sent a message using the contact form at !contact_form_url.");
+ $message['#body'][] = $form_values['message'];
+
+ // Collect variables for later replacement
+ $message['#variables'] = array(
+ '!contact_category' => $contact->category,
+ '!contact_subject' => $form_values['subject'],
+ '!contact_name' => $form_values['name'],
+ );
+
+ // Send the e-mail to the recipients using the default site language:
+ $message['#to'] = $contact->recipients;
+ $message['#from'] = $from;
+ $message['#language'] = language_default();
+
+ drupal_mail('contact-page-mail', $message);
- // If the user requests it, send a copy.
+ // If the user requests it, send a copy using current language.
if ($form_values['copy']) {
- drupal_mail('contact-page-copy', $from, $subject, $body, $from);
+ $message['#to'] = $from;
+ $message['#langcode'] = $language->language;
+
+ drupal_mail('contact-page-copy', $message);
}
// Send an auto-reply if necessary:
if ($contact->reply) {
- drupal_mail('contact-page-autoreply', $from, $subject, wordwrap($contact->reply), $contact->recipients);
+ $message['#mail_id'] = 'contact-page-autoreply';
+ $message['#to'] = $from;
+ $message['body'][] = $contact->reply;
+ $message['#from'] = $contact->recipients;
+ $message['#langcode'] = $language->language;
+
+ drupal_mail($message);
}
// Log the operation:
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.650
diff -u -r1.650 common.inc
--- includes/common.inc 1 Jun 2007 09:49:11 -0000 1.650
+++ includes/common.inc 3 Jun 2007 17:40:43 -0000
@@ -2276,30 +2276,58 @@
* Send an e-mail message, using Drupal variables and default settings.
* More information in the
* PHP function reference for mail()
- * @param $mailkey
+ *
+ * This function automatically renders the 'subject' and 'body' elements
+ * if present, using text rendering functions.
+ *
+ * @see drupal_render_text
+ *
+ * @see drupal_render_mail
+ *
+ * The mail data is an array that should have the following elements:
+ *
+ * #mail_id
* A key to identify the mail sent, for altering.
- * @param $to
+ * #to
* The mail address or addresses where the message will be send to. The
* formatting of this string must comply with RFC 2822. Some examples are:
* user@example.com
* user@example.com, anotheruser@example.com
* User
* User , Another User
- * @param $subject
- * Subject of the e-mail to be sent. This must not contain any newline
- * characters, or the mail may not be sent properly.
- * @param $body
- * Message to be sent. Drupal will format the correct line endings for you.
- * @param $from
+ * #subject
+ * Subject of the e-mail to be sent. It can be a text array for rendering
+ * or an plain text. This must not contain any newline characters, or the
+ * mail may not be sent properly.
+ *
+ * #body
+ * Message to be sent.It can be a plain text or an array for text rendering.
+ * Drupal will format the correct line endings for you.
+ *
+ * Optional elements
+ *
+ * #from
* Sets From, Reply-To, Return-Path and Error-To to this value, if given.
- * @param $headers
+ * #headers
* Associative array containing the headers to add. This is typically
* used to add extra headers (From, Cc, and Bcc).
- * When sending mail, the mail must contain a From header.
+ * When sending mail, the mail must contain a From header.
+ * #language
+ * Language object to localize some parts of the e-mail
+ * #variables
+ * Tokens for replacement when rendering the body or the header
+ * #params
+ * Optional parameters to build the mail
+ *
+ * @param $message
+ * An array containing all the mail data. It supports text rendering for header
+ * and body.
+ *
* @return Returns TRUE if the mail was successfully accepted for delivery,
* FALSE otherwise.
*/
-function drupal_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array()) {
+function drupal_mail($mail_id, &$message = array()) {
+ // Add default headers
$defaults = array(
'MIME-Version' => '1.0',
'Content-Type' => 'text/plain; charset=UTF-8; format=flowed',
@@ -2310,21 +2338,39 @@
// Return-Path headers should have a domain authorized to use the originating
// SMTP server. Errors-To is redundant, but shouldn't hurt.
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
+
+ // Add default properties
+ $message += array(
+ '#mail_id' => $mail_id,
+ '#from' => $default_from,
+ '#headers' => array(),
+ '#variables' => array(),
+ '#language' => language_default(),
+ );
+
if ($default_from) {
- $defaults['From'] = $defaults['Reply-To'] = $defaults['Sender'] = $defaults['Return-Path'] = $defaults['Errors-To'] = $default_from;
- }
- if ($from) {
- $defaults['From'] = $defaults['Reply-To'] = $from;
+ $defaults['Sender'] = $defaults['Return-Path'] = $defaults['Errors-To'] = $default_from;
}
- $headers = array_merge($defaults, $headers);
+ $defaults['From'] = $defaults['Reply-To'] = $message['#from'];
- // Bundle up the variables into a structured array for altering.
- $message = array('#mail_id' => $mailkey, '#to' => $to, '#subject' => $subject, '#body' => $body, '#from' => $from, '#headers' => $headers);
+ $message['#headers'] += $defaults;
+
+ // Allow modules to alter message and add their variables
drupal_alter('mail', $message);
+
$mailkey = $message['#mail_id'];
$to = $message['#to'];
- $subject = $message['#subject'];
- $body = $message['#body'];
+
+ // We render subject and body. First add defaults for mail body
+ if (is_array($message['#body'])) {
+ // If the body is an array, may need defaults for rendering
+ $message['#body'] += array('#wordwrap' => 75, '#glue' => "\n\n");
+ }
+ // We render the variables only once preparing them for substitution
+ $variables = drupal_render_arguments($message['#variables'], $message['#language']);
+ $subject = drupal_render_text($message['#subject'], $message['#language'], $variables);
+ $body = drupal_render_text($message['#body'], $message['#language'], $variables);
+
$from = $message['#from'];
$headers = $message['#headers'];
@@ -2599,6 +2645,206 @@
}
/**
+ * Returns text lines ready for later rendering.
+ *
+ * This function outputs arrays containing text information
+ * ready for rendering with drupal_text_render()
+ *
+ * @see drupal_text_render()
+ *
+ * @param $value
+ * String containing the text to be localized or replaced and rendered
+ * @param $replace
+ * Whether to do text replacement with provided tokens
+ * @param $localize
+ * Whether to run the string through localization system
+ * @param $type
+ * Optional type of element, will default to 'string'
+ * @prefix
+ * Prefix for the string after rendering. Useful to compose html text.
+ * @sufix
+ * Sufix for the string after rendering. Useful to compose html text.
+ */
+function text($value, $replace = TRUE, $localize = FALSE, $type = 'string', $prefix = '', $sufix = '') {
+ return array(
+ '#type' => $type,
+ '#value' => $value,
+ '#replace' => $replace,
+ '#localize' => $localize,
+ '#prefix' => $prefix,
+ '#sufix' => $sufix
+ );
+}
+
+/**
+ * Shorthand function for translatable text lines
+ *
+ * This is only a wrapper for text() function for quick writing
+ * and for marking the strings to be localized for the locale extractor.
+ *
+ * @see text()
+ *
+ * @param $value
+ * String to be localized and then replaced with tokens
+ */
+function text_t($value) {
+ return text($value, TRUE, TRUE);
+}
+
+/**
+ * Render different types of text arrays into strings.
+ *
+ * This function should be used for composing complex texts or email texts. Texts are
+ * composed using arrays, similar to forms, with some parameters, and then rendered using
+ * this function. It supports localization of single text lines and also
+ * has some internal caching allowing quick localization of a single text to multiple
+ * languages.
+ *
+ * Example to print the same message in all available languages:
+ *
+ * @code
+ * // Delayed localization with parameter substitution
+ *
+ * // There are other types of arrays that may be rendered so we have to state the type.
+ * // Each array line will be rendered as a string and glued together at the end.
+ *
+ * // We set the text type for it to be rendered right
+ * $text['#type'] = 'text';
+ * // This text will be localized and replaced with variables
+ * $text[] = text_t('Hello !username,');
+ * // This text will be localized and replaced with variables
+ * $text[] = text_t('A new !content_type has been posted to !site_name:');
+ * // Simple string, won't be localized nor replaced with variables
+ * $text[] = $node->title.'.';
+ * // This text will be replaced but not localized
+ * $text[] = text('!site_slogan');
+ *
+ * // This one is more tricky. A variable whose default will be localized when rendering
+ * $text[] => array(
+ * '#type' => 'variable',
+ * '#name' => 'site_slogan',
+ * '#default'=> text_t('Drupal rocks!'), // We can nest arguments and text arrays !!
+ * );
+ * // Special formats for the text
+ * $text['#glue'] = ' '; // Will be used for gluing the lines together
+ * // Variables for replacement
+ * $args['!site_name'] => variable_get('site_name', 'Drupal'); // Simple text, won't be localized
+ * $args['!content_type'] => text_t($node->type); // The variable will be localized
+ * $args['!username'] = $user->name;
+ *
+ * // Localize for all languages
+ * $output = '';
+ * foreach (language_list() as $language) {
+ * $output .= $language->name .':'. drupal_render_text($text, $args, $language->language);
+ * }
+ *
+ * @endcode
+ *
+ * @see text()
+ *
+ * @see text_t()
+ *
+ * @param $text
+ * Text to be rendered in array form
+ * @param $langcode
+ * Optional language code, for language different to current one
+ * @param $variables
+ * Arguments ready for replacement
+ * @param $defaults
+ * Internal use only
+ *
+ * @return
+ * Plain text rendered according to parameters.
+ */
+function drupal_render_text(&$text, $language, $variables = array(), $defaults = array(), $debug = FALSE) {
+ static $text_defaults = array('#type' => 'text', '#value' => '', '#replace' => FALSE, '#localize' => FALSE,
+ '#wordwrap' => 0, '#glue' => "\n", '#param' => array(), '#rendered' => array(),
+ '#prefix' => '', '#sufix' => '', '#cache' => FALSE
+ );
+
+ // Add defaults. If plain text, or no text type return value
+ if (!is_array($text)) {
+ $text = array('#type' => 'value', '#value' => $text);
+ }
+
+ // Add defaults before processing, in the right order for overriding
+ $text += $defaults + $text_defaults;
+
+ // If already rendered for this language, and is cacheable just return value
+ if ($text['#cache'] && isset($text['#rendered'][$language->language])) {
+ return $text['#rendered'][$languag->language];
+ }
+
+ // Get value depending on type
+ switch ($text['#type']) {
+ case 'text':
+ // Array of text lines, render each line and merge
+ foreach (element_children($text) as $index) {
+ // We render each text line passing the wordwrap paramater
+ $value[] = drupal_render_text($text[$index], $language, $variables, array('#wordwrap' => $text['#wordwrap']), $debug);
+ }
+ // Now we glue the text together
+ $value = implode($text['#glue'], $value);
+ break;
+ case 'variable':
+ // The default value may need to be localized so we render it
+ $value = variable_get($text['#name'], drupal_render_text($text['#default'], $language, array(), array(), $debug));
+ break;
+ case 'value':
+ case 'string':
+ default:
+ $value = $text['#value'];
+ break;
+ }
+
+ // Process optional parameters. Localize, replace, wordwrap....
+ if ($text['#localize']) {
+ $value = t($value, array(), $language->language);
+ }
+ if ($text['#replace'] && $variables) {
+ $value = strtr($value, $variables);
+ }
+ if ($text['#wordwrap']) {
+ $value = wordwrap($value, $text['#wordwrap']);
+ }
+ $value = $text['#prefix'] . $value . $text['#sufix'];
+
+ // We cache this text for this language unless specified otherwise
+ if ($text['#cache']) {
+ $text['#rendered'][$language->language] = $value;
+ }
+ // Debug support, temporary
+ if ($debug) drupal_set_message("drupal_render_text: type=".$text['#type'].' value='.$text['#value'].' result='.$value);
+
+ return $value;
+}
+
+/**
+ * Render an array of text arguments for replacement
+ */
+function drupal_render_arguments($args, $language) {
+ $variables = array();
+ // Render variables for replacement, values will be also rendered
+ // We pass the full variables array, to the next one to allow complex composition
+ foreach (element_children($args) as $name) {
+ $value = drupal_render_text($args[$name], $language, $variables);
+ switch ($name[0]) {
+ case '@':
+ $variables[$name] = check_plain($value);
+ break;
+ case '%':
+ $variables[$name] = theme('placeholder', $value);
+ break;
+ case '!':
+ default:
+ // Just asign result
+ $variables[$name] = $value;
+ }
+ }
+ return $variables;
+}
+
+/**
* Function used by uasort in drupal_render() to sort structured arrays
* by weight.
*/
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.177
diff -u -r1.177 locale.module
--- modules/locale/locale.module 30 May 2007 08:08:58 -0000 1.177
+++ modules/locale/locale.module 3 Jun 2007 17:40:45 -0000
@@ -186,12 +186,14 @@
* Implementation of hook_user().
*/
function locale_user($type, $edit, &$user, $category = NULL) {
- if ($type == 'form' && $category == 'account' && variable_get('language_count', 1) > 1 && variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE) == LANGUAGE_NEGOTIATION_PATH) {
+ global $language;
+ if (variable_get('language_count', 1) > 1 && ($type == 'register' && user_access('administer users') || $type == 'form' && $category == 'account' )) {
$languages = language_list('enabled');
$languages = $languages['1'];
- if ($user->language == '') {
- $user->language = language_default('language');
- }
+
+ // If user ir being created, so we set user language to the current page one
+ $user_language = $user ? user_language($user) : $language;
+
$names = array();
foreach ($languages as $langcode => $language) {
$names[$langcode] = t($language->name) .' ('. $language->native .')';
@@ -200,11 +202,12 @@
'#title' => t('Interface language settings'),
'#weight' => 1,
);
+
$form['locale']['language'] = array('#type' => 'radios',
'#title' => t('Language'),
- '#default_value' => $user->language,
+ '#default_value' => $user_language->language,
'#options' => $names,
- '#description' => t('Selecting a different locale will change the interface language of the site.'),
+ '#description' => t('Selecting a locale will set the default site interface and mail language for this account.'),
);
return $form;
}
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.788
diff -u -r1.788 user.module
--- modules/user/user.module 30 May 2007 08:08:59 -0000 1.788
+++ modules/user/user.module 3 Jun 2007 17:40:48 -0000
@@ -1205,6 +1205,67 @@
}
/**
+ * Send an e-mail message to a user account or a destination mail address.
+ *
+ * This is basically a wrapper for drupal_mail(), but some predefined variables
+ * are added and when the destination mail address belongs to a user, some properties
+ * are pulled from the user account.
+ *
+ * @see drupal_mail()
+ *
+ * @param $destination
+ * User account or e-mail address to which the e-mail will be sent.
+ * @param $message
+ * Message array.
+ * @return
+ * Returns TRUE if the mail was successfully accepted for
+ * delivery, FALSE otherwise.
+ */
+function user_mail($mail_id, $destination, &$message = array()) {
+ // Get user account for destination
+ $account = is_object($destination) ? $destination : user_load(array('mail' => $destination));
+
+ // Get language from user account or from parameters. If the user has a language
+ // that will be it. If not, a language may be passed depending on which type of mail
+ // it is. I.e. for password recovery page, it will be current language, but for contact
+ // messages it will be the site default.
+ if ($account && $account->language) {
+ $language = user_language($account);
+ } else {
+ $language = isset($message['#language']) ? $message['#language'] : language_default();
+ }
+
+ // Add properties to message array
+ $message['#to'] = $mail = $account ? $account->mail : $destination;
+ $message['#language'] = $language;
+ $message['#user'] = $account;
+
+ // Further e-mail processing, rendering, etc, and send e-mail
+ return drupal_mail($mail_id, $message);
+}
+
+/**
+ * Returns the code of the language preferred by the
+ * user if set or the default language code.
+ *
+ * @param $account
+ * Optional user account. Falls back to the current $user.
+ */
+function user_language($account = NULL) {
+ global $user;
+
+ $account = isset($account) ? $account : $user;
+
+ // The user language will be the site default if no language is set for the account.
+ if (isset($account->language) && $account->language) {
+ $language_list = language_list();
+ return $language_list[$account->language];
+ } else {
+ return language_default();
+ }
+}
+
+/**
* Menu callback; process one time login link and redirects to the user page on success.
*/
function user_pass_reset($uid, $timestamp, $hashed_pass, $action = NULL) {
@@ -1386,7 +1447,7 @@
}
else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) {
// No e-mail verification is required, create new user account, and login user immediately.
- _user_mail_notify('register_no_approval_required', $account, $pass);
+ _user_mail_notify('register_no_approval_required', $account, array('!password' => $pass));
user_authenticate($account->name, trim($pass));
$form_state['redirect'] = '';
return;
@@ -1394,7 +1455,7 @@
else if ($account->status || $notify) {
// Create new user account, no administrator approval required.
$op = $notify ? 'register_admin_created' : 'register_no_approval_required';
- _user_mail_notify($op, $account, $pass);
+ _user_mail_notify($op, $account, array('!password' => $pass));
if ($notify) {
drupal_set_message(t('Password and further instructions have been e-mailed to the new user %user.', array('%user' => $name)));
}
@@ -1406,9 +1467,8 @@
}
else {
// Create new user account, administrator approval required.
- _user_mail_notify('register_pending_approval', $account, $pass);
+ _user_mail_notify('register_pending_approval', $account, array('!password' => $pass));
drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.
In the meantime, your password and further instructions have been sent to your e-mail address.'));
-
}
}
}
@@ -1658,45 +1718,63 @@
/*** Administrative features ***********************************************/
-function _user_mail_text($messageid, $variables = array()) {
-
- // Check if an admin setting overrides the default string.
- if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) {
- return strtr($admin_setting, $variables);
- }
- // No override, return with default strings.
- else {
- switch ($messageid) {
- case 'register_no_approval_required_subject':
- return t('Account details for !username at !site', $variables);
- case 'register_no_approval_required_body':
- return t("!username,\n\nThank you for registering at !site. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables);
- case 'register_admin_created_subject':
- return t('An administrator created an account for you at !site', $variables);
- case 'register_admin_created_body':
- return t("!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables);
- case 'register_pending_approval_subject':
- return t('Account details for !username at !site (pending admin approval)', $variables);
- case 'register_pending_approval_body':
- return t("!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\n\n\n-- !site team", $variables);
- case 'password_reset_subject':
- return t('Replacement login information for !username at !site', $variables);
- case 'password_reset_body':
- return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables);
- case 'status_activated_subject':
- return t('Account details for !username at !site (approved)', $variables);
- case 'status_activated_body':
- return "!username,\n\nYour account at !site has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\nOnce you have set your own password, you will be able to log in to !login_uri in the future using the following username:\n\nusername: !username\n";
- case 'status_blocked_subject':
- return t('Account details for !username at !site (blocked)', $variables);
- case 'status_blocked_body':
- return "!username,\n\nYour account on !site has been blocked.";
- case 'status_deleted_subject':
- return t('Account details for !username at !site (deleted)', $variables);
- case 'status_deleted_body':
- return "!username,\n\nYour account on !site has been deleted.";
- }
+/**
+ * Generate text for the built in emails sent in user.module.
+ *
+ * @param $messageid
+ * Message identifier as used in user_mail().
+ * @param $variables
+ * Values to replace placeholders in the text with.
+ */
+function _user_mail_text($messageid) {
+ // Get default text. We use text_t() to mark text for the locale extractor and because
+ // the text will be localized later using drupal_render_text().
+
+ switch ($messageid) {
+ case 'register_no_approval_required_subject':
+ $default = text_t('Account details for !user_name at !site_name');
+ break;
+ case 'register_no_approval_required_body':
+ $default = text_t("!user_name,\n\nThank you for registering at !site_name. You may now log in to !login_uri using the following username and password:\n\nusername: !user_name\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!user_login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !user_edit_uri so you can change your password.\n\n\n-- !site_name team");
+ break;
+ case 'register_admin_created_subject':
+ $default = text_t('An administrator created an account for you at !site_name');
+ break;
+ case 'register_admin_created_body':
+ $default = text_t("!user_name,\n\nA site administrator at !site_name has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !user_name\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!user_login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !user_edit_uri so you can change your password.\n\n\n-- !site_name team");
+ break;
+ case 'register_pending_approval_subject':
+ $default = text_t('Account details for !user_name at !site_name (pending admin approval)');
+ break;
+ case 'register_pending_approval_body':
+ $default = text_t("!user_name,\n\nThank you for registering at !site_name. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\n\n\n-- !site_name team");
+ break;
+ case 'password_reset_subject':
+ $default = text_t('Replacement login information for !user_name at !site_name');
+ break;
+ case 'password_reset_body':
+ $default = text_t("!user_name,\n\nA request to reset the password for your account has been made at !site_name.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!user_login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !user_edit_uri so you can change your password.");
+ break;
+ case 'status_activated_subject':
+ $default = text_t('Account details for !user_name at !site_name (approved)');
+ break;
+ case 'status_activated_body':
+ $default = text_t("!user_name,\n\nYour account at !site_name has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n!user_login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !user_edit_uri so you can change your password.\n\nOnce you have set your own password, you will be able to log in to !login_uri in the future using the following username:\n\nusername: !user_name\n");
+ break;
+ case 'status_blocked_subject':
+ $default = text_t('Account details for !user_name at !site_name (blocked)');
+ break;
+ case 'status_blocked_body':
+ $default = text_t("!user_name,\n\nYour account on !site_name has been blocked.");
+ break;
+ case 'status_deleted_subject':
+ $default = text_t('Account details for !user_name at !site_name (deleted)');
+ break;
+ case 'status_deleted_body':
+ $default = text_t("!user_name,\n\nYour account on !site_name has been deleted.");
+ break;
}
+ return array('#type' => 'variable', '#name' => 'user_mail_'. $messageid, '#default' => $default);
}
function user_admin_check_user() {
@@ -2450,7 +2528,7 @@
);
// These email tokens are shared for all settings, so just define
// the list once to help ensure they stay in sync.
- $email_token_help = t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.';
+ $email_token_help = t('Available variables are:') .' !user_name, !site_name, !password, !uri_full, !uri_brief, !mailto, !date, !login_uri, !user_edit_uri, !user_login_url.';
$form['email']['admin_created'] = array(
'#type' => 'fieldset',
@@ -3071,83 +3149,103 @@
}
/**
- * Return an array of token to value mappings for user e-mail messages.
- *
- * @param $account
- * The user object of the account being notified. Must contain at
- * least the fields 'uid', 'name', and 'mail'.
- * @param $password
- * Optional string containing the user's current password (if known).
- * @return
- * Array of mappings from token names to values (for use with strtr()).
+ * Implementation of hook_mail_tokens().
*/
-function user_mail_tokens($account, $password = NULL) {
+function user_mail_alter(&$message) {
global $base_url;
+
+ $language = isset($message['#language']) ? $message['#language'] : language_default();
+
+ // Site-wide tokens
$tokens = array(
- '!username' => $account->name,
- '!site' => variable_get('site_name', 'Drupal'),
- '!login_url' => user_pass_reset_url($account),
- '!uri' => $base_url,
- '!uri_brief' => substr($base_url, strlen('http://')),
- '!mailto' => $account->mail,
- '!date' => format_date(time()),
- '!login_uri' => url('user', array('absolute' => TRUE)),
- '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)),
+ '!site_name' => variable_get('site_name', 'Drupal'),
+ '!site_uri_full' => $base_url,
+ '!site_uri_brief' => substr($base_url, strlen('http://')),
+ '!date' => format_date(time()),
+ '!message_mailto' => $message['#to'],
);
- if (!empty($password)) {
- $tokens['!password'] = $password;
+
+ // User dependent values. We make a distinction between the user receiving the e-mail
+ // and the account the e-mail is about
+ if (isset($message['#account']) && $account = $message['#account']) {
+ $tokens += array(
+ '!account_name' => $account->name,
+ '!account_login_url' => user_pass_reset_url($account),
+ '!account_edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE, 'language' => $language)),
+ );
}
- return $tokens;
+ if (isset($message['#user']) && $user = $message['#user']) {
+ $tokens += array(
+ '!user_name' => $user->name,
+ '!user_login_url' => user_pass_reset_url($user),
+ '!user_edit_uri' => url('user/'. $user->uid .'/edit', array('absolute' => TRUE, 'language' => $language)),
+ );
+ }
+ $message['#variables'] += $tokens;
+ var_dump($message);
}
/**
* Conditionally create and send a notification email when a certain
* operation happens on the given user account.
*
+ * @see user_mail()
* @see user_mail_tokens()
* @see drupal_mail()
*
* @param $op
- * The operation being performed on the account. Possible values:
- * 'register_admin_created': Welcome message for user created by the admin
- * 'register_no_approval_required': Welcome message when user self-registers
- * 'register_pending_approval': Welcome message, user pending admin approval
- * 'password_reset': Password recovery request
- * 'status_activated': Account activated
- * 'status_blocked': Account blocked
- * 'status_deleted': Account deleted
+ * The operation being performed on the account. Possible values:
+ * 'register_admin_created': Welcome message for user created by the admin
+ * 'register_no_approval_required': Welcome message when user self-registers
+ * 'register_pending_approval': Welcome message, user pending admin approval
+ * 'password_reset': Password recovery request
+ * 'status_activated': Account activated
+ * 'status_blocked': Account blocked
+ * 'status_deleted': Account deleted
*
* @param $account
- * The user object of the account being notified. Must contain at
- * least the fields 'uid', 'name', and 'mail'.
+ * The user object of the account being notified. Must contain at
+ * least the fields 'uid', 'name', and 'mail'.
*
- * @param $password
- * Optional string containing the user's current password (if known).
+ * @param $variables
+ * Optional variables for text replacement
*
* @return
- * The return value from drupal_mail(), if ends up being called.
+ * The return value from drupal_mail(), if ends up being called.
*/
-function _user_mail_notify($op, $account, $password = NULL) {
+function _user_mail_notify($op, $account, $variables) {
+ global $language;
+
$mail_id = 'user-'. strtr($op, '_', '-');
+
if ($op == 'register_pending_approval') {
// Special case, since we need to distinguish what we send to the
// user and what we send to the administrator, handled below.
$mail_id .= '-user';
}
+
// By default, we always notify except for deleted and blocked.
$default_notify = ($op != 'status_deleted' && $op != 'status_blocked');
$notify = variable_get('user_mail_'. $op .'_notify', $default_notify);
$result = NULL;
+
if ($notify) {
- $from = variable_get('site_mail', ini_get('sendmail_from'));
- $variables = user_mail_tokens($account, $password);
- $subject = _user_mail_text($op .'_subject', $variables);
- $body = _user_mail_text($op .'_body', $variables);
- $result = drupal_mail($mail_id, $account->mail, $subject, $body, $from);
+ $message['#subject'] = _user_mail_text($op .'_subject');
+ $message['#body'][] = _user_mail_text($op .'_body');
+ $message['#variables'] = $variables;
+ $message['#account'] = $account;
+ // This is the only case when the e-mail should be in the current language instead of default
+ $message['#language'] = ($op == 'password_reset') ? $language : language_default();
+ $result = user_mail($mail_id, $account, $message);
if ($op == 'register_pending_approval') {
// If a user registered requiring admin approval, notify the admin, too.
- drupal_mail('user-register-approval-admin', $from, $subject, t("!username has applied for an account.\n\n!edit_uri", $variables), $from);
+ // The admin mail should be in the admin's language or site default language
+ $message['#language'] = language_default();
+ $message['#body'][] = text_t("!account_name has applied for an account.");
+ $message['#body'][] = text("!account_edit_uri");
+ user_mail('user-register-approval-admin', variable_get('site_mail', ini_get('sendmail_from')), $message);
}
}
+
return $result;
}