summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-10-16 03:01:55 +0000
committerDries Buytaert <dries@buytaert.net>2009-10-16 03:01:55 +0000
commit13d3072f418835569f37f65b5055e5b3180fad2e (patch)
tree6964b91e90d3bddbc3d5ce302897c35a248ddf6b /includes
parentb965f7478f34c78b747ad6667738828599e86df7 (diff)
downloadbrdo-13d3072f418835569f37f65b5055e5b3180fad2e.tar.gz
brdo-13d3072f418835569f37f65b5055e5b3180fad2e.tar.bz2
- Patch #356074 by chx, Damien Tournoud: provide a sequences API.
Diffstat (limited to 'includes')
-rw-r--r--includes/mail.inc60
-rw-r--r--includes/module.inc61
-rw-r--r--includes/token.inc18
3 files changed, 96 insertions, 43 deletions
diff --git a/includes/mail.inc b/includes/mail.inc
index f1797b7bb..4b3706188 100644
--- a/includes/mail.inc
+++ b/includes/mail.inc
@@ -14,7 +14,7 @@
* appropriate places in the template. Processed e-mail templates are
* requested from hook_mail() from the module sending the e-mail. Any module
* can modify the composed e-mail message array using hook_mail_alter().
- * Finally drupal_mail_sending_system()->mail() sends the e-mail, which can
+ * Finally drupal_mail_system()->mail() sends the e-mail, which can
* be reused if the exact same composed e-mail is to be sent to multiple
* recipients.
*
@@ -78,8 +78,8 @@
* @param $from
* Sets From to this value, if given.
* @param $send
- * Send the message directly, without calling
- * drupal_mail_sending_system()->mail() manually.
+ * Send the message directly, without calling drupal_mail_system()->mail()
+ * manually.
* @return
* The $message array structure containing all details of the
* message. If already sent ($send = TRUE), then the 'result' element
@@ -93,6 +93,8 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
// Bundle up the variables into a structured array for altering.
$message = array(
'id' => $module . '_' . $key,
+ 'module' => $module,
+ 'key' => $key,
'to' => $to,
'from' => isset($from) ? $from : $default_from,
'language' => $language,
@@ -129,12 +131,15 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
// Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
drupal_alter('mail', $message);
- // Concatenate and wrap the e-mail body.
- $message['body'] = is_array($message['body']) ? drupal_wrap_mail(implode("\n\n", $message['body'])) : drupal_wrap_mail($message['body']);
+ // Retrieve the responsible implementation for this message.
+ $system = drupal_mail_system($module, $key);
+
+ // Format the message body.
+ $message = $system->format($message);
// Optionally send e-mail.
if ($send) {
- $message['result'] = drupal_mail_sending_system($module, $key)->mail($message);
+ $message['result'] = $system->mail($message);
// Log errors
if (!$message['result']) {
@@ -149,11 +154,23 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
/**
* Returns an object that implements the MailSystemInterface.
*
- * Allows for one or more custom mail backends to send mail messages
+ * Allows for one or more custom mail backends to format and send mail messages
* composed using drupal_mail().
*
+ * An implementation needs to implement the following methods:
+ * - format: Allows to preprocess, format, and postprocess a mail
+ * message before it is passed to the sending system. By default, all messages
+ * may contain HTML and are converted to plain-text by the DefaultMailSystem
+ * implementation. For example, an alternative implementation could override
+ * the default implementation and additionally sanitize the HTML for usage in
+ * a MIME-encoded e-mail, but still invoking the DefaultMailSystem
+ * implementation to generate an alternate plain-text version for sending.
+ * - mail: Sends a message through a custom mail sending engine.
+ * By default, all messages are sent via PHP's mail() function by the
+ * DefaultMailSystem implementation.
+ *
* The selection of a particular implementation is controlled via the variable
- * 'mail_sending_system', which is a keyed array. The default implementation
+ * 'mail_system', which is a keyed array. The default implementation
* is the class whose name is the value of 'default-system' key. A more specific
* match first to key and then to module will be used in preference to the
* default. To specificy a different class for all mail sent by one module, set
@@ -195,11 +212,12 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
* A key to identify the e-mail sent. The final e-mail ID for the e-mail
* alter hook in drupal_mail() would have been {$module}_{$key}.
*/
-function drupal_mail_sending_system($module, $key) {
+function drupal_mail_system($module, $key) {
$instances = &drupal_static(__FUNCTION__, array());
$id = $module . '_' . $key;
- $configuration = variable_get('mail_sending_system', array('default-system' => 'DefaultMailSystem'));
+
+ $configuration = variable_get('mail_system', array('default-system' => 'DefaultMailSystem'));
// Look for overrides for the default class, starting from the most specific
// id, and falling back to the module name.
@@ -230,7 +248,18 @@ function drupal_mail_sending_system($module, $key) {
*/
interface MailSystemInterface {
/**
- * Send an e-mail message composed by drupal_mail().
+ * Format a message composed by drupal_mail() prior sending.
+ *
+ * @param $message
+ * A message array, as described in hook_mail_alter().
+ *
+ * @return
+ * The formatted $message.
+ */
+ public function format(array $message);
+
+ /**
+ * Send a message composed by drupal_mail().
*
* @param $message
* Message array with at least the following elements:
@@ -452,9 +481,10 @@ function drupal_html_to_text($string, $allowed_tags = NULL) {
}
// Process blocks of text.
else {
- // Convert inline HTML text to plain text.
- $value = trim(preg_replace('/\s+/', ' ', decode_entities($value)));
- if (strlen($value)) {
+ // Convert inline HTML text to plain text; not removing line-breaks or
+ // white-space, since that breaks newlines when sanitizing plain-text.
+ $value = trim(decode_entities($value));
+ if (drupal_strlen($value)) {
$chunk = $value;
}
}
@@ -466,7 +496,7 @@ function drupal_html_to_text($string, $allowed_tags = NULL) {
$chunk = $casing($chunk);
}
// Format it and apply the current indentation.
- $output .= drupal_wrap_mail($chunk, implode('', $indent)) . "\n";
+ $output .= drupal_wrap_mail($chunk, implode('', $indent));
// Remove non-quotation markers from indentation.
$indent = array_map('_drupal_html_to_text_clean', $indent);
}
diff --git a/includes/module.inc b/includes/module.inc
index ee5446873..4213469ff 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -361,6 +361,8 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
if ($reset) {
$implementations = array();
cache_set('module_implements', array());
+ drupal_static_reset('module_hook_info');
+ cache_clear_all('hook_info', 'cache');
return;
}
@@ -376,18 +378,25 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
}
if (!isset($implementations[$hook])) {
+ $hook_info = module_hook_info();
$implementations[$hook] = array();
$list = module_list(FALSE, FALSE, $sort);
foreach ($list as $module) {
- if (module_hook($module, $hook)) {
- $implementations[$hook][$module] = $module;
+ $include_file = FALSE;
+ if (module_hook($module, $hook) || (isset($hook_info[$hook]['group']) && $include_file = module_load_include('inc', $module, $module . '.' . $hook_info[$hook]['group']) && module_hook($module, $hook))) {
+ $implementations[$hook][$module] = $include_file ? $hook_info[$hook]['group'] : FALSE;
// We added something to the cache, so write it when we are done.
$implementations['#write_cache'] = TRUE;
}
}
}
else {
- foreach ($implementations[$hook] as $module) {
+ foreach ($implementations[$hook] as $module => $group) {
+ // If this hook implementation is stored in a lazy-loaded file, so include
+ // that file first.
+ if ($group) {
+ module_load_include('inc', $module, "$module.$group");
+ }
// It is possible that a module removed a hook implementation without the
// implementations cache being rebuilt yet, so we check module_hook() on
// each request to avoid undefined function errors.
@@ -400,13 +409,45 @@ function module_implements($hook, $sort = FALSE, $reset = FALSE) {
}
}
- // The explicit cast forces a copy to be made. This is needed because
- // $implementations[$hook] is only a reference to an element of
- // $implementations and if there are nested foreaches (due to nested node
- // API calls, for example), they would both manipulate the same array's
- // references, which causes some modules' hooks not to be called.
- // See also http://www.zend.com/zend/art/ref-count.php.
- return (array)$implementations[$hook];
+ return array_keys($implementations[$hook]);
+}
+
+/**
+ * Retrieve a list of what hooks are explicitly declared.
+ */
+function module_hook_info() {
+ $hook_info = &drupal_static(__FUNCTION__, array());
+
+ if (empty($hook_info)) {
+ $cache = cache_get('hook_info');
+ if ($cache === FALSE) {
+ // Rebuild the cache and save it.
+ // We can't use module_invoke_all() here or it would cause an infinite
+ // loop.
+ foreach (module_list() as $module) {
+ $function = $module . '_hook_info';
+ if (function_exists($function)) {
+ $result = $function();
+ if (isset($result) && is_array($result)) {
+ $hook_info = array_merge_recursive($hook_info, $result);
+ }
+ }
+ }
+ // We can't use drupal_alter() for the same reason as above.
+ foreach (module_list() as $module) {
+ $function = $module . '_hook_info_alter';
+ if (function_exists($function)) {
+ $function($hook_info);
+ }
+ }
+ cache_set('hook_info', $hook_info);
+ }
+ else {
+ $hook_info = $cache->data;
+ }
+ }
+
+ return $hook_info;
}
/**
diff --git a/includes/token.inc b/includes/token.inc
index 097e77709..47e7201a2 100644
--- a/includes/token.inc
+++ b/includes/token.inc
@@ -153,7 +153,6 @@ function token_scan($text) {
function token_generate($type, array $tokens, array $data = array(), array $options = array()) {
$results = array();
$options += array('sanitize' => TRUE);
- _token_initialize();
$result = module_invoke_all('tokens', $type, $tokens, $data, $options);
foreach ($result as $original => $replacement) {
@@ -227,25 +226,8 @@ function token_find_with_prefix(array $tokens, $prefix, $delimiter = ':') {
function token_info() {
$data = &drupal_static(__FUNCTION__);
if (!isset($data)) {
- _token_initialize();
$data = module_invoke_all('token_info');
drupal_alter('token_info', $data);
}
return $data;
}
-
-/**
- * Load modulename.tokens.inc for all enabled modules.
- */
-function _token_initialize() {
- $initialized = &drupal_static(__FUNCTION__);
- if (!$initialized) {
- foreach (module_list() as $module) {
- $filename = DRUPAL_ROOT . '/' . drupal_get_path('module', $module) . "/$module.tokens.inc";
- if (file_exists($filename)) {
- include_once $filename;
- }
- }
- $initialized = TRUE;
- }
-}