| 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 = '<?phpclass ' . $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;}
 |