mailsystem.module in Mail System 7.3
Same filename and directory in other branches
Provide UI for controlling the mail_system variable.
File
mailsystem.moduleView source
<?php
/**
* @file
* Provide UI for controlling the mail_system variable.
*/
/**
* Implements hook_permission().
*
* Defines a permission for managing the mail_system variable.
*/
function mailsystem_permission() {
return array(
'administer mailsystem' => array(
'title' => t('Administer Mail System'),
'description' => t('Select the default, per-module, and per-mailing <a href="!interface"><code>@interface</code></a> to use for formatting and sending email messages.', array(
'!interface' => url('http://api.drupal.org/api/drupal/includes--mail.inc/interface/MailSystemInterface/7'),
'@interface' => 'MailSystemInterface',
)),
),
);
}
/**
* Implements hook_menu().
*/
function mailsystem_menu() {
$items['admin/config/system/mailsystem'] = array(
'title' => 'Mail System',
'description' => 'Configure per-module Mail System settings.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mailsystem_admin_settings',
),
'access arguments' => array(
'administer mailsystem',
),
'file' => 'mailsystem.admin.inc',
);
return $items;
}
/**
* Returns the id for the default mail_system setting.
*/
function mailsystem_default_id() {
// @todo: Is there a way to get this from core?
return 'default-system';
}
/**
* Returns the value for the default mail_system setting.
*/
function mailsystem_default_value() {
// @todo: Is there a way to get this from core?
return 'DefaultMailSystem';
}
/**
* Returns the default settings for the mail_system variable.
*/
function mailsystem_defaults() {
return array(
mailsystem_default_id() => mailsystem_default_value(),
);
}
/**
* Returns the current mail_system settings.
*
* @return array
* The contents of the mail_system variable merged with its defaults.
*/
function mailsystem_get() {
return array_merge(mailsystem_defaults(), variable_get('mail_system', mailsystem_defaults()));
}
/**
* Returns a list of module delegations.
*
* @return array
* An associative array ($id => $value) where:
* - $id is the machine-readable module name optionally followed by '_'
* and a key.
* - $value is an associative array whose keys are the names of methods
* defined by MailSystemInterface and whose values are the names of
* the class to use for that method.
*/
function mailsystem_read_settings() {
$mail_system = mailsystem_get();
$settings = array();
foreach ($mail_system as $id => $class) {
if ($class == 'MailsystemDelegateMailSystem') {
$settings[$id] = variable_get('mailsystem_delegate:' . $id);
}
else {
$settings[$id]['mail'] = $class;
$settings[$id]['format'] = $class;
}
}
return $settings;
}
/**
* Helps other modules safely set their own key within mail_system.
*
* This function should be called from hook_enable() implementations.
*
* @param array $setting
* An associative array ($id => $value) where:
* - $id is the machine-readable module name optionally followed by '_'
* and a key.
* - $value is one of
* - (string) The name of a class that implements MailSystemInterface.
* - (array) An associative array whose keys are the names of methods
* defined by MailSystemInterface and whose values are the names of
* the class to use for that method.
*
* @see drupal_mail()
*/
function mailsystem_set(array $setting) {
$mail_system = mailsystem_get();
foreach ($setting as $key => $class) {
variable_del("mailsystem_delegate:{$key}");
if (is_array($class)) {
// Save the settings for our delegateer-class into a variable.
$setting[$key] = mailsystem_delegate_set_mailsystem_settings($key, $class);
}
}
variable_set('mail_system', array_merge(mailsystem_get(), $setting));
}
/**
* Helps other modules safely remove their settings from mail_system.
*
* Function should be called from the other module's hook_disable() function.
*
* @param array $setting
* An associative array ($module => $classname) describing
* a module and associated MailSystemInterface class that are being disabled.
* - $module is the machine-readable module name.
* - $classname is a class that implements MailSystemInterface.
*
* If $classname is empty, only the $module entry is removed.
*/
function mailsystem_clear(array $setting) {
variable_set('mail_system', array_merge(mailsystem_defaults(), array_diff_key(array_diff(mailsystem_get(), $setting), $setting)));
foreach (array_keys($setting) as $key) {
variable_del("mailsystem_delegate:{$key}");
}
}
/**
* Save settings for the delegate mail system for a given mail-id.
*
* @param int $id
* Is the machine-readable module name optionally followed by '_'
* and a key.
* @param array $settings
* An associative array whose keys are the names of methods
* defined by MailSystemInterface and whose values are the names of
* the class to use for that method.
*
* @return string
* A string specifying the name of the delegator class.
*/
function mailsystem_delegate_set_mailsystem_settings($id, array $settings) {
variable_set('mailsystem_delegate:' . $id, $settings);
return 'MailsystemDelegateMailSystem';
}
/**
* Returns an MailSystemInterface class instance for a given action.
*
* Of a class implementing the MailSystemInterface
* responsible for performing the given action.
*
* @param string $module
* The machine-readable module name.
* @param string $key
* The email key.
* @param string $action
* The name of the MailSystemInterface method to be invoked. Should be one of:
* - format: Format a message composed by drupal_mail() prior to sending.
* - mail: Send a message composed by drupal_mail().
*
* @return MailSystemInterface
* A mail system implementation.
*
* @see drupal_mail_system()
*/
function _mailsystem_delegate_get_mailsystem($module, $key, $action) {
$instances =& drupal_static(__FUNCTION__, array());
// Try to use custom settings defined for the message's module and key.
$settings = variable_get('mailsystem_delegate:' . $module . '_' . $key);
if ($settings === NULL) {
// Try to use custom settings defined for the message's module.
$settings = variable_get('mailsystem_delegate:' . $module);
}
if ($settings === NULL) {
// Try to use the configured site-wide default mail system settings.
$settings = variable_get('mailsystem_delegate:' . mailsystem_default_id());
}
// Use the class configured for the given action.
if ($settings && isset($settings[$action])) {
$class = $settings[$action];
}
else {
$mailsystems = mailsystem_get();
$class = $mailsystems[mailsystem_default_id()];
// Fallback to drupal default in order to prevent an infinite recursion.
if ($class == 'MailsystemDelegateMailSystem') {
$class = mailsystem_default_value();
}
}
if (empty($instances[$class])) {
$interfaces = class_implements($class);
if (isset($interfaces['MailSystemInterface'])) {
$instances[$class] = new $class();
}
else {
throw new Exception(t('Class %class does not implement interface %interface', array(
'%class' => $class,
'%interface' => 'MailSystemInterface',
)));
}
}
return $instances[$class];
}
/**
* Returns a list of classes which implement MailSystemInterface.
*
* This method assumes that all classes which implement MailSystemInterface
* have filenames containing '.mail.' or class names containing 'MailSystem'.
*
* If necessary you may override the default discovery whitelist by setting
* the mailsystem_get_classes_whitelist and mailsystem_get_classes_blacklist
* variables. The default value is as follows:
*
* @code
* variable_set('mailsystem_get_classes_whitelist', array(
* array(
* 'field' => 'name',
* 'value' => '%MailSystem',
* 'operator' => 'LIKE',
* ),
* array(
* 'field' => 'filename',
* 'value' => '%.mail.%',
* 'operator' => 'LIKE',
* ),
* ));
*
* variable_set('mailsystem_get_classes_blacklist', array(
* array(
* 'field' => 'filename',
* 'value' => '%.test',
* 'operator' => 'NOT LIKE',
* ),
* ));
* @endcode
*
* The 'field' value specifies in which database-field of the registry table
* the lookup for 'value' should take place. Typical values for 'field' are
* either 'name' for the classname or 'filename' for the name of the file the
* class is contained in.
*
* For example, if your own mail system implementation called 'MyMailer' should
* be available in the mailsystem module you may add the following record to
* the whitelist:
*
* @code
* array(
* 'field' => 'name',
* 'value' => 'MyMailer',
* );
* @endcode
*
* Note that if you set the blacklist, you need to negate the operator. Use
* 'NOT Like' or the not-equal operator '<>'.
*/
function mailsystem_get_classes() {
$mailsystem_classes =& drupal_static(__FUNCTION__);
if (!isset($mailsystem_classes)) {
$query = db_select('registry', 'registry')
->fields('registry', array(
'name',
'filename',
))
->condition('type', 'class');
if ($whitelist = _mailsystem_get_registry_whitelist_condition()) {
$query
->condition($whitelist);
}
if ($blacklist = _mailsystem_get_registry_blacklist_condition()) {
$query
->condition($blacklist);
}
$mail_classes = $query
->execute()
->fetchAllKeyed();
$mailsystem_classes = array();
foreach ($mail_classes as $classname => $classfile) {
if (file_exists($classfile)) {
$interfaces = class_implements($classname);
if (isset($interfaces['MailSystemInterface'])) {
$mailsystem_classes[$classname] = $classname;
}
}
}
ksort($mailsystem_classes);
}
return $mailsystem_classes;
}
/**
* Return a DatabaseCondition representing the registry-whitelist.
*
* @return DatabaseCondition|null
* DatabaseCondition representing the whitelist conditions or NULL.
*
* @see mailsystem_get_classes
*/
function _mailsystem_get_registry_whitelist_condition() {
$whitelist = variable_get('mailsystem_get_classes_whitelist', array(
array(
'field' => 'name',
'value' => '%MailSystem',
'operator' => 'LIKE',
),
array(
'field' => 'filename',
'value' => '%.mail.%',
'operator' => 'LIKE',
),
));
if (!empty($whitelist)) {
$or = db_or();
foreach ($whitelist as $entry) {
if (!empty($entry['field']) && !empty($entry['value']) && !empty($entry['operator'])) {
$or
->condition($entry['field'], $entry['value'], $entry['operator']);
$condition_added = TRUE;
}
}
if ($or
->count()) {
return $or;
}
}
}
/**
* Return a DatabaseCondition representing the registry-blacklist.
*
* By default all files ending with .test are excluded if the simpletest module
* is disabled. The blacklist pattern can be overridden using the variable
* mailsystem_get_classes_blacklist.
*
* @return DatabaseCondition|null
* DatabaseCondition representing the blacklist conditions or NULL.
*
* @see mailsystem_get_classes
*/
function _mailsystem_get_registry_blacklist_condition() {
if (!module_exists('simpletest')) {
$default_blacklist = array(
array(
'field' => 'filename',
'value' => '%.test',
'operator' => 'NOT LIKE',
),
);
}
else {
$default_blacklist = array();
}
$blacklist = variable_get('mailsystem_get_classes_blacklist', $default_blacklist);
if (!empty($blacklist)) {
$and = db_and();
foreach ($blacklist as $entry) {
if (!empty($entry['field']) && !empty($entry['value']) && !empty($entry['operator'])) {
$and
->condition($entry['field'], $entry['value'], $entry['operator']);
}
}
if ($and
->count()) {
return $and;
}
}
}
/**
* Implements hook_theme_registry_alter().
*/
function mailsystem_theme_registry_alter(&$theme_registry) {
module_load_include('inc', 'mailsystem', 'mailsystem.theme');
return mailsystem_theme_theme_registry_alter($theme_registry);
}
/**
* Retrieves the key of the theme used to render the emails.
*
* @todo Add some kind of hook to let other modules alter this behavior.
*/
function mailsystem_get_mail_theme() {
global $theme_key;
$theme = variable_get('mailsystem_theme', 'current');
switch ($theme) {
case 'default':
$theme = variable_get('theme_default', NULL);
break;
case 'current':
$theme = $theme_key;
break;
case 'domain':
// Fetch the theme for the current domain.
if (module_exists('domain_theme')) {
// Assign the selected theme, based on the active domain.
global $_domain;
$domain_theme = domain_theme_lookup($_domain['domain_id']);
// The above returns -1 on failure.
$theme = $domain_theme != -1 ? $domain_theme['theme'] : $theme_key;
}
break;
}
return $theme;
}
/**
* Implements hook_system_info_alter().
*
* Prevent the module from being disabled while the mail_system variable is
* still using the MailsystemDelegateMailSystem class.
*/
function mailsystem_system_info_alter(&$info, $file, $type) {
if ($type == 'module' && $file->name == 'mailsystem') {
$mail_system = mailsystem_get();
foreach ($mail_system as $key => $class) {
if ($class == 'MailsystemDelegateMailSystem') {
$info['required'] = TRUE;
$info['explanation'] = t('<em>Mail System</em> cannot be disabled until each custom setting on its <a href="@url">configure page</a> is either removed, or uses the same class for both its formatting and delivery class.', array(
'@url' => url('admin/config/system/mailsystem'),
));
}
}
}
}
Functions
Name | Description |
---|---|
mailsystem_clear | Helps other modules safely remove their settings from mail_system. |
mailsystem_defaults | Returns the default settings for the mail_system variable. |
mailsystem_default_id | Returns the id for the default mail_system setting. |
mailsystem_default_value | Returns the value for the default mail_system setting. |
mailsystem_delegate_set_mailsystem_settings | Save settings for the delegate mail system for a given mail-id. |
mailsystem_get | Returns the current mail_system settings. |
mailsystem_get_classes | Returns a list of classes which implement MailSystemInterface. |
mailsystem_get_mail_theme | Retrieves the key of the theme used to render the emails. |
mailsystem_menu | Implements hook_menu(). |
mailsystem_permission | Implements hook_permission(). |
mailsystem_read_settings | Returns a list of module delegations. |
mailsystem_set | Helps other modules safely set their own key within mail_system. |
mailsystem_system_info_alter | Implements hook_system_info_alter(). |
mailsystem_theme_registry_alter | Implements hook_theme_registry_alter(). |
_mailsystem_delegate_get_mailsystem | Returns an MailSystemInterface class instance for a given action. |
_mailsystem_get_registry_blacklist_condition | Return a DatabaseCondition representing the registry-blacklist. |
_mailsystem_get_registry_whitelist_condition | Return a DatabaseCondition representing the registry-whitelist. |