123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- <?php
- /**
- * @file
- * Provide UI for controlling the mail_system variable.
- */
- /**
- * Implements hook_init().
- *
- * Caches the list of MailSystemInterface classes, and removes classes
- * from the mail_system variable which are no longer available.
- *
- * @see mailsystem_get_classes()
- */
- function mailsystem_init() {
- mailsystem_get_classes();
- // @todo Remove this when issue #299138 gets resolved.
- if (!function_exists('mailsystem_html_to_text')) {
- module_load_include('inc', 'mailsystem', 'html_to_text');
- }
- }
- /**
- * 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 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 the default list of MailSystemInterface methods.
- *
- * @return
- * An array whose keys are the names of the methods defined by
- * MailSystemInterface and whose values are the default class used to
- * provide that method.
- */
- function mailsystem_default_methods() {
- $mail_system = mailsystem_get();
- $default_class = $mail_system[mailsystem_default_id()];
- $methods = get_class_methods('MailSystemInterface');
- return array_combine(
- $methods,
- array_fill(0, count($methods), $default_class)
- );
- }
- /**
- * Creates and registers a new MailSystemInterface class.
- *
- * The newly-created class gets its name and each of its class methods from the
- * other classes specified by the $class parameter.
- *
- * @param $class An associative array of ($method_name => $class_name) tuples,
- * where each $method_name is the name of a class method to be created, and
- * each $class_name is the name of a class to use for that method.
- *
- * @return
- * The name of the newly-created class if successful; otherwise FALSE.
- */
- function mailsystem_create_class($classes) {
- // Merge in defaults.
- $classes += mailsystem_default_methods();
- ksort($classes);
- // Do not create a new class whose methods all derive from the same class.
- if (count(array_unique($classes)) === 1) {
- return FALSE;
- }
- $class_name = implode('__', $classes);
- // Ensure that the mailsystem directory exists.
- $class_dir = file_build_uri('mailsystem');
- if (!file_prepare_directory($class_dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
- return FALSE;
- }
- // Build the class filename.
- $class_file = drupal_realpath($class_dir) . DIRECTORY_SEPARATOR . "$class_name.mail.inc";
- // Strip DRUPAL_ROOT.
- $drupal_root = drupal_realpath(DRUPAL_ROOT) . DIRECTORY_SEPARATOR;
- $class_file = preg_replace('#^' . preg_quote($drupal_root, '#') . '#', '', $class_file);
- // Build the class implementation as a string.
- $class_contents = '<?php
- class ' . $class_name . ' implements MailSystemInterface {';
- // Create a protected variable to hold each method class.
- foreach (array_keys($classes) as $method) {
- $class_contents .= '
- protected $' . $method . 'Class;';
- }
- // Create a class construction function to populate the variables.
- $class_contents .= '
- public function __construct() {';
- foreach ($classes as $method => $class) {
- $class_contents .= '
- if (drupal_autoload_class(\'' . $class . '\')) {
- $this->' . $method . 'Class = new ' . $class . ';
- }
- else {
- $this->' . $method . 'Class = new ' . mailsystem_default_value() . ';
- }';
- }
- $class_contents .= '
- }';
- // Create each class method.
- foreach (array_keys($classes) as $method) {
- $class_contents .= '
- public function ' . $method . '(array $message) {
- return $this->' . $method . 'Class->' . $method . '($message);
- }';
- }
- $class_contents .= '
- }
- ';
- if (file_unmanaged_save_data($class_contents, $class_file, FILE_EXISTS_REPLACE)) {
- // Remove any conflicting registry entries to avoid a database error.
- $class_condition = db_and()
- ->condition('name', $class_name)
- ->condition('type', 'class');
- $file_condition = db_and()
- ->condition('filename', $class_file);
- db_delete('registry_file')
- ->condition($file_condition);
- db_delete('registry')->condition(
- db_or()->condition($class_condition)
- ->condition($file_condition)
- );
- // Make sure that registry functions are available.
- require_once 'includes/registry.inc';
- // Parse the newly-created class file and add it to the registry.
- _registry_parse_file($class_file, $class_contents, 'mailsystem');
- // Clear the mailsystem cache so that it will pick up the new class.
- drupal_static_reset('mailsystem_get_classes');
- drupal_set_message(
- t('Class <code>%class</code> written to <code>%file</code>.',
- array('%class' => $class_name, '%file' => $class_file)
- )
- );
- }
- return $class_name;
- }
- /**
- * Helps other modules safely set their own key within mail_system. This
- * function should be called from hook_enable() implementations.
- *
- * @param $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(), mailsystem_default_methods()
- */
- function mailsystem_set(array $setting) {
- $mail_system = mailsystem_get();
- foreach ($setting as $key => $class) {
- if (is_array($class)) {
- unset($setting[$key]);
- if ($new_class = mailsystem_create_class($class)) {
- $setting[$key] = $new_class;
- }
- }
- }
- variable_set('mail_system', array_merge(mailsystem_get(), $setting));
- }
- /**
- * Helps other modules safely remove their settings from mail_system. This
- * function should be called from the other module's hook_disable() function.
- *
- * @param $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.
- *
- * @param $class
- * The name of the class to be removed, if any.
- */
- function mailsystem_clear(array $setting) {
- variable_set(
- 'mail_system',
- array_merge(
- mailsystem_defaults(),
- array_diff_key(array_diff(mailsystem_get(), $setting), $setting)
- )
- );
- }
- /**
- * Returns a list of classes which implement MailSystemInterface.
- */
- function &mailsystem_get_classes() {
- $mailsystem_classes = &drupal_static(__FUNCTION__);
- if (!isset($mailsystem_classes)) {
- $mailsystem_classes = array();
- // @todo Is there a better way to find all mail-related classes?
- $declared_classes = get_declared_classes();
- $all_classes = array_combine(
- $declared_classes,
- array_fill(0, count($declared_classes), 0)
- );
- $mail_classes = db_select('registry', 'registry')
- ->distinct()
- ->fields('registry', array('name', 'filename'))
- ->where("type=:type AND ( filename like :filename OR name like :name )",
- // Making the HUGE assumption that all classes which implement
- // MailSystemInterface have filenames containing '.mail.' or
- // classnames ending in 'MailSystem'.
- array(
- ':type' => 'class',
- ':name' => '%MailSystem',
- ':filename' => '%.mail.%',
- )
- )
- ->execute()
- ->fetchAllKeyed();
- foreach ($mail_classes as $classname => $classfile) {
- if ( file_exists($classfile)
- && drupal_autoload_class($classname)
- ) {
- $all_classes[$classname] = 1;
- }
- }
- foreach ($all_classes as $classname => $autoload) {
- if ( ($autoload || preg_match('/MailSystem/', $classname))
- && ($object = new $classname)
- && ($object instanceof MailSystemInterface)
- ) {
- $mailsystem_classes[$classname] = $classname;
- }
- elseif ($autoload) {
- // Clear classes that are no longer available.
- db_delete('registry')
- ->condition('name', $classname)
- ->execute();
- }
- }
- foreach (array_unique(mailsystem_get()) as $classname) {
- if (class_exists($classname)) {
- $mailsystem_classes[$classname] = $classname;
- }
- else {
- mailsystem_clear(array(mailsystem_default_id() => $classname));
- }
- }
- ksort($mailsystem_classes);
- }
- return $mailsystem_classes;
- }
- /**
- * 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;
- }
|